KITAQ SERIES • REFERENZAUSGABE
KITAQFC-BIBLIOTHEK
NES-Bibliotheken und -Geräte
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.
kitaqfc · 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.
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 fc_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.

Quelltext herunterladen / Prüfstatus
.\kitaqfc\kitaqfc.exe kitaq-docs/samples/fc_font.c -I kitaqfc/lib -I kitaq-docs/samples -o out/fc_font.nes --mapper=nrom --nes-chr=kitaq-docs/samples/font.chr// Display the letters, digits and punctuation from the supplied ascii.c font.
// Expected: Uppercase, lowercase, numbers and all 30 supplied punctuation glyphs
#include "fc_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(void) {
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 fc_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.

Quelltext herunterladen / Prüfstatus
.\kitaqfc\kitaqfc.exe kitaq-docs/samples/fc_hello.c -I kitaqfc/lib -I kitaq-docs/samples -o out/fc_hello.nes --mapper=nrom --nes-chr=kitaq-docs/samples/font.chr// Display a first message on screen.
// Expected: HELLO WORLD and 042
#include "fc_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(void) {
m_init();
m_text(2,3,"HELLO");
m_text(2,5,"HELLO WORLD");
m_number(42);
while (1) { m_wait(); }
}Mit breiterem Zwischentyp rechnen fc_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.

Quelltext herunterladen / Prüfstatus
.\kitaqfc\kitaqfc.exe kitaq-docs/samples/fc_arithmetic.c -I kitaqfc/lib -I kitaq-docs/samples -o out/fc_arithmetic.nes --mapper=nrom --nes-chr=kitaq-docs/samples/font.chr// Variables, arithmetic and type conversion.
// Expected: 030
#include "fc_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(void) {
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 fc_control.c
Zweck: Erprobt for, continue, while und if/else in einer kleinen Berechnung.
Funktionsweise: Die for-Schleife addiert 0 bis 7, überspringt dabei 3 und erhält 25. Die while-Schleife zählt bis 32 weiter; das folgende if weist bei Übereinstimmung den Wert 42 zu.
Bedienung und erwartetes Ergebnis: 042 ist das Endergebnis. Das Programm verwendet eine if/else-Verzweigung.

Quelltext herunterladen / Prüfstatus
.\kitaqfc\kitaqfc.exe kitaq-docs/samples/fc_control.c -I kitaqfc/lib -I kitaq-docs/samples -o out/fc_control.nes --mapper=nrom --nes-chr=kitaq-docs/samples/font.chr// Conditional branches and loops.
// Expected: 042
#include "fc_common.h"
// Exercise loop control and a final branch, then display the selected value 42.
void main(void) {
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<32) { sum++; }
if (sum==32) sum=42; else sum=0;
m_number(sum);
while (1) { m_wait(); }
}Funktionen, Arrays, Strukturen und Zeiger fc_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.](../verification/fc_aggregate.png)
Quelltext herunterladen / Prüfstatus
.\kitaqfc\kitaqfc.exe kitaq-docs/samples/fc_aggregate.c -I kitaqfc/lib -I kitaq-docs/samples -o out/fc_aggregate.nes --mapper=nrom --nes-chr=kitaq-docs/samples/font.chr// Functions, arrays, structures and pointers.
// Expected: 042
#include "fc_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(void) {
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 fc_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.

Quelltext herunterladen / Prüfstatus
.\kitaqfc\kitaqfc.exe kitaq-docs/samples/fc_bits_memory.c -I kitaqfc/lib -I kitaq-docs/samples -o out/fc_bits_memory.nes --mapper=nrom --nes-chr=kitaq-docs/samples/font.chr// Bit operations and memory copying.
// Expected: 010
#include "fc_common.h"
// Clear the source bytes, set bits 3 and 1, copy the buffer, and display 8 + 2 = 10.
void main(void) {
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 fc_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.

Quelltext herunterladen / Prüfstatus
.\kitaqfc\kitaqfc.exe kitaqfc/lib/input.c kitaq-docs/samples/fc_input.c -I kitaqfc/lib -I kitaq-docs/samples -o out/fc_input.nes --mapper=nrom --nes-chr=kitaq-docs/samples/font.chr// Distinguish a new button press from a held button.
// Expected: 000 initially; A increments once per press
#include "fc_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(void) {
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 fc_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.

Quelltext herunterladen / Prüfstatus
.\kitaqfc\kitaqfc.exe kitaqfc/lib/fixed.c kitaq-docs/samples/fc_fixed.c -I kitaqfc/lib -I kitaq-docs/samples -o out/fc_fixed.nes --mapper=nrom --nes-chr=kitaq-docs/samples/font.chr// Calculate with signed Q8.8 fixed-point values.
// Expected: 012
#include "fc_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(void) {
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 fc_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.

Quelltext herunterladen / Prüfstatus
.\kitaqfc\kitaqfc.exe kitaqfc/lib/entity.c kitaq-docs/samples/fc_entity.c -I kitaqfc/lib -I kitaq-docs/samples -o out/fc_entity.nes --mapper=nrom --nes-chr=kitaq-docs/samples/font.chr// Allocate an entity from a fixed-capacity object pool.
// Expected: 001
#include "fc_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(void) {
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 fc_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.

Quelltext herunterladen / Prüfstatus
.\kitaqfc\kitaqfc.exe kitaqfc/lib/debug.c kitaq-docs/samples/fc_debug.c -I kitaqfc/lib -I kitaq-docs/samples -o out/fc_debug.nes --mapper=nrom --nes-chr=kitaq-docs/samples/font.chr// Record diagnostic values in the debug trace.
// Expected: 001; trace log contains HP=42
#include "fc_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(void) {
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 fc_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.

Quelltext herunterladen / Prüfstatus
.\kitaqfc\kitaqfc.exe kitaqfc/lib/chain.c kitaq-docs/samples/fc_chain.c -I kitaqfc/lib -I kitaq-docs/samples -o out/fc_chain.nes --mapper=nrom --nes-chr=kitaq-docs/samples/font.chr// Store a position history in a ring buffer.
// Expected: 042; history contains (20,30)
#include "fc_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(void) {
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 fc_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.

Quelltext herunterladen / Prüfstatus
.\kitaqfc\kitaqfc.exe kitaqfc/lib/system.c kitaq-docs/samples/fc_system.c -I kitaqfc/lib -I kitaq-docs/samples -o out/fc_system.nes --mapper=nrom --nes-chr=kitaq-docs/samples/font.chr// Count completed frame waits.
// Expected: 002
#include "fc_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(void) {
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 fc_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.

Quelltext herunterladen / Prüfstatus
.\kitaqfc\kitaqfc.exe kitaqfc/lib/runtime.c kitaqfc/lib/scene.c kitaq-docs/samples/fc_scene.c -I kitaqfc/lib -I kitaq-docs/samples -o out/fc_scene.nes --mapper=nrom --nes-chr=kitaq-docs/samples/font.chr// The scene streaming module shares runtime.c queue symbols, even though this demo only changes IDs.
#define MANUAL_FC_RUNTIME 1
// Switch the current scene ID.
// Expected: 001; no callbacks registered
#include "fc_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(void) {
m_init();
m_text(2,3,"SCENE");
scene_init(manual_scenes,2); scene_change(1);
m_number(scene_get_current());
while (1) { m_wait(); }
}Gebrochene Q5.3-Bewegung aufsummieren fc_subpixel.c
Zweck: Behält Subpixelbewegungen als Rest bei und überträgt ganze Pixel auf die Position.
Funktionsweise: Ausgehend von X=40 addiert die Schleife achtmal 2/8 Pixel. Eine Rechtsverschiebung liefert die ganzen Pixel; eine Maske behält den Rest bei.
Bedienung und erwartetes Ergebnis: Die Gesamtbewegung beträgt zwei Pixel; deshalb erscheint X=42 als 042. Dieses Beispiel manueller Integration behandelt positive Bewegung; negative Bewegung benötigt einen entsprechenden Übertrag beim Subtrahieren.

Quelltext herunterladen / Prüfstatus
.\kitaqfc\kitaqfc.exe kitaq-docs/samples/fc_subpixel.c -I kitaqfc/lib -I kitaq-docs/samples -o out/fc_subpixel.nes --mapper=nrom --nes-chr=kitaq-docs/samples/font.chr// Accumulate Q5.3 eighth-pixel motion into an integer coordinate.
// Expected: 042; explicit game-side integration using header constants
#include "fc_common.h"
#include "physics2d.h"
// Integrate eight increments of 2/8 pixel. Carry whole pixels into X and
// retain the fractional remainder with the supplied mask, moving X from 40 to 42.
void main(void) {
m_init();
m_text(2,3,"SUBPIXEL");
KQ2DPosition x; KQ2DFraction frac; KQ2DSpeed speed; u8 i;
// This example demonstrates positive motion only; signed negative motion needs a matching carry/borrow path.
x=40; frac=0; speed=2;
for(i=0;i<8;i++) {
frac=(u8)(frac+speed);
x=(u8)(x+(frac>>KQ2D_SUBPIXEL_BITS));
frac=(u8)(frac & KQ2D_SUBPIXEL_MASK);
}
m_number(x);
while (1) { m_wait(); }
}Den NES-Hintergrund scrollen fc_scroll.c
Zweck: Verschiebt den Hintergrund durch Aktualisieren der PPU-Scrollposition.
Funktionsweise: Nach __scroll_set(0,0) erhöht das Programm phase einmal pro Frame und verwendet den Wert als horizontale Position.
Bedienung und erwartetes Ergebnis: Das Wort SCROLL ändert seine horizontale Position. phase springt von 255 auf 0 zurück. Dies ist kein Beispiel für eine breite Karte über mehrere Nametables.

Quelltext herunterladen / Prüfstatus
.\kitaqfc\kitaqfc.exe kitaq-docs/samples/fc_scroll.c -I kitaqfc/lib -I kitaq-docs/samples -o out/fc_scroll.nes --mapper=nrom --nes-chr=kitaq-docs/samples/font.chr// Scroll the NES background horizontally.
// Expected: title scrolls horizontally
#include "fc_common.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(void) {
m_init();
m_text(2,3,"SCROLL");
__scroll_set(0,0);
while (1) { m_wait(); phase++; __scroll_set(phase,0); }
}Eine Tile-Aktualisierung über NMI anwenden fc_vram_queue.c
Zweck: Reicht aus dem Hauptprogramm eine PPU-Aktualisierung ein, die anschließend im NMI-Ablauf angewendet wird.
Funktionsweise: __vramq_put reiht Tile 52 für Nametable-Adresse 0x2103 ein; __vramq_commit reicht die Aktualisierung ein. Diese Adresse entspricht Tile-Koordinate (3,8).
Bedienung und erwartetes Ergebnis: Bei Hintergrundkoordinate (3,8) erscheint eine einzelne 4. Tile 52 ist in der mitgelieferten Schrift die Ziffer 4.

Quelltext herunterladen / Prüfstatus
.\kitaqfc\kitaqfc.exe kitaq-docs/samples/fc_vram_queue.c -I kitaqfc/lib -I kitaq-docs/samples -o out/fc_vram_queue.nes --mapper=nrom --nes-chr=kitaq-docs/samples/font.chr// Submit a VRAM update for the NMI handler.
// Expected: 4 at (3,8)
#include "fc_common.h"
// Queue tile 52 at nametable address 0x2103, corresponding to (3,8), and
// commit the queue so the NMI update path displays the digit 4.
void main(void) {
m_init();
m_text(2,3,"VRAM QUEUE");
__vramq_put(0x2103,52); __vramq_commit();
while (1) { m_wait(); }
}Ein NES-OAM-Sprite anzeigen fc_sprite.c
Zweck: Bereitet Spritefarben und OAM-Daten vor, um ein Bild unabhängig vom Hintergrund zu zeichnen.
Funktionsweise: Das Programm lädt die Spritepalette, setzt Eintrag 0 auf Position (70,80), Tile 65 und Attribute 0, aktiviert die Darstellung und wiederholt den OAM-DMA.
Bedienung und erwartetes Ergebnis: Ein unbewegtes A erscheint als Sprite. Das Beispiel zeigt OAM-Einrichtung und -Übertragung, keine Animation.

Quelltext herunterladen / Prüfstatus
.\kitaqfc\kitaqfc.exe kitaq-docs/samples/fc_sprite.c -I kitaqfc/lib -I kitaq-docs/samples -o out/fc_sprite.nes --mapper=nrom --nes-chr=kitaq-docs/samples/font.chr// Display a sprite using NES OAM.
// Expected: A sprite on screen
#include "fc_common.h"
// Load the sprite palette, assign font tile 65 to OAM slot zero, enable
// background/sprite display, and transfer OAM after each frame wait.
void main(void) {
m_init();
m_text(2,3,"SPRITE");
__palette_sp_load(manual_pal); __sprite_set(0,70,80,65,0);
__ppu_mask_set(0x1E);
while (1) { m_wait(); __oam_dma(); }
}Einen APU-Pulston abspielen fc_sound.c
Zweck: Stellt Steuer-, Timer- und Längenwerte des eingebauten NES-Pulskanals ein.
Funktionsweise: Nach nes_apu_init ruft das Programm nes_sfx_square1(0xBF,400,20) auf. Steuerwert 0xBF wählt konstante Lautstärke und hält den Längenzähler an, sodass der Ton anhält. 20 ist ein Index der Längentabelle, keine Dauer von 20 Frames.
Bedienung und erwartetes Ergebnis: Während 042 angezeigt wird, erklingt ein anhaltender Pulston. Beenden Sie ihn mit nes_apu_silence_all. Die Bildschirmanzeige allein bestätigt keine Tonausgabe.

Quelltext herunterladen / Prüfstatus
.\kitaqfc\kitaqfc.exe kitaqfc/lib/audio.c kitaq-docs/samples/fc_sound.c -I kitaqfc/lib -I kitaq-docs/samples -o out/fc_sound.nes --mapper=nrom --nes-chr=kitaq-docs/samples/font.chr// Play a pulse-channel effect on the built-in NES APU.
// Expected: 042 and a pulse tone
#include "fc_common.h"
#include "audio.h"
// Initialize the APU, trigger pulse channel 1 with the chosen timer/length
// values, and leave the screen displaying 42 while the hardware plays the tone.
void main(void) {
m_init();
m_text(2,3,"SOUND");
// Control BF selects constant volume and halts the length counter, so this tone sustains.
// Call nes_apu_silence_all when the game should stop it; 20 is a length-table index, not frames.
nes_apu_init(); nes_sfx_square1(0xBF,400,20);
m_number(42);
while (1) { m_wait(); }
}API-Referenz der Bibliothek
294 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.
actor.h — Arrays für Spielakteure
NesActor bündelt Weltposition, Bildschirmposition und Rechteckgröße. Hilfsfunktionen projizieren durch die Kamera, schreiben Metasprite-OAM und prüfen Überlappungen in Weltkoordinaten. Geschwindigkeit, Aussortieren außerhalb des Bildschirms und OAM-DMA verwaltet das Spiel.
nes_actor_collide
Prüft die Überlappung achsenparalleler Akteursrechtecke in Weltkoordinaten.
Syntax
unsigned char nes_actor_collide(struct NesActor* a, struct NesActor* b);Parameter
aErster Akteur.
bZweiter Akteur.
Rückgabewert
Gibt bei Überlappung 1 zurück, bei Trennung oder bloßer Kantenberührung 0.
Bedingungen und Grenzen
Verwenden Sie positive Breiten und Höhen und halten Sie Position+Größe≤65535. Bildschirmkoordinaten, attr und flags werden ignoriert.
Anwendungsbeispiel
result[3]=nes_actor_collide(&a,&b);nes_actor_set_world(&b,315,95);result[4]=nes_actor_collide(&a,&b);Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Projizieren Sie Weltposition (300,95) durch Kamera (268,32): Rote und blaue 8×8-Teile erscheinen bei (32,64) und (40,64). Dies zeigt den rohen OAM-Y-Wert 63 als sichtbares Y=64 sowie den Wechsel des Kollisionsergebnisses von null bei Kantenberührung zu eins bei einem Pixel Überlappung.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\batch3_actor.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch3_actor.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chrImplementierung und Quelltext
kitaqfc/lib/actor.h:29
Test overlap in world coordinates with exclusive right/bottom edges. Keep position-plus-size sums within u16; touching edges are not collisions. Require positive widths and heights; zero extents are not rejected before the edge tests.
kitaqfc/lib/actor.c:49
unsigned char nes_actor_collide(struct NesActor* a, struct NesActor* b)
{
unsigned short a_right;
unsigned short b_right;
unsigned short a_bottom;
unsigned short b_bottom;
a_right = (unsigned short)(a->world_x + a->width);
b_right = (unsigned short)(b->world_x + b->width);
a_bottom = (unsigned short)(a->world_y + a->height);
b_bottom = (unsigned short)(b->world_y + b->height);
if (a_right <= b->world_x)
{
return 0;
}
if (b_right <= a->world_x)
{
return 0;
}
if (a_bottom <= b->world_y)
{
return 0;
}
if (b_bottom <= a->world_y)
{
return 0;
}
return 1;
}nes_actor_draw_metasprite
Schreibt mit den zwischengespeicherten Bildschirmkoordinaten des Akteurs ein Metasprite in das Schatten-OAM.
Syntax
unsigned char nes_actor_draw_metasprite(struct NesActor* actor, unsigned char oam_index, unsigned char* metasprite);Parameter
actorZeiger auf einen beschreibbaren NesActor.
oam_indexErster Slot, 0..63; reservieren Sie Platz für alle Teile.
metaspriteVier-Byte-Datensätze dx,dy,tile,attr; dx=255 beendet die Liste.
Rückgabewert
Gibt den nächsten OAM-Slotindex zurück, mit Umlauf am Ende der 64 Slots.
Bedingungen und Grenzen
Binden Sie runtime.c ein. Die Warteschlange kopiert Nutzdaten für eine spätere NMI oder eine sichere Übertragung bei ausgeschalteter Darstellung. Serialisieren Sie Erzeugung und Verbrauch. Geht bei mehreren Zeilen die Kapazität aus, bleiben zuvor aufgenommene Zeilen eingereiht.
Wendet die attr/flags-Felder des Akteurs nicht an. Y ist ein rohes OAM-Byte, daher liegt die sichtbare Oberkante ein Pixel tiefer. Zum Anzeigen des Schattenpuffers ist ein OAM-DMA erforderlich.
Anwendungsbeispiel
result[5]=nes_actor_draw_metasprite(&a,0,parts);result[6]=nes_oam_shadow[3];result[7]=nes_oam_shadow[7];nes_oam_dma(2);Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Projizieren Sie Weltposition (300,95) durch Kamera (268,32): Rote und blaue 8×8-Teile erscheinen bei (32,64) und (40,64). Dies zeigt den rohen OAM-Y-Wert 63 als sichtbares Y=64 sowie den Wechsel des Kollisionsergebnisses von null bei Kantenberührung zu eins bei einem Pixel Überlappung.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\batch3_actor.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch3_actor.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chrImplementierung und Quelltext
kitaqfc/lib/actor.h:25
Draw the byte-stream metasprite at cached screen coordinates and return its next OAM index. Actor attr/flags are not applied by this wrapper.
kitaqfc/lib/actor.c:41
unsigned char nes_actor_draw_metasprite(struct NesActor* actor, unsigned char oam_index, unsigned char* metasprite)
{
return nes_metasprite_draw(oam_index, actor->screen_x, actor->screen_y, metasprite);
}nes_actor_set_world
Setzt Welt-X/Y eines Akteurs.
Syntax
void nes_actor_set_world(struct NesActor* actor, unsigned short x, unsigned short y);Parameter
actorZeiger auf einen beschreibbaren NesActor.
xWelt-X, 0..65535 Pixel.
yWelt-Y, 0..65535 Pixel.
Rückgabewert
Kein Rückgabewert.
Bedingungen und Grenzen
Aktualisiert screen_x/screen_y nicht. Rufen Sie update_screen zur Projektion durch die Kamera auf.
Anwendungsbeispiel
nes_actor_set_world(&a,300,95);nes_actor_set_world(&b,316,95);result[0]=a.world_x;Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Projizieren Sie Weltposition (300,95) durch Kamera (268,32): Rote und blaue 8×8-Teile erscheinen bei (32,64) und (40,64). Dies zeigt den rohen OAM-Y-Wert 63 als sichtbares Y=64 sowie den Wechsel des Kollisionsergebnisses von null bei Kantenberührung zu eins bei einem Pixel Überlappung.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\batch3_actor.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch3_actor.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chrImplementierung und Quelltext
kitaqfc/lib/actor.h:19
Set the actor's 16-bit world position without updating cached screen coordinates.
kitaqfc/lib/actor.c:19
void nes_actor_set_world(struct NesActor* actor, unsigned short x, unsigned short y)
{
actor->world_x = x;
actor->world_y = y;
}nes_actor_update_screen
Zieht Kamerakoordinaten von Weltkoordinaten ab und speichert die unteren Bytes als Bildschirmkoordinaten zwischen.
Syntax
void nes_actor_update_screen(struct NesActor* actor, unsigned short camera_x, unsigned short camera_y);Parameter
actorZeiger auf einen beschreibbaren NesActor.
camera_xWelt-X der Kamera.
camera_yWelt-Y der Kamera.
Rückgabewert
Kein Rückgabewert.
Bedingungen und Grenzen
Negative Ergebnisse oder Werte ≥256 laufen um. Akteure außerhalb des Bildschirms werden nicht ausgeblendet; das Spiel muss sie vor dem Zeichnen aussortieren.
Anwendungsbeispiel
nes_actor_update_screen(&a,268,32);result[1]=a.screen_x;result[2]=a.screen_y;Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Projizieren Sie Weltposition (300,95) durch Kamera (268,32): Rote und blaue 8×8-Teile erscheinen bei (32,64) und (40,64). Dies zeigt den rohen OAM-Y-Wert 63 als sichtbares Y=64 sowie den Wechsel des Kollisionsergebnisses von null bei Kantenberührung zu eins bei einem Pixel Überlappung.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\batch3_actor.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch3_actor.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chrImplementierung und Quelltext
kitaqfc/lib/actor.h:22
Subtract the camera and retain only the low coordinate bytes. This performs wrapping projection, not clipping; callers must hide actors outside the viewport.
kitaqfc/lib/actor.c:27
void nes_actor_update_screen(struct NesActor* actor, unsigned short camera_x, unsigned short camera_y)
{
unsigned short dx;
unsigned short dy;
dx = (unsigned short)(actor->world_x - camera_x);
dy = (unsigned short)(actor->world_y - camera_y);
actor->screen_x = (unsigned char)dx;
actor->screen_y = (unsigned char)dy;
}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, wählt deren ROM-Bank und überträgt sämtliche Daten mit __vram_write in Blöcken von höchstens 128 Byte. Anschließend wird die von bank_get_current() gespeicherte Bank wiederhergestellt. Zwischen den Blöcken wird nicht auf das nächste Bild gewartet.
Verwenden Sie beschreibbaren CHR RAM für Muster und schalten Sie die Darstellung bei langen Transfers ab. Innerhalb von VBlank muss der gesamte Vorgang in die verfügbare Zeit passen; 128-Byte-Blöcke gewährleisten das nicht. Das Beispiel nutzt --mapper=mmc1 --board=surom512. Bei generischen Boards erzeugt das Weglassen von --nes-chr leeren CHR ROM, keinen CHR RAM.
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
u8 asset_get(u8 asset_id, AssetDesc* out_desc);Parameter
asset_idRessourcenindex ab null. In der registrierten Tabelle gilt für eine gültige ID
asset_id < count.out_descBeschreibbarer 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
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 FC zeigt das blaue Paar bei (16,64) __far_memcpy, das grüne bei (16,96) asset_load_raw mit anschließender CHR-Übertragung. Jedes Paar belegt 16×8 Pixel auf schwarzem Hintergrund. So werden die kopierten Bilddaten sichtbar, nicht nur numerische Statuswerte.
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\asset_banks.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\asset_banks.nes --mapper=mmc1 --board=surom512 --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/asset.h:25
Copy a descriptor from its ROM bank into caller storage. Null output or an out-of-range ID returns zero without reading the table.
kitaqfc/lib/asset.c:18
u8 asset_get(u8 asset_id, AssetDesc* out_desc)
{
if (out_desc == 0) return 0;
if (asset_id >= asset_table_count) return 0;
__far_memcpy((u8*)out_desc, asset_table_bank, (u16)(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
u8 asset_get_bank(u8 asset_id);Parameter
asset_idRessourcenindex 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
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 FC zeigt das blaue Paar bei (16,64) __far_memcpy, das grüne bei (16,96) asset_load_raw mit anschließender CHR-Übertragung. Jedes Paar belegt 16×8 Pixel auf schwarzem Hintergrund. So werden die kopierten Bilddaten sichtbar, nicht nur numerische Statuswerte.
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\asset_banks.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\asset_banks.nes --mapper=mmc1 --board=surom512 --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/asset.h:33
Return the asset bank or zero on lookup failure; bank zero may also be valid.
kitaqfc/lib/asset.c:74
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
u16 asset_get_len(u8 asset_id);Parameter
asset_idRessourcenindex 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
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 FC zeigt das blaue Paar bei (16,64) __far_memcpy, das grüne bei (16,96) asset_load_raw mit anschließender CHR-Übertragung. Jedes Paar belegt 16×8 Pixel auf schwarzem Hintergrund. So werden die kopierten Bilddaten sichtbar, nicht nur numerische Statuswerte.
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\asset_banks.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\asset_banks.nes --mapper=mmc1 --board=surom512 --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/asset.h:38
Return the descriptor byte length, or zero for an invalid ID.
kitaqfc/lib/asset.c:91
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
const u8* asset_get_ptr(u8 asset_id);Parameter
asset_idRessourcenindex 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
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 FC zeigt das blaue Paar bei (16,64) __far_memcpy, das grüne bei (16,96) asset_load_raw mit anschließender CHR-Übertragung. Jedes Paar belegt 16×8 Pixel auf schwarzem Hintergrund. So werden die kopierten Bilddaten sichtbar, nicht nur numerische Statuswerte.
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\asset_banks.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\asset_banks.nes --mapper=mmc1 --board=surom512 --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/asset.h:36
Return the stored address without switching banks. Pair it with the descriptor bank before reading banked ROM; a failed lookup returns null.
kitaqfc/lib/asset.c:83
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
u8 asset_load_raw(u8 asset_id, void* dst, u16 max_len);Parameter
asset_idRessourcenindex ab null. In der registrierten Tabelle gilt für eine gültige ID
asset_id < count.dstZiel 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_lenHö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
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 FC zeigt das blaue Paar bei (16,64) __far_memcpy, das grüne bei (16,96) asset_load_raw mit anschließender CHR-Übertragung. Jedes Paar belegt 16×8 Pixel auf schwarzem Hintergrund. So werden die kopierten Bilddaten sichtbar, nicht nur numerische Statuswerte.
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\asset_banks.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\asset_banks.nes --mapper=mmc1 --board=surom512 --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/asset.h:28
Copy the smaller of the asset length and max_len using a bank-aware transfer. Return one for a valid ID even when the payload is truncated.
kitaqfc/lib/asset.c:28
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;
__far_memcpy((u8*)dst, desc.bank, (u16)desc.ptr, len);
return 1;
}asset_load_tiles
Sucht eine RAW- oder TILES-Ressource, wählt deren ROM-Bank und überträgt sämtliche Daten mit __vram_write in Blöcken von höchstens 128 Byte. Anschließend wird die von bank_get_current() gespeicherte Bank wiederhergestellt. Zwischen den Blöcken wird nicht auf das nächste Bild gewartet.
Syntax
u8 asset_load_tiles(u8 asset_id, u16 vram_dst);Parameter
asset_idRessourcenindex ab null. In der registrierten Tabelle gilt für eine gültige ID
asset_id < count.vram_dstByteadresse des PPU, keine CPU-Adresse oder Kachelnummer. Kachelmuster werden in beschreibbaren CHR RAM bei
$0000–$1FFFgeladen, mit 16 Byte je Kachel. Der gesamte Transfer muss im vorgesehenen PPU-Bereich bleiben.
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.
asset_load_tiles stellt die von bank.c vermerkte Bank wieder her, keinen vom Mapper zurückgelesenen Wert. Initialisieren und pflegen Sie diesen Zustand mit bank_switch. Direkte Mapper-Zugriffe oder alleinige Aufrufe von __bankswitch aktualisieren den Bibliothekszustand nicht. Die Kopier-Intrinsic stellt separat den Compilerzustand wieder her.
Verwenden Sie beschreibbaren CHR RAM für Muster und schalten Sie die Darstellung bei langen Transfers ab. Innerhalb von VBlank muss der gesamte Vorgang in die verfügbare Zeit passen; 128-Byte-Blöcke gewährleisten das nicht. Das Beispiel nutzt --mapper=mmc1 --board=surom512. Bei generischen Boards erzeugt das Weglassen von --nes-chr leeren CHR ROM, keinen CHR RAM.
Anwendungsbeispiel
loaded=asset_load_tiles(0,0x0010); // 144 bytes: library uploads chunks of 128 and 16 bytes.
expect(loaded==1 && bank_get_current()==1 && *asset_bank_marker==0xA1,24);
// LCD and NMI are off; CHR RAM is writable. The library selects payload bank 2 and restores bank 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 FC zeigt das blaue Paar bei (16,64) __far_memcpy, das grüne bei (16,96) asset_load_raw mit anschließender CHR-Übertragung. Jedes Paar belegt 16×8 Pixel auf schwarzem Hintergrund. So werden die kopierten Bilddaten sichtbar, nicht nur numerische Statuswerte.
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\asset_banks.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\asset_banks.nes --mapper=mmc1 --board=surom512 --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/asset.h:31
Switch to the asset bank, upload tile/raw data in chunks of at most 128 bytes, then restore the bank recorded by this library. The caller supplies safe PPU timing.
kitaqfc/lib/asset.c:41
u8 asset_load_tiles(u8 asset_id, u16 vram_dst)
{
AssetDesc desc;
const u8* src;
u16 len;
u8 chunk;
u8 old_bank;
if (asset_get(asset_id, &desc) == 0) return 0;
if (desc.type != ASSET_TYPE_TILES && desc.type != ASSET_TYPE_RAW) return 0;
// Restoration uses the library shadow, not a mapper readback; initialize and maintain that shadow.
old_bank = bank_get_current();
bank_switch(desc.bank);
src = desc.ptr;
len = desc.len;
// This loop uploads the entire asset synchronously. Chunking does not wait for another frame.
// Use writable CHR RAM for tile data and keep the source bank visible throughout the transfer.
while (len != 0) {
if (len > 128) chunk = 128;
else chunk = (u8)len;
__vram_write(vram_dst, src, chunk);
vram_dst = (u16)(vram_dst + chunk);
src = src + chunk;
len = (u16)(len - chunk);
}
bank_switch(old_bank);
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
void asset_set_table(u8 bank, const AssetDesc* table, u8 count);Parameter
bank8-Bit-Nummer der ROM-Bank mit der Deskriptortabelle, nicht mit den Nutzdaten.
tableNahzeiger auf
countaufeinanderfolgendeAssetDesc-Einträge. Solange die Tabelle registriert ist, müssen allecount * 6Byte in ihrer ROM-Bank lesbar bleiben.countAnzahl 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
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 FC zeigt das blaue Paar bei (16,64) __far_memcpy, das grüne bei (16,96) asset_load_raw mit anschließender CHR-Übertragung. Jedes Paar belegt 16×8 Pixel auf schwarzem Hintergrund. So werden die kopierten Bilddaten sichtbar, nicht nur numerische Statuswerte.
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\asset_banks.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\asset_banks.nes --mapper=mmc1 --board=surom512 --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/asset.h:22
Retain a bank-qualified descriptor table; the caller keeps its storage valid.
kitaqfc/lib/asset.c:9
void asset_set_table(u8 bank, const AssetDesc* table, u8 count)
{
asset_table_bank = bank;
asset_table = table;
asset_table_count = count;
}attribute.h — Nametable-Attribute
Der gemeinsame 64-Byte-Attributschattenpuffer belegt CPU-RAM $03E0..$041F. Reservieren Sie diesen Bereich. Ein Attributbyte deckt 4×4 Kacheln ab; jedes Zwei-Bit-Feld wählt die Palette für einen 2×2-Kachelquadranten.
Bearbeitet Palettenquadranten rechteckweise und reiht nur betroffene Attributbytes ein, mit Prüfung der 32×30-Kachelgrenzen. Die Eingabe palette_map ist eine fertige 64-Byte-Attributtabelle, kein einzelner Farbwert pro Kachel.
nes_attr_queue_rect
Kopiert die ein Kachelrechteck abdeckenden Attributbytezeilen in die Warteschlange.
Syntax
unsigned char nes_attr_queue_rect(unsigned short nt_base, unsigned char tile_x, unsigned char tile_y, unsigned char width, unsigned char height);Parameter
nt_baseLogische Nametable-Basis $2000/$2400/$2800/$2C00; die Spiegelung bestimmt die physische Unabhängigkeit.
tile_xLinke Kachelspalte, sichtbarer Bereich 0..31.
tile_yObere Kachelzeile, sichtbarer Bereich 0..29.
widthBreite in Kacheln.
heightHöhe in Kacheln.
Rückgabewert
Gibt bei vollständiger Aufnahme oder leerem Rechteck 1 zurück, bei ungültigen Grenzen oder unzureichender Kapazität 0. Ungültige Grenzen reihen nichts ein.
Bedingungen und Grenzen
Der gemeinsame 64-Byte-Attributschattenpuffer belegt CPU-RAM $03E0..$041F. Reservieren Sie diesen Bereich. Ein Attributbyte deckt 4×4 Kacheln ab; jedes Zwei-Bit-Feld wählt die Palette für einen 2×2-Kachelquadranten.
Binden Sie runtime.c ein. Die Warteschlange kopiert Nutzdaten für eine spätere NMI oder eine sichere Übertragung bei ausgeschalteter Darstellung. Serialisieren Sie Erzeugung und Verbrauch. Geht bei mehreren Zeilen die Kapazität aus, bleiben zuvor aufgenommene Zeilen eingereiht.
Ein Attributbyte deckt 4×4 Kacheln ab. Betroffene Bytes werden vollständig übertragen; erhalten Sie daher im Schattenpuffer die richtigen Werte benachbarter Quadranten.
Anwendungsbeispiel
result[5]=nes_attr_queue_rect(0x2000,2,4,4,4);result[6]=nes_vram_queue_used;result[7]=nes_attr_queue_rect(0x2000,10,4,4,4);result[8]=nes_attr_queue_rect(0x2000,30,28,2,2);nes_vram_queue_nmi_flush();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 rechteckige Attributübertragungen: Rot 32×32 bei (16,32), Blau 32×32 bei (80,32), Grün 16×16 rechts unten bei (240,224). Das Beispiel erhält benachbarte Quadranten und erreicht korrekt das letzte Attributbyte.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\batch3_attributes.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch3_attributes.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chrImplementierung und Quelltext
kitaqfc/lib/attribute.h:15
Queue the attribute bytes covering a tile rectangle within 32x30 tiles. Empty rectangles succeed; invalid bounds fail without queuing. Capacity failure may leave earlier rows queued.
kitaqfc/lib/attribute.c:81
unsigned char nes_attr_queue_rect(unsigned short nt_base, unsigned char tile_x, unsigned char tile_y, unsigned char width, unsigned char height)
{
unsigned char qx0;
unsigned char qy0;
unsigned char qx1;
unsigned char qy1;
unsigned char row;
unsigned char col;
// The runtime queue copies these local bytes before return; they are not retained pointers.
// Caller coordinates must keep each computed row length within eight bytes.
unsigned char line[8];
unsigned short ppu_addr;
unsigned char len;
if (width == 0 || height == 0) return 1;
if (tile_x >= 32 || tile_y >= 30) return 0;
if (width > (unsigned char)(32 - tile_x) || height > (unsigned char)(30 - tile_y)) return 0;
qx0 = (unsigned char)(tile_x >> 2);
qy0 = (unsigned char)(tile_y >> 2);
qx1 = (unsigned char)((tile_x + width - 1) >> 2);
qy1 = (unsigned char)((tile_y + height - 1) >> 2);
row = qy0;
while (1)
{
len = (unsigned char)(qx1 - qx0 + 1);
col = 0;
while (col != len)
{
line[col] = nes_attr_shadow[(unsigned char)(row * 8 + qx0 + col)];
col = (unsigned char)(col + 1);
}
ppu_addr = (unsigned short)(nes_attr_base_from_nt(nt_base) + (unsigned short)(row * 8 + qx0));
if (nes_vram_queue_try_write(ppu_addr, line, len) == 0)
{
return 0;
}
if (row == qy1)
{
break;
}
row = (unsigned char)(row + 1);
}
return 1;
}nes_attr_shadow_build_from_palette_map
Kopiert 64 bereits gepackte Attributbytes in den gemeinsamen Schattenpuffer.
Syntax
void nes_attr_shadow_build_from_palette_map(unsigned char* src64);Parameter
src64Lesbare, gepackte 64-Byte-Attributtabelle, kein Array einzelner Paletten-IDs je Kachel.
Rückgabewert
Kein Rückgabewert.
Bedingungen und Grenzen
Der gemeinsame 64-Byte-Attributschattenpuffer belegt CPU-RAM $03E0..$041F. Reservieren Sie diesen Bereich. Ein Attributbyte deckt 4×4 Kacheln ab; jedes Zwei-Bit-Feld wählt die Palette für einen 2×2-Kachelquadranten.
Anwendungsbeispiel
for(i=0;i<64;i++)table[i]=0;table[0]=0xE4;nes_attr_shadow_build_from_palette_map(table);result[0]=nes_attr_shadow[0];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 rechteckige Attributübertragungen: Rot 32×32 bei (16,32), Blau 32×32 bei (80,32), Grün 16×16 rechts unten bei (240,224). Das Beispiel erhält benachbarte Quadranten und erreicht korrekt das letzte Attributbyte.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\batch3_attributes.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch3_attributes.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chrImplementierung und Quelltext
kitaqfc/lib/attribute.h:8
KITAQFC phase15 attribute patch helpers. Copy 64 already-packed attribute bytes into shadow storage. This does not convert one palette ID per tile into NES attribute bitfields. The source must expose all 64 packed bytes and stay readable for the duration of this copy.
kitaqfc/lib/attribute.c:26
void nes_attr_shadow_build_from_palette_map(unsigned char* src64)
{
unsigned char i;
i = 0;
while (i != 64)
{
nes_attr_shadow[i] = (unsigned char)(src64[i] & 0xFF);
i = (unsigned char)(i + 1);
}
}nes_attr_shadow_fill_rect
Ersetzt die Palettenfelder aller 2×2-Kachelquadranten, die ein Rechteck berührt.
Syntax
void nes_attr_shadow_fill_rect(unsigned char tile_x, unsigned char tile_y, unsigned char width, unsigned char height, unsigned char pal_index);Parameter
tile_xLinke Kachelspalte, sichtbarer Bereich 0..31.
tile_yObere Kachelzeile, sichtbarer Bereich 0..29.
widthBreite in Kacheln.
heightHöhe in Kacheln.
pal_indexPalettenindex; nur die unteren zwei Bits werden verwendet.
Rückgabewert
Kein Rückgabewert.
Bedingungen und Grenzen
Der gemeinsame 64-Byte-Attributschattenpuffer belegt CPU-RAM $03E0..$041F. Reservieren Sie diesen Bereich. Ein Attributbyte deckt 4×4 Kacheln ab; jedes Zwei-Bit-Feld wählt die Palette für einen 2×2-Kachelquadranten.
Halten Sie das gesamte Rechteck innerhalb von 32×30 Kacheln. Leere oder ungültige Rechtecke ändern nichts. Ungerade Grenzen werden auf Quadrantengrenzen erweitert, sodass benachbarte Kacheln außerhalb ebenfalls die neue Palette erhalten können.
Anwendungsbeispiel
nes_attr_shadow_fill_rect(2,4,4,4,1);nes_attr_shadow_fill_rect(10,4,4,4,2);nes_attr_shadow_fill_rect(30,28,2,2,3);result[1]=nes_attr_shadow[8];result[2]=nes_attr_shadow[9];result[3]=nes_attr_shadow[15];result[4]=nes_attr_shadow[63];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 rechteckige Attributübertragungen: Rot 32×32 bei (16,32), Blau 32×32 bei (80,32), Grün 16×16 rechts unten bei (240,224). Das Beispiel erhält benachbarte Quadranten und erreicht korrekt das letzte Attributbyte.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\batch3_attributes.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch3_attributes.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chrImplementierung und Quelltext
kitaqfc/lib/attribute.h:11
Apply a palette to every two-by-two tile quadrant touched by the rectangle. Empty or out-of-range rectangles leave the shadow unchanged.
kitaqfc/lib/attribute.c:39
void nes_attr_shadow_fill_rect(unsigned char tile_x, unsigned char tile_y, unsigned char width, unsigned char height, unsigned char pal_index)
{
unsigned char qx0;
unsigned char qy0;
unsigned char qx1;
unsigned char qy1;
unsigned char qx;
unsigned char qy;
if (width == 0 || height == 0) return;
if (tile_x >= 32 || tile_y >= 30) return;
if (width > (unsigned char)(32 - tile_x) || height > (unsigned char)(30 - tile_y)) return;
qx0 = nes_attr_rect_left(tile_x);
qy0 = nes_attr_rect_top(tile_y);
qx1 = nes_attr_rect_left((unsigned char)(tile_x + width - 1));
qy1 = nes_attr_rect_top((unsigned char)(tile_y + height - 1));
qy = qy0;
while (1)
{
qx = qx0;
while (1)
{
nes_attr_shadow_set_quad((unsigned char)(qx << 1), (unsigned char)(qy << 1), pal_index);
if (qx == qx1)
{
break;
}
qx = (unsigned char)(qx + 1);
}
if (qy == qy1)
{
break;
}
qy = (unsigned char)(qy + 1);
}
}audio.h — Musik, Soundeffekte und Audiosteuerung
Direktsteuerung der zwei Pulse, des Dreiecks, Rauschens und DMC der Standard-APU. Kein Musiksequenzer oder automatischer Mischer; Timing und Stimmenbelegung verwaltet das Spiel.
Diese Hilfe schreibt eine Einkanal-APU_STATUS-Maske und deaktiviert andere Stimmen; sie ist kein Mehrstimmenmischer. Bei Puls und Dreieck ist period ein Timerwert: Kleinere Werte erzeugen höhere Töne. Beispieltonhöhen und -dauern wurden mit NTSC-Timing geprüft.
DMC liest ROM ab einer 64-Byte-Grenze in $C000..$FFC0. Die Länge beträgt 16*n+1 Bytes in 1..4081. Diese Hilfen prüfen weder Ausrichtung noch Bereiche und wechseln keine Banken. Das Beispiel legt eigene Daten mit __aligned(64) in der festen Bank 0 ab und prüft deren Lage zur Laufzeit.
nes_apu_channel_enable
Ersetzt den Aktivierungszustand aller fünf APU-Kanäle durch die angegebene Maske.
Syntax
void nes_apu_channel_enable(u8 mask);Parameter
maskVollständige APU_STATUS-Aktivierungsmaske. Bits 0..4 wählen pulse1, pulse2, triangle, noise und DMC; obere Bits werden verworfen.
Rückgabewert
Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.
Anwendungsbeispiel
// NTSC: pulse A4 (~440 Hz), triangle A3 (~220 Hz), noise, then two short effects.
#include "fc_sound_example.h"
void main(void) {
sound_begin("APU CHANNELS AND BLIPS");
// Constant volume 12, length halt and 50% duty. Each helper replaces 4015.
nes_sfx_square1(0xBC,253,0);
sound_result[0]=(u8)(APU_STATUS&0x1F);
sound_wait(30);
nes_apu_channel_enable(0); sound_wait(15);
nes_sfx_square2(0x7C,253,0);
sound_result[1]=(u8)(APU_STATUS&0x1F);
sound_wait(30); nes_apu_silence_all(); sound_wait(15);
nes_sfx_triangle(0xFF,253,0);
sound_result[2]=(u8)(APU_STATUS&0x1F);
sound_wait(30); nes_apu_silence_all(); sound_wait(15);
nes_sfx_noise(0x3C,5,0);
sound_result[3]=(u8)(APU_STATUS&0x1F);
sound_wait(30); nes_apu_silence_all(); sound_wait(15);
nes_sfx_tick_blip(); sound_wait(30); nes_apu_silence_all(); sound_wait(15);
nes_sfx_move_blip(); sound_wait(30); nes_apu_silence_all(); sound_wait(15);
sound_end();
}Erwartetes Ergebnis
Zu hören sind pulse1, pulse2, triangle, noise, tick und move. Timer 253 ergibt unter NTSC etwa 440-Hz-Pulse und ein 220-Hz-Dreieck. Tick liegt bei etwa 111 Hz, move bei etwa 174 Hz und endet früher. Der letzte Abschnitt ist still.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\sound_channels.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\fc-channels.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/audio.h:17
Replace all five channel-enable bits in APU_STATUS; this is not an additive enable.
kitaqfc/lib/audio.c:43
void nes_apu_channel_enable(u8 mask)
{
APU_STATUS = (u8)(mask & 0x1F);
}nes_apu_init
Deaktiviert Frame-IRQ, aktiviert vier Stimmen und setzt stille Steuerwerte. DMC bleibt deaktiviert.
Syntax
void nes_apu_init(void);Rückgabewert
Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.
Anwendungsbeispiel
// NTSC: pulse A4 (~440 Hz), triangle A3 (~220 Hz), noise, then two short effects.
#include "fc_sound_example.h"
void main(void) {
sound_begin("APU CHANNELS AND BLIPS");
// Constant volume 12, length halt and 50% duty. Each helper replaces 4015.
nes_sfx_square1(0xBC,253,0);
sound_result[0]=(u8)(APU_STATUS&0x1F);
sound_wait(30);
nes_apu_channel_enable(0); sound_wait(15);
nes_sfx_square2(0x7C,253,0);
sound_result[1]=(u8)(APU_STATUS&0x1F);
sound_wait(30); nes_apu_silence_all(); sound_wait(15);
nes_sfx_triangle(0xFF,253,0);
sound_result[2]=(u8)(APU_STATUS&0x1F);
sound_wait(30); nes_apu_silence_all(); sound_wait(15);
nes_sfx_noise(0x3C,5,0);
sound_result[3]=(u8)(APU_STATUS&0x1F);
sound_wait(30); nes_apu_silence_all(); sound_wait(15);
nes_sfx_tick_blip(); sound_wait(30); nes_apu_silence_all(); sound_wait(15);
nes_sfx_move_blip(); sound_wait(30); nes_apu_silence_all(); sound_wait(15);
sound_end();
}Erwartetes Ergebnis
Zu hören sind pulse1, pulse2, triangle, noise, tick und move. Timer 253 ergibt unter NTSC etwa 440-Hz-Pulse und ein 220-Hz-Dreieck. Tick liegt bei etwa 111 Hz, move bei etwa 174 Hz und endet früher. Der letzte Abschnitt ist still.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\sound_channels.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\fc-channels.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/audio.h:15
Disable frame IRQs, enable the four tonal/noise channels and install quiet control defaults. DMC remains disabled.
kitaqfc/lib/audio.c:28
void nes_apu_init(void)
{
APU_FRAME = 0x40;
APU_STATUS = 0x0F;
SQ1_VOL = 0x10;
SQ1_SWEEP = 0x08;
SQ2_VOL = 0x10;
SQ2_SWEEP = 0x08;
TRI_LINEAR = 0x80;
NOISE_VOL = 0x10;
DMC_FREQ = 0x00;
DMC_RAW = 0x00;
}nes_apu_silence_all
Deaktiviert alle Kanäle und löscht Puls-/Rauschlautstärke sowie DMC-Ausgabe.
Syntax
void nes_apu_silence_all(void);Rückgabewert
Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.
Anwendungsbeispiel
// NTSC: pulse A4 (~440 Hz), triangle A3 (~220 Hz), noise, then two short effects.
#include "fc_sound_example.h"
void main(void) {
sound_begin("APU CHANNELS AND BLIPS");
// Constant volume 12, length halt and 50% duty. Each helper replaces 4015.
nes_sfx_square1(0xBC,253,0);
sound_result[0]=(u8)(APU_STATUS&0x1F);
sound_wait(30);
nes_apu_channel_enable(0); sound_wait(15);
nes_sfx_square2(0x7C,253,0);
sound_result[1]=(u8)(APU_STATUS&0x1F);
sound_wait(30); nes_apu_silence_all(); sound_wait(15);
nes_sfx_triangle(0xFF,253,0);
sound_result[2]=(u8)(APU_STATUS&0x1F);
sound_wait(30); nes_apu_silence_all(); sound_wait(15);
nes_sfx_noise(0x3C,5,0);
sound_result[3]=(u8)(APU_STATUS&0x1F);
sound_wait(30); nes_apu_silence_all(); sound_wait(15);
nes_sfx_tick_blip(); sound_wait(30); nes_apu_silence_all(); sound_wait(15);
nes_sfx_move_blip(); sound_wait(30); nes_apu_silence_all(); sound_wait(15);
sound_end();
}Erwartetes Ergebnis
Zu hören sind pulse1, pulse2, triangle, noise, tick und move. Timer 253 ergibt unter NTSC etwa 440-Hz-Pulse und ein 220-Hz-Dreieck. Tick liegt bei etwa 111 Hz, move bei etwa 174 Hz und endet früher. Der letzte Abschnitt ist still.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\sound_channels.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\fc-channels.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/audio.h:19
Disable every channel and clear volume/DMC output settings used by this helper.
kitaqfc/lib/audio.c:49
void nes_apu_silence_all(void)
{
APU_STATUS = 0x00;
SQ1_VOL = 0x10;
SQ2_VOL = 0x10;
TRI_LINEAR = 0x80;
NOISE_VOL = 0x10;
DMC_FREQ = 0x00;
DMC_RAW = 0x00;
}nes_dmc_config
Konfiguriert DMC-Steuerung/-Ausgabe und wandelt Sampleadresse und -länge in Registereinheiten um.
Syntax
void nes_dmc_config(u8 flags_rate, u8 output_level, u16 sample_addr, u16 sample_len);Parameter
flags_rateDMC: Bit 7 IRQ, Bit 6 Schleife, unteres Halbbyte Ratenindex. Das Beispiel aktiviert IRQ nicht.
output_levelAnfänglicher DMC-Ausgabezähler 0..127; geschrieben werden nur die unteren sieben Bits.
sample_addrCPU-Adresse der DMC-Daten: eine 64-Byte-Grenze in $C000..$FFC0.
sample_lenBytelänge 16*n+1 in 1..4081. Übergeben Sie weder null noch eine nicht darstellbare Länge.
Rückgabewert
Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.
Bedingungen und Grenzen
DMC liest ROM ab einer 64-Byte-Grenze in $C000..$FFC0. Die Länge beträgt 16*n+1 Bytes in 1..4081. Diese Hilfen prüfen weder Ausrichtung noch Bereiche und wechseln keine Banken. Das Beispiel legt eigene Daten mit __aligned(64) in der festen Bank 0 ab und prüft deren Lage zur Laufzeit.
Anwendungsbeispiel
// A 17-byte original delta pattern, aligned to a 64-byte DMC start boundary.
#include "fc_sound_example.h"
#pragma bank 0
__aligned(64) __prg_rom u8 delta[17]={0xFF,0xFF,0,0,0xFF,0xFF,0,0,0xFF,0xFF,0,0,0xFF,0xFF,0,0,0xAA};
void main(void) {
sound_begin("DMC ORIGINAL DELTAS");
sound_result[0]=(u8)(((u16)delta&63)==0);
sound_result[1]=(u8)((u16)delta>=0xC000);
// Loop at NTSC rate index 10; start the output accumulator at its midpoint.
nes_dmc_config(0x4A,64,(u16)delta,17);
nes_dmc_start();
sound_wait(60);
nes_dmc_stop(); sound_wait(30);
nes_dmc_play(0x4C,64,(u16)delta,17);
sound_wait(60);
nes_dmc_stop(); sound_wait(30);
sound_end();
}Erwartetes Ergebnis
Ein eigenes Deltamuster spielt mit Rate 10, pausiert und spielt dann schneller mit Rate 12. Der DMC-Stopp erhält den Ausgabezähler, daher kann die Pause einen Transienten enthalten. Der letzte Vorgang schaltet die gesamte APU stumm.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\sound_dmc.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\fc-dmc.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/audio.h:38
Convert a CPU sample address and byte length to DMC register units. Supply an address in 0xC000-0xFFC0 aligned to 64 bytes and a representable length 16*n+1 in 1..4081; inputs are narrowed without validation or bank management.
kitaqfc/lib/audio.c:115
void nes_dmc_config(u8 flags_rate, u8 output_level, u16 sample_addr, u16 sample_len)
{
DMC_FREQ = flags_rate;
DMC_RAW = (u8)(output_level & 0x7F);
// Keep the sample bytes mapped at these CPU addresses during playback; this does not select a ROM bank.
DMC_START = (u8)((sample_addr - 0xC000) >> 6);
DMC_LEN = (u8)((sample_len - 1) >> 4);
}nes_dmc_play
Konfiguriert das DMC-Sample und startet sofort die Wiedergabe.
Syntax
void nes_dmc_play(u8 flags_rate, u8 output_level, u16 sample_addr, u16 sample_len);Parameter
flags_rateDMC: Bit 7 IRQ, Bit 6 Schleife, unteres Halbbyte Ratenindex. Das Beispiel aktiviert IRQ nicht.
output_levelAnfänglicher DMC-Ausgabezähler 0..127; geschrieben werden nur die unteren sieben Bits.
sample_addrCPU-Adresse der DMC-Daten: eine 64-Byte-Grenze in $C000..$FFC0.
sample_lenBytelänge 16*n+1 in 1..4081. Übergeben Sie weder null noch eine nicht darstellbare Länge.
Rückgabewert
Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.
Bedingungen und Grenzen
DMC liest ROM ab einer 64-Byte-Grenze in $C000..$FFC0. Die Länge beträgt 16*n+1 Bytes in 1..4081. Diese Hilfen prüfen weder Ausrichtung noch Bereiche und wechseln keine Banken. Das Beispiel legt eigene Daten mit __aligned(64) in der festen Bank 0 ab und prüft deren Lage zur Laufzeit.
Anwendungsbeispiel
// A 17-byte original delta pattern, aligned to a 64-byte DMC start boundary.
#include "fc_sound_example.h"
#pragma bank 0
__aligned(64) __prg_rom u8 delta[17]={0xFF,0xFF,0,0,0xFF,0xFF,0,0,0xFF,0xFF,0,0,0xFF,0xFF,0,0,0xAA};
void main(void) {
sound_begin("DMC ORIGINAL DELTAS");
sound_result[0]=(u8)(((u16)delta&63)==0);
sound_result[1]=(u8)((u16)delta>=0xC000);
// Loop at NTSC rate index 10; start the output accumulator at its midpoint.
nes_dmc_config(0x4A,64,(u16)delta,17);
nes_dmc_start();
sound_wait(60);
nes_dmc_stop(); sound_wait(30);
nes_dmc_play(0x4C,64,(u16)delta,17);
sound_wait(60);
nes_dmc_stop(); sound_wait(30);
sound_end();
}Erwartetes Ergebnis
Ein eigenes Deltamuster spielt mit Rate 10, pausiert und spielt dann schneller mit Rate 12. Der DMC-Stopp erhält den Ausgabezähler, daher kann die Pause einen Transienten enthalten. Der letzte Vorgang schaltet die gesamte APU stumm.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\sound_dmc.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\fc-dmc.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/audio.h:44
Install sample parameters, then start DMC using the full-channel enable mask.
kitaqfc/lib/audio.c:137
void nes_dmc_play(u8 flags_rate, u8 output_level, u16 sample_addr, u16 sample_len)
{
nes_dmc_config(flags_rate, output_level, sample_addr, sample_len);
nes_dmc_start();
}nes_dmc_start
Schreibt APU_STATUS=0x1F und aktiviert DMC sowie alle vier anderen Stimmen.
Syntax
void nes_dmc_start(void);Rückgabewert
Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.
Bedingungen und Grenzen
DMC liest ROM ab einer 64-Byte-Grenze in $C000..$FFC0. Die Länge beträgt 16*n+1 Bytes in 1..4081. Diese Hilfen prüfen weder Ausrichtung noch Bereiche und wechseln keine Banken. Das Beispiel legt eigene Daten mit __aligned(64) in der festen Bank 0 ab und prüft deren Lage zur Laufzeit.
Anwendungsbeispiel
// A 17-byte original delta pattern, aligned to a 64-byte DMC start boundary.
#include "fc_sound_example.h"
#pragma bank 0
__aligned(64) __prg_rom u8 delta[17]={0xFF,0xFF,0,0,0xFF,0xFF,0,0,0xFF,0xFF,0,0,0xFF,0xFF,0,0,0xAA};
void main(void) {
sound_begin("DMC ORIGINAL DELTAS");
sound_result[0]=(u8)(((u16)delta&63)==0);
sound_result[1]=(u8)((u16)delta>=0xC000);
// Loop at NTSC rate index 10; start the output accumulator at its midpoint.
nes_dmc_config(0x4A,64,(u16)delta,17);
nes_dmc_start();
sound_wait(60);
nes_dmc_stop(); sound_wait(30);
nes_dmc_play(0x4C,64,(u16)delta,17);
sound_wait(60);
nes_dmc_stop(); sound_wait(30);
sound_end();
}Erwartetes Ergebnis
Ein eigenes Deltamuster spielt mit Rate 10, pausiert und spielt dann schneller mit Rate 12. Der DMC-Stopp erhält den Ausgabezähler, daher kann die Pause einen Transienten enthalten. Der letzte Vorgang schaltet die gesamte APU stumm.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\sound_dmc.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\fc-dmc.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/audio.h:40
Enable DMC together with all four other channels by replacing the status mask.
kitaqfc/lib/audio.c:125
void nes_dmc_start(void)
{
APU_STATUS = 0x1F;
}nes_dmc_stop
Schreibt APU_STATUS=0x0F, stoppt DMC und setzt die Aktivierungsbits aller vier anderen Stimmen.
Syntax
void nes_dmc_stop(void);Rückgabewert
Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.
Bedingungen und Grenzen
DMC liest ROM ab einer 64-Byte-Grenze in $C000..$FFC0. Die Länge beträgt 16*n+1 Bytes in 1..4081. Diese Hilfen prüfen weder Ausrichtung noch Bereiche und wechseln keine Banken. Das Beispiel legt eigene Daten mit __aligned(64) in der festen Bank 0 ab und prüft deren Lage zur Laufzeit.
Anwendungsbeispiel
// A 17-byte original delta pattern, aligned to a 64-byte DMC start boundary.
#include "fc_sound_example.h"
#pragma bank 0
__aligned(64) __prg_rom u8 delta[17]={0xFF,0xFF,0,0,0xFF,0xFF,0,0,0xFF,0xFF,0,0,0xFF,0xFF,0,0,0xAA};
void main(void) {
sound_begin("DMC ORIGINAL DELTAS");
sound_result[0]=(u8)(((u16)delta&63)==0);
sound_result[1]=(u8)((u16)delta>=0xC000);
// Loop at NTSC rate index 10; start the output accumulator at its midpoint.
nes_dmc_config(0x4A,64,(u16)delta,17);
nes_dmc_start();
sound_wait(60);
nes_dmc_stop(); sound_wait(30);
nes_dmc_play(0x4C,64,(u16)delta,17);
sound_wait(60);
nes_dmc_stop(); sound_wait(30);
sound_end();
}Erwartetes Ergebnis
Ein eigenes Deltamuster spielt mit Rate 10, pausiert und spielt dann schneller mit Rate 12. Der DMC-Stopp erhält den Ausgabezähler, daher kann die Pause einen Transienten enthalten. Der letzte Vorgang schaltet die gesamte APU stumm.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\sound_dmc.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\fc-dmc.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/audio.h:42
Disable DMC while leaving all four other channel-enable bits set.
kitaqfc/lib/audio.c:131
void nes_dmc_stop(void)
{
APU_STATUS = 0x0F;
}nes_sfx_move_blip
Triggert Puls 1 mit Steuerwert 0x5A, Timer 0x0280 und Längenindex 2 für einen höheren, kürzeren Bewegungston.
Syntax
void nes_sfx_move_blip(void);Rückgabewert
Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.
Bedingungen und Grenzen
Diese Hilfe schreibt eine Einkanal-APU_STATUS-Maske und deaktiviert andere Stimmen; sie ist kein Mehrstimmenmischer. Bei Puls und Dreieck ist period ein Timerwert: Kleinere Werte erzeugen höhere Töne. Beispieltonhöhen und -dauern wurden mit NTSC-Timing geprüft.
Anwendungsbeispiel
// NTSC: pulse A4 (~440 Hz), triangle A3 (~220 Hz), noise, then two short effects.
#include "fc_sound_example.h"
void main(void) {
sound_begin("APU CHANNELS AND BLIPS");
// Constant volume 12, length halt and 50% duty. Each helper replaces 4015.
nes_sfx_square1(0xBC,253,0);
sound_result[0]=(u8)(APU_STATUS&0x1F);
sound_wait(30);
nes_apu_channel_enable(0); sound_wait(15);
nes_sfx_square2(0x7C,253,0);
sound_result[1]=(u8)(APU_STATUS&0x1F);
sound_wait(30); nes_apu_silence_all(); sound_wait(15);
nes_sfx_triangle(0xFF,253,0);
sound_result[2]=(u8)(APU_STATUS&0x1F);
sound_wait(30); nes_apu_silence_all(); sound_wait(15);
nes_sfx_noise(0x3C,5,0);
sound_result[3]=(u8)(APU_STATUS&0x1F);
sound_wait(30); nes_apu_silence_all(); sound_wait(15);
nes_sfx_tick_blip(); sound_wait(30); nes_apu_silence_all(); sound_wait(15);
nes_sfx_move_blip(); sound_wait(30); nes_apu_silence_all(); sound_wait(15);
sound_end();
}Erwartetes Ergebnis
Zu hören sind pulse1, pulse2, triangle, noise, tick und move. Timer 253 ergibt unter NTSC etwa 440-Hz-Pulse und ein 220-Hz-Dreieck. Tick liegt bei etwa 111 Hz, move bei etwa 174 Hz und endet früher. Der letzte Abschnitt ist still.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\sound_channels.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\fc-channels.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/audio.h:33
Trigger the predefined pulse-1 movement effect.
kitaqfc/lib/audio.c:107
void nes_sfx_move_blip(void)
{
nes_sfx_square1(0x5A, 0x0280, 2);
}nes_sfx_noise
Aktiviert nur Rauschen und schreibt Hüllkurve, Periode/Modus und Längenindex.
Syntax
void nes_sfx_noise(u8 volume, u8 period_mode, u8 length_index);Parameter
volumeRohe Rauschsteuerung: Bit 5 Längenzählerstopp, Bit 4 konstante Lautstärke, unteres Halbbyte Lautstärke oder Hüllkurvenperiode.
period_modeRauschregister: Bit 7 Kurzmodus, unteres Halbbyte Periodentabellenindex.
length_indexLängentabellenindex 0..31, keine Frameanzahl. Nur die unteren fünf Bits erreichen das Register.
Rückgabewert
Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.
Bedingungen und Grenzen
Diese Hilfe schreibt eine Einkanal-APU_STATUS-Maske und deaktiviert andere Stimmen; sie ist kein Mehrstimmenmischer. Bei Puls und Dreieck ist period ein Timerwert: Kleinere Werte erzeugen höhere Töne. Beispieltonhöhen und -dauern wurden mit NTSC-Timing geprüft.
Anwendungsbeispiel
// NTSC: pulse A4 (~440 Hz), triangle A3 (~220 Hz), noise, then two short effects.
#include "fc_sound_example.h"
void main(void) {
sound_begin("APU CHANNELS AND BLIPS");
// Constant volume 12, length halt and 50% duty. Each helper replaces 4015.
nes_sfx_square1(0xBC,253,0);
sound_result[0]=(u8)(APU_STATUS&0x1F);
sound_wait(30);
nes_apu_channel_enable(0); sound_wait(15);
nes_sfx_square2(0x7C,253,0);
sound_result[1]=(u8)(APU_STATUS&0x1F);
sound_wait(30); nes_apu_silence_all(); sound_wait(15);
nes_sfx_triangle(0xFF,253,0);
sound_result[2]=(u8)(APU_STATUS&0x1F);
sound_wait(30); nes_apu_silence_all(); sound_wait(15);
nes_sfx_noise(0x3C,5,0);
sound_result[3]=(u8)(APU_STATUS&0x1F);
sound_wait(30); nes_apu_silence_all(); sound_wait(15);
nes_sfx_tick_blip(); sound_wait(30); nes_apu_silence_all(); sound_wait(15);
nes_sfx_move_blip(); sound_wait(30); nes_apu_silence_all(); sound_wait(15);
sound_end();
}Erwartetes Ergebnis
Zu hören sind pulse1, pulse2, triangle, noise, tick und move. Timer 253 ergibt unter NTSC etwa 440-Hz-Pulse und ein 220-Hz-Dreieck. Tick liegt bei etwa 111 Hz, move bei etwa 174 Hz und endet früher. Der letzte Abschnitt ist still.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\sound_channels.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\fc-channels.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/audio.h:29
Enable only noise and load envelope/control, period/mode and length fields.
kitaqfc/lib/audio.c:92
void nes_sfx_noise(u8 volume, u8 period_mode, u8 length_index)
{
APU_STATUS = 0x08;
NOISE_VOL = volume;
NOISE_LO = period_mode;
NOISE_HI = (u8)(length_index << 3);
}nes_sfx_square1
Aktiviert nur Puls 1, deaktiviert Sweep und schreibt Steuerwert, Timer und Längenindex.
Syntax
void nes_sfx_square1(u8 duty_volume, u16 period, u8 length_index);Parameter
duty_volumeRohe Pulssteuerung: Bits 7..6 Tastgrad, Bit 5 Längenzählerstopp, Bit 4 konstante Lautstärke, unteres Halbbyte Lautstärke oder Hüllkurvenperiode.
period11-Bit-Timer 0..2047. Pulsfrequenz: CPU-Takt/[16*(period+1)]; Dreieckfrequenz: CPU-Takt/[32*(period+1)].
length_indexLängentabellenindex 0..31, keine Frameanzahl. Nur die unteren fünf Bits erreichen das Register.
Rückgabewert
Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.
Bedingungen und Grenzen
Diese Hilfe schreibt eine Einkanal-APU_STATUS-Maske und deaktiviert andere Stimmen; sie ist kein Mehrstimmenmischer. Bei Puls und Dreieck ist period ein Timerwert: Kleinere Werte erzeugen höhere Töne. Beispieltonhöhen und -dauern wurden mit NTSC-Timing geprüft.
Anwendungsbeispiel
// NTSC: pulse A4 (~440 Hz), triangle A3 (~220 Hz), noise, then two short effects.
#include "fc_sound_example.h"
void main(void) {
sound_begin("APU CHANNELS AND BLIPS");
// Constant volume 12, length halt and 50% duty. Each helper replaces 4015.
nes_sfx_square1(0xBC,253,0);
sound_result[0]=(u8)(APU_STATUS&0x1F);
sound_wait(30);
nes_apu_channel_enable(0); sound_wait(15);
nes_sfx_square2(0x7C,253,0);
sound_result[1]=(u8)(APU_STATUS&0x1F);
sound_wait(30); nes_apu_silence_all(); sound_wait(15);
nes_sfx_triangle(0xFF,253,0);
sound_result[2]=(u8)(APU_STATUS&0x1F);
sound_wait(30); nes_apu_silence_all(); sound_wait(15);
nes_sfx_noise(0x3C,5,0);
sound_result[3]=(u8)(APU_STATUS&0x1F);
sound_wait(30); nes_apu_silence_all(); sound_wait(15);
nes_sfx_tick_blip(); sound_wait(30); nes_apu_silence_all(); sound_wait(15);
nes_sfx_move_blip(); sound_wait(30); nes_apu_silence_all(); sound_wait(15);
sound_end();
}Erwartetes Ergebnis
Zu hören sind pulse1, pulse2, triangle, noise, tick und move. Timer 253 ergibt unter NTSC etwa 440-Hz-Pulse und ein 220-Hz-Dreieck. Tick liegt bei etwa 111 Hz, move bei etwa 174 Hz und endet früher. Der letzte Abschnitt ist still.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\sound_channels.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\fc-channels.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/audio.h:23
Enable only pulse 1, disable its sweep and load control, 11-bit timer and length-table index. Starting this effect disables the other APU channels.
kitaqfc/lib/audio.c:62
void nes_sfx_square1(u8 duty_volume, u16 period, u8 length_index)
{
APU_STATUS = 0x01;
SQ1_SWEEP = 0x08;
SQ1_VOL = duty_volume;
SQ1_LO = (u8)period;
// Only the low five length-index bits and low eleven timer bits reach the registers.
SQ1_HI = (u8)((u8)(length_index << 3) | (u8)((period >> 8) & 0x07));
}nes_sfx_square2
Aktiviert nur Puls 2, deaktiviert Sweep und schreibt Steuerwert, Timer und Längenindex.
Syntax
void nes_sfx_square2(u8 duty_volume, u16 period, u8 length_index);Parameter
duty_volumeRohe Pulssteuerung: Bits 7..6 Tastgrad, Bit 5 Längenzählerstopp, Bit 4 konstante Lautstärke, unteres Halbbyte Lautstärke oder Hüllkurvenperiode.
period11-Bit-Timer 0..2047. Pulsfrequenz: CPU-Takt/[16*(period+1)]; Dreieckfrequenz: CPU-Takt/[32*(period+1)].
length_indexLängentabellenindex 0..31, keine Frameanzahl. Nur die unteren fünf Bits erreichen das Register.
Rückgabewert
Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.
Bedingungen und Grenzen
Diese Hilfe schreibt eine Einkanal-APU_STATUS-Maske und deaktiviert andere Stimmen; sie ist kein Mehrstimmenmischer. Bei Puls und Dreieck ist period ein Timerwert: Kleinere Werte erzeugen höhere Töne. Beispieltonhöhen und -dauern wurden mit NTSC-Timing geprüft.
Anwendungsbeispiel
// NTSC: pulse A4 (~440 Hz), triangle A3 (~220 Hz), noise, then two short effects.
#include "fc_sound_example.h"
void main(void) {
sound_begin("APU CHANNELS AND BLIPS");
// Constant volume 12, length halt and 50% duty. Each helper replaces 4015.
nes_sfx_square1(0xBC,253,0);
sound_result[0]=(u8)(APU_STATUS&0x1F);
sound_wait(30);
nes_apu_channel_enable(0); sound_wait(15);
nes_sfx_square2(0x7C,253,0);
sound_result[1]=(u8)(APU_STATUS&0x1F);
sound_wait(30); nes_apu_silence_all(); sound_wait(15);
nes_sfx_triangle(0xFF,253,0);
sound_result[2]=(u8)(APU_STATUS&0x1F);
sound_wait(30); nes_apu_silence_all(); sound_wait(15);
nes_sfx_noise(0x3C,5,0);
sound_result[3]=(u8)(APU_STATUS&0x1F);
sound_wait(30); nes_apu_silence_all(); sound_wait(15);
nes_sfx_tick_blip(); sound_wait(30); nes_apu_silence_all(); sound_wait(15);
nes_sfx_move_blip(); sound_wait(30); nes_apu_silence_all(); sound_wait(15);
sound_end();
}Erwartetes Ergebnis
Zu hören sind pulse1, pulse2, triangle, noise, tick und move. Timer 253 ergibt unter NTSC etwa 440-Hz-Pulse und ein 220-Hz-Dreieck. Tick liegt bei etwa 111 Hz, move bei etwa 174 Hz und endet früher. Der letzte Abschnitt ist still.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\sound_channels.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\fc-channels.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/audio.h:25
Enable only pulse 2 and load its control/timer/length fields, disabling other channels.
kitaqfc/lib/audio.c:73
void nes_sfx_square2(u8 duty_volume, u16 period, u8 length_index)
{
APU_STATUS = 0x02;
SQ2_SWEEP = 0x08;
SQ2_VOL = duty_volume;
SQ2_LO = (u8)period;
SQ2_HI = (u8)((u8)(length_index << 3) | (u8)((period >> 8) & 0x07));
}nes_sfx_tick_blip
Triggert Puls 1 mit Steuerwert 0x9A, Timer 0x03F0 und Längenindex 4 für einen kurzen tiefen Tick.
Syntax
void nes_sfx_tick_blip(void);Rückgabewert
Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.
Bedingungen und Grenzen
Diese Hilfe schreibt eine Einkanal-APU_STATUS-Maske und deaktiviert andere Stimmen; sie ist kein Mehrstimmenmischer. Bei Puls und Dreieck ist period ein Timerwert: Kleinere Werte erzeugen höhere Töne. Beispieltonhöhen und -dauern wurden mit NTSC-Timing geprüft.
Anwendungsbeispiel
// NTSC: pulse A4 (~440 Hz), triangle A3 (~220 Hz), noise, then two short effects.
#include "fc_sound_example.h"
void main(void) {
sound_begin("APU CHANNELS AND BLIPS");
// Constant volume 12, length halt and 50% duty. Each helper replaces 4015.
nes_sfx_square1(0xBC,253,0);
sound_result[0]=(u8)(APU_STATUS&0x1F);
sound_wait(30);
nes_apu_channel_enable(0); sound_wait(15);
nes_sfx_square2(0x7C,253,0);
sound_result[1]=(u8)(APU_STATUS&0x1F);
sound_wait(30); nes_apu_silence_all(); sound_wait(15);
nes_sfx_triangle(0xFF,253,0);
sound_result[2]=(u8)(APU_STATUS&0x1F);
sound_wait(30); nes_apu_silence_all(); sound_wait(15);
nes_sfx_noise(0x3C,5,0);
sound_result[3]=(u8)(APU_STATUS&0x1F);
sound_wait(30); nes_apu_silence_all(); sound_wait(15);
nes_sfx_tick_blip(); sound_wait(30); nes_apu_silence_all(); sound_wait(15);
nes_sfx_move_blip(); sound_wait(30); nes_apu_silence_all(); sound_wait(15);
sound_end();
}Erwartetes Ergebnis
Zu hören sind pulse1, pulse2, triangle, noise, tick und move. Timer 253 ergibt unter NTSC etwa 440-Hz-Pulse und ein 220-Hz-Dreieck. Tick liegt bei etwa 111 Hz, move bei etwa 174 Hz und endet früher. Der letzte Abschnitt ist still.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\sound_channels.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\fc-channels.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/audio.h:31
Trigger the predefined pulse-1 tick effect; it inherits the exclusive-channel behavior.
kitaqfc/lib/audio.c:101
void nes_sfx_tick_blip(void)
{
nes_sfx_square1(0x9A, 0x03F0, 4);
}nes_sfx_triangle
Aktiviert nur Dreieck und schreibt Linearcounter, Timer und Längenindex.
Syntax
void nes_sfx_triangle(u8 linear, u16 period, u8 length_index);Parameter
linearDreieck-Linearcounter: Bit 7 Steuerung/Längenstopp, untere sieben Bits Nachladewert.
period11-Bit-Timer 0..2047. Pulsfrequenz: CPU-Takt/[16*(period+1)]; Dreieckfrequenz: CPU-Takt/[32*(period+1)].
length_indexLängentabellenindex 0..31, keine Frameanzahl. Nur die unteren fünf Bits erreichen das Register.
Rückgabewert
Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.
Bedingungen und Grenzen
Diese Hilfe schreibt eine Einkanal-APU_STATUS-Maske und deaktiviert andere Stimmen; sie ist kein Mehrstimmenmischer. Bei Puls und Dreieck ist period ein Timerwert: Kleinere Werte erzeugen höhere Töne. Beispieltonhöhen und -dauern wurden mit NTSC-Timing geprüft.
Anwendungsbeispiel
// NTSC: pulse A4 (~440 Hz), triangle A3 (~220 Hz), noise, then two short effects.
#include "fc_sound_example.h"
void main(void) {
sound_begin("APU CHANNELS AND BLIPS");
// Constant volume 12, length halt and 50% duty. Each helper replaces 4015.
nes_sfx_square1(0xBC,253,0);
sound_result[0]=(u8)(APU_STATUS&0x1F);
sound_wait(30);
nes_apu_channel_enable(0); sound_wait(15);
nes_sfx_square2(0x7C,253,0);
sound_result[1]=(u8)(APU_STATUS&0x1F);
sound_wait(30); nes_apu_silence_all(); sound_wait(15);
nes_sfx_triangle(0xFF,253,0);
sound_result[2]=(u8)(APU_STATUS&0x1F);
sound_wait(30); nes_apu_silence_all(); sound_wait(15);
nes_sfx_noise(0x3C,5,0);
sound_result[3]=(u8)(APU_STATUS&0x1F);
sound_wait(30); nes_apu_silence_all(); sound_wait(15);
nes_sfx_tick_blip(); sound_wait(30); nes_apu_silence_all(); sound_wait(15);
nes_sfx_move_blip(); sound_wait(30); nes_apu_silence_all(); sound_wait(15);
sound_end();
}Erwartetes Ergebnis
Zu hören sind pulse1, pulse2, triangle, noise, tick und move. Timer 253 ergibt unter NTSC etwa 440-Hz-Pulse und ein 220-Hz-Dreieck. Tick liegt bei etwa 111 Hz, move bei etwa 174 Hz und endet früher. Der letzte Abschnitt ist still.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\sound_channels.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\fc-channels.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/audio.h:27
Enable only triangle and load linear-counter, timer and length fields.
kitaqfc/lib/audio.c:83
void nes_sfx_triangle(u8 linear, u16 period, u8 length_index)
{
APU_STATUS = 0x04;
TRI_LINEAR = linear;
TRI_LO = (u8)period;
TRI_HI = (u8)((u8)(length_index << 3) | (u8)((period >> 8) & 0x07));
}audio_vblank.h — NMI-gesteuerte Vierkanalmusik
Die Vierkanalmusik läuft in der NMI weiter. Initialisieren Sie den Treiber, legen Sie ein Musikstück fest und füllen Sie die Warteschlange vor. Aktivieren Sie dann NMI für die Wiedergabe und füllen Sie aus dem Hauptprogramm nach. Die NMI liest eine RAM-Warteschlange. Bei rechtzeitigem Nachfüllen reicht dadurch wenig RAM für einen langen Stream. Jeder Kanal hat unabhängige HOLD/STOP-Befehle.
Ein Datensatz besteht aus fünf Bytes: delay, CH1, CH2, CH3, CH4. Eine Dauer von 1 bis 255 gibt an, wie viele NMI-Ticks der neue Zustand anhält. Null beendet die Wiedergabe; die übrigen vier Bytes werden ignoriert. Tonwerte von 0 bis 71 entsprechen C2 bis B7 (24=C4). Rauschwerte von 0 bis 15 wählen eine Periode im langen Modus, 16 bis 31 im kurzen Modus. Für jeden Kanal gilt: 255=NES_AUDIO_HOLD behält den Zustand bei, 254=NES_AUDIO_STOP schaltet ihn stumm.
Dieser Vierkanaltreiber ist auf NTSC abgestimmt: CH1=Impuls 1, CH2=Impuls 2, CH3=Dreieck und CH4=Rauschen, mit den Indizes 0 bis 3. DMC und Erweiterungsaudio werden nicht wiedergegeben. Verwenden Sie ihn nicht gleichzeitig mit direkten APU-Zugriffen, etwa den Effekten in audio.c. Es gibt weder eine PAL-Tonhöhentabelle noch eine PAL-Tempokorrektur.
Läuft die Dauer ab, ohne dass ein weiterer BGM-Datensatz vorliegt, verstummen die BGM-Noten. Nach Eingang neuer Daten geht es bei einer NMI weiter. Ein unabhängiger SFX läuft weiter. Gezählt werden Eintritte in den Datenmangel, nicht alle leeren Frames. Das Einreihen reiner HOLD-Werte stellt die vorherigen BGM-Noten nicht wieder her. Füllen Sie normalerweise pro Frame nach und halten Sie vor längeren Arbeiten ausreichend Wiedergabezeit in der Warteschlange bereit.
| Wartezeit | CH1: Puls 1 | CH2: Puls 2 | CH3: Dreieck | CH4: Rauschen |
|---|---|---|---|---|
| 24 | 24 (C4) | 12 (C3) | 0 (C2) | 2 |
Vom Compiler angebundener NMI-Hook
nes_audio_vblank_init
Initialisiert APU und Warteschlange und setzt Wiedergabe, Nachfüllzustand sowie Datenmangelzähler zurück.
Syntax
void nes_audio_vblank_init(void);Rückgabewert
Kein Rückgabewert.
Bedingungen und Grenzen
Binden Sie audio_vblank.h ein und nehmen Sie audio_vblank.c genau einmal in den Build auf. Der Compiler lässt sowohl den Standard-NMI-Handler als auch einen eigenen NMI-Handler den Musik-Hook einmal aufrufen. Aktivieren Sie PPU-NMI. Die Hauptschleife ruft keine Musikaktualisierung auf.
Dieser Vierkanaltreiber ist auf NTSC abgestimmt: CH1=Impuls 1, CH2=Impuls 2, CH3=Dreieck und CH4=Rauschen, mit den Indizes 0 bis 3. DMC und Erweiterungsaudio werden nicht wiedergegeben. Verwenden Sie ihn nicht gleichzeitig mit direkten APU-Zugriffen, etwa den Effekten in audio.c. Es gibt weder eine PAL-Tonhöhentabelle noch eine PAL-Tempokorrektur.
Deaktiviert APU-Frame-IRQs, DMC und den Sweep der Impulskanäle. Die Vorgaben sind: Impuls 1 mit 50 % Tastgrad und Lautstärke 12, Impuls 2 mit 25 % und Lautstärke 10, für Noten freigegebener Dreieckskanal sowie Rauschlautstärke 8. Die Initialisierung startet weder Musik noch NMI.
Anwendungsbeispiel
nes_audio_vblank_init();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 eigens komponierte vierkanalige Phrase einmal ab. Während das Hauptprogramm 90 Frames lang Ganzzahlberechnungen ohne Nachfüllen ausführt, läuft die Musik weiter. „PHRASE COMPLETE / SILENT“ und „UNDERRUNS 0 / MATH OK“ bedeuten, dass die Wiedergabe beendet ist, kein Datenmangel auftrat und die Rechenergebnisse stimmen. Prüfen Sie in der Audioaufnahme die Impulsmelodie und ihre Begleitung, den Dreiecksbass und das Rauschen. Am Ende herrscht Stille. Das Bild zeigt die Steuerungsergebnisse; den Klang beurteilen Sie anhand der Audioaufnahme.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\audio_vblank.c .\kitaq-docs\samples\api-examples\fc\audio_vblank.c -I .\kitaqfc\lib -I .\kitaq-docs\samples --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr -o .\out\audio_vblank.nes --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/audio_vblank.h:19
Reset the queue, feeder and diagnostic counters; silence and initialize the APU. Owns the four basic channels and disables DMC and APU frame IRQs.
kitaqfc/lib/audio_vblank.c:67
void nes_audio_vblank_init(void){
nes_audio_vblank_stop();nav_underruns=0;nav_frame=0x40;
nav_sweep1=8;nav_sweep2=8;nav_dmc_flags=0;nav_dmc_level=0;
nav_timbre[0]=0xBC;nav_timbre[1]=0x7A;nav_timbre[2]=0xFF;nav_timbre[3]=0x38;
}nes_audio_vblank_enqueue
Prüft einen Datensatz und kopiert ihn in die RAM-Warteschlange. Damit lässt sich Musik im Spielcode erzeugen, ohne Daten aus dem ROM nachzufüllen.
Syntax
u8 nes_audio_vblank_enqueue(const u8* record);Parameter
recordAdresse von fünf lesbaren Bytes, die bis zur Rückkehr des Aufrufs gültig bleiben muss. Danach darf das Quellarray wiederverwendet werden. Null wird abgewiesen.
Rückgabewert
Gibt bei Annahme 1 zurück. Eine volle Warteschlange, Null oder ungültige Ton- bzw. Rauschwerte führen zu 0, ohne die Warteschlange zu ändern. Die vier Kanalbytes eines Abschlussdatensatzes werden nicht geprüft.
Bedingungen und Grenzen
Binden Sie audio_vblank.h ein und nehmen Sie audio_vblank.c genau einmal in den Build auf. Der Compiler lässt sowohl den Standard-NMI-Handler als auch einen eigenen NMI-Handler den Musik-Hook einmal aufrufen. Aktivieren Sie PPU-NMI. Die Hauptschleife ruft keine Musikaktualisierung auf.
Dieser Vierkanaltreiber ist auf NTSC abgestimmt: CH1=Impuls 1, CH2=Impuls 2, CH3=Dreieck und CH4=Rauschen, mit den Indizes 0 bis 3. DMC und Erweiterungsaudio werden nicht wiedergegeben. Verwenden Sie ihn nicht gleichzeitig mit direkten APU-Zugriffen, etwa den Effekten in audio.c. Es gibt weder eine PAL-Tonhöhentabelle noch eine PAL-Tempokorrektur.
Der 40-Byte-Ringpuffer im RAM hat acht physische Plätze. Einer bleibt frei, damit sich voll und leer unterscheiden lassen. Nutzbar sind somit sieben Datensätze. Verwenden Sie nur einen Produzenten im Hauptprogramm; fügen Sie aus der NMI keine Daten hinzu und führen Sie dort weder Nachfüllen noch Initialisierung aus. Der Produzent veröffentlicht die ein Byte große Schreibposition erst nach dem Kopieren des vollständigen Datensatzes. Dadurch kann die NMI keinen unvollständigen Datensatz lesen.
Ein Datensatz besteht aus fünf Bytes: delay, CH1, CH2, CH3, CH4. Eine Dauer von 1 bis 255 gibt an, wie viele NMI-Ticks der neue Zustand anhält. Null beendet die Wiedergabe; die übrigen vier Bytes werden ignoriert. Tonwerte von 0 bis 71 entsprechen C2 bis B7 (24=C4). Rauschwerte von 0 bis 15 wählen eine Periode im langen Modus, 16 bis 31 im kurzen Modus. Für jeden Kanal gilt: 255=NES_AUDIO_HOLD behält den Zustand bei, 254=NES_AUDIO_STOP schaltet ihn stumm.
Anwendungsbeispiel
result[6]=nes_audio_vblank_enqueue(quiet_record); // Copy five bytes into RAM.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 eigens komponierte vierkanalige Phrase einmal ab. Während das Hauptprogramm 90 Frames lang Ganzzahlberechnungen ohne Nachfüllen ausführt, läuft die Musik weiter. „PHRASE COMPLETE / SILENT“ und „UNDERRUNS 0 / MATH OK“ bedeuten, dass die Wiedergabe beendet ist, kein Datenmangel auftrat und die Rechenergebnisse stimmen. Prüfen Sie in der Audioaufnahme die Impulsmelodie und ihre Begleitung, den Dreiecksbass und das Rauschen. Am Ende herrscht Stille. Das Bild zeigt die Steuerungsergebnisse; den Klang beurteilen Sie anhand der Audioaufnahme.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\audio_vblank.c .\kitaq-docs\samples\api-examples\fc\audio_vblank.c -I .\kitaqfc\lib -I .\kitaq-docs\samples --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr -o .\out\audio_vblank.nes --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/audio_vblank.h:22
Copy one complete validated record to RAM and publish it atomically last. Return 1 on success, 0 for null/invalid/full. Call from one foreground producer.
kitaqfc/lib/audio_vblank.c:74
u8 nes_audio_vblank_enqueue(const u8* record){
u8 next;u8 i;u8 value;
nav_invalid=0;
if(record==0){nav_invalid=1;return 0;}
next=nav_head+5;if(next==40)next=0;
if(next==nav_tail)return 0;
if(record[0]!=0){
for(i=1;i<5;i++){
value=record[i];
if(value<254){
if(i<4){if(value>71){nav_invalid=1;return 0;}}
else{if(value>31){nav_invalid=1;return 0;}}
}
}
}
for(i=0;i<5;i++)nav_queue[(__safe_index u8)(nav_head+i)]=record[i];
nav_head=next;return 1;
}nes_audio_vblank_queued
Gibt die Anzahl der Datensätze zurück, die von der NMI noch nicht verbraucht wurden.
Syntax
u8 nes_audio_vblank_queued(void);Rückgabewert
Gibt 0 bis 7 wartende BGM-Datensätze zurück. Die laufende Dauer und sämtliche SFX-Datensätze zählen nicht mit. Da die NMI Daten verbraucht, ist das Ergebnis nur eine Momentaufnahme.
Bedingungen und Grenzen
Binden Sie audio_vblank.h ein und nehmen Sie audio_vblank.c genau einmal in den Build auf. Der Compiler lässt sowohl den Standard-NMI-Handler als auch einen eigenen NMI-Handler den Musik-Hook einmal aufrufen. Aktivieren Sie PPU-NMI. Die Hauptschleife ruft keine Musikaktualisierung auf.
Dieser Vierkanaltreiber ist auf NTSC abgestimmt: CH1=Impuls 1, CH2=Impuls 2, CH3=Dreieck und CH4=Rauschen, mit den Indizes 0 bis 3. DMC und Erweiterungsaudio werden nicht wiedergegeben. Verwenden Sie ihn nicht gleichzeitig mit direkten APU-Zugriffen, etwa den Effekten in audio.c. Es gibt weder eine PAL-Tonhöhentabelle noch eine PAL-Tempokorrektur.
Der 40-Byte-Ringpuffer im RAM hat acht physische Plätze. Einer bleibt frei, damit sich voll und leer unterscheiden lassen. Nutzbar sind somit sieben Datensätze. Verwenden Sie nur einen Produzenten im Hauptprogramm; fügen Sie aus der NMI keine Daten hinzu und führen Sie dort weder Nachfüllen noch Initialisierung aus. Der Produzent veröffentlicht die ein Byte große Schreibposition erst nach dem Kopieren des vollständigen Datensatzes. Dadurch kann die NMI keinen unvollständigen Datensatz lesen.
Anwendungsbeispiel
result[1]=nes_audio_vblank_queued(); // Seven records after prefill.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 eigens komponierte vierkanalige Phrase einmal ab. Während das Hauptprogramm 90 Frames lang Ganzzahlberechnungen ohne Nachfüllen ausführt, läuft die Musik weiter. „PHRASE COMPLETE / SILENT“ und „UNDERRUNS 0 / MATH OK“ bedeuten, dass die Wiedergabe beendet ist, kein Datenmangel auftrat und die Rechenergebnisse stimmen. Prüfen Sie in der Audioaufnahme die Impulsmelodie und ihre Begleitung, den Dreiecksbass und das Rauschen. Am Ende herrscht Stille. Das Bild zeigt die Steuerungsergebnisse; den Klang beurteilen Sie anhand der Audioaufnahme.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\audio_vblank.c .\kitaq-docs\samples\api-examples\fc\audio_vblank.c -I .\kitaqfc\lib -I .\kitaq-docs\samples --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr -o .\out\audio_vblank.nes --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/audio_vblank.h:24
Return queued records (0..7), excluding the record whose delay is in progress.
kitaqfc/lib/audio_vblank.c:94
u8 nes_audio_vblank_queued(void){
u8 head;u8 tail;head=nav_head;tail=nav_tail;
if(head<tail)head=head+40;
return (head-tail)/5;
}nes_audio_vblank_free
Gibt die Anzahl freier Datensatzplätze in der Warteschlange zurück.
Syntax
u8 nes_audio_vblank_free(void);Rückgabewert
Gibt 0 bis 7 freie BGM-Plätze zurück, entsprechend 7−queued(). Das ist eine Platzanzahl; jeder Platz umfasst fünf Bytes. Der separate 35-Byte-SFX-Puffer gehört nicht zu dieser Warteschlange.
Bedingungen und Grenzen
Binden Sie audio_vblank.h ein und nehmen Sie audio_vblank.c genau einmal in den Build auf. Der Compiler lässt sowohl den Standard-NMI-Handler als auch einen eigenen NMI-Handler den Musik-Hook einmal aufrufen. Aktivieren Sie PPU-NMI. Die Hauptschleife ruft keine Musikaktualisierung auf.
Dieser Vierkanaltreiber ist auf NTSC abgestimmt: CH1=Impuls 1, CH2=Impuls 2, CH3=Dreieck und CH4=Rauschen, mit den Indizes 0 bis 3. DMC und Erweiterungsaudio werden nicht wiedergegeben. Verwenden Sie ihn nicht gleichzeitig mit direkten APU-Zugriffen, etwa den Effekten in audio.c. Es gibt weder eine PAL-Tonhöhentabelle noch eine PAL-Tempokorrektur.
Der 40-Byte-Ringpuffer im RAM hat acht physische Plätze. Einer bleibt frei, damit sich voll und leer unterscheiden lassen. Nutzbar sind somit sieben Datensätze. Verwenden Sie nur einen Produzenten im Hauptprogramm; fügen Sie aus der NMI keine Daten hinzu und führen Sie dort weder Nachfüllen noch Initialisierung aus. Der Produzent veröffentlicht die ein Byte große Schreibposition erst nach dem Kopieren des vollständigen Datensatzes. Dadurch kann die NMI keinen unvollständigen Datensatz lesen.
Anwendungsbeispiel
result[2]=nes_audio_vblank_free(); // No free slots immediately after prefill.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 eigens komponierte vierkanalige Phrase einmal ab. Während das Hauptprogramm 90 Frames lang Ganzzahlberechnungen ohne Nachfüllen ausführt, läuft die Musik weiter. „PHRASE COMPLETE / SILENT“ und „UNDERRUNS 0 / MATH OK“ bedeuten, dass die Wiedergabe beendet ist, kein Datenmangel auftrat und die Rechenergebnisse stimmen. Prüfen Sie in der Audioaufnahme die Impulsmelodie und ihre Begleitung, den Dreiecksbass und das Rauschen. Am Ende herrscht Stille. Das Bild zeigt die Steuerungsergebnisse; den Klang beurteilen Sie anhand der Audioaufnahme.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\audio_vblank.c .\kitaq-docs\samples\api-examples\fc\audio_vblank.c -I .\kitaqfc\lib -I .\kitaq-docs\samples --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr -o .\out\audio_vblank.nes --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/audio_vblank.h:26
Return available record slots (0..7), not bytes.
kitaqfc/lib/audio_vblank.c:99
u8 nes_audio_vblank_free(void){return 7-nes_audio_vblank_queued();}nes_audio_vblank_start
Aktiviert das Auslesen der RAM-Warteschlange. Der erste Datensatz wird bei der nächsten NMI entnommen.
Syntax
void nes_audio_vblank_start(void);Rückgabewert
Kein Rückgabewert.
Bedingungen und Grenzen
Binden Sie audio_vblank.h ein und nehmen Sie audio_vblank.c genau einmal in den Build auf. Der Compiler lässt sowohl den Standard-NMI-Handler als auch einen eigenen NMI-Handler den Musik-Hook einmal aufrufen. Aktivieren Sie PPU-NMI. Die Hauptschleife ruft keine Musikaktualisierung auf.
Dieser Vierkanaltreiber ist auf NTSC abgestimmt: CH1=Impuls 1, CH2=Impuls 2, CH3=Dreieck und CH4=Rauschen, mit den Indizes 0 bis 3. DMC und Erweiterungsaudio werden nicht wiedergegeben. Verwenden Sie ihn nicht gleichzeitig mit direkten APU-Zugriffen, etwa den Effekten in audio.c. Es gibt weder eine PAL-Tonhöhentabelle noch eine PAL-Tempokorrektur.
Initialisieren Sie zuerst den Treiber und fügen Sie Datensätze hinzu. Dieser Aufruf aktiviert keine NMI und ändert weder die laufende Dauer noch die Leseposition. Setzen Sie einen pausierten Treiber mit pause(0) fort; start allein hebt die Pause nicht auf.
Läuft die Dauer ab, ohne dass ein weiterer BGM-Datensatz vorliegt, verstummen die BGM-Noten. Nach Eingang neuer Daten geht es bei einer NMI weiter. Ein unabhängiger SFX läuft weiter. Gezählt werden Eintritte in den Datenmangel, nicht alle leeren Frames. Das Einreihen reiner HOLD-Werte stellt die vorherigen BGM-Noten nicht wieder her. Füllen Sie normalerweise pro Frame nach und halten Sie vor längeren Arbeiten ausreichend Wiedergabezeit in der Warteschlange bereit.
Anwendungsbeispiel
nes_audio_vblank_start(); // Consume the copied record on the next NMI.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 eigens komponierte vierkanalige Phrase einmal ab. Während das Hauptprogramm 90 Frames lang Ganzzahlberechnungen ohne Nachfüllen ausführt, läuft die Musik weiter. „PHRASE COMPLETE / SILENT“ und „UNDERRUNS 0 / MATH OK“ bedeuten, dass die Wiedergabe beendet ist, kein Datenmangel auftrat und die Rechenergebnisse stimmen. Prüfen Sie in der Audioaufnahme die Impulsmelodie und ihre Begleitung, den Dreiecksbass und das Rauschen. Am Ende herrscht Stille. Das Bild zeigt die Steuerungsergebnisse; den Klang beurteilen Sie anhand der Audioaufnahme.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\audio_vblank.c .\kitaq-docs\samples\api-examples\fc\audio_vblank.c -I .\kitaqfc\lib -I .\kitaq-docs\samples --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr -o .\out\audio_vblank.nes --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/audio_vblank.h:28
Enable consumption at the next NMI. Does not enable PPU NMI itself.
kitaqfc/lib/audio_vblank.c:100
void nes_audio_vblank_start(void){nav_active=1;}nes_audio_vblank_stop
Deaktiviert die Wiedergabe, schaltet die vier Kanäle stumm und verwirft Warteschlange sowie ROM-Nachfüllzustand.
Syntax
void nes_audio_vblank_stop(void);Rückgabewert
Kein Rückgabewert.
Bedingungen und Grenzen
Binden Sie audio_vblank.h ein und nehmen Sie audio_vblank.c genau einmal in den Build auf. Der Compiler lässt sowohl den Standard-NMI-Handler als auch einen eigenen NMI-Handler den Musik-Hook einmal aufrufen. Aktivieren Sie PPU-NMI. Die Hauptschleife ruft keine Musikaktualisierung auf.
Dieser Vierkanaltreiber ist auf NTSC abgestimmt: CH1=Impuls 1, CH2=Impuls 2, CH3=Dreieck und CH4=Rauschen, mit den Indizes 0 bis 3. DMC und Erweiterungsaudio werden nicht wiedergegeben. Verwenden Sie ihn nicht gleichzeitig mit direkten APU-Zugriffen, etwa den Effekten in audio.c. Es gibt weder eine PAL-Tonhöhentabelle noch eine PAL-Tempokorrektur.
Stoppt BGM und SFX und verwirft Warteschlange, Nachfüllzustand, beide Wiedergabepositionen und Pausenzustand. Klangfarben und Datenmangelzähler bleiben erhalten; NMI wird nicht deaktiviert. Mit pause bleibt die Position erhalten. Auch set_music und play_music führen diesen Stopp intern aus und brechen dadurch SFX ab.
Anwendungsbeispiel
nes_audio_vblank_stop(); // Clear the feeder and queued records; silence now.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 eigens komponierte vierkanalige Phrase einmal ab. Während das Hauptprogramm 90 Frames lang Ganzzahlberechnungen ohne Nachfüllen ausführt, läuft die Musik weiter. „PHRASE COMPLETE / SILENT“ und „UNDERRUNS 0 / MATH OK“ bedeuten, dass die Wiedergabe beendet ist, kein Datenmangel auftrat und die Rechenergebnisse stimmen. Prüfen Sie in der Audioaufnahme die Impulsmelodie und ihre Begleitung, den Dreiecksbass und das Rauschen. Am Ende herrscht Stille. Das Bild zeigt die Steuerungsergebnisse; den Klang beurteilen Sie anhand der Audioaufnahme.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\audio_vblank.c .\kitaq-docs\samples\api-examples\fc\audio_vblank.c -I .\kitaqfc\lib -I .\kitaq-docs\samples --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr -o .\out\audio_vblank.nes --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/audio_vblank.h:30
Disable consumption, silence, discard queued records and clear the feeder.
kitaqfc/lib/audio_vblank.c:29
void nes_audio_vblank_stop(void){
u8 i;
nav_paused=1;nav_active=0;nav_sfx_active=0;nav_status=0;
nav_delay=0;nav_enabled=0;nav_head=0;nav_tail=0;
nav_source=0;nav_cursor=0;nav_count=0;nav_left=0;nav_starved=0;
nav_previous_mask=0;nav_effective_mask=0;nav_refresh=0;
for(i=0;i<4;i++){nav_notes[(__safe_index u8)i]=254;nav_sfx_notes[(__safe_index u8)i]=254;}
nav_paused=0;
}nes_audio_vblank_set_music
Stoppt die Wiedergabe und legt einen Stream als Nachfüllquelle fest. Das Kopieren in die Warteschlange und der Wiedergabestart sind getrennte Vorgänge.
Syntax
u8 nes_audio_vblank_set_music(const u8* records,u16 count,u8 loop);Parameter
recordsAnfang des Streams in lesbarem ROM oder RAM. Halten Sie die Daten bis zum Ende des Nachfüllens verfügbar. Es findet kein Bankwechsel statt: Blenden Sie beim Aufruf von refill die passende ROM-Bank ein. Die NMI liest ausschließlich die ins RAM kopierten Datensätze.
countAnzahl lesbarer Fünf-Byte-Datensätze von 1 bis 13107, keine Byteanzahl. Sämtliche count×5 Bytes müssen in einem zusammenhängenden gültigen CPU-Adressbereich liegen.
loopNull wählt einmalige Wiedergabe, jeder andere Wert wiederholt ab dem Anfang. Fügen Sie in einen sich wiederholenden Stream keinen Abschlussdatensatz mit Dauer null ein.
Rückgabewert
Gibt bei gültigem Zeiger und gültiger Anzahl 1 zurück; bei Nullzeiger, Anzahl null oder einer Anzahl über 13107 wird 0 zurückgegeben. Auch bei einem Fehlschlag werden die bisherige Wiedergabe gestoppt und wartende Daten verworfen. Der Inhalt der Datensätze wird beim Nachfüllen geprüft.
Bedingungen und Grenzen
Binden Sie audio_vblank.h ein und nehmen Sie audio_vblank.c genau einmal in den Build auf. Der Compiler lässt sowohl den Standard-NMI-Handler als auch einen eigenen NMI-Handler den Musik-Hook einmal aufrufen. Aktivieren Sie PPU-NMI. Die Hauptschleife ruft keine Musikaktualisierung auf.
Dieser Vierkanaltreiber ist auf NTSC abgestimmt: CH1=Impuls 1, CH2=Impuls 2, CH3=Dreieck und CH4=Rauschen, mit den Indizes 0 bis 3. DMC und Erweiterungsaudio werden nicht wiedergegeben. Verwenden Sie ihn nicht gleichzeitig mit direkten APU-Zugriffen, etwa den Effekten in audio.c. Es gibt weder eine PAL-Tonhöhentabelle noch eine PAL-Tempokorrektur.
Ein Datensatz besteht aus fünf Bytes: delay, CH1, CH2, CH3, CH4. Eine Dauer von 1 bis 255 gibt an, wie viele NMI-Ticks der neue Zustand anhält. Null beendet die Wiedergabe; die übrigen vier Bytes werden ignoriert. Tonwerte von 0 bis 71 entsprechen C2 bis B7 (24=C4). Rauschwerte von 0 bis 15 wählen eine Periode im langen Modus, 16 bis 31 im kurzen Modus. Für jeden Kanal gilt: 255=NES_AUDIO_HOLD behält den Zustand bei, 254=NES_AUDIO_STOP schaltet ihn stumm.
Anwendungsbeispiel
result[5]=nes_audio_vblank_set_music(song,8,0); // Attach without starting.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 eigens komponierte vierkanalige Phrase einmal ab. Während das Hauptprogramm 90 Frames lang Ganzzahlberechnungen ohne Nachfüllen ausführt, läuft die Musik weiter. „PHRASE COMPLETE / SILENT“ und „UNDERRUNS 0 / MATH OK“ bedeuten, dass die Wiedergabe beendet ist, kein Datenmangel auftrat und die Rechenergebnisse stimmen. Prüfen Sie in der Audioaufnahme die Impulsmelodie und ihre Begleitung, den Dreiecksbass und das Rauschen. Am Ende herrscht Stille. Das Bild zeigt die Steuerungsergebnisse; den Klang beurteilen Sie anhand der Audioaufnahme.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\audio_vblank.c .\kitaq-docs\samples\api-examples\fc\audio_vblank.c -I .\kitaqfc\lib -I .\kitaq-docs\samples --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr -o .\out\audio_vblank.nes --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/audio_vblank.h:33
Stop and attach a readable five-byte-record stream; return 0 for null, zero count or a count above 13107. Nonzero loop repeats the stream. Does not start.
kitaqfc/lib/audio_vblank.c:110
u8 nes_audio_vblank_set_music(const u8* records,u16 count,u8 loop){
nes_audio_vblank_stop();
if(records==0||count==0||count>13107)return 0;
nav_source=records;nav_cursor=records;nav_count=count;nav_left=count;nav_loop=loop;
return 1;
}nes_audio_vblank_refill
Füllt bis zu sieben Datensätze aus dem festgelegten Stream in freie Plätze. Dieser Vorgang im Hauptprogramm ermöglicht es einer kleinen RAM-Warteschlange, ein langes Musikstück wiederzugeben.
Syntax
u8 nes_audio_vblank_refill(void);Rückgabewert
Gibt die Anzahl angenommener Datensätze von 0 bis 7 zurück, einschließlich des automatisch angehängten Abschlussdatensatzes bei einmaliger Wiedergabe. Ohne Quelle oder bei voller Warteschlange wird 0 zurückgegeben. Ein ungültiger Datensatz stoppt die Wiedergabe, verwirft Warteschlange und Nachfüllzustand und führt zu 0 als Rückgabewert.
Bedingungen und Grenzen
Binden Sie audio_vblank.h ein und nehmen Sie audio_vblank.c genau einmal in den Build auf. Der Compiler lässt sowohl den Standard-NMI-Handler als auch einen eigenen NMI-Handler den Musik-Hook einmal aufrufen. Aktivieren Sie PPU-NMI. Die Hauptschleife ruft keine Musikaktualisierung auf.
Dieser Vierkanaltreiber ist auf NTSC abgestimmt: CH1=Impuls 1, CH2=Impuls 2, CH3=Dreieck und CH4=Rauschen, mit den Indizes 0 bis 3. DMC und Erweiterungsaudio werden nicht wiedergegeben. Verwenden Sie ihn nicht gleichzeitig mit direkten APU-Zugriffen, etwa den Effekten in audio.c. Es gibt weder eine PAL-Tonhöhentabelle noch eine PAL-Tempokorrektur.
Anfang des Streams in lesbarem ROM oder RAM. Halten Sie die Daten bis zum Ende des Nachfüllens verfügbar. Es findet kein Bankwechsel statt: Blenden Sie beim Aufruf von refill die passende ROM-Bank ein. Die NMI liest ausschließlich die ins RAM kopierten Datensätze.
Null wählt einmalige Wiedergabe, jeder andere Wert wiederholt ab dem Anfang. Fügen Sie in einen sich wiederholenden Stream keinen Abschlussdatensatz mit Dauer null ein.
Läuft die Dauer ab, ohne dass ein weiterer BGM-Datensatz vorliegt, verstummen die BGM-Noten. Nach Eingang neuer Daten geht es bei einer NMI weiter. Ein unabhängiger SFX läuft weiter. Gezählt werden Eintritte in den Datenmangel, nicht alle leeren Frames. Das Einreihen reiner HOLD-Werte stellt die vorherigen BGM-Noten nicht wieder her. Füllen Sie normalerweise pro Frame nach und halten Sie vor längeren Arbeiten ausreichend Wiedergabezeit in der Warteschlange bereit.
ROM-Nachfüllen und direktes Einreihen nutzen dieselbe Warteschlange. Kombinieren Sie beides nur mit bewusst festgelegter Reihenfolge. Nachfüllen spielt keine Datensätze ab und startet den Verbraucher nicht. Ein Stopp wegen ungültiger Daten schaltet die APU allerdings stumm.
Anwendungsbeispiel
nes_audio_vblank_refill();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 eigens komponierte vierkanalige Phrase einmal ab. Während das Hauptprogramm 90 Frames lang Ganzzahlberechnungen ohne Nachfüllen ausführt, läuft die Musik weiter. „PHRASE COMPLETE / SILENT“ und „UNDERRUNS 0 / MATH OK“ bedeuten, dass die Wiedergabe beendet ist, kein Datenmangel auftrat und die Rechenergebnisse stimmen. Prüfen Sie in der Audioaufnahme die Impulsmelodie und ihre Begleitung, den Dreiecksbass und das Rauschen. Am Ende herrscht Stille. Das Bild zeigt die Steuerungsergebnisse; den Klang beurteilen Sie anhand der Audioaufnahme.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\audio_vblank.c .\kitaq-docs\samples\api-examples\fc\audio_vblank.c -I .\kitaqfc\lib -I .\kitaq-docs\samples --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr -o .\out\audio_vblank.nes --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/audio_vblank.h:37
Copy at most seven records from the attached stream. Return copies accepted. A one-shot feeder appends a delay-zero terminator after the last timed record. Keep the stream's ROM bank mapped during this foreground call only.
kitaqfc/lib/audio_vblank.c:118
u8 nes_audio_vblank_refill(void){
u8 copied;copied=0;
while(copied<7&&nav_source!=0){
if(nav_left==0){
if(nav_loop!=0){nav_cursor=nav_source;nav_left=nav_count;}
else {if(nes_audio_vblank_enqueue(nav_end)!=0){copied++;nav_source=0;}return copied;}
}
if(nes_audio_vblank_enqueue(nav_cursor)==0){
// The producer-only flag distinguishes malformed data from full.
// Re-reading occupancy here would race NMI freeing a full queue.
if(nav_invalid!=0){nes_audio_vblank_stop();return 0;}
return copied;
}
copied++;nav_cursor=nav_cursor+5;nav_left--;
}
return copied;
}nes_audio_vblank_play_music
Legt ein Musikstück fest, füllt die Warteschlange vor und aktiviert die Wiedergabe mit einem Aufruf. Dies ist der übliche Einstieg zum Starten einer Phrase.
Syntax
u8 nes_audio_vblank_play_music(const u8* records,u16 count,u8 loop);Parameter
recordsAnfang des Streams in lesbarem ROM oder RAM. Halten Sie die Daten bis zum Ende des Nachfüllens verfügbar. Es findet kein Bankwechsel statt: Blenden Sie beim Aufruf von refill die passende ROM-Bank ein. Die NMI liest ausschließlich die ins RAM kopierten Datensätze.
countAnzahl lesbarer Fünf-Byte-Datensätze von 1 bis 13107, keine Byteanzahl. Sämtliche count×5 Bytes müssen in einem zusammenhängenden gültigen CPU-Adressbereich liegen.
loopNull wählt einmalige Wiedergabe, jeder andere Wert wiederholt ab dem Anfang. Fügen Sie in einen sich wiederholenden Stream keinen Abschlussdatensatz mit Dauer null ein.
Rückgabewert
Gibt 1 zurück, wenn Einrichtung und erstes Vorfüllen erfolgreich sind, andernfalls 0 bei ungültiger Einrichtung oder dabei erkannten ungültigen Daten. Ein Erfolg bestätigt nicht das gesamte Musikstück: Fehlerhafte spätere Datensätze werden erst bei späteren refill-Aufrufen entdeckt.
Bedingungen und Grenzen
Binden Sie audio_vblank.h ein und nehmen Sie audio_vblank.c genau einmal in den Build auf. Der Compiler lässt sowohl den Standard-NMI-Handler als auch einen eigenen NMI-Handler den Musik-Hook einmal aufrufen. Aktivieren Sie PPU-NMI. Die Hauptschleife ruft keine Musikaktualisierung auf.
Dieser Vierkanaltreiber ist auf NTSC abgestimmt: CH1=Impuls 1, CH2=Impuls 2, CH3=Dreieck und CH4=Rauschen, mit den Indizes 0 bis 3. DMC und Erweiterungsaudio werden nicht wiedergegeben. Verwenden Sie ihn nicht gleichzeitig mit direkten APU-Zugriffen, etwa den Effekten in audio.c. Es gibt weder eine PAL-Tonhöhentabelle noch eine PAL-Tempokorrektur.
Rufen Sie zuerst einmal init auf. play_music behält Klangfarben und Datenmangelzähler bei. Rufen Sie bei langen oder wiederholten Streams weiterhin regelmäßig refill auf.
Anwendungsbeispiel
result[0]=nes_audio_vblank_play_music(song,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
Das Beispiel spielt eine eigens komponierte vierkanalige Phrase einmal ab. Während das Hauptprogramm 90 Frames lang Ganzzahlberechnungen ohne Nachfüllen ausführt, läuft die Musik weiter. „PHRASE COMPLETE / SILENT“ und „UNDERRUNS 0 / MATH OK“ bedeuten, dass die Wiedergabe beendet ist, kein Datenmangel auftrat und die Rechenergebnisse stimmen. Prüfen Sie in der Audioaufnahme die Impulsmelodie und ihre Begleitung, den Dreiecksbass und das Rauschen. Am Ende herrscht Stille. Das Bild zeigt die Steuerungsergebnisse; den Klang beurteilen Sie anhand der Audioaufnahme.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\audio_vblank.c .\kitaq-docs\samples\api-examples\fc\audio_vblank.c -I .\kitaqfc\lib -I .\kitaq-docs\samples --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr -o .\out\audio_vblank.nes --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/audio_vblank.h:39
Set the stream, prefill the queue and start. Return 0 for invalid setup/data.
kitaqfc/lib/audio_vblank.c:135
u8 nes_audio_vblank_play_music(const u8* records,u16 count,u8 loop){
if(nes_audio_vblank_set_music(records,count,loop)==0)return 0;
if(nes_audio_vblank_refill()==0)return 0;
nes_audio_vblank_start();return 1;
}nes_audio_vblank_is_playing
Meldet, ob das Auslesen der Warteschlange durch NMI aktiviert ist.
Syntax
u8 nes_audio_vblank_is_playing(void);Rückgabewert
Gibt 1 zurück, solange der BGM-Verbraucher aktiviert ist, auch während Pause oder Datenmangel; nach Stopp oder Ende wird 0 zurückgegeben. Ein allein laufender SFX ergibt ebenfalls 0. Der Wert sagt weder aus, ob etwas hörbar ist, noch ob ein SFX aktiv ist.
Bedingungen und Grenzen
Binden Sie audio_vblank.h ein und nehmen Sie audio_vblank.c genau einmal in den Build auf. Der Compiler lässt sowohl den Standard-NMI-Handler als auch einen eigenen NMI-Handler den Musik-Hook einmal aufrufen. Aktivieren Sie PPU-NMI. Die Hauptschleife ruft keine Musikaktualisierung auf.
Dieser Vierkanaltreiber ist auf NTSC abgestimmt: CH1=Impuls 1, CH2=Impuls 2, CH3=Dreieck und CH4=Rauschen, mit den Indizes 0 bis 3. DMC und Erweiterungsaudio werden nicht wiedergegeben. Verwenden Sie ihn nicht gleichzeitig mit direkten APU-Zugriffen, etwa den Effekten in audio.c. Es gibt weder eine PAL-Tonhöhentabelle noch eine PAL-Tempokorrektur.
Läuft die Dauer ab, ohne dass ein weiterer BGM-Datensatz vorliegt, verstummen die BGM-Noten. Nach Eingang neuer Daten geht es bei einer NMI weiter. Ein unabhängiger SFX läuft weiter. Gezählt werden Eintritte in den Datenmangel, nicht alle leeren Frames. Das Einreihen reiner HOLD-Werte stellt die vorherigen BGM-Noten nicht wieder her. Füllen Sie normalerweise pro Frame nach und halten Sie vor längeren Arbeiten ausreichend Wiedergabezeit in der Warteschlange bereit.
Anwendungsbeispiel
while(nes_audio_vblank_is_playing()!=0){
// example:nes_audio_vblank_refill:start
nes_audio_vblank_refill();
// example:nes_audio_vblank_refill:end
__nmi_wait();
}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 eigens komponierte vierkanalige Phrase einmal ab. Während das Hauptprogramm 90 Frames lang Ganzzahlberechnungen ohne Nachfüllen ausführt, läuft die Musik weiter. „PHRASE COMPLETE / SILENT“ und „UNDERRUNS 0 / MATH OK“ bedeuten, dass die Wiedergabe beendet ist, kein Datenmangel auftrat und die Rechenergebnisse stimmen. Prüfen Sie in der Audioaufnahme die Impulsmelodie und ihre Begleitung, den Dreiecksbass und das Rauschen. Am Ende herrscht Stille. Das Bild zeigt die Steuerungsergebnisse; den Klang beurteilen Sie anhand der Audioaufnahme.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\audio_vblank.c .\kitaq-docs\samples\api-examples\fc\audio_vblank.c -I .\kitaqfc\lib -I .\kitaq-docs\samples --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr -o .\out\audio_vblank.nes --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/audio_vblank.h:41
Return 1 while the BGM consumer is enabled, including a recoverable queue underrun.
kitaqfc/lib/audio_vblank.c:101
u8 nes_audio_vblank_is_playing(void){return nav_active;}nes_audio_vblank_underruns
Gibt die Anzahl der Datenmangelereignisse der Warteschlange zurück und hilft damit, den zeitlichen Spielraum zum Nachfüllen einzuschätzen.
Syntax
u8 nes_audio_vblank_underruns(void);Rückgabewert
Gibt 0 bis 255 zurück und bleibt nach Erreichen von 255 auf diesem Wert. Gezählt werden Datenmangelereignisse, nicht alle wartenden Frames. init setzt den Zähler zurück; stop und ein Musikwechsel behalten ihn bei. Ein regulärer Abschlussdatensatz gilt nicht als Datenmangel.
Bedingungen und Grenzen
Binden Sie audio_vblank.h ein und nehmen Sie audio_vblank.c genau einmal in den Build auf. Der Compiler lässt sowohl den Standard-NMI-Handler als auch einen eigenen NMI-Handler den Musik-Hook einmal aufrufen. Aktivieren Sie PPU-NMI. Die Hauptschleife ruft keine Musikaktualisierung auf.
Dieser Vierkanaltreiber ist auf NTSC abgestimmt: CH1=Impuls 1, CH2=Impuls 2, CH3=Dreieck und CH4=Rauschen, mit den Indizes 0 bis 3. DMC und Erweiterungsaudio werden nicht wiedergegeben. Verwenden Sie ihn nicht gleichzeitig mit direkten APU-Zugriffen, etwa den Effekten in audio.c. Es gibt weder eine PAL-Tonhöhentabelle noch eine PAL-Tempokorrektur.
Läuft die Dauer ab, ohne dass ein weiterer BGM-Datensatz vorliegt, verstummen die BGM-Noten. Nach Eingang neuer Daten geht es bei einer NMI weiter. Ein unabhängiger SFX läuft weiter. Gezählt werden Eintritte in den Datenmangel, nicht alle leeren Frames. Das Einreihen reiner HOLD-Werte stellt die vorherigen BGM-Noten nicht wieder her. Füllen Sie normalerweise pro Frame nach und halten Sie vor längeren Arbeiten ausreichend Wiedergabezeit in der Warteschlange bereit.
Anwendungsbeispiel
result[4]=nes_audio_vblank_underruns(); // Zero: queued time covered the busy section.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 eigens komponierte vierkanalige Phrase einmal ab. Während das Hauptprogramm 90 Frames lang Ganzzahlberechnungen ohne Nachfüllen ausführt, läuft die Musik weiter. „PHRASE COMPLETE / SILENT“ und „UNDERRUNS 0 / MATH OK“ bedeuten, dass die Wiedergabe beendet ist, kein Datenmangel auftrat und die Rechenergebnisse stimmen. Prüfen Sie in der Audioaufnahme die Impulsmelodie und ihre Begleitung, den Dreiecksbass und das Rauschen. Am Ende herrscht Stille. Das Bild zeigt die Steuerungsergebnisse; den Klang beurteilen Sie anhand der Audioaufnahme.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\audio_vblank.c .\kitaq-docs\samples\api-examples\fc\audio_vblank.c -I .\kitaqfc\lib -I .\kitaq-docs\samples --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr -o .\out\audio_vblank.nes --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/audio_vblank.h:43
Saturating count of starvation episodes, cleared by init; END is not starvation.
kitaqfc/lib/audio_vblank.c:102
u8 nes_audio_vblank_underruns(void){return nav_underruns;}nes_audio_vblank_set_timbre
Legt Tastgrad oder Pegel für die nächste Note eines Kanals fest, ohne dessen aktuelle Note erneut auszulösen.
Syntax
u8 nes_audio_vblank_set_timbre(u8 channel,u8 control);Parameter
channel0=CH1 Impuls 1, 1=CH2 Impuls 2, 2=CH3 Dreieck, 3=CH4 Rauschen. Werte ab 4 werden abgewiesen.
controlBei Impulskanälen wählen die Bits 7..6 den Tastgrad (0=12,5 %, 1=25 %, 2=50 %, 3=75 %); die Bits 3..0 legen die konstante Lautstärke von 0 bis 15 fest. Beim Rauschen dienen die Bits 3..0 normalerweise ebenfalls als konstante Lautstärke. Verknüpfen Sie den Wert per OR mit NES_AUDIO_NOISE_ENVELOPE (128), um diese Bits als Abklingperiode von 0 bis 15 zu verwenden: Die nächste Rauschnote beginnt bei Lautstärke 15 und klingt einmal ab. Größere Perioden sind langsamer; 15 dauert etwa eine Sekunde. Der Längenzähler des Rauschkanals lässt das Abklingen vollständig zu. Beim Dreieckskanal bedeutet null eine stumme nächste Note; jeder andere Wert macht sie hörbar.
Rückgabewert
Gibt für einen gültigen Kanal 1 zurück. Werte ab 4 ergeben 0, ohne Änderungen vorzunehmen.
Bedingungen und Grenzen
Binden Sie audio_vblank.h ein und nehmen Sie audio_vblank.c genau einmal in den Build auf. Der Compiler lässt sowohl den Standard-NMI-Handler als auch einen eigenen NMI-Handler den Musik-Hook einmal aufrufen. Aktivieren Sie PPU-NMI. Die Hauptschleife ruft keine Musikaktualisierung auf.
Dieser Vierkanaltreiber ist auf NTSC abgestimmt: CH1=Impuls 1, CH2=Impuls 2, CH3=Dreieck und CH4=Rauschen, mit den Indizes 0 bis 3. DMC und Erweiterungsaudio werden nicht wiedergegeben. Verwenden Sie ihn nicht gleichzeitig mit direkten APU-Zugriffen, etwa den Effekten in audio.c. Es gibt weder eine PAL-Tonhöhentabelle noch eine PAL-Tempokorrektur.
Anwendungsbeispiel
nes_audio_vblank_set_timbre(3,NES_AUDIO_NOISE_ENVELOPE|15);
result[3]=nes_audio_vblank_play_sfx(noise,1,8); // Bit 3 owns CH4; no BGM needed.
// The slow one-shot envelope fades by itself. It does not loop at zero.Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Es ist keine Eingabe erforderlich. CH1 spielt BGM bei etwa 220 Hz, wechselt für 30 Frames zu einem SFX bei etwa 880 Hz und kehrt dann zur aktuellen BGM zurück. Nach einer stummen Pause von 30 Frames läuft die BGM weiter. Ein zweiter Effekt wird nach 15 Frames ausdrücklich abgebrochen. Abschließend klingt das CH4-Rauschen einmal langsam ab. COMPLETE / ALL CHANNELS OFF kennzeichnet das Ende. Prüfen Sie anhand der beigefügten Aufnahme die Tonhöhenwechsel, die stumme Pause und das Abklingen des Rauschens.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\audio_vblank.c .\kitaq-docs\samples\api-examples\fc\audio_vblank_effects.c -I .\kitaqfc\lib -I .\kitaq-docs\samples --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr -o .\out\audio_vblank_effects.nes --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/audio_vblank.h:50
Configure the next note: pulse bits 7..6 select duty and 3..0 select volume; noise uses volume 3..0, or NES_AUDIO_NOISE_ENVELOPE | decay_period (0..15) for a one-shot hardware envelope (larger periods decay more slowly). The next noise note starts at volume 15; its length permits a full decay. Triangle uses zero for silent, nonzero for full level. Return 0 for channel >=4. Hardware has no triangle volume control.
kitaqfc/lib/audio_vblank.c:103
u8 nes_audio_vblank_set_timbre(u8 channel,u8 control){
if(channel>=4)return 0;
if(channel<2)nav_timbre[(__safe_index u8)channel]=(control&0xCF)|0x30;
else if(channel==2){if(control==0)nav_timbre[2]=0x80;else nav_timbre[2]=0xFF;}
else {if((control&128)!=0)nav_timbre[3]=control&15;else nav_timbre[3]=(control&15)|0x30;}
return 1;
}nes_audio_vblank_pause
Pausiert BGM und SFX oder setzt beide fort, wobei ihre Wiedergabepositionen erhalten bleiben.
Syntax
void nes_audio_vblank_pause(u8 on);Parameter
onEin Wert ungleich null pausiert, null setzt fort. Beim Pausieren werden die vier APU-Kanäle sofort deaktiviert.
Rückgabewert
Kein Rückgabewert.
Bedingungen und Grenzen
Binden Sie audio_vblank.h ein und nehmen Sie audio_vblank.c genau einmal in den Build auf. Der Compiler lässt sowohl den Standard-NMI-Handler als auch einen eigenen NMI-Handler den Musik-Hook einmal aufrufen. Aktivieren Sie PPU-NMI. Die Hauptschleife ruft keine Musikaktualisierung auf.
Dieser Vierkanaltreiber ist auf NTSC abgestimmt: CH1=Impuls 1, CH2=Impuls 2, CH3=Dreieck und CH4=Rauschen, mit den Indizes 0 bis 3. DMC und Erweiterungsaudio werden nicht wiedergegeben. Verwenden Sie ihn nicht gleichzeitig mit direkten APU-Zugriffen, etwa den Effekten in audio.c. Es gibt weder eine PAL-Tonhöhentabelle noch eine PAL-Tempokorrektur.
Rufen Sie die Funktion aus dem Hauptprogramm auf. Die NMI verbraucht die kopierten SFX-Daten. Lassen Sie diese Bibliothek sowohl BGM als auch SFX verwalten und betreiben Sie keinen weiteren APU-Treiber gleichzeitig.
Während der Pause ändern sich weder BGM-Dauer und Warteschlangenposition noch SFX-Dauer und -Position. Das Hauptprogramm kann weiterhin nachfüllen. Die erste NMI nach dem Fortsetzen löst die aktuellen Noten erneut aus und führt den normalen Tick aus. Wellenformphase und ein bereits teilweise abgeklungener Hüllkurvenpegel werden nicht gespeichert. Das von is_playing gemeldete BGM-Aktivierungsflag bleibt unverändert. Null fordert auch bei bereits laufender Wiedergabe eine Wiederherstellung der Noten an; rufen Sie dies daher nicht in jedem Frame auf.
Anwendungsbeispiel
nes_audio_vblank_pause(1); // Freeze BGM and SFX, and mute immediately.
phase=3;wait_frames(30); // Refill may copy data; neither timeline advances.
nes_audio_vblank_pause(0); // Restore held notes on the next NMI.Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Es ist keine Eingabe erforderlich. CH1 spielt BGM bei etwa 220 Hz, wechselt für 30 Frames zu einem SFX bei etwa 880 Hz und kehrt dann zur aktuellen BGM zurück. Nach einer stummen Pause von 30 Frames läuft die BGM weiter. Ein zweiter Effekt wird nach 15 Frames ausdrücklich abgebrochen. Abschließend klingt das CH4-Rauschen einmal langsam ab. COMPLETE / ALL CHANNELS OFF kennzeichnet das Ende. Prüfen Sie anhand der beigefügten Aufnahme die Tonhöhenwechsel, die stumme Pause und das Abklingen des Rauschens.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\audio_vblank.c .\kitaq-docs\samples\api-examples\fc\audio_vblank_effects.c -I .\kitaqfc\lib -I .\kitaq-docs\samples --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr -o .\out\audio_vblank_effects.nes --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/audio_vblank.h:54
Any nonzero argument freezes both timelines and mutes immediately. Zero resumes from the stored delays and restores held notes on the next NMI. BGM is_playing remains enabled during pause. Refill may still fill the queue.
kitaqfc/lib/audio_vblank.c:40
void nes_audio_vblank_pause(u8 on){
if(on!=0){nav_paused=1;nav_status=0;}
else{nav_refresh=1;nav_paused=0;}
}nes_audio_vblank_play_sfx
Kopiert einen kurzen Effekt ins RAM und übernimmt ab der nächsten NMI vorübergehend die Ausgabe der ausgewählten Kanäle.
Syntax
u8 nes_audio_vblank_play_sfx(const u8* records,u8 count,u8 mask);Parameter
recordsAnfang der Fünf-Byte-Datensätze. Halten Sie count×5 Bytes bis zur Rückkehr des Aufrufs lesbar und eingeblendet. Nach dem Kopieren darf die Quelle wiederverwendet werden.
count1 bis 7 Datensätze mit insgesamt höchstens 35 Bytes. Jede Dauer muss zwischen 1 und 255 liegen. SFX verwenden keine Abschlussdatensätze mit Dauer null, sondern enden nach den angegebenen Datensätzen.
maskDie unteren vier Bits wählen die Kanäle: 1=CH1, 2=CH2, 4=CH3, 8=CH4. Verknüpfen Sie Bits per OR, um mehrere auszuwählen. Höhere Bits werden ignoriert; sind die unteren vier Bits null, wird die Maske abgewiesen.
Rückgabewert
Gibt nach dem Kopieren und Aktivieren des Effekts 1 zurück. Bei Nullzeiger, ungültiger Anzahl, fehlender Kanalauswahl, Dauer null oder ungültigen Ton- bzw. Rauschwerten wird 0 zurückgegeben. Ungültige Eingaben lassen den aktuellen Effekt unverändert. Werte nicht ausgewählter Kanäle werden ebenfalls geprüft.
Bedingungen und Grenzen
Binden Sie audio_vblank.h ein und nehmen Sie audio_vblank.c genau einmal in den Build auf. Der Compiler lässt sowohl den Standard-NMI-Handler als auch einen eigenen NMI-Handler den Musik-Hook einmal aufrufen. Aktivieren Sie PPU-NMI. Die Hauptschleife ruft keine Musikaktualisierung auf.
Dieser Vierkanaltreiber ist auf NTSC abgestimmt: CH1=Impuls 1, CH2=Impuls 2, CH3=Dreieck und CH4=Rauschen, mit den Indizes 0 bis 3. DMC und Erweiterungsaudio werden nicht wiedergegeben. Verwenden Sie ihn nicht gleichzeitig mit direkten APU-Zugriffen, etwa den Effekten in audio.c. Es gibt weder eine PAL-Tonhöhentabelle noch eine PAL-Tempokorrektur.
Rufen Sie die Funktion aus dem Hauptprogramm auf. Die NMI verbraucht die kopierten SFX-Daten. Lassen Sie diese Bibliothek sowohl BGM als auch SFX verwalten und betreiben Sie keinen weiteren APU-Treiber gleichzeitig.
Die BGM läuft im Hintergrund weiter. Nach dem Effekt geben die Kanäle wieder deren aktuelle Noten aus. Es gibt einen SFX-Stream; ein neuer Aufruf ersetzt ihn. HOLD/STOP entsprechen den BGM-Werten, aber die gehaltenen Noten eines Effekts beginnen im gestoppten Zustand. Ein anfängliches HOLD übernimmt daher keine BGM-Note. SFX können ohne BGM laufen. Ein während der Pause eingereihter Effekt wartet auf das Fortsetzen. Die Klangfarben werden mit der BGM geteilt.
Anwendungsbeispiel
result[1]=nes_audio_vblank_play_sfx(effect,1,1); // Mask bit 0 owns CH1.
// The BGM timeline keeps advancing; its current CH1 note returns after 30 ticks.Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Es ist keine Eingabe erforderlich. CH1 spielt BGM bei etwa 220 Hz, wechselt für 30 Frames zu einem SFX bei etwa 880 Hz und kehrt dann zur aktuellen BGM zurück. Nach einer stummen Pause von 30 Frames läuft die BGM weiter. Ein zweiter Effekt wird nach 15 Frames ausdrücklich abgebrochen. Abschließend klingt das CH4-Rauschen einmal langsam ab. COMPLETE / ALL CHANNELS OFF kennzeichnet das Ende. Prüfen Sie anhand der beigefügten Aufnahme die Tonhöhenwechsel, die stumme Pause und das Abklingen des Rauschens.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\audio_vblank.c .\kitaq-docs\samples\api-examples\fc\audio_vblank_effects.c -I .\kitaqfc\lib -I .\kitaq-docs\samples --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr -o .\out\audio_vblank_effects.nes --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/audio_vblank.h:62
Copy 1..7 timed records. Bits 0..3 select channels temporarily owned by SFX. BGM continues underneath and its current notes return when the effect ends. Return 1 after copying; 0 for null, invalid count/data or an empty low mask. Ignore mask bits 4..7. All fields are validated, even unselected channels. Delay zero is not accepted for SFX. Invalid input preserves the current SFX. Replacement restarts the effect; the first HOLD starts from a stopped note. The source need only stay mapped/readable until this foreground call returns.
kitaqfc/lib/audio_vblank.c:47
u8 nes_audio_vblank_play_sfx(const u8* records,u8 count,u8 mask){
u8 i;u8 ch;u8 value;u8 bytes;
if(records==0||count==0||count>7||(mask&15)==0)return 0;
bytes=(u8)(count+count+count+count+count);
i=0;
while(i<bytes){
if(records[i]==0)return 0;
ch=1;while(ch<5){
value=records[i+ch];
if(value<254){if(ch<4){if(value>71)return 0;}else{if(value>31)return 0;}}
ch++;
}
i=i+5;
}
nav_sfx_active=0;
for(i=0;i<bytes;i++)nav_sfx_queue[(__safe_index u8)i]=records[i];
for(i=0;i<4;i++)nav_sfx_notes[(__safe_index u8)i]=254;
nav_sfx_mask=mask&15;nav_sfx_cursor=0;nav_sfx_length=bytes;nav_sfx_delay=0;
nav_sfx_active=1;return 1;
}nes_audio_vblank_stop_sfx
Gibt die vom Effekt belegten Kanäle frei, damit die nächste NMI die aktuellen BGM-Noten wiederherstellt.
Syntax
void nes_audio_vblank_stop_sfx(void);Rückgabewert
Kein Rückgabewert.
Bedingungen und Grenzen
Binden Sie audio_vblank.h ein und nehmen Sie audio_vblank.c genau einmal in den Build auf. Der Compiler lässt sowohl den Standard-NMI-Handler als auch einen eigenen NMI-Handler den Musik-Hook einmal aufrufen. Aktivieren Sie PPU-NMI. Die Hauptschleife ruft keine Musikaktualisierung auf.
Dieser Vierkanaltreiber ist auf NTSC abgestimmt: CH1=Impuls 1, CH2=Impuls 2, CH3=Dreieck und CH4=Rauschen, mit den Indizes 0 bis 3. DMC und Erweiterungsaudio werden nicht wiedergegeben. Verwenden Sie ihn nicht gleichzeitig mit direkten APU-Zugriffen, etwa den Effekten in audio.c. Es gibt weder eine PAL-Tonhöhentabelle noch eine PAL-Tempokorrektur.
Rufen Sie die Funktion aus dem Hauptprogramm auf. Die NMI verbraucht die kopierten SFX-Daten. Lassen Sie diese Bibliothek sowohl BGM als auch SFX verwalten und betreiben Sie keinen weiteren APU-Treiber gleichzeitig.
Dieser Aufruf schreibt keine APU-Register. BGM-Warteschlange, Position und Aktivierungszustand bleiben erhalten. Lief nur ein SFX, setzt die nächste NMI die Kanäle auf gestoppte Noten zurück. Während einer Pause wird die Änderung beim Fortsetzen wirksam. Verwenden Sie stop, um sofort stummzuschalten und beide Wiedergabepositionen zu verwerfen.
Anwendungsbeispiel
nes_audio_vblank_stop_sfx(); // Release effect ownership at the next NMI.
// BGM continues at its current position; this does not restart the song.Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Es ist keine Eingabe erforderlich. CH1 spielt BGM bei etwa 220 Hz, wechselt für 30 Frames zu einem SFX bei etwa 880 Hz und kehrt dann zur aktuellen BGM zurück. Nach einer stummen Pause von 30 Frames läuft die BGM weiter. Ein zweiter Effekt wird nach 15 Frames ausdrücklich abgebrochen. Abschließend klingt das CH4-Rauschen einmal langsam ab. COMPLETE / ALL CHANNELS OFF kennzeichnet das Ende. Prüfen Sie anhand der beigefügten Aufnahme die Tonhöhenwechsel, die stumme Pause und das Abklingen des Rauschens.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\audio_vblank.c .\kitaq-docs\samples\api-examples\fc\audio_vblank_effects.c -I .\kitaqfc\lib -I .\kitaq-docs\samples --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr -o .\out\audio_vblank_effects.nes --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/audio_vblank.h:65
Release effect ownership at the next NMI, restoring current BGM notes. This does not stop or restart the BGM and does not write the APU immediately.
kitaqfc/lib/audio_vblank.c:44
void nes_audio_vblank_stop_sfx(void){nav_sfx_active=0;}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 FC-Beispiel verwendet logische MMC3-Banken: Bank 0 enthält gemeinsamen Code unter $C000–$FFFF, die gewählte 16-KiB-Bank wird unter $8000–$BFFF eingeblendet. Dies sind Banknummern des Compilers, nicht die rohen 8-KiB-Registerwerte des Mappers. Initialisieren Sie den Bibliothekszustand mit bank_switch. Auf FC ist far_call ein Makro für benannte Funktionsaufrufe; übergeben Sie die Funktionsbank, vorzugsweise mit __bankof ermittelt.
bank_get_current
Liefert die zuletzt von bank_switch gespeicherte Banknummer. Gelesen wird der Softwarezustand, nicht ein Register des Moduls.
Syntax
u8 bank_get_current(void);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
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 02: Das Makro far_call und __farcall rufen den Callback jeweils einmal auf.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\banked_data_calls.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\banked_data_calls.nes --mapper=mmc3 --nes-chr=.\kitaq-docs\samples\font.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/bank.h:18
Read this wrapper's bank shadow; arbitrary mapper writes do not update it.
kitaqfc/lib/bank.c:14
u8 bank_get_current(void)
{
return kq_bank_current;
}bank_switch
Speichert die angeforderte Bank in der Bibliothek und wählt sie anschließend über die zum Mapper passende PRG-Umschaltung des Compilers.
Syntax
void bank_switch(u8 bank);Parameter
bankVorzeichenlose 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.
FC-Banknummern sind logische Nummern des Compilers. Null bezeichnet gemeinsames ROM, kein Umschaltziel; die Hilfsroutine setzt null auf Bank 1 um. Bei SUROM512 sind nur 1–30 gültig: Eine direkt an das Umschalt-Intrinsic übergebene Konstante außerhalb des Bereichs führt zu einem Buildfehler; ein ungültiger Laufzeitwert wählt 1 und setzt den Mapper-Fehlerzustand. Lesen Sie gemeinsames ROM direkt, statt Bank null anzufordern.
Anwendungsbeispiel
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 02: Das Makro far_call und __farcall rufen den Callback jeweils einmal auf.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\banked_data_calls.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\banked_data_calls.nes --mapper=mmc3 --nes-chr=.\kitaq-docs\samples\font.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/bank.h:16
Record the bank in the library shadow and invoke the mapper-aware compiler intrinsic.
kitaqfc/lib/bank.c:7
void bank_switch(u8 bank)
{
kq_bank_current = bank;
__bankswitch(bank);
}far_call
Wird zu __farcall((bank), func) expandiert. Das Makro erhält das Ziel als für den Compiler sichtbaren Funktionsnamen; es ist kein indirekter Aufruf über einen Callback-Zeiger.
Syntax
#define far_call(bank, func) __farcall((bank), func)Parameter
bankVorzeichenlose 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.
funcDeklarierter Name einer Funktion ohne Parameter. Dieses Intrinsic für benannte Aufrufe akzeptiert keine Variable mit einer Funktionsadresse. Das Argument bank wird nicht als Callback-Parameter weitergereicht.
Rückgabewert
Der Ergebnistyp richtet sich nach der aufgerufenen Funktion. Ein void-Callback liefert keinen Wert; u8- und u16-Callbacks liefern ihren Skalarwert. Das gezeigte Beispiel verwendet void-Callbacks.
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.
FC-Banknummern sind logische Nummern des Compilers. Null bezeichnet gemeinsames ROM, kein Umschaltziel; die Hilfsroutine setzt null auf Bank 1 um. Bei SUROM512 sind nur 1–30 gültig: Eine direkt an das Umschalt-Intrinsic übergebene Konstante außerhalb des Bereichs führt zu einem Buildfehler; ein ungültiger Laufzeitwert wählt 1 und setzt den Mapper-Fehlerzustand. Lesen Sie gemeinsames ROM direkt, statt Bank null anzufordern.
Anwendungsbeispiel
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 02: Das Makro far_call und __farcall rufen den Callback jeweils einmal auf.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\banked_data_calls.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\banked_data_calls.nes --mapper=mmc3 --nes-chr=.\kitaq-docs\samples\font.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/bank.h:36
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
void far_data_read(u8 bank, const void* addr, void* dst, u16 len);Parameter
bankVorzeichenlose 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.
addrNahzeiger auf lesbare Bytes in der gewählten ROM-Bank. Er enthält keine Banknummer.
dstZiel 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.
lenByteanzahl, 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.
FC-Banknummern sind logische Nummern des Compilers. Null bezeichnet gemeinsames ROM, kein Umschaltziel; die Hilfsroutine setzt null auf Bank 1 um. Bei SUROM512 sind nur 1–30 gültig: Eine direkt an das Umschalt-Intrinsic übergebene Konstante außerhalb des Bereichs führt zu einem Buildfehler; ein ungültiger Laufzeitwert wählt 1 und setzt den Mapper-Fehlerzustand. Lesen Sie gemeinsames ROM direkt, statt Bank null anzufordern.
Anwendungsbeispiel
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 02: Das Makro far_call und __farcall rufen den Callback jeweils einmal auf.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\banked_data_calls.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\banked_data_calls.nes --mapper=mmc3 --nes-chr=.\kitaq-docs\samples\font.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/bank.h:24
Copy len bytes from banked ROM to caller-owned writable storage.
kitaqfc/lib/bank.c:32
void far_data_read(u8 bank, const void* addr, void* dst, u16 len)
{
__far_memcpy((u8*)dst, bank, (u16)addr, len);
}far_data_read16
Liest mit __farpeek16 zwei aufeinanderfolgende Bytes als Little-Endian-Wort. Das erste Byte bildet die unteren acht Bits.
Syntax
u16 far_data_read16(u8 bank, const void* addr);Parameter
bankVorzeichenlose 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.
addrNahzeiger 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.
FC-Banknummern sind logische Nummern des Compilers. Null bezeichnet gemeinsames ROM, kein Umschaltziel; die Hilfsroutine setzt null auf Bank 1 um. Bei SUROM512 sind nur 1–30 gültig: Eine direkt an das Umschalt-Intrinsic übergebene Konstante außerhalb des Bereichs führt zu einem Buildfehler; ein ungültiger Laufzeitwert wählt 1 und setzt den Mapper-Fehlerzustand. Lesen Sie gemeinsames ROM direkt, statt Bank null anzufordern.
Anwendungsbeispiel
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 02: Das Makro far_call und __farcall rufen den Callback jeweils einmal auf.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\banked_data_calls.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\banked_data_calls.nes --mapper=mmc3 --nes-chr=.\kitaq-docs\samples\font.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/bank.h:22
Read a 16-bit value through the bank-aware compiler intrinsic.
kitaqfc/lib/bank.c:26
u16 far_data_read16(u8 bank, const void* addr)
{
return __farpeek16(bank, (u16)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
u8 far_data_read8(u8 bank, const void* addr);Parameter
bankVorzeichenlose 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.
addrNahzeiger 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.
FC-Banknummern sind logische Nummern des Compilers. Null bezeichnet gemeinsames ROM, kein Umschaltziel; die Hilfsroutine setzt null auf Bank 1 um. Bei SUROM512 sind nur 1–30 gültig: Eine direkt an das Umschalt-Intrinsic übergebene Konstante außerhalb des Bereichs führt zu einem Buildfehler; ein ungültiger Laufzeitwert wählt 1 und setzt den Mapper-Fehlerzustand. Lesen Sie gemeinsames ROM direkt, statt Bank null anzufordern.
Anwendungsbeispiel
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 02: Das Makro far_call und __farcall rufen den Callback jeweils einmal auf.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\banked_data_calls.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\banked_data_calls.nes --mapper=mmc3 --nes-chr=.\kitaq-docs\samples\font.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/bank.h:20
Read one byte from an explicit ROM bank and 16-bit CPU address.
kitaqfc/lib/bank.c:20
u8 far_data_read8(u8 bank, const void* addr)
{
return __farpeek8(bank, (u16)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
void farptr_make(BankPtr* out, u8 bank, const u8* ptr);Parameter
outZeiger auf beschreibbaren Speicher für einen drei Byte großen BankPtr. Ein Nullzeiger für out führt zu keiner Schreiboperation.
bankVorzeichenlose 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.
ptrIm 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
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 02: Das Makro far_call und __farcall rufen den Callback jeweils einmal auf.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\banked_data_calls.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\banked_data_calls.nes --mapper=mmc3 --nes-chr=.\kitaq-docs\samples\font.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/bank.h:26
Store a bank/address pair without reading memory; null output is ignored.
kitaqfc/lib/bank.c:38
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
void farptr_read(BankPtr ptr, void* dst, u16 len);Parameter
ptrEin BankPtr-Wert mit den Feldern bank und ptr. Übergeben Sie den Deskriptor selbst, nicht seine Adresse. Der Deskriptor des Aufrufers bleibt unverändert.
dstZiel 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.
lenByteanzahl, 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.
FC-Banknummern sind logische Nummern des Compilers. Null bezeichnet gemeinsames ROM, kein Umschaltziel; die Hilfsroutine setzt null auf Bank 1 um. Bei SUROM512 sind nur 1–30 gültig: Eine direkt an das Umschalt-Intrinsic übergebene Konstante außerhalb des Bereichs führt zu einem Buildfehler; ein ungültiger Laufzeitwert wählt 1 und setzt den Mapper-Fehlerzustand. Lesen Sie gemeinsames ROM direkt, statt Bank null anzufordern.
Anwendungsbeispiel
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 02: Das Makro far_call und __farcall rufen den Callback jeweils einmal auf.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\banked_data_calls.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\banked_data_calls.nes --mapper=mmc3 --nes-chr=.\kitaq-docs\samples\font.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/bank.h:32
Copy len bytes from a far pointer; the caller provides a sufficiently large destination.
kitaqfc/lib/bank.c:58
void farptr_read(BankPtr ptr, void* dst, u16 len)
{
__far_memcpy((u8*)dst, ptr.bank, (u16)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
u16 farptr_read16(BankPtr ptr);Parameter
ptrEin 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.
FC-Banknummern sind logische Nummern des Compilers. Null bezeichnet gemeinsames ROM, kein Umschaltziel; die Hilfsroutine setzt null auf Bank 1 um. Bei SUROM512 sind nur 1–30 gültig: Eine direkt an das Umschalt-Intrinsic übergebene Konstante außerhalb des Bereichs führt zu einem Buildfehler; ein ungültiger Laufzeitwert wählt 1 und setzt den Mapper-Fehlerzustand. Lesen Sie gemeinsames ROM direkt, statt Bank null anzufordern.
Anwendungsbeispiel
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 02: Das Makro far_call und __farcall rufen den Callback jeweils einmal auf.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\banked_data_calls.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\banked_data_calls.nes --mapper=mmc3 --nes-chr=.\kitaq-docs\samples\font.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/bank.h:30
Read a 16-bit value using both components of the far pointer.
kitaqfc/lib/bank.c:52
u16 farptr_read16(BankPtr ptr)
{
return __farpeek16(ptr.bank, (u16)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
u8 farptr_read8(BankPtr ptr);Parameter
ptrEin 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.
FC-Banknummern sind logische Nummern des Compilers. Null bezeichnet gemeinsames ROM, kein Umschaltziel; die Hilfsroutine setzt null auf Bank 1 um. Bei SUROM512 sind nur 1–30 gültig: Eine direkt an das Umschalt-Intrinsic übergebene Konstante außerhalb des Bereichs führt zu einem Buildfehler; ein ungültiger Laufzeitwert wählt 1 und setzt den Mapper-Fehlerzustand. Lesen Sie gemeinsames ROM direkt, statt Bank null anzufordern.
Anwendungsbeispiel
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 02: Das Makro far_call und __farcall rufen den Callback jeweils einmal auf.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\banked_data_calls.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\banked_data_calls.nes --mapper=mmc3 --nes-chr=.\kitaq-docs\samples\font.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/bank.h:28
Read one byte using both the bank and address of the supplied far pointer.
kitaqfc/lib/bank.c:46
u8 farptr_read8(BankPtr ptr)
{
return __farpeek8(ptr.bank, (u16)ptr.ptr);
}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
s16 chain_wrap_delta(u8 target, u8 current, u16 size);Parameter
targetZielkoordinate, 0..size−1.
currentAktuelle Koordinate, 0..size−1.
sizeLä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
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\chain_wrap.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\chain_wrap.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/chain.h:39
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.
kitaqfc/lib/chain.c:103
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 (((u16)delta & 0x8000) != 0) {
if ((u16)(0 - delta) > (u16)half) delta = (s16)(delta + (s16)size);
} else if ((u16)delta > (u16)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
u8 chain_body_init(ChainBody* body, u8* x, u8* y, u8* heading, u8 capacity, u16 width, u16 height);Parameter
bodyZiel-
ChainBody; null wird ignoriert. Übergeben Sie außer bei der Initialisierung einen initialisierten Zustand.xArray der Gelenk-X-Koordinaten.
yArray der Gelenk-Y-Koordinaten.
headingArray der Gelenkrichtungen.
capacityReservierte Array-Länge, 1..255.
widthBreite des umlaufenden Felds, 1..256.
heightHö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
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\chain_body.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\chain_body.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\chain_body.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/chain.h:57
Attach three non-overlapping capacity-byte arrays. Return 1 on success. Invalid storage, zero capacity or dimensions outside 1..256 disable the body.
kitaqfc/lib/chain.c:127
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
u8 chain_body_reset(ChainBody* body, u8 count, u8 head_x, u8 head_y, u8 heading);Parameter
bodyZiel-
ChainBody; null wird ignoriert. Übergeben Sie außer bei der Initialisierung einen initialisierten Zustand.countGelenkanzahl einschließlich Kopf, 1..capacity.
head_xKopf-X-Koordinate, auf die Feldbreite umlaufend abgebildet.
head_yKopf-Y-Koordinate, auf die Feldhöhe umlaufend abgebildet.
headingKopfrichtung 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
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\chain_body.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\chain_body.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\chain_body.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/chain.h:61
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.
kitaqfc/lib/chain.c:143
u8 chain_body_reset(ChainBody* body, u8 count, u8 head_x, u8 head_y, u8 heading)
{
// Cache caller storage once; following math and old-heading propagation
// use these local values. Avoid decoding packed struct pointers per joint.
u8* coord_x;u8* coord_y;u8* directions;u16 width;u16 height;
u8 i;
u8 x;
u8 y;
s16 ox;
s16 oy;
if (body == 0) return 0;
if (count == 0 || count > body->capacity) return 0;
coord_x=body->x;coord_y=body->y;directions=body->heading;
width=body->width;height=body->height;
heading = (u8)(heading & 15);
x = chain_body_wrap((s16)head_x, width);
y = chain_body_wrap((s16)head_y, height);
ox = chain_body_offset_x(heading);
oy = chain_body_offset_y(heading);
i = 0;
while (i < count) {
coord_x[(__safe_index u8)i] = x;
coord_y[(__safe_index u8)i] = y;
directions[(__safe_index u8)i] = heading;
x = chain_body_wrap((s16)((s16)x - ox), width);
y = chain_body_wrap((s16)((s16)y - oy), 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
void chain_body_step(ChainBody* body, u8 head_x, u8 head_y, u8 heading);Parameter
bodyZiel-
ChainBody; null wird ignoriert. Übergeben Sie außer bei der Initialisierung einen initialisierten Zustand.head_xKopf-X-Koordinate, auf die Feldbreite umlaufend abgebildet.
head_yKopf-Y-Koordinate, auf die Feldhöhe umlaufend abgebildet.
headingKopfrichtung 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
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\chain_body.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\chain_body.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\chain_body.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/chain.h:66
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.
kitaqfc/lib/chain.c:175
void chain_body_step(ChainBody* body, u8 head_x, u8 head_y, u8 heading)
{
// Cache caller storage once; following math and old-heading propagation
// use these local values. Avoid decoding packed struct pointers per joint.
u8* coord_x;u8* coord_y;u8* directions;u16 width;u16 height;
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;
coord_x=body->x;coord_y=body->y;directions=body->heading;
width=body->width;height=body->height;
heading = (u8)(heading & 15);
coord_x[0] = chain_body_wrap((s16)head_x, width);
coord_y[0] = chain_body_wrap((s16)head_y, height);
directions[0] = heading;
pull = heading;
i = 1;
while (i < body->count) {
previous = (u8)(i - 1);
old = directions[(__safe_index u8)i];
x = coord_x[(__safe_index u8)i];
y = coord_y[(__safe_index u8)i];
tx = chain_body_wrap((s16)((s16)coord_x[(__safe_index u8)previous] - chain_body_offset_x(pull)), width);
ty = chain_body_wrap((s16)((s16)coord_y[(__safe_index u8)previous] - chain_body_offset_y(pull)), height);
sx = chain_body_correction(chain_wrap_delta(tx, x, width));
sy = chain_body_correction(chain_wrap_delta(ty, y, height));
directions[(__safe_index u8)i] = pull;
coord_x[(__safe_index u8)i] = chain_body_wrap((s16)((s16)x + sx), width);
coord_y[(__safe_index u8)i] = chain_body_wrap((s16)((s16)y + sy), 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
u8 chain_body_grow(ChainBody* body);Parameter
bodyZiel-
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
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\chain_body.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\chain_body.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\chain_body.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/chain.h:69
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.
kitaqfc/lib/chain.c:218
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
void chain_body_clear(ChainBody* body);Parameter
bodyZiel-
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
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\chain_body.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\chain_body.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\chain_body.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/chain.h:71
Remove all joints while retaining caller-owned storage and playfield settings.
kitaqfc/lib/chain.c:233
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
void chain_clear(Chain* chain);Parameter
chainZeiger 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 FC-Version tut bei chain == 0 nichts.
Anwendungsbeispiel
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch_chain.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch_chain.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/chain.h:24
Forget the recorded points without clearing or freeing the backing storage.
kitaqfc/lib/chain.c:16
void chain_clear(Chain* chain)
{
if (chain == 0) return;
chain->count = 0;
chain->head = 0;
}chain_get_count
Liest die Anzahl der aktuell im Verlauf verfügbaren Positionen.
Syntax
u8 chain_get_count(const Chain* chain);Parameter
chainZeiger 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
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch_chain.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch_chain.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/chain.h:33
Return the number of stored points, or zero for a null chain.
kitaqfc/lib/chain.c:66
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
u8 chain_get_segment(const Chain* chain, u8 index, ChainPoint* out);Parameter
chainZeiger auf das initialisierte
Chain-Objekt.indexAlter des Punkts: 0 bezeichnet den neuesten,
count - 1den ältesten noch gespeicherten Punkt.outEigenstä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
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).

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch_chain.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch_chain.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/chain.h:31
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.
kitaqfc/lib/chain.c:42
u8 chain_get_segment(const Chain* chain, u8 index, ChainPoint* out)
{
u8 pos;
// Do not alias out with the backing ring: it is cleared before the requested point is read.
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[(__safe_index u8)pos].x;
out->y = chain->points[(__safe_index u8)pos].y;
return 1;
}chain_init
Verknüpft Speicher mit einem Ringpuffer für Positionsverläufe und beginnt ohne aufgezeichnete Punkte.
Syntax
void chain_init(Chain* chain, ChainPoint* storage, u8 capacity);Parameter
chainZu initialisierendes, beschreibbares
Chain-Objekt.storageArray mit Platz für
capacityEinträge vom TypChainPoint.capacityAnzahl 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 FC-Version tut bei chain == 0 nichts.
Anwendungsbeispiel
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch_chain.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch_chain.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/chain.h:22
Attach caller-owned ring storage and start with no recorded points. The storage must remain valid for the lifetime of the chain.
kitaqfc/lib/chain.c:5
void chain_init(Chain* chain, ChainPoint* storage, u8 capacity)
{
if (chain == 0) return;
// A nonzero capacity requires writable storage for that many complete ChainPoint records.
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
void chain_push_head(Chain* chain, s16 x, s16 y);Parameter
chainZeiger auf das initialisierte
Chain-Objekt.xX-Koordinate des neuen Punkts mit Vorzeichen.
yY-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
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch_chain.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch_chain.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/chain.h:27
Move the ring head backward and store the newest point. Once full, each push replaces the oldest point; zero capacity is a no-op.
kitaqfc/lib/chain.c:25
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 = (u8)(chain->head - 1);
chain->points[(__safe_index u8)chain->head].x = x;
chain->points[(__safe_index u8)chain->head].y = y;
if (chain->count < chain->capacity) chain->count = (u8)(chain->count + 1);
}collision.h — Kollisionstests für Rechtecke und andere Formen
Prüft Rechteck/Rechteck- und Rechteck/Punkt-Überlappungen in FC-Weltkoordinaten mit vorzeichenlosen 16-Bit-Positionen.
nes_box16_contains_point
Prüft, ob ein Punkt innerhalb eines FC-Rechtecks liegt. Die linke und obere Kante zählen dazu, die rechte und untere nicht.
Syntax
unsigned char nes_box16_contains_point(struct NesBox16* box, unsigned short px, unsigned short py);Parameter
boxLesbares
NesBox16; übergeben Sie keinen Nullzeiger.pxX-Koordinate des Punkts als vorzeichenloser 16-Bit-Wert.
pyY-Koordinate des Punkts als vorzeichenloser 16-Bit-Wert.
Rückgabewert
Gibt innerhalb 1 zurück, außerhalb 0.
Bedingungen und Grenzen
x, y sind vorzeichenlose 16-Bit-Koordinaten; Breite und Höhe sind Byte-Werte. Verwenden Sie positive Abmessungen und halten Sie die Summen aus Koordinate und Abmessung bei höchstens 65535. Rechtecke über einen Koordinatenüberlauf hinweg werden nicht unterstützt.
Anwendungsbeispiel
result[6]=nes_box16_contains_point(&na,9,1);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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch_geometry.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch_geometry.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/collision.h:18
Test a half-open box: left/top edges are included and right/bottom edges excluded. Callers provide valid pointers and non-overflowing edge coordinates.
kitaqfc/lib/collision.c:49
unsigned char nes_box16_contains_point(struct NesBox16* box, unsigned short px, unsigned short py)
{
unsigned short right;
unsigned short bottom;
right = (unsigned short)(box->x + box->w);
bottom = (unsigned short)(box->y + box->h);
if (px < box->x)
{
return 0;
}
if (py < box->y)
{
return 0;
}
if (px >= right)
{
return 0;
}
if (py >= bottom)
{
return 0;
}
return 1;
}nes_box16_intersects
Prüft, ob sich zwei per Zeiger übergebene FC-Rechtecke mit einer Fläche größer als null überlappen.
Syntax
unsigned char nes_box16_intersects(struct NesBox16* a, struct NesBox16* b);Parameter
aErstes lesbares
NesBox16; übergeben Sie keinen Nullzeiger.bZweites lesbares
NesBox16.
Rückgabewert
Gibt bei Überlappung 1 zurück, bei getrennten Rechtecken oder bloßer Kantenberührung 0.
Bedingungen und Grenzen
x, y sind vorzeichenlose 16-Bit-Koordinaten; Breite und Höhe sind Byte-Werte. Verwenden Sie positive Abmessungen und halten Sie die Summen aus Koordinate und Abmessung bei höchstens 65535. Rechtecke über einen Koordinatenüberlauf hinweg werden nicht unterstützt.
Anwendungsbeispiel
result[5]=nes_box16_intersects(&na,&nb);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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch_geometry.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch_geometry.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/collision.h:15
Test two axis-aligned world boxes using exclusive right/bottom edges. Coordinate-plus-size sums must fit u16; touching edges return false. Both boxes must have positive dimensions; the overlap test has no separate empty-box guard.
kitaqfc/lib/collision.c:15
unsigned char nes_box16_intersects(struct NesBox16* a, struct NesBox16* b)
{
unsigned short a_right;
unsigned short b_right;
unsigned short a_bottom;
unsigned short b_bottom;
a_right = (unsigned short)(a->x + a->w);
b_right = (unsigned short)(b->x + b->w);
a_bottom = (unsigned short)(a->y + a->h);
b_bottom = (unsigned short)(b->y + b->h);
if (a_right <= b->x)
{
return 0;
}
if (b_right <= a->x)
{
return 0;
}
if (a_bottom <= b->y)
{
return 0;
}
if (b_bottom <= a->y)
{
return 0;
}
return 1;
}danmaku — Pool mit 64 Geschossen
danmaku ist ein Festkommapool für 64 Geschosse. Initialisieren Sie ihn, erzeugen Sie Geschosse, rufen Sie step für Bewegung und Kollisionen sowie draw zum Aufbau von OAM auf und führen Sie anschließend DMA während VBlank aus. Spielereingaben, Schaden, Punkte und Audio behandelt der Spielcode. Das Beispiel lädt eine eigens gestaltete Rautenkachel ins CHR-RAM; die Bibliothek kann auch Sprites aus CHR-ROM verwenden.
danmaku_reset
Deaktiviert alle Geschosse und setzt Treffer- und Streifereignisse, Höchst- und Gesamtzähler sowie die Zeiger für Vergabe und Zeichenreihenfolge zurück.
Syntax
void danmaku_reset(void);Rückgabewert
Kein Rückgabewert.
Bedingungen und Grenzen
Spielerposition und dm_invulnerable bleiben erhalten. OAM und Anzeige werden nicht gelöscht. Um sichtbare Geschosse zu entfernen, zeichnen Sie den leeren Pool und führen DMA aus oder blenden die OAM-Einträge separat aus.
Reservieren Sie beschreibbares PRG-RAM der Cartridge bei $6000–$627F (640 Bytes) für 64 Geschosse. Aktivieren Sie dieses RAM im Cartridge-Mapper. Aufgrund des gemeinsam genutzten Zustands ist die Bibliothek nicht reentrant.
dm_count ist die Anzahl aktiver Geschosse, dm_peak deren bisheriger Höchststand. Die 16-Bit-Zähler dm_spawned und dm_rejected zählen erfolgreiche bzw. fehlgeschlagene Erzeugungsversuche und laufen nach 65535 auf null über. dm_x und dm_y sind die Mittelpunktkoordinaten. Ignorieren Sie diese Werte, wenn dm_active null ist.
KUROSAKI prüft vier Compilerkonfigurationen auf sämtliche Pixel, Geschossanzahl und -positionen, reserviertes OAM und wechselnde Zeichenreihenfolge. Separate numerische Prüfungen decken Treffer, Streifkontakte, das Entfernen außerhalb des Bildschirms und einen vollen Pool ab. Tests auf echter Hardware wurden nicht durchgeführt.
Anwendungsbeispiel
danmaku_reset();Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Die vier gelben Geschosse links haben sich von (48,64) aus jeweils 16 Pixel nach oben, unten, links und rechts bewegt. Die sechzehn gelben Geschosse rechts bilden einen Ring etwa 32 Pixel um (160,104). Der cyanfarbene Spieler bei (112,192) belegt den reservierten OAM-Platz null. Das Beispiel hält das Bild nach sechzehn Logikaktualisierungen fest.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\danmaku_patterns.c -I .\kitaqfc\lib --mapper=nrom --nes-chr-ram -o .\out\danmaku_patterns.nes --no-cache --no-disasm
.\kurosaki\kurosaki.exe run .\out\danmaku_patterns.nes --headless --frames 180 --png .\out\danmaku_patterns.pngImplementierung und Quelltext
kitaqfc/lib/danmaku.h:26
Reset the pool, counters and rotating OAM priority. Player settings survive.
kitaqfc/lib/danmaku.c:40
void danmaku_reset(void) {
danmaku_clear();
dm_peak=0;dm_spawned=0;dm_rejected=0;dm_cursor=0;dm_draw_phase=0;
}danmaku_clear
Deaktiviert alle Geschosse und setzt dm_count, dm_hit und dm_graze auf null. Damit entfernen Sie Geschosse während des Spiels.
Syntax
void danmaku_clear(void);Rückgabewert
Kein Rückgabewert.
Bedingungen und Grenzen
Behält dm_peak, dm_spawned, dm_rejected, die Zeiger für Vergabe und Zeichenreihenfolge sowie die Spielereinstellungen bei. Das Beispiel erzeugt ein Geschoss und entfernt es wieder: Die aktive Anzahl wird null, die Gesamtzahl erzeugter Geschosse bleibt eins. Aktualisieren Sie OAM separat.
Reservieren Sie beschreibbares PRG-RAM der Cartridge bei $6000–$627F (640 Bytes) für 64 Geschosse. Aktivieren Sie dieses RAM im Cartridge-Mapper. Aufgrund des gemeinsam genutzten Zustands ist die Bibliothek nicht reentrant.
dm_count ist die Anzahl aktiver Geschosse, dm_peak deren bisheriger Höchststand. Die 16-Bit-Zähler dm_spawned und dm_rejected zählen erfolgreiche bzw. fehlgeschlagene Erzeugungsversuche und laufen nach 65535 auf null über. dm_x und dm_y sind die Mittelpunktkoordinaten. Ignorieren Sie diese Werte, wenn dm_active null ist.
KUROSAKI prüft vier Compilerkonfigurationen auf sämtliche Pixel, Geschossanzahl und -positionen, reserviertes OAM und wechselnde Zeichenreihenfolge. Separate numerische Prüfungen decken Treffer, Streifkontakte, das Entfernen außerhalb des Bildschirms und einen vollen Pool ab. Tests auf echter Hardware wurden nicht durchgeführt.
Anwendungsbeispiel
danmaku_clear();Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Die vier gelben Geschosse links haben sich von (48,64) aus jeweils 16 Pixel nach oben, unten, links und rechts bewegt. Die sechzehn gelben Geschosse rechts bilden einen Ring etwa 32 Pixel um (160,104). Der cyanfarbene Spieler bei (112,192) belegt den reservierten OAM-Platz null. Das Beispiel hält das Bild nach sechzehn Logikaktualisierungen fest.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\danmaku_patterns.c -I .\kitaqfc\lib --mapper=nrom --nes-chr-ram -o .\out\danmaku_patterns.nes --no-cache --no-disasm
.\kurosaki\kurosaki.exe run .\out\danmaku_patterns.nes --headless --frames 180 --png .\out\danmaku_patterns.pngImplementierung und Quelltext
kitaqfc/lib/danmaku.h:28
Remove all bullets and step events; preserve lifetime/peak counters.
kitaqfc/lib/danmaku.c:35
void danmaku_clear(void) {
u8 i;
for(i=0;i<64;i++)dm_active[i]=0;
dm_count=0;dm_hit=0;dm_graze=0;
}danmaku_spawn
Sucht zyklisch einen freien Poolplatz und initialisiert Position, Geschwindigkeit und den Zustand „noch kein Streifkontakt“. Die Erzeugung allein bewegt das Geschoss nicht und prüft keine Kollisionen.
Syntax
u8 danmaku_spawn(u8 x, u8 y, s8 vx, s8 vy);Parameter
xHorizontale Mittelpunktkoordinate in Pixeln; zulässig sind 8 bis 247.
yVertikale Mittelpunktkoordinate in Pixeln; zulässig sind 24 bis 231.
vxHorizontale Geschwindigkeit im vorzeichenbehafteten Q4.4-Format. 16 bewegt um ein Pixel pro Aktualisierung, −16 um ein Pixel in die Gegenrichtung. Die Werte −128 bis 127 stehen für −8 bis +7,9375 Pixel.
vyVertikale Geschwindigkeit im vorzeichenbehafteten Q4.4-Format. 16 bewegt um ein Pixel pro Aktualisierung, −16 um ein Pixel in die Gegenrichtung. Die Werte −128 bis 127 stehen für −8 bis +7,9375 Pixel.
Rückgabewert
Gibt bei Erfolg 1 zurück, bei ungültiger Position oder vollem Pool mit 64 Plätzen dagegen 0. Erfolg erhöht dm_count und dm_spawned und aktualisiert bei Bedarf dm_peak. Ein Fehlschlag erhöht dm_rejected.
Bedingungen und Grenzen
Reservieren Sie beschreibbares PRG-RAM der Cartridge bei $6000–$627F (640 Bytes) für 64 Geschosse. Aktivieren Sie dieses RAM im Cartridge-Mapper. Aufgrund des gemeinsam genutzten Zustands ist die Bibliothek nicht reentrant.
dm_count ist die Anzahl aktiver Geschosse, dm_peak deren bisheriger Höchststand. Die 16-Bit-Zähler dm_spawned und dm_rejected zählen erfolgreiche bzw. fehlgeschlagene Erzeugungsversuche und laufen nach 65535 auf null über. dm_x und dm_y sind die Mittelpunktkoordinaten. Ignorieren Sie diese Werte, wenn dm_active null ist.
KUROSAKI prüft vier Compilerkonfigurationen auf sämtliche Pixel, Geschossanzahl und -positionen, reserviertes OAM und wechselnde Zeichenreihenfolge. Separate numerische Prüfungen decken Treffer, Streifkontakte, das Entfernen außerhalb des Bildschirms und einen vollen Pool ab. Tests auf echter Hardware wurden nicht durchgeführt.
Anwendungsbeispiel
danmaku_spawn(48,64,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 vier gelben Geschosse links haben sich von (48,64) aus jeweils 16 Pixel nach oben, unten, links und rechts bewegt. Die sechzehn gelben Geschosse rechts bilden einen Ring etwa 32 Pixel um (160,104). Der cyanfarbene Spieler bei (112,192) belegt den reservierten OAM-Platz null. Das Beispiel hält das Bild nach sechzehn Logikaktualisierungen fest.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\danmaku_patterns.c -I .\kitaqfc\lib --mapper=nrom --nes-chr-ram -o .\out\danmaku_patterns.nes --no-cache --no-disasm
.\kurosaki\kurosaki.exe run .\out\danmaku_patterns.nes --headless --frames 180 --png .\out\danmaku_patterns.pngImplementierung und Quelltext
kitaqfc/lib/danmaku.h:31
Allocate a bullet at pixel-center x/y with signed 1/16-pixel velocities. Return one on success, zero outside the playfield or when all 64 slots are full.
kitaqfc/lib/danmaku.c:44
u8 danmaku_spawn(u8 x,u8 y,s8 vx,s8 vy) {
u8 i,n;
if(x<8 || x>=248 || y<24 || y>=232){dm_rejected++;return 0;}
i=dm_cursor;
for(n=0;n<64;n++) {
if(dm_active[i]==0) {
dm_x[i]=x;dm_y[i]=y;dm_fraction_x[i]=0;dm_fraction_y[i]=0;
// Expand signed Q4.4 to a two-byte two's-complement Q8.8 step.
dm_vx_integer[i]=(u8)((s16)vx>>4);dm_vx_fraction[i]=(u8)((u8)vx<<4);
dm_vy_integer[i]=(u8)((s16)vy>>4);dm_vy_fraction[i]=(u8)((u8)vy<<4);
dm_grazed[i]=0;dm_active[i]=1;dm_cursor=(u8)((i+1)&63);
dm_count++;if(dm_count>dm_peak)dm_peak=dm_count;
dm_spawned++;return 1;
}
i=(u8)((i+1)&63);
}
dm_rejected++;return 0;
}danmaku_fan
Erzeugt Geschosse mit jeweils festem Richtungszuwachs. Schrittweite und Anzahl ermöglichen einen Fächer oder einen vollständigen Ring.
Syntax
void danmaku_fan(u8 x, u8 y, u8 direction, u8 step, u8 count, u8 speed);Parameter
xHorizontale Mittelpunktkoordinate in Pixeln; zulässig sind 8 bis 247.
yVertikale Mittelpunktkoordinate in Pixeln; zulässig sind 24 bis 231.
directionAnfangsrichtung in 32 Schritten pro Umdrehung: 0 rechts, 8 unten, 16 links, 24 oben. Es werden nur die unteren fünf Bits verwendet.
stepRichtungszuwachs nach jedem Geschoss, umlaufend modulo 32. Bei null fliegen alle Geschosse in dieselbe Richtung.
countAnzahl der Erzeugungsversuche. Werte über 64 werden auf 64 begrenzt; null bewirkt nichts.
speedGeschwindigkeitsbetrag in Sechzehntelpixeln pro Aktualisierung: 16 entspricht einem Pixel, 32 zwei Pixeln. Werte über 64 werden auf 64 begrenzt.
Rückgabewert
Kein Rückgabewert.
Bedingungen und Grenzen
Die Geschwindigkeiten stammen aus einer ganzzahligen Sinustabelle und werden gegen null abgeschnitten. Diagonale Geschwindigkeiten und Radien sind daher quantisiert. Ein voller Pool bricht die restlichen Versuche nicht ab; jeder Fehlschlag erhöht dm_rejected.
Reservieren Sie beschreibbares PRG-RAM der Cartridge bei $6000–$627F (640 Bytes) für 64 Geschosse. Aktivieren Sie dieses RAM im Cartridge-Mapper. Aufgrund des gemeinsam genutzten Zustands ist die Bibliothek nicht reentrant.
dm_count ist die Anzahl aktiver Geschosse, dm_peak deren bisheriger Höchststand. Die 16-Bit-Zähler dm_spawned und dm_rejected zählen erfolgreiche bzw. fehlgeschlagene Erzeugungsversuche und laufen nach 65535 auf null über. dm_x und dm_y sind die Mittelpunktkoordinaten. Ignorieren Sie diese Werte, wenn dm_active null ist.
KUROSAKI prüft vier Compilerkonfigurationen auf sämtliche Pixel, Geschossanzahl und -positionen, reserviertes OAM und wechselnde Zeichenreihenfolge. Separate numerische Prüfungen decken Treffer, Streifkontakte, das Entfernen außerhalb des Bildschirms und einen vollen Pool ab. Tests auf echter Hardware wurden nicht durchgeführt.
Anwendungsbeispiel
danmaku_fan(160,104,0,2,16,32);Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Die vier gelben Geschosse links haben sich von (48,64) aus jeweils 16 Pixel nach oben, unten, links und rechts bewegt. Die sechzehn gelben Geschosse rechts bilden einen Ring etwa 32 Pixel um (160,104). Der cyanfarbene Spieler bei (112,192) belegt den reservierten OAM-Platz null. Das Beispiel hält das Bild nach sechzehn Logikaktualisierungen fest.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\danmaku_patterns.c -I .\kitaqfc\lib --mapper=nrom --nes-chr-ram -o .\out\danmaku_patterns.nes --no-cache --no-disasm
.\kurosaki\kurosaki.exe run .\out\danmaku_patterns.nes --headless --frames 180 --png .\out\danmaku_patterns.pngImplementierung und Quelltext
kitaqfc/lib/danmaku.h:34
Emit up to 64 bullets. Angles wrap in 32 steps: 0 right, 8 down, 16 left, 24 up. Speed is in 1/16 pixel, clamped to 64. Each failed allocation counts.
kitaqfc/lib/danmaku.c:62
void danmaku_fan(u8 x,u8 y,u8 direction,u8 step,u8 count,u8 speed) {
u8 i,angle;s16 vx,vy;
if(count>64)count=64;if(speed>64)speed=64;
angle=(u8)(direction&31);
for(i=0;i<count;i++) {
vx=(s16)Danmaku_Sin[(u8)((angle+8)&31)]*(s16)speed;
vy=(s16)Danmaku_Sin[angle]*(s16)speed;
danmaku_spawn(x,y,(s8)(vx/64),(s8)(vy/64));
angle=(u8)((angle+step)&31);
}
}danmaku_step
Bewegt jedes aktive Geschoss einmal, entfernt Geschosse außerhalb des Bildschirms und prüft Treffer sowie Streifkontakte am Spieler. Die Geschosszeit schreitet mit den Aufrufen fort, nicht mit der tatsächlich verstrichenen Zeit.
Syntax
void danmaku_step(void);Rückgabewert
Kein Rückgabewert.
Bedingungen und Grenzen
Setzen Sie dm_player_x und dm_player_y vor dem Aufruf auf den Spielermittelpunkt. Nach der Bewegung gilt ein Abstand von höchstens drei Pixeln auf beiden Achsen als Treffer. Ist dm_invulnerable null, wird dm_hit auf eins gesetzt und das Geschoss entfernt. Bei Unverwundbarkeit bleibt es aktiv.
Außerhalb des Trefferbereichs ergibt ein Abstand von höchstens elf Pixeln auf beiden Achsen einmal pro Geschoss einen Streifkontakt. dm_hit und dm_graze werden beim Eintritt zurückgesetzt und beschreiben nur diese Aktualisierung. Ein Geschoss im Trefferbereich zählt bei unverwundbarem Spieler nicht als Streifkontakt.
Diese Funktion schreibt weder OAM noch ruft sie Schadens- oder Sound-Callbacks auf. Lesen Sie dm_hit und dm_graze aus und aktualisieren Sie Spielerzustand oder Punktestand im Spielcode.
Reservieren Sie beschreibbares PRG-RAM der Cartridge bei $6000–$627F (640 Bytes) für 64 Geschosse. Aktivieren Sie dieses RAM im Cartridge-Mapper. Aufgrund des gemeinsam genutzten Zustands ist die Bibliothek nicht reentrant.
dm_count ist die Anzahl aktiver Geschosse, dm_peak deren bisheriger Höchststand. Die 16-Bit-Zähler dm_spawned und dm_rejected zählen erfolgreiche bzw. fehlgeschlagene Erzeugungsversuche und laufen nach 65535 auf null über. dm_x und dm_y sind die Mittelpunktkoordinaten. Ignorieren Sie diese Werte, wenn dm_active null ist.
KUROSAKI prüft vier Compilerkonfigurationen auf sämtliche Pixel, Geschossanzahl und -positionen, reserviertes OAM und wechselnde Zeichenreihenfolge. Separate numerische Prüfungen decken Treffer, Streifkontakte, das Entfernen außerhalb des Bildschirms und einen vollen Pool ab. Tests auf echter Hardware wurden nicht durchgeführt.
Anwendungsbeispiel
danmaku_step();Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Die vier gelben Geschosse links haben sich von (48,64) aus jeweils 16 Pixel nach oben, unten, links und rechts bewegt. Die sechzehn gelben Geschosse rechts bilden einen Ring etwa 32 Pixel um (160,104). Der cyanfarbene Spieler bei (112,192) belegt den reservierten OAM-Platz null. Das Beispiel hält das Bild nach sechzehn Logikaktualisierungen fest.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\danmaku_patterns.c -I .\kitaqfc\lib --mapper=nrom --nes-chr-ram -o .\out\danmaku_patterns.nes --no-cache --no-disasm
.\kurosaki\kurosaki.exe run .\out\danmaku_patterns.nes --headless --frames 180 --png .\out\danmaku_patterns.pngImplementierung und Quelltext
kitaqfc/lib/danmaku.h:38
Move all live bullets once. Remove offscreen/hitting bullets. Hit uses a +/-3-pixel box; graze uses +/-11, once per bullet. Events describe this step. This updates logic only; it neither writes OAM nor calls a game damage handler.
kitaqfc/lib/danmaku.c:73
void danmaku_step(void) {
// Byte arrays let the 6502 move every slot without multiplying a structure
// index. Carry propagates fractional motion into the signed integer step.
__asm {
LDX #0
STX dm_count
STX dm_hit
STX dm_graze
dm_tick_loop:
LDA dm_active,X
BNE dm_tick_live
JMP dm_tick_next
dm_tick_live:
CLC
LDA dm_fraction_x,X
ADC dm_vx_fraction,X
STA dm_fraction_x,X
LDA dm_x,X
ADC dm_vx_integer,X
STA dm_x,X
CMP #8
BCC dm_tick_kill
CMP #248
BCS dm_tick_kill
CLC
LDA dm_fraction_y,X
ADC dm_vy_fraction,X
STA dm_fraction_y,X
LDA dm_y,X
ADC dm_vy_integer,X
STA dm_y,X
CMP #24
BCC dm_tick_kill
CMP #232
BCS dm_tick_kill
// Unsigned absolute distances avoid false collisions across screen wrap.
LDA dm_x,X
SEC
SBC dm_player_x
BCS dm_tick_dx
EOR #255
CLC
ADC #1
dm_tick_dx:
STA dm_distance_x
LDA dm_y,X
SEC
SBC dm_player_y
BCS dm_tick_dy
EOR #255
CLC
ADC #1
dm_tick_dy:
STA dm_distance_y
CMP #4
BCS dm_tick_graze
LDA dm_distance_x
CMP #4
BCS dm_tick_graze
LDA dm_invulnerable
BNE dm_tick_count
LDA #1
STA dm_hit
dm_tick_kill:
LDA #0
STA dm_active,X
JMP dm_tick_next
dm_tick_graze:
LDA dm_grazed,X
BNE dm_tick_count
LDA dm_distance_x
CMP #12
BCS dm_tick_count
LDA dm_distance_y
CMP #12
BCS dm_tick_count
LDA #1
STA dm_grazed,X
INC dm_graze
dm_tick_count:
INC dm_count
dm_tick_next:
INX
CPX #64
BEQ dm_tick_done
JMP dm_tick_loop
dm_tick_done:
}
}danmaku_draw
Erstellt 8×8-Sprites aus den Geschossmittelpunkten und schreibt den angeforderten Bereich des Schatten-OAM, ohne Geschosse zu bewegen oder Kollisionen zu prüfen.
Syntax
u8 danmaku_draw(u8 first_oam, u8 slots, u8 tile, u8 attributes);Parameter
first_oamErster OAM-Platz (0 bis 63). Werte ab 64 geben ohne Schreibzugriff null zurück. Das Beispiel beginnt bei eins, um Platz null für den Spieler freizuhalten.
slotsAnzahl aufeinanderfolgender verfügbarer Plätze, begrenzt auf 64−first_oam. Null schreibt nichts, schaltet die Zeichenpriorität aber dennoch weiter.
tileVon allen Geschossen geteilte 8×8-Musterkachel. Stellen Sie den 8×8-Spritemodus ein; dieser Aufruf verwendet für jedes Geschoss dieselbe Form.
attributesGemeinsame NES-Spriteattribute aller Geschosse: Bits 0–1 Palette, Bit 5 hinter dem Hintergrund, Bit 6 horizontale Spiegelung, Bit 7 vertikale Spiegelung.
Rückgabewert
Gibt die Anzahl ins OAM geschriebener Geschosse zurück: das Minimum aus aktiver Anzahl und verfügbaren Plätzen.
Bedingungen und Grenzen
Verschiebt den anfänglichen Geschossplatz bei jedem Aufruf um 13 modulo 64, damit nicht stets dieselben Geschosse Vorrang haben. Ungenutzte Plätze im angeforderten Bereich werden mit Y=240 ausgeblendet; OAM außerhalb dieses Bereichs bleibt unverändert.
Zieht vier von Mittelpunkt-X und fünf von Mittelpunkt-Y ab. Die Hardware addiert eins zu OAM-Y und zentriert dadurch das Sprite. Rufen Sie __oam_dma selbst während VBlank auf. Die Hardwaregrenze von acht Sprites pro Scanline gilt weiterhin.
Reservieren Sie beschreibbares PRG-RAM der Cartridge bei $6000–$627F (640 Bytes) für 64 Geschosse. Aktivieren Sie dieses RAM im Cartridge-Mapper. Aufgrund des gemeinsam genutzten Zustands ist die Bibliothek nicht reentrant.
dm_count ist die Anzahl aktiver Geschosse, dm_peak deren bisheriger Höchststand. Die 16-Bit-Zähler dm_spawned und dm_rejected zählen erfolgreiche bzw. fehlgeschlagene Erzeugungsversuche und laufen nach 65535 auf null über. dm_x und dm_y sind die Mittelpunktkoordinaten. Ignorieren Sie diese Werte, wenn dm_active null ist.
KUROSAKI prüft vier Compilerkonfigurationen auf sämtliche Pixel, Geschossanzahl und -positionen, reserviertes OAM und wechselnde Zeichenreihenfolge. Separate numerische Prüfungen decken Treffer, Streifkontakte, das Entfernen außerhalb des Bildschirms und einen vollen Pool ab. Tests auf echter Hardware wurden nicht durchgeführt.
Anwendungsbeispiel
bullet_result[9]=danmaku_draw(1,24,1,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 vier gelben Geschosse links haben sich von (48,64) aus jeweils 16 Pixel nach oben, unten, links und rechts bewegt. Die sechzehn gelben Geschosse rechts bilden einen Ring etwa 32 Pixel um (160,104). Der cyanfarbene Spieler bei (112,192) belegt den reservierten OAM-Platz null. Das Beispiel hält das Bild nach sechzehn Logikaktualisierungen fest.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\danmaku_patterns.c -I .\kitaqfc\lib --mapper=nrom --nes-chr-ram -o .\out\danmaku_patterns.nes --no-cache --no-disasm
.\kurosaki\kurosaki.exe run .\out\danmaku_patterns.nes --headless --frames 180 --png .\out\danmaku_patterns.pngImplementierung und Quelltext
kitaqfc/lib/danmaku.h:43
Write up to slots consecutive shadow-OAM entries starting at first_oam. Rotate bullet priority by 13 modulo 64 and hide unused entries in that range. tile is an 8x8 sprite centered at (4,4). Return the number emitted. DMA is caller-owned and belongs in VBlank. Hardware's eight-per-scanline limit remains.
kitaqfc/lib/danmaku.c:162
u8 danmaku_draw(u8 first_oam,u8 slots,u8 tile,u8 attributes) {
u8 i,n,drawn;
if(first_oam>=64)return 0;
if(slots>(u8)(64-first_oam))slots=(u8)(64-first_oam);
dm_draw_phase=(u8)((dm_draw_phase+13)&63);i=dm_draw_phase;drawn=0;
for(n=0;n<64;n++) {
if(dm_active[i]!=0 && drawn<slots) {
__sprite_set((u8)(first_oam+drawn),(u8)(dm_x[i]-4),(u8)(dm_y[i]-5),tile,attributes);
drawn++;
}
i=(u8)((i+1)&63);
}
for(n=drawn;n<slots;n++)__sprite_hide((u8)(first_oam+n));
return drawn;
}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
void debug_assert_fail(u16 code);Parameter
codeZu 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
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch_debug.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch_debug.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/debug.h:36
Store the assertion code even if the log is full, then attempt an ASSERT entry. The helper records failure but does not stop execution.
kitaqfc/lib/debug.c:67
void debug_assert_fail(u16 code)
{
kq_debug_last_assert = code;
debug_push(debug_assert_label, code);
}debug_get_last_assert
Liest den letzten Assertion-Code unabhängig vom verfügbaren Protokollspeicher.
Syntax
u16 debug_get_last_assert(void);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
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch_debug.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch_debug.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/debug.h:42
Read the latest assertion code, initially zero after debug_init.
kitaqfc/lib/debug.c:86
u16 debug_get_last_assert(void)
{
return kq_debug_last_assert;
}debug_get_trace_count
Liest die Anzahl gültiger Einträge im Trace-Array.
Syntax
u8 debug_get_trace_count(void);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
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch_debug.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch_debug.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/debug.h:38
Read the number of valid entries in the fixed trace buffer.
kitaqfc/lib/debug.c:74
u8 debug_get_trace_count(void)
{
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
const DebugTraceEntry* debug_get_trace_log(void);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
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch_debug.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch_debug.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/debug.h:40
Borrow the internal trace array; bound inspection by debug_get_trace_count.
kitaqfc/lib/debug.c:80
const DebugTraceEntry* debug_get_trace_log(void)
{
return kq_debug_trace_log;
}debug_init
Initialisiert die gültige Protokolllänge, die Frame-Kennung und den letzten Assertion-Code.
Syntax
void debug_init(void);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
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch_debug.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch_debug.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/debug.h:25
Build the RAM-resident ASSERT label and reset log length, frame tag and last assertion code. Old log storage bytes are not erased.
kitaqfc/lib/debug.c:14
void debug_init(void)
{
debug_assert_label[0] = 'A';
debug_assert_label[1] = 'S';
debug_assert_label[2] = 'S';
debug_assert_label[3] = 'E';
debug_assert_label[4] = 'R';
debug_assert_label[5] = 'T';
debug_assert_label[6] = 0;
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
void debug_mark_frame(const u8* label);Parameter
labelNullterminierte 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
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch_debug.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch_debug.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/debug.h:29
Append a named marker with the reserved marker value 0xFFFF.
kitaqfc/lib/debug.c:48
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
void debug_set_frame(u16 frame);Parameter
frame16-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
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch_debug.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch_debug.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/debug.h:27
Choose the frame tag stored in subsequent debug entries.
kitaqfc/lib/debug.c:29
void debug_set_frame(u16 frame)
{
kq_debug_frame = frame;
}debug_trace_u16
Protokolliert einen benannten 16-Bit-Punktestand oder Zähler.
Syntax
void debug_trace_u16(const u8* name, u16 value);Parameter
nameNullterminierte Bezeichnung in Speicher, der bis zur Auswertung lesbar bleiben muss.
valueZu 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
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch_debug.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch_debug.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/debug.h:33
Append a 16-bit value with the current frame tag.
kitaqfc/lib/debug.c:60
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
void debug_trace_u8(const u8* name, u8 value);Parameter
nameNullterminierte Bezeichnung in Speicher, der bis zur Auswertung lesbar bleiben muss.
valueWert 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
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch_debug.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch_debug.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/debug.h:31
Widen a byte value into the trace entry's 16-bit value field.
kitaqfc/lib/debug.c:54
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
#define KITAQGB_ASSERT(cond) do { if (!(cond)) debug_assert_fail((u16)1); } while (0)Parameter
condBedingung, 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
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch_debug.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch_debug.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/debug.h:48
#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
#define KITAQGB_ASSERT_CODE(cond, code) do { if (!(cond)) debug_assert_fail((u16)(code)); } while (0)Parameter
condBedingung, die erfüllt sein soll.
codeCode-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
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch_debug.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch_debug.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/debug.h:49
#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
#define KITAQGB_MARK_FRAME(label) debug_mark_frame((const u8*)(label))Parameter
labelNullterminierte 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
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch_debug.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch_debug.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/debug.h:47
#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
#define KITAQGB_TRACE(name, value) debug_trace_u16((const u8*)(name), (u16)(value))Parameter
nameNullterminierte Bezeichnung in Speicher, der bis zur Auswertung lesbar bleiben muss.
valueAusdruck, 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
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch_debug.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch_debug.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/debug.h:46
#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
#define KITAQGB_TRACE_U16(name, value) debug_trace_u16((const u8*)(name), (u16)(value))Parameter
nameNullterminierte Bezeichnung in Speicher, der bis zur Auswertung lesbar bleiben muss.
valueAusdruck, 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
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch_debug.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch_debug.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/debug.h:45
#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
#define KITAQGB_TRACE_U8(name, value) debug_trace_u8((const u8*)(name), (u8)(value))Parameter
nameNullterminierte Bezeichnung in Speicher, der bis zur Auswertung lesbar bleiben muss.
valueAusdruck, 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
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch_debug.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch_debug.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/debug.h:44
#define KITAQGB_TRACE_U8(name, value) debug_trace_u8((const u8*)(name), (u8)(value))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.
Lege den Callback in die gemeinsame PRG-Bank 0 oder halte seine Bank während des gesamten Aufrufs eingeblendet. Ein Funktionszeiger enthält eine 16-Bit-CPU-Adresse und schaltet keine Bank um. Parameter und lokale Variablen der FC-Funktionen belegen feste Speicherbereiche. Rufe den Entity-Durchlauf daher weder rekursiv auf noch erneut aus einem Interrupt, während er bereits läuft.
entity_clear_all
Gibt alle Entities frei und setzt ihre Felder einschließlich der Markierung für fehlende Sprites zurück.
Syntax
void entity_clear_all(void);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
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 FC-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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\entity.c .\kitaq-docs\samples\api-examples\fc\entity_pool.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\entity_pool.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr --no-disasmImplementierung und Quelltext
kitaqfc/lib/entity.h:47
Release every entity and restore deterministic defaults, including the no-sprite sentinel.
kitaqfc/lib/entity.c:14
void entity_clear_all(void)
{
u8 i;
i = 0;
while (i < ENTITY_MAX) {
entity_pool[(__safe_index u8)i].active = 0;
entity_pool[(__safe_index u8)i].type = 0;
entity_pool[(__safe_index u8)i].x = 0;
entity_pool[(__safe_index u8)i].y = 0;
entity_pool[(__safe_index u8)i].vx = 0;
entity_pool[(__safe_index u8)i].vy = 0;
entity_pool[(__safe_index u8)i].state = 0;
entity_pool[(__safe_index u8)i].timer = 0;
entity_pool[(__safe_index u8)i].sprite = 0xFF;
i = (u8)(i + 1);
}
}entity_count_active
Zählt belegte Entity-Plätze, ohne ihren Zustand zu ändern.
Syntax
u8 entity_count_active(void);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
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 FC-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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\entity.c .\kitaq-docs\samples\api-examples\fc\entity_pool.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\entity_pool.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr --no-disasmImplementierung und Quelltext
kitaqfc/lib/entity.h:45
Count occupied slots without changing entity state.
kitaqfc/lib/entity.c:94
u8 entity_count_active(void)
{
u8 i;
u8 count;
i = 0;
count = 0;
while (i < ENTITY_MAX) {
if (entity_pool[(__safe_index u8)i].active != 0) count = (u8)(count + 1);
i = (u8)(i + 1);
}
return count;
}entity_create
Reserviert eine Entity mit Typ und Position; liefert ihre wiederverwendbare ID oder bei vollem Pool 0xFF.
Syntax
u8 entity_create(u8 type, s16 x, s16 y);Parameter
typeVom Spiel definierte Typkennung von 0 bis 255. Der Pool speichert sie, wählt damit aber weder Verhalten noch Zeichenroutinen aus.
x, yVorzeichenbehaftete 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
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 FC-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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\entity.c .\kitaq-docs\samples\api-examples\fc\entity_pool.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\entity_pool.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr --no-disasmImplementierung und Quelltext
kitaqfc/lib/entity.h:32
Returns a reusable slot ID, or 0xFF if no slot is free.
kitaqfc/lib/entity.c:34
u8 entity_create(u8 type, s16 x, s16 y)
{
u8 i;
i = 0;
while (i < ENTITY_MAX) {
if (entity_pool[(__safe_index u8)i].active == 0) {
entity_pool[(__safe_index u8)i].active = 1;
entity_pool[(__safe_index u8)i].type = type;
entity_pool[(__safe_index u8)i].x = x;
entity_pool[(__safe_index u8)i].y = y;
entity_pool[(__safe_index u8)i].vx = 0;
entity_pool[(__safe_index u8)i].vy = 0;
entity_pool[(__safe_index u8)i].state = 0;
entity_pool[(__safe_index u8)i].timer = 0;
entity_pool[(__safe_index u8)i].sprite = 0xFF;
return i;
}
i = (u8)(i + 1);
}
return 0xFF;
}entity_destroy
Gibt den Platz von Entity id frei; die Nutzdaten werden erst bei erneuter Belegung zurückgesetzt.
Syntax
void entity_destroy(u8 id);Parameter
idWiederverwendbarer 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
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 FC-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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\entity.c .\kitaq-docs\samples\api-examples\fc\entity_pool.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\entity_pool.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr --no-disasmImplementierung und Quelltext
kitaqfc/lib/entity.h:35
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.
kitaqfc/lib/entity.c:58
void entity_destroy(u8 id)
{
if (id >= ENTITY_MAX) return;
entity_pool[(__safe_index u8)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
void entity_draw_all(EntityFn fn);Parameter
fnFunktionszeiger mit Signatur
void fn(u8 id). Er erhält eine Platz-ID; auf Felder greifen Sie überentity_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.
Lege den Callback in die gemeinsame PRG-Bank 0 oder halte seine Bank während des gesamten Aufrufs eingeblendet. Ein Funktionszeiger enthält eine 16-Bit-CPU-Adresse und schaltet keine Bank um. Parameter und lokale Variablen der FC-Funktionen belegen feste Speicherbereiche. Rufe den Entity-Durchlauf daher weder rekursiv auf noch erneut aus einem Interrupt, während er bereits läuft.
Anwendungsbeispiel
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 FC-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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\entity.c .\kitaq-docs\samples\api-examples\fc\entity_pool.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\entity_pool.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr --no-disasmImplementierung und Quelltext
kitaqfc/lib/entity.h:43
Call the drawing callback for each active slot, using the same traversal rules as update. The callback submits drawing data; the pool does not allocate sprites.
kitaqfc/lib/entity.c:88
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
Entity* entity_get(u8 id);Parameter
idWiederverwendbarer 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
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 FC-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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\entity.c .\kitaq-docs\samples\api-examples\fc\entity_pool.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\entity_pool.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr --no-disasmImplementierung und Quelltext
kitaqfc/lib/entity.h:37
Returns null for an invalid or inactive ID; the returned pointer aliases reusable pool storage.
kitaqfc/lib/entity.c:66
Entity* entity_get(u8 id)
{
if (id >= ENTITY_MAX) return 0;
if (entity_pool[(__safe_index u8)id].active == 0) return 0;
return &entity_pool[(__safe_index u8)id];
}entity_init
Initialisiert alle Plätze im Entity-Pool.
Syntax
void entity_init(void);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
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 FC-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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\entity.c .\kitaq-docs\samples\api-examples\fc\entity_pool.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\entity_pool.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr --no-disasmImplementierung und Quelltext
kitaqfc/lib/entity.h:30
Reset every slot before the game starts using the pool.
kitaqfc/lib/entity.c:8
void entity_init(void)
{
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
void entity_update_all(EntityFn fn);Parameter
fnFunktionszeiger mit Signatur
void fn(u8 id). Er erhält eine Platz-ID; auf Felder greifen Sie überentity_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.
Lege den Callback in die gemeinsame PRG-Bank 0 oder halte seine Bank während des gesamten Aufrufs eingeblendet. Ein Funktionszeiger enthält eine 16-Bit-CPU-Adresse und schaltet keine Bank um. Parameter und lokale Variablen der FC-Funktionen belegen feste Speicherbereiche. Rufe den Entity-Durchlauf daher weder rekursiv auf noch erneut aus einem Interrupt, während er bereits läuft.
Anwendungsbeispiel
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 FC-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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\entity.c .\kitaq-docs\samples\api-examples\fc\entity_pool.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\entity_pool.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr --no-disasmImplementierung und Quelltext
kitaqfc/lib/entity.h:40
Call fn(id) for each active slot in ascending order. A null callback does nothing. Changes to later slots take effect during the same traversal. Do not reenter this traversal.
kitaqfc/lib/entity.c:75
void entity_update_all(EntityFn fn)
{
u8 i;
if (fn == 0) return;
i = 0;
while (i < ENTITY_MAX) {
if (entity_pool[(__safe_index u8)i].active != 0) fn(i);
i = (u8)(i + 1);
}
}FDS-Dateien und Speicherplätze fester Größe
fds_file.h bietet das Laden von Dateien in Spielpuffer und das Schreiben in einen reservierten Speicherplatz auf Diskette. fds_save.h bindet dieselben Deklarationen ein. Verwenden Sie fds_overlay.h für Aufrufe von Overlay-Code.
__fds_load_file() / __fds_save_file()
fds_file_io.c fds_file_io_manifest.json fds_file_io_payload.bin
fds_sound.h
Deklariert Compiler-Intrinsics für 64-stufige Wellenform, Modulationstabelle, Tonhöhe, Lautstärke und Hüllkurven. KITAQFC erzeugt ihre Implementierungen.
Erstellen Sie mit --mapper=fds ein .fds-Abbild. Diese Lektion verwendet Sound ohne Datenträger-I/O. Die Aufnahme nutzt KUROSAKIs direkten RAM-Start und Audiomodell. Die leere Testfirmware implementiert keine BIOS-Routinen und wird nicht verteilt. Normaler Diskettenstart und echte Hardware benötigen eine passende Startumgebung.
Funktionsreferenz: __fds_sound_enable, __fds_wave_load, __fds_mod_load, __fds_freq_set, __fds_volume_set, __fds_env_set
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
fix8 fix_div(fix8 a, fix8 b);Parameter
aLinker Operand im Q8.8-Format.
bRechter 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
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch_math.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch_math.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/fixed.h:35
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.
kitaqfc/lib/fixed.c:26
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
fix8 fix_from_int(s16 n);Parameter
nDie 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
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch_math.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch_math.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/fixed.h:26
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.
kitaqfc/lib/fixed.c:5
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
fix8 fix_lerp(fix8 a, fix8 b, u8 t_q8);Parameter
aLinker Operand im Q8.8-Format.
bRechter Operand im Q8.8-Format.
t_q8Interpolationsgewicht 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
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch_math.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch_math.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/fixed.h:38
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.
kitaqfc/lib/fixed.c:34
fix8 fix_lerp(fix8 a, fix8 b, u8 t_q8)
{
fix8 d;
// The endpoint difference must fit s16 before the reduced-precision interpolation.
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
fix8 fix_mul(fix8 a, fix8 b);Parameter
aLinker Operand im Q8.8-Format.
bRechter 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
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch_math.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch_math.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/fixed.h:31
Approximate 8.8 multiplication by discarding four low bits from each operand before multiplying. This trades precision for a smaller intermediate product.
kitaqfc/lib/fixed.c:18
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
s16 fix_to_int(fix8 x);Parameter
xDer 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
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch_math.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch_math.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/fixed.h:28
Discard the eight fractional bits using a signed right shift.
kitaqfc/lib/fixed.c:11
s16 fix_to_int(fix8 x)
{
return (s16)(x >> 8);
}kq_abs_s16
Ermittelt den Betrag eines vorzeichenbehafteten 16-Bit-Werts.
Syntax
s16 kq_abs_s16(s16 v);Parameter
vVorzeichenbehafteter 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
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch_math_limits.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch_math_limits.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/fixed.h:41
Return the magnitude in s16. The most-negative s16 has no positive s16 representation and must be excluded by callers needing a nonnegative result.
kitaqfc/lib/fixed.c:44
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
s16 kq_clamp_s16(s16 v, s16 lo, s16 hi);Parameter
vZu begrenzender Wert mit Vorzeichen.
loEinschließlich geltende Untergrenze.
hiEinschließ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
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch_math_limits.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch_math_limits.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/fixed.h:47
Clamp to an inclusive interval; callers must provide lo <= hi.
kitaqfc/lib/fixed.c:65
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
s16 kq_max_s16(s16 a, s16 b);Parameter
aErster zu vergleichender Wert mit Vorzeichen.
bZweiter 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
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch_math_limits.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch_math_limits.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/fixed.h:45
Select the larger signed value.
kitaqfc/lib/fixed.c:58
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
s16 kq_min_s16(s16 a, s16 b);Parameter
aErster zu vergleichender Wert mit Vorzeichen.
bZweiter 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
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch_math_limits.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch_math_limits.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/fixed.h:43
Select the smaller signed value.
kitaqfc/lib/fixed.c:51
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
u8 kq_point_in_rect(s16 x, s16 y, KQRect r);Parameter
xX-Koordinate des Punkts im Koordinatensystem des Rechtecks.
yY-Koordinate des Punkts.
rZu 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
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);__vramq_commit();__vramq_exec();
}}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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch_geometry.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch_geometry.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/fixed.h:54
Test a half-open rectangle: left/top edges are included, right/bottom excluded. The coordinate-plus-size sums must remain representable as s16.
kitaqfc/lib/fixed.c:86
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
u8 kq_rect_intersect(KQRect a, KQRect b);Parameter
aErstes Rechteck, als Wert übergeben:
x, ygeben die linke obere Ecke an,w, hseine Breite und Höhe.bZweites 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
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch_geometry.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch_geometry.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/fixed.h:51
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.
kitaqfc/lib/fixed.c:75
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.
Liest Controller 1 mit __pad_read1_safe, ordnet die NES-Bits in das gemeinsame BTN_*-Format um, speichert den vorherigen Zustand und berechnet Druck-, Loslass- und Wiederholungsmasken. Controller 2 wird nicht erfasst. Einmal pro Eingabetakt aufrufen.
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
u8 btn_down(u8 mask);Parameter
maskEine
BTN_*-Maske oder mehrere mit|verknüpfte Masken. Eine einzige passende Taste genügt;BTN_A | BTN_Bverlangt 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.
Anwendungsbeispiel
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\input.c .\kitaq-docs\samples\api-examples\fc\input_aliases.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\input_aliases.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr --no-disasm --no-cacheImplementierung und Quelltext
kitaqfc/lib/input.h:53
#define btn_down input_downkitaqfc/lib/input.c:85
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
u8 btn_pressed(u8 mask);Parameter
maskEine
BTN_*-Maske oder mehrere mit|verknüpfte Masken. Eine einzige passende Taste genügt;BTN_A | BTN_Bverlangt 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.
Anwendungsbeispiel
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\input.c .\kitaq-docs\samples\api-examples\fc\input_aliases.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\input_aliases.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr --no-disasm --no-cacheImplementierung und Quelltext
kitaqfc/lib/input.h:54
#define btn_pressed input_pressedkitaqfc/lib/input.c:87
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
u8 btn_released(u8 mask);Parameter
maskEine
BTN_*-Maske oder mehrere mit|verknüpfte Masken. Eine einzige passende Taste genügt;BTN_A | BTN_Bverlangt 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.
Anwendungsbeispiel
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\input.c .\kitaq-docs\samples\api-examples\fc\input_aliases.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\input_aliases.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr --no-disasm --no-cacheImplementierung und Quelltext
kitaqfc/lib/input.h:55
#define btn_released input_releasedkitaqfc/lib/input.c:89
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
u8 btn_repeat(u8 mask);Parameter
maskEine
BTN_*-Maske oder mehrere mit|verknüpfte Masken. Eine einzige passende Taste genügt;BTN_A | BTN_Bverlangt 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.
Anwendungsbeispiel
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\input.c .\kitaq-docs\samples\api-examples\fc\input_aliases.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\input_aliases.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr --no-disasm --no-cacheImplementierung und Quelltext
kitaqfc/lib/input.h:56
#define btn_repeat input_repeatkitaqfc/lib/input.c:91
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
u8 input_current(void);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
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\input.c .\kitaq-docs\samples\api-examples\fc\input_edges.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\input_edges.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr --no-disasm --no-cacheImplementierung und Quelltext
kitaqfc/lib/input.h:49
Read the complete translated held-button mask.
kitaqfc/lib/input.c:93
u8 input_current(void) { return kq_input_keys; }input_down
Prüft, ob eine durch mask gewählte Taste gerade gehalten wird.
Syntax
u8 input_down(u8 mask);Parameter
maskEine
BTN_*-Maske oder mehrere mit|verknüpfte Masken. Eine einzige passende Taste genügt;BTN_A | BTN_Bverlangt 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
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\input.c .\kitaq-docs\samples\api-examples\fc\input_edges.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\input_edges.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr --no-disasm --no-cacheImplementierung und Quelltext
kitaqfc/lib/input.h:41
Return true when any masked logical button is held.
kitaqfc/lib/input.c:85
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
void input_init(void);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
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\input.c .\kitaq-docs\samples\api-examples\fc\input_edges.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\input_edges.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr --no-disasm --no-cacheImplementierung und Quelltext
kitaqfc/lib/input.h:35
Clear held/edge/repeat masks and reset each independent repeat countdown.
kitaqfc/lib/input.c:34
void input_init(void)
{
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 = (u8)(i + 1);
}
}input_pressed
Prüft, ob eine maskierte Taste bei der letzten Eingabeaktualisierung neu gedrückt wurde.
Syntax
u8 input_pressed(u8 mask);Parameter
maskEine
BTN_*-Maske oder mehrere mit|verknüpfte Masken. Eine einzige passende Taste genügt;BTN_A | BTN_Bverlangt 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
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\input.c .\kitaq-docs\samples\api-examples\fc\input_edges.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\input_edges.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr --no-disasm --no-cacheImplementierung und Quelltext
kitaqfc/lib/input.h:43
Return true when any masked button became pressed in the latest input update.
kitaqfc/lib/input.c:87
u8 input_pressed(u8 mask) { return (u8)((kq_input_press_keys & mask) != 0); }input_previous
Liefert die gespeicherte Tastenmaske vor der letzten Eingabeaktualisierung.
Syntax
u8 input_previous(void);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
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\input.c .\kitaq-docs\samples\api-examples\fc\input_edges.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\input_edges.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr --no-disasm --no-cacheImplementierung und Quelltext
kitaqfc/lib/input.h:51
Read the translated held-button mask from before the latest update.
kitaqfc/lib/input.c:95
u8 input_previous(void) { return kq_input_prev_keys; }input_released
Prüft, ob eine maskierte Taste bei der letzten Eingabeaktualisierung losgelassen wurde.
Syntax
u8 input_released(u8 mask);Parameter
maskEine
BTN_*-Maske oder mehrere mit|verknüpfte Masken. Eine einzige passende Taste genügt;BTN_A | BTN_Bverlangt 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
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\input.c .\kitaq-docs\samples\api-examples\fc\input_edges.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\input_edges.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr --no-disasm --no-cacheImplementierung und Quelltext
kitaqfc/lib/input.h:45
Return true when any masked button became released in the latest update.
kitaqfc/lib/input.c:89
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
u8 input_repeat(u8 mask);Parameter
maskEine
BTN_*-Maske oder mehrere mit|verknüpfte Masken. Eine einzige passende Taste genügt;BTN_A | BTN_Bverlangt 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
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\input.c .\kitaq-docs\samples\api-examples\fc\input_edges.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\input_edges.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr --no-disasm --no-cacheImplementierung und Quelltext
kitaqfc/lib/input.h:47
Return true for a masked initial press or scheduled repeat pulse.
kitaqfc/lib/input.c:91
u8 input_repeat(u8 mask) { return (u8)((kq_input_repeat_keys & mask) != 0); }input_update
Liest Controller 1 mit __pad_read1_safe, ordnet die NES-Bits in das gemeinsame BTN_*-Format um, speichert den vorherigen Zustand und berechnet Druck-, Loslass- und Wiederholungsmasken. Controller 2 wird nicht erfasst. Einmal pro Eingabetakt aufrufen.
Syntax
void input_update(void);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.
Die sichere Abfrage wiederholt Paare vollständiger Lesevorgänge, bis beide Masken übereinstimmen. Jeder Lesevorgang strobt $4016 und setzt die serielle Leseposition beider Controller zurück. Die Zahl der Versuche ist unbegrenzt. Diese Prüfung belegt keine Kompatibilität mit sämtlichen DMC-/Peripheriekombinationen.
Anwendungsbeispiel
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\input.c .\kitaq-docs\samples\api-examples\fc\input_edges.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\input_edges.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr --no-disasm --no-cacheImplementierung und Quelltext
kitaqfc/lib/input.h:39
Read controller 1 through the safe intrinsic, translate its bit order and derive press/release edges. Repeat delays count calls to this function, so call it once per intended input tick.
kitaqfc/lib/input.c:52
void input_update(void)
{
u8 i;
u8 raw;
kq_input_prev_keys = kq_input_keys;
raw = __pad_read1_safe();
kq_input_keys = input_translate_pad(raw);
kq_input_press_keys = (u8)(kq_input_keys & (u8)(kq_input_keys ^ kq_input_prev_keys));
kq_input_release_keys = (u8)(kq_input_prev_keys & (u8)(kq_input_keys ^ kq_input_prev_keys));
kq_input_repeat_keys = kq_input_press_keys;
i = 0;
while (i < 8) {
u8 mask;
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] = (u8)(input_repeat_timer[i] - 1);
} 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 = (u8)(i + 1);
}
}input_repeat.h — Wiederholung bei gehaltener Taste
Diese Ergänzung zu pad.c fügt Controller 1 unabhängige Wiederholungszähler pro Taste hinzu. Wartezeit und Intervall zur Laufzeit einstellen, den Controller abfragen und die Wiederholung einmal pro Takt weiterführen. Druck-, Loslass- und Halteabfragen nutzen den Controllerzustand; nur die Wiederholungsabfrage hängt von nes_pad_repeat_step() ab.
Anfangszähler von 0 bis 255. Nach dem sofortigen Impuls eines neuen Tastendrucks folgt der nächste nach delay + 1 Wiederholungsschritten. Gezählt werden Aufrufe von nes_pad_repeat_step(), nur bei genau einem Aufruf pro Frame entsprechen sie Frames.
Zähler zwischen späteren Impulsen, von 0 bis 255. Das tatsächliche Intervall beträgt interval + 1 Schritte; 0 liefert nach der Anfangswartezeit in jedem gehaltenen Schritt einen Impuls. Die acht Tastenzähler arbeiten unabhängig.
nes_pad_held
Filtert die zuletzt erfassten gehaltenen Tasten von Controller 1. Für fortlaufende Aktionen, solange ausgewählte Tasten gedrückt bleiben. Liest den gespeicherten Zustand ohne erneute Hardwareabfrage.
Syntax
unsigned char nes_pad_held(unsigned char mask);Parameter
maskDie im rohen NES-Bitformat beizubehaltenden Tasten, bei Bedarf mit
|kombiniert. 0 wählt nichts. Das Argument ist ein Filter, keine Controller-Portnummer.
Rückgabewert
Die passenden Bits der gespeicherten Maske an ihren ursprünglichen Positionen. Der Wert kann größer als 1 sein; 0 bedeutet kein Treffer. Die Abfrage verbraucht das Ereignis nicht.
Bedingungen und Grenzen
Rohes NES-Format: A=0x01, B=0x02, SELECT=0x04, START=0x08, UP=0x10, DOWN=0x20, LEFT=0x40, RIGHT=0x80. Ein gesetztes Bit bedeutet gedrückt. Verwende diese Werte mit nes_pad_* und rohen __pad_*-Ergebnissen, nicht die gemeinsamen BTN_*-Masken aus input.h.
Initialisiere die vier nes_pad1_*-Zustandsbytes vor der ersten Abfrage mit 0. Danach einmal pro Eingabetakt abfragen. pressed = current & ~previous und released = previous & ~current beschreiben die letzte Abfrage. Der Wiederholungszustand wird separat durch nes_pad_repeat_step() aktualisiert.
Anwendungsbeispiel
if (nes_pad_held(0x02)!=0) held_ticks++; // B is bit 1 in NES raw format.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 erklärt die Reihenfolge Einlesen → Wiederholung aktualisieren → Zustand abfragen und zeigt, dass die NES-Abfragen maskierte Bits statt des Wahrheitswerts 1 liefern. Verwenden Sie nes_pad_repeat_config(3, 1), halten Sie B für 40 Aktualisierungen gedrückt und lassen Sie los. FIRST HELD, FIRST TRIGGER und FIRST REPEAT sind 2; HELD TICKS ist 40, PULSE COUNT ist 19 und RELEASE BITS ist 2. Die erste Wiederholung folgt vier Aktualisierungen nach dem ersten Impuls; danach beträgt der Abstand zwei Aktualisierungen. FAILED CHECKS muss 0 sein. Eine andere Haltedauer verändert die Impulszahl.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\pad.c .\kitaqfc\lib\input_repeat.c .\kitaq-docs\samples\api-examples\fc\pad_repeat.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\pad_repeat.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr --no-disasm --no-cacheImplementierung und Quelltext
kitaqfc/lib/input_repeat.h:28
Return the requested currently-held bits in the NES pad layout.
kitaqfc/lib/input_repeat.c:103
unsigned char nes_pad_held(unsigned char mask)
{
return (unsigned char)(nes_pad1_cur & mask);
}nes_pad_release
Filtert die Loslassereignisse von Controller 1: ausgewählte Tasten, die zuvor gehalten wurden und nun losgelassen sind. Weiteres Loslassen erzeugt bei der nächsten Abfrage kein neues Ereignis.
Syntax
unsigned char nes_pad_release(unsigned char mask);Parameter
maskDie im rohen NES-Bitformat beizubehaltenden Tasten, bei Bedarf mit
|kombiniert. 0 wählt nichts. Das Argument ist ein Filter, keine Controller-Portnummer.
Rückgabewert
Die passenden Bits der gespeicherten Maske an ihren ursprünglichen Positionen. Der Wert kann größer als 1 sein; 0 bedeutet kein Treffer. Die Abfrage verbraucht das Ereignis nicht.
Bedingungen und Grenzen
Rohes NES-Format: A=0x01, B=0x02, SELECT=0x04, START=0x08, UP=0x10, DOWN=0x20, LEFT=0x40, RIGHT=0x80. Ein gesetztes Bit bedeutet gedrückt. Verwende diese Werte mit nes_pad_* und rohen __pad_*-Ergebnissen, nicht die gemeinsamen BTN_*-Masken aus input.h.
Initialisiere die vier nes_pad1_*-Zustandsbytes vor der ersten Abfrage mit 0. Danach einmal pro Eingabetakt abfragen. pressed = current & ~previous und released = previous & ~current beschreiben die letzte Abfrage. Der Wiederholungszustand wird separat durch nes_pad_repeat_step() aktualisiert.
Anwendungsbeispiel
if (nes_pad_release(0x02)!=0) {
release_bits=nes_pad_release(0x02); // Returns the released B bit, 2.
if (nes_pad_held(0x02)!=0 || nes_pad_trigger(0x02)!=0 || nes_pad_repeat(0x02)!=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 erklärt die Reihenfolge Einlesen → Wiederholung aktualisieren → Zustand abfragen und zeigt, dass die NES-Abfragen maskierte Bits statt des Wahrheitswerts 1 liefern. Verwenden Sie nes_pad_repeat_config(3, 1), halten Sie B für 40 Aktualisierungen gedrückt und lassen Sie los. FIRST HELD, FIRST TRIGGER und FIRST REPEAT sind 2; HELD TICKS ist 40, PULSE COUNT ist 19 und RELEASE BITS ist 2. Die erste Wiederholung folgt vier Aktualisierungen nach dem ersten Impuls; danach beträgt der Abstand zwei Aktualisierungen. FAILED CHECKS muss 0 sein. Eine andere Haltedauer verändert die Impulszahl.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\pad.c .\kitaqfc\lib\input_repeat.c .\kitaq-docs\samples\api-examples\fc\pad_repeat.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\pad_repeat.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr --no-disasm --no-cacheImplementierung und Quelltext
kitaqfc/lib/input_repeat.h:26
Return the requested newly-released bits from the latest pad poll.
kitaqfc/lib/input_repeat.c:97
unsigned char nes_pad_release(unsigned char mask)
{
return (unsigned char)(nes_pad1_released & mask);
}nes_pad_repeat
Filtert die Impulse des letzten nes_pad_repeat_step(). Enthält neue Tastendrücke und geplante Wiederholungen beim Halten. Diese Abfrage führt die Zähler nicht weiter.
Syntax
unsigned char nes_pad_repeat(unsigned char mask);Parameter
maskDie im rohen NES-Bitformat beizubehaltenden Tasten, bei Bedarf mit
|kombiniert. 0 wählt nichts. Das Argument ist ein Filter, keine Controller-Portnummer.
Rückgabewert
Die passenden Bits der gespeicherten Maske an ihren ursprünglichen Positionen. Der Wert kann größer als 1 sein; 0 bedeutet kein Treffer. Die Abfrage verbraucht das Ereignis nicht.
Bedingungen und Grenzen
Rohes NES-Format: A=0x01, B=0x02, SELECT=0x04, START=0x08, UP=0x10, DOWN=0x20, LEFT=0x40, RIGHT=0x80. Ein gesetztes Bit bedeutet gedrückt. Verwende diese Werte mit nes_pad_* und rohen __pad_*-Ergebnissen, nicht die gemeinsamen BTN_*-Masken aus input.h.
Initialisiere die vier nes_pad1_*-Zustandsbytes vor der ersten Abfrage mit 0. Danach einmal pro Eingabetakt abfragen. pressed = current & ~previous und released = previous & ~current beschreiben die letzte Abfrage. Der Wiederholungszustand wird separat durch nes_pad_repeat_step() aktualisiert.
Anwendungsbeispiel
if (nes_pad_repeat(0x02)!=0) {
if (pulse_count==1 && held_ticks-previous_pulse!=4) failures++;
if (pulse_count>1 && held_ticks-previous_pulse!=2) failures++;
previous_pulse=held_ticks; pulse_count++;
if (nes_pad_repeat(0x02)!=2) failures++; // Querying again preserves the pulse.
}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 erklärt die Reihenfolge Einlesen → Wiederholung aktualisieren → Zustand abfragen und zeigt, dass die NES-Abfragen maskierte Bits statt des Wahrheitswerts 1 liefern. Verwenden Sie nes_pad_repeat_config(3, 1), halten Sie B für 40 Aktualisierungen gedrückt und lassen Sie los. FIRST HELD, FIRST TRIGGER und FIRST REPEAT sind 2; HELD TICKS ist 40, PULSE COUNT ist 19 und RELEASE BITS ist 2. Die erste Wiederholung folgt vier Aktualisierungen nach dem ersten Impuls; danach beträgt der Abstand zwei Aktualisierungen. FAILED CHECKS muss 0 sein. Eine andere Haltedauer verändert die Impulszahl.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\pad.c .\kitaqfc\lib\input_repeat.c .\kitaq-docs\samples\api-examples\fc\pad_repeat.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\pad_repeat.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr --no-disasm --no-cacheImplementierung und Quelltext
kitaqfc/lib/input_repeat.h:24
Return the requested repeat-pulse bits from the latest repeat step.
kitaqfc/lib/input_repeat.c:91
unsigned char nes_pad_repeat(unsigned char mask)
{
return (unsigned char)(nes_pad1_repeat & mask);
}nes_pad_repeat_config
Setzt zur Laufzeit Anfangswartezeit und Wiederholungsintervall, löscht nes_pad1_repeat und setzt die acht Tastenzähler auf delay. Fragt den Controller nicht ab und löscht keine Halte-, Druck- oder Loslassmasken.
Syntax
void nes_pad_repeat_config(unsigned char delay, unsigned char interval);Parameter
delayAnfangszähler von 0 bis 255. Nach dem sofortigen Impuls eines neuen Tastendrucks folgt der nächste nach
delay + 1Wiederholungsschritten. Gezählt werden Aufrufe vonnes_pad_repeat_step(), nur bei genau einem Aufruf pro Frame entsprechen sie Frames.intervalZähler zwischen späteren Impulsen, von 0 bis 255. Das tatsächliche Intervall beträgt
interval + 1Schritte; 0 liefert nach der Anfangswartezeit in jedem gehaltenen Schritt einen Impuls. Die acht Tastenzähler arbeiten unabhängig.
Rückgabewert
Keiner (void).
Bedingungen und Grenzen
Rohes NES-Format: A=0x01, B=0x02, SELECT=0x04, START=0x08, UP=0x10, DOWN=0x20, LEFT=0x40, RIGHT=0x80. Ein gesetztes Bit bedeutet gedrückt. Verwende diese Werte mit nes_pad_* und rohen __pad_*-Ergebnissen, nicht die gemeinsamen BTN_*-Masken aus input.h.
Anwendungsbeispiel
nes_pad_repeat_config(3,1); // Next pulse after 4 held updates, then every 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 Programm erklärt die Reihenfolge Einlesen → Wiederholung aktualisieren → Zustand abfragen und zeigt, dass die NES-Abfragen maskierte Bits statt des Wahrheitswerts 1 liefern. Verwenden Sie nes_pad_repeat_config(3, 1), halten Sie B für 40 Aktualisierungen gedrückt und lassen Sie los. FIRST HELD, FIRST TRIGGER und FIRST REPEAT sind 2; HELD TICKS ist 40, PULSE COUNT ist 19 und RELEASE BITS ist 2. Die erste Wiederholung folgt vier Aktualisierungen nach dem ersten Impuls; danach beträgt der Abstand zwei Aktualisierungen. FAILED CHECKS muss 0 sein. Eine andere Haltedauer verändert die Impulszahl.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\pad.c .\kitaqfc\lib\input_repeat.c .\kitaq-docs\samples\api-examples\fc\pad_repeat.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\pad_repeat.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr --no-disasm --no-cacheImplementierung und Quelltext
kitaqfc/lib/input_repeat.h:16
Set initial/repeat countdowns and clear repeat output. Zero countdowns are allowed and cause a repeat on the next held-button step. A fresh press emits immediately. Held repeats follow after delay+1 and then interval+1 steps. These are call counts, not milliseconds; use one fresh pad poll before each step.
kitaqfc/lib/input_repeat.c:21
void nes_pad_repeat_config(unsigned char delay, unsigned char interval)
{
unsigned char i;
nes_pad_repeat_delay = delay;
nes_pad_repeat_interval = interval;
nes_pad1_repeat = 0;
i = 0;
while (i != 8)
{
nes_pad1_repeat_counter[i] = delay;
i = i + 1;
}
}nes_pad_repeat_step
Berechnet nes_pad1_repeat aus den zuletzt abgefragten Halte- und Druckmasken neu und führt jeden Zähler um einen Schritt weiter. Zuerst nes_pad_poll(), dann diese Funktion einmal aufrufen. Eine veraltete Druckmaske setzt die Anfangswartezeit immer wieder zurück und erzeugt wiederholt Anfangsimpulse.
Syntax
void nes_pad_repeat_step(void);Rückgabewert
Keiner (void).
Bedingungen und Grenzen
Rohes NES-Format: A=0x01, B=0x02, SELECT=0x04, START=0x08, UP=0x10, DOWN=0x20, LEFT=0x40, RIGHT=0x80. Ein gesetztes Bit bedeutet gedrückt. Verwende diese Werte mit nes_pad_* und rohen __pad_*-Ergebnissen, nicht die gemeinsamen BTN_*-Masken aus input.h.
Initialisiere die vier nes_pad1_*-Zustandsbytes vor der ersten Abfrage mit 0. Danach einmal pro Eingabetakt abfragen. pressed = current & ~previous und released = previous & ~current beschreiben die letzte Abfrage. Der Wiederholungszustand wird separat durch nes_pad_repeat_step() aktualisiert.
Anwendungsbeispiel
nes_pad_repeat_step(); // Once after each fresh poll; getters do not advance time.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 erklärt die Reihenfolge Einlesen → Wiederholung aktualisieren → Zustand abfragen und zeigt, dass die NES-Abfragen maskierte Bits statt des Wahrheitswerts 1 liefern. Verwenden Sie nes_pad_repeat_config(3, 1), halten Sie B für 40 Aktualisierungen gedrückt und lassen Sie los. FIRST HELD, FIRST TRIGGER und FIRST REPEAT sind 2; HELD TICKS ist 40, PULSE COUNT ist 19 und RELEASE BITS ist 2. Die erste Wiederholung folgt vier Aktualisierungen nach dem ersten Impuls; danach beträgt der Abstand zwei Aktualisierungen. FAILED CHECKS muss 0 sein. Eine andere Haltedauer verändert die Impulszahl.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\pad.c .\kitaqfc\lib\input_repeat.c .\kitaq-docs\samples\api-examples\fc\pad_repeat.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\pad_repeat.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr --no-disasm --no-cacheImplementierung und Quelltext
kitaqfc/lib/input_repeat.h:20
Generate per-button repeat bits from the most recently polled pad state. Poll first, then call once per tick; a countdown reaching zero emits on the following step, so an interval N leaves N decrement steps between pulses.
kitaqfc/lib/input_repeat.c:40
void nes_pad_repeat_step(void)
{
unsigned char bit_index;
unsigned char mask;
unsigned char counter;
nes_pad1_repeat = 0;
bit_index = 0;
mask = 1;
while (mask != 0)
{
if ((nes_pad1_cur & mask) == 0)
{
nes_pad1_repeat_counter[bit_index] = nes_pad_repeat_delay;
}
else
{
if ((nes_pad1_pressed & mask) != 0)
{
nes_pad1_repeat = nes_pad1_repeat | mask;
nes_pad1_repeat_counter[bit_index] = nes_pad_repeat_delay;
}
else
{
counter = nes_pad1_repeat_counter[bit_index];
if (counter == 0)
{
nes_pad1_repeat = nes_pad1_repeat | mask;
nes_pad1_repeat_counter[bit_index] = nes_pad_repeat_interval;
}
else
{
nes_pad1_repeat_counter[bit_index] = counter - 1;
}
}
}
bit_index = bit_index + 1;
// Byte overflow terminates the scan after the eighth button; each button has its own countdown.
mask = mask + mask;
}
}nes_pad_trigger
Filtert mit mask die neuen Tastendrücke von Controller 1. Für eine einmalige Aktion beim Wechsel einer ausgewählten Taste von losgelassen zu gedrückt.
Syntax
unsigned char nes_pad_trigger(unsigned char mask);Parameter
maskDie im rohen NES-Bitformat beizubehaltenden Tasten, bei Bedarf mit
|kombiniert. 0 wählt nichts. Das Argument ist ein Filter, keine Controller-Portnummer.
Rückgabewert
Die passenden Bits der gespeicherten Maske an ihren ursprünglichen Positionen. Der Wert kann größer als 1 sein; 0 bedeutet kein Treffer. Die Abfrage verbraucht das Ereignis nicht.
Bedingungen und Grenzen
Rohes NES-Format: A=0x01, B=0x02, SELECT=0x04, START=0x08, UP=0x10, DOWN=0x20, LEFT=0x40, RIGHT=0x80. Ein gesetztes Bit bedeutet gedrückt. Verwende diese Werte mit nes_pad_* und rohen __pad_*-Ergebnissen, nicht die gemeinsamen BTN_*-Masken aus input.h.
Initialisiere die vier nes_pad1_*-Zustandsbytes vor der ersten Abfrage mit 0. Danach einmal pro Eingabetakt abfragen. pressed = current & ~previous und released = previous & ~current beschreiben die letzte Abfrage. Der Wiederholungszustand wird separat durch nes_pad_repeat_step() aktualisiert.
Anwendungsbeispiel
if (nes_pad_trigger(0x02)!=0) {
first_trigger=nes_pad_trigger(0x02); // Returns 2, not Boolean 1.
first_held=nes_pad_held(0x02); first_repeat=nes_pad_repeat(0x02);
if (first_trigger!=2 || first_held!=2 || first_repeat!=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
Dieses Programm erklärt die Reihenfolge Einlesen → Wiederholung aktualisieren → Zustand abfragen und zeigt, dass die NES-Abfragen maskierte Bits statt des Wahrheitswerts 1 liefern. Verwenden Sie nes_pad_repeat_config(3, 1), halten Sie B für 40 Aktualisierungen gedrückt und lassen Sie los. FIRST HELD, FIRST TRIGGER und FIRST REPEAT sind 2; HELD TICKS ist 40, PULSE COUNT ist 19 und RELEASE BITS ist 2. Die erste Wiederholung folgt vier Aktualisierungen nach dem ersten Impuls; danach beträgt der Abstand zwei Aktualisierungen. FAILED CHECKS muss 0 sein. Eine andere Haltedauer verändert die Impulszahl.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\pad.c .\kitaqfc\lib\input_repeat.c .\kitaq-docs\samples\api-examples\fc\pad_repeat.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\pad_repeat.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr --no-disasm --no-cacheImplementierung und Quelltext
kitaqfc/lib/input_repeat.h:22
Return the requested newly-pressed bits, not a normalized Boolean.
kitaqfc/lib/input_repeat.c:85
unsigned char nes_pad_trigger(unsigned char mask)
{
return (unsigned char)(nes_pad1_pressed & mask);
}metasprite.h — Bilder aus mehreren Sprites
Verfügbar als C-Funktion in metasprite.c sowie als Makro in nes_game.h, das zu __metasprite_draw expandiert. Beide lesen denselben terminierten Datenstrom und schreiben identische OAM-Einträge aus vier Bytes. Die Beispiele kompilieren beide Formen getrennt.
Die C-Metasprite-Funktionen benötigen nes_oam_shadow[256]. runtime.c definiert diesen Puffer bei 0x0200, reserviert zusätzlich 0x0300–0x03BF für seine VRAM-Warteschlange und stellt __nes_nmi bereit. Binden Sie jede Implementierung nur einmal ein und stimmen Sie die Interruptbehandlung mit dem übrigen Programm ab.
nes_metasprite_draw
Verfügbar als C-Funktion in metasprite.c sowie als Makro in nes_game.h, das zu __metasprite_draw expandiert. Beide lesen denselben terminierten Datenstrom und schreiben identische OAM-Einträge aus vier Bytes. Die Beispiele kompilieren beide Formen getrennt.
Entpackt eine mit einer Endmarkierung versehene Folge von Sprite-Teilen in aufeinanderfolgende Einträge des Schattenpuffers der Seite 02. Jeder Teil addiert seine X/Y-Offsets von je einem Byte zur Basisposition und enthält eine eigene Kachel samt Attributen. Zurückgegeben wird der nächste OAM-Index.
Syntax
unsigned char nes_metasprite_draw(unsigned char oam_index, unsigned char base_x, unsigned char base_y, unsigned char* metasprite);
// Macro from nes_game.h:
#define nes_metasprite_draw(i,x,y,data) __metasprite_draw((i),(x),(y),(data))Parameter
oam_index / iSprite-Index von 0 bis 63, kein Byte-Offset. Intern wird er mit vier multipliziert und als 8-Bit-Position gespeichert. Werte außerhalb des Bereichs werden modulo 64 umgebrochen und können einen anderen Eintrag überschreiben. Eine Belegungsprüfung findet nicht statt.
base_x / xHorizontale Position in Pixeln als vorzeichenloses Byte; keine Tile-Koordinate.
base_y / yY-Byte des OAM. Für eine Oberkante unterhalb der Zeile null wird ihre Position minus eins übergeben; 239..255 liegen außerhalb der 240 sichtbaren Zeilen.
metasprite / dataZeiger auf lesbare Datensätze aus vier Byte:
dx, dy, tile, attr. Ein0xFFan der nächsten dx-Position beendet die Folge; weitere Bytes sind nicht nötig. Offsets werden modulo 256 addiert:0xFEsteht für −2 und dy=0xFFdarf −1 darstellen. dx=0xFFist hingegen die Endmarkierung und kann nicht für −1 verwendet werden. Der Zeiger muss im eingeblendeten Speicher gültig sein.
Rückgabewert
Nächster OAM-Index: (oam_index + geschriebene_Teile) modulo 64. Das ist eine Schreibposition, nicht die Anzahl gezeichneter Teile. Bei einer leeren Folge wird oam_index modulo 64 zurückgegeben.
Bedingungen und Grenzen
Wählen Sie die Header bewusst: nes_game.h und der Sammelheader fc.h definieren die Makros. Für die C-Funktionen binden Sie runtime.h beziehungsweise metasprite.h samt Implementierungen ohne diese Makros ein, oder entfernen Sie die gleichnamigen Makros zuvor mit #undef. Das parameterlose DMA-Makro akzeptiert das Argument page der C-Funktion nicht.
Die C-Metasprite-Funktionen benötigen nes_oam_shadow[256]. runtime.c definiert diesen Puffer bei 0x0200, reserviert zusätzlich 0x0300–0x03BF für seine VRAM-Warteschlange und stellt __nes_nmi bereit. Binden Sie jede Implementierung nur einmal ein und stimmen Sie die Interruptbehandlung mit dem übrigen Programm ab.
Diese Operationen ändern den CPU-RAM bei 0x0200–0x02FF, nicht sofort das Hardware-OAM. Übertragen Sie die fertige Seite mit __oam_dma. Belegungsflags, Koordinatenfelder und Zähler der Sprite-Bibliothek werden nicht mitgeführt. Interrupt-Routinen dürfen eine noch unvollständige Seite weder ändern noch übertragen.
Anzahl der Teile, Bildausschnitt und Kapazität werden nicht geprüft. Fügen Sie eine Endmarkierung ein und verwenden Sie höchstens 64−oam_index Teile. Koordinaten laufen modulo 256 über; nach Eintrag 63 wird bei Eintrag 0 weitergeschrieben. Eine leere Folge ändert nichts. Das Format unterscheidet sich vom MetaSpritePart-Array mit expliziter Anzahl, das metasprite_draw in der Sprite-Bibliothek verwendet.
Anwendungsbeispiel
demo_next=nes_metasprite_draw(4,144,31,demo_parts); // C function: returns 6.Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
C-RUNTIME kombiniert die C-Funktionen. PAIR zeigt zwei 8×8-Pfeile bei (144,32) und (152,32), den zweiten horizontal gespiegelt. Ein weiteres Paar bei y=64 wird ausgeblendet; HIDE RANGE muss daher leer bleiben. Die beiden Zeichenaufrufe verwenden die Slots 4–5 und 6–7 und ergeben NEXT 08. Seite 02 wird nach Seite 04 kopiert; nur Slot 8 wechselt vom Pfeil-Tile 128 zum Quadrat-Tile 129. nes_oam_dma(4) muss neben PAGE 04 bei (144,96) ein grünes Quadrat anzeigen, während Seite 02 Tile 128 behält.
Die Pfeile haben rote Ränder, grüne Schäfte und blaue Details an der Spitze; das Quadrat-Tile 129 ist grün. Die Prüfung vergleicht pro Bild 8.704 Farbpixel, alle 256 übertragenen OAM-Bytes und die Beschriftungen. Physische Hardware wurde nicht getestet.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\oam_c_helpers.c -I .\kitaqfc\lib -I .\kitaq-docs\samples --nes-chr=.\kitaq-docs\samples\sprite_example.chr -o .\out\oam_c_helpers.nes --no-cache --no-disasmAnwendungsbeispiel
fc_oam_next=nes_metasprite_draw(5,136,95,fc_oam_pair); // Returns 7 after two entries.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 zeigt jede Operation in einer beschrifteten Zeile. SET und MOVE zeigen 8×8-Pfeile nach rechts bei (144,16) und (144,32), TILE ein grünes Quadrat bei (144,48) und ATTR den in beiden Achsen gespiegelten Pfeil bei (144,64). HIDE bei (144,80) und CLEAR bei (144,112) müssen leer bleiben. META zeigt zwei Pfeile bei (136,96) und (144,96), den zweiten horizontal gespiegelt. NEXT 07 bezeichnet die nächste Position nach den Einträgen 5 und 6. Die Ränder sind rot, der Schaft grün und die Spitzendetails blau. Geprüft werden 8.704 Pixel je Bild und die übertragenen OAM-Bytes; echte Hardware wurde nicht getestet.
Das Programm ALIASES bereitet die beschrifteten Zeilen mit Makros aus nes_game.h vor und sendet Seite 02 mit nes_oam_dma(). TRANSFER zeigt den 8×8-Pfeil bei (144,128). Das Beispiel verwendet die Makros, ohne runtime.c oder metasprite.c einzubinden.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\oam_aliases.c -I .\kitaqfc\lib -I .\kitaq-docs\samples --nes-chr=.\kitaq-docs\samples\sprite_example.chr -o .\out\oam_aliases.nes --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/metasprite.h:12
Optional declarations for the phase 10 NES metasprite helper. Metasprite data layout: [dx, dy, tile, attr] repeated, terminated by dx=0xFF Read four-byte records [dx,dy,tile,attr] until dx=0xFF, writing them to shadow OAM. Coordinates and destination offsets wrap as bytes. The caller must supply a terminator and enough unused slots; there is no capacity guard. Return the next slot index derived from the final wrapped byte offset.
kitaqfc/lib/metasprite.c:18
unsigned char nes_metasprite_draw(unsigned char oam_index, unsigned char base_x, unsigned char base_y, unsigned char* metasprite)
{
unsigned char dst;
unsigned char dx;
dst = oam_index + oam_index;
dst = dst + dst;
while (1)
{
dx = metasprite[0];
if (dx == 0xFF)
{
break;
}
// These are raw OAM Y bytes, not a corrected screen-top coordinate; no allocation bookkeeping is updated.
nes_oam_shadow[dst] = (unsigned char)(base_y + metasprite[1]);
nes_oam_shadow[(unsigned char)(dst + 1)] = metasprite[2];
nes_oam_shadow[(unsigned char)(dst + 2)] = metasprite[3];
nes_oam_shadow[(unsigned char)(dst + 3)] = (unsigned char)(base_x + dx);
dst = (unsigned char)(dst + 4);
metasprite = metasprite + 4;
}
return (unsigned char)(dst >> 2);
}nes_metasprite_hide_from
Blendet aufeinanderfolgende Einträge im OAM-Schattenpuffer aus, indem jedes Y-Byte auf 0xF8 gesetzt wird. Tile, Attribute und X bleiben erhalten. Diese C-Funktion überträgt kein OAM und gibt keine Belegungen der Sprite-Bibliothek frei.
Syntax
void nes_metasprite_hide_from(unsigned char oam_index, unsigned char sprite_count);Parameter
oam_indexSprite-Index von 0 bis 63, kein Byte-Offset. Intern wird er mit vier multipliziert und als 8-Bit-Position gespeichert. Werte außerhalb des Bereichs werden modulo 64 umgebrochen und können einen anderen Eintrag überschreiben. Eine Belegungsprüfung findet nicht statt.
sprite_countAnzahl auszublendender Einträge von 0 bis
64−oam_index. Null verändert nichts. Bei größeren Werten läuft der Bytezeiger zum Anfang zurück und kann dort OAM-Einträge ausblenden; die Funktion prüft den Bereich nicht.
Rückgabewert
Keiner (void).
Bedingungen und Grenzen
Die C-Metasprite-Funktionen benötigen nes_oam_shadow[256]. runtime.c definiert diesen Puffer bei 0x0200, reserviert zusätzlich 0x0300–0x03BF für seine VRAM-Warteschlange und stellt __nes_nmi bereit. Binden Sie jede Implementierung nur einmal ein und stimmen Sie die Interruptbehandlung mit dem übrigen Programm ab.
Diese Operationen ändern den CPU-RAM bei 0x0200–0x02FF, nicht sofort das Hardware-OAM. Übertragen Sie die fertige Seite mit __oam_dma. Belegungsflags, Koordinatenfelder und Zähler der Sprite-Bibliothek werden nicht mitgeführt. Interrupt-Routinen dürfen eine noch unvollständige Seite weder ändern noch übertragen.
Anwendungsbeispiel
nes_metasprite_hide_from(6,2); // Hide slots 6 and 7; the pair at slots 4 and 5 remains.Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
C-RUNTIME kombiniert die C-Funktionen. PAIR zeigt zwei 8×8-Pfeile bei (144,32) und (152,32), den zweiten horizontal gespiegelt. Ein weiteres Paar bei y=64 wird ausgeblendet; HIDE RANGE muss daher leer bleiben. Die beiden Zeichenaufrufe verwenden die Slots 4–5 und 6–7 und ergeben NEXT 08. Seite 02 wird nach Seite 04 kopiert; nur Slot 8 wechselt vom Pfeil-Tile 128 zum Quadrat-Tile 129. nes_oam_dma(4) muss neben PAGE 04 bei (144,96) ein grünes Quadrat anzeigen, während Seite 02 Tile 128 behält.
Die Pfeile haben rote Ränder, grüne Schäfte und blaue Details an der Spitze; das Quadrat-Tile 129 ist grün. Die Prüfung vergleicht pro Bild 8.704 Farbpixel, alle 256 übertragenen OAM-Bytes und die Beschriftungen. Physische Hardware wurde nicht getestet.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\oam_c_helpers.c -I .\kitaqfc\lib -I .\kitaq-docs\samples --nes-chr=.\kitaq-docs\samples\sprite_example.chr -o .\out\oam_c_helpers.nes --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/metasprite.h:17
Hide consecutive shadow slots by setting Y to 0xF8. Keep the requested range within 64 slots to avoid wrapping and hiding earlier entries.
kitaqfc/lib/metasprite.c:49
void nes_metasprite_hide_from(unsigned char oam_index, unsigned char sprite_count)
{
unsigned char dst;
dst = oam_index + oam_index;
dst = dst + dst;
while (sprite_count != 0)
{
nes_oam_shadow[dst] = 0xF8;
dst = (unsigned char)(dst + 4);
sprite_count = sprite_count - 1;
}
}nametable_asset.h — Nametable-Ressourcen und ihre Platzierung
Überträgt 32-Kachelzeilen, Rechtecke mit Zeilenabstand, Füllungen und vollständige Bildschirme mit 960+64 Bytes; bearbeitet und überträgt auch Attributschattendaten. Wählen Sie je nach Situation sofortige Übertragungen oder späteren Warteschlangenverbrauch.
Setzen Sie bei direkten Übertragungen das PPUCTRL-Inkrement auf eins und verwenden Sie die Einrichtung bei ausgeschalteter Darstellung oder ein ausreichend langes VBlank-Fenster. Diese Hilfsfunktionen schalten die Darstellung nicht aus und warten nicht.
Binden Sie runtime.c ein. Die Warteschlange kopiert Nutzdaten für eine spätere NMI oder eine sichere Übertragung bei ausgeschalteter Darstellung. Serialisieren Sie Erzeugung und Verbrauch. Geht bei mehreren Zeilen die Kapazität aus, bleiben zuvor aufgenommene Zeilen eingereiht.
nes_attr_apply_now
Überträgt alle 64 Schattenbytes sofort in die Attributtabelle einer Nametable.
Syntax
void nes_attr_apply_now(unsigned short nt_base);Parameter
nt_baseLogische Nametable-Basis $2000/$2400/$2800/$2C00; die Spiegelung bestimmt die physische Unabhängigkeit.
Rückgabewert
Kein Rückgabewert.
Bedingungen und Grenzen
Der gemeinsame 64-Byte-Attributschattenpuffer belegt CPU-RAM $03E0..$041F. Reservieren Sie diesen Bereich. Ein Attributbyte deckt 4×4 Kacheln ab; jedes Zwei-Bit-Feld wählt die Palette für einen 2×2-Kachelquadranten.
Setzen Sie bei direkten Übertragungen das PPUCTRL-Inkrement auf eins und verwenden Sie die Einrichtung bei ausgeschalteter Darstellung oder ein ausreichend langes VBlank-Fenster. Diese Hilfsfunktionen schalten die Darstellung nicht aus und warten nicht.
Anwendungsbeispiel
nes_attr_apply_now(0x2000);Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Kombinieren Sie Zeilen-, Rechteck-, Füll- und vollständige Tabellenübertragungen. Zwei rote 32×8-Balken erscheinen über einem blauen 16×16-Quadrat und roten 16×24/32×24-Rechtecken. Direkte und eingereihte Übertragungen zeichnen an unterschiedlichen Positionen.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\batch3_nametable.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch3_nametable.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chrImplementierung und Quelltext
kitaqfc/lib/nametable_asset.h:20
Upload all attribute shadow bytes immediately; the caller provides safe PPU timing.
kitaqfc/lib/nametable_asset.c:90
void nes_attr_apply_now(unsigned short nt_base)
{
nes_ppu_stream_write(nes_attr_base_from_nt(nt_base), nes_attr_shadow, 64);
}nes_attr_base_from_nt
Addiert $3C0 zur Nametable-Basis, um ihre Attributtabelle zu finden.
Syntax
unsigned short nes_attr_base_from_nt(unsigned short nt_base);Parameter
nt_baseLogische Nametable-Basis $2000/$2400/$2800/$2C00; die Spiegelung bestimmt die physische Unabhängigkeit.
Rückgabewert
Gibt nt_base+$3C0 ohne Eingabeprüfung zurück.
Anwendungsbeispiel
result[1]=nes_attr_base_from_nt(0x2400);Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Kombinieren Sie Zeilen-, Rechteck-, Füll- und vollständige Tabellenübertragungen. Zwei rote 32×8-Balken erscheinen über einem blauen 16×16-Quadrat und roten 16×24/32×24-Rechtecken. Direkte und eingereihte Übertragungen zeichnen an unterschiedlichen Positionen.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\batch3_nametable.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch3_nametable.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chrImplementierung und Quelltext
kitaqfc/lib/nametable_asset.h:11
Locate the 64-byte attribute table at offset 0x03C0 from a nametable base.
kitaqfc/lib/nametable_asset.c:30
unsigned short nes_attr_base_from_nt(unsigned short nt_base)
{
return (unsigned short)(nt_base + 0x03C0);
}nes_attr_queue_all
Kopiert den gesamten Attributschattenpuffer in die Warteschlange.
Syntax
unsigned char nes_attr_queue_all(unsigned short nt_base);Parameter
nt_baseLogische Nametable-Basis $2000/$2400/$2800/$2C00; die Spiegelung bestimmt die physische Unabhängigkeit.
Rückgabewert
Gibt bei Aufnahme 1 zurück, bei voller Warteschlange 0; ein Eintrag benötigt 67 Warteschlangenbytes.
Bedingungen und Grenzen
Der gemeinsame 64-Byte-Attributschattenpuffer belegt CPU-RAM $03E0..$041F. Reservieren Sie diesen Bereich. Ein Attributbyte deckt 4×4 Kacheln ab; jedes Zwei-Bit-Feld wählt die Palette für einen 2×2-Kachelquadranten.
Binden Sie runtime.c ein. Die Warteschlange kopiert Nutzdaten für eine spätere NMI oder eine sichere Übertragung bei ausgeschalteter Darstellung. Serialisieren Sie Erzeugung und Verbrauch. Geht bei mehreren Zeilen die Kapazität aus, bleiben zuvor aufgenommene Zeilen eingereiht.
Anwendungsbeispiel
result[5]=nes_attr_queue_all(0x2000);result[6]=nes_vram_queue_used;nes_vram_queue_nmi_flush();Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Kombinieren Sie Zeilen-, Rechteck-, Füll- und vollständige Tabellenübertragungen. Zwei rote 32×8-Balken erscheinen über einem blauen 16×16-Quadrat und roten 16×24/32×24-Rechtecken. Direkte und eingereihte Übertragungen zeichnen an unterschiedlichen Positionen.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\batch3_nametable.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch3_nametable.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chrImplementierung und Quelltext
kitaqfc/lib/nametable_asset.h:22
Copy all shadow attribute bytes into the runtime queue and return its admission result.
kitaqfc/lib/nametable_asset.c:97
unsigned char nes_attr_queue_all(unsigned short nt_base)
{
return nes_vram_queue_try_write(nes_attr_base_from_nt(nt_base), nes_attr_shadow, 64);
}nes_attr_shadow_clear
Füllt alle 64 Schattenbytes mit demselben gepackten Wert.
Syntax
void nes_attr_shadow_clear(unsigned char value);Parameter
valueGepacktes Attributbyte; beispielsweise wählt 0x55 Palette 1 in allen Quadranten, 0xAA wählt Palette 2.
Rückgabewert
Kein Rückgabewert.
Bedingungen und Grenzen
Der gemeinsame 64-Byte-Attributschattenpuffer belegt CPU-RAM $03E0..$041F. Reservieren Sie diesen Bereich. Ein Attributbyte deckt 4×4 Kacheln ab; jedes Zwei-Bit-Feld wählt die Palette für einen 2×2-Kachelquadranten.
Anwendungsbeispiel
nes_attr_shadow_clear(0x55);result[2]=nes_attr_shadow[63];Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Kombinieren Sie Zeilen-, Rechteck-, Füll- und vollständige Tabellenübertragungen. Zwei rote 32×8-Balken erscheinen über einem blauen 16×16-Quadrat und roten 16×24/32×24-Rechtecken. Direkte und eingereihte Übertragungen zeichnen an unterschiedlichen Positionen.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\batch3_nametable.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch3_nametable.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chrImplementierung und Quelltext
kitaqfc/lib/nametable_asset.h:13
Fill all 64 shadow bytes with an already-packed attribute value.
kitaqfc/lib/nametable_asset.c:36
void nes_attr_shadow_clear(unsigned char value)
{
__memset(nes_attr_shadow, value, 64);
}nes_attr_shadow_copy
Kopiert eine vollständige Attributtabelle als Ausgangspunkt für Bearbeitungen in den RAM.
Syntax
void nes_attr_shadow_copy(unsigned char* src64);Parameter
src64Lesbare, gepackte 64-Byte-Attributtabelle, kein Array einzelner Paletten-IDs je Kachel.
Rückgabewert
Kein Rückgabewert.
Bedingungen und Grenzen
Der gemeinsame 64-Byte-Attributschattenpuffer belegt CPU-RAM $03E0..$041F. Reservieren Sie diesen Bereich. Ein Attributbyte deckt 4×4 Kacheln ab; jedes Zwei-Bit-Feld wählt die Palette für einen 2×2-Kachelquadranten.
Anwendungsbeispiel
for(i=0;i<64;i++)table[i]=0x55;nes_attr_shadow_copy(table);result[3]=nes_attr_shadow[0];Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Kombinieren Sie Zeilen-, Rechteck-, Füll- und vollständige Tabellenübertragungen. Zwei rote 32×8-Balken erscheinen über einem blauen 16×16-Quadrat und roten 16×24/32×24-Rechtecken. Direkte und eingereihte Übertragungen zeichnen an unterschiedlichen Positionen.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\batch3_nametable.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch3_nametable.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chrImplementierung und Quelltext
kitaqfc/lib/nametable_asset.h:15
Copy an entire packed attribute table into shadow RAM without writing the PPU.
kitaqfc/lib/nametable_asset.c:42
void nes_attr_shadow_copy(unsigned char* src64)
{
__memcpy(nes_attr_shadow, src64, 64);
}nes_attr_shadow_set_quad
Ersetzt die Palette eines 2×2-Kachelquadranten und erhält die übrigen Felder desselben Bytes.
Syntax
void nes_attr_shadow_set_quad(unsigned char tile_x, unsigned char tile_y, unsigned char pal_index);Parameter
tile_xLinke Kachelspalte, sichtbarer Bereich 0..31.
tile_yObere Kachelzeile, sichtbarer Bereich 0..29.
pal_indexDie unteren zwei Bits des Palettenindex.
Rückgabewert
Kein Rückgabewert.
Bedingungen und Grenzen
Der gemeinsame 64-Byte-Attributschattenpuffer belegt CPU-RAM $03E0..$041F. Reservieren Sie diesen Bereich. Ein Attributbyte deckt 4×4 Kacheln ab; jedes Zwei-Bit-Feld wählt die Palette für einen 2×2-Kachelquadranten.
Halten Sie Koordinaten unter 32. Ungerade Koordinaten wählen den zugehörigen 2×2-Quadranten. Sichtbare Zeilen sind 0..29.
Anwendungsbeispiel
nes_attr_shadow_set_quad(4,8,2);result[4]=nes_attr_shadow[17];Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Kombinieren Sie Zeilen-, Rechteck-, Füll- und vollständige Tabellenübertragungen. Zwei rote 32×8-Balken erscheinen über einem blauen 16×16-Quadrat und roten 16×24/32×24-Rechtecken. Direkte und eingereihte Übertragungen zeichnen an unterschiedlichen Positionen.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\batch3_nametable.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch3_nametable.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chrImplementierung und Quelltext
kitaqfc/lib/nametable_asset.h:18
Replace only the chosen quadrant's palette bits, preserving its neighbors. Palette IDs are masked to two bits; tile coordinates must fit the shadow table.
kitaqfc/lib/nametable_asset.c:72
void nes_attr_shadow_set_quad(unsigned char tile_x, unsigned char tile_y, unsigned char pal_index)
{
unsigned char idx;
unsigned char shift;
unsigned char mask;
unsigned char value;
idx = nes_attr_index(tile_x, tile_y);
shift = nes_attr_shift(tile_x, tile_y);
pal_index = (unsigned char)(pal_index & 3);
value = nes_attr_shadow[idx];
mask = (unsigned char)(3 << shift);
value = (unsigned char)(value & (unsigned char)(~mask));
value = (unsigned char)(value | (unsigned char)(pal_index << shift));
nes_attr_shadow[idx] = value;
}nes_nametable_apply_now
Überträgt 960 Kachel-IDs, gefolgt von einer 64-Byte-Attributtabelle.
Syntax
void nes_nametable_apply_now(unsigned short nt_base, unsigned char* nam960, unsigned char* attr64);Parameter
nt_baseLogische Nametable-Basis $2000/$2400/$2800/$2C00; die Spiegelung bestimmt die physische Unabhängigkeit.
nam960Zeilenweise angeordnetes 32×30-Kachelarray.
attr6464 gepackte Attributbytes; müssen nicht aus dem gemeinsamen Schattenpuffer stammen.
Rückgabewert
Kein Rückgabewert.
Bedingungen und Grenzen
Setzen Sie bei direkten Übertragungen das PPUCTRL-Inkrement auf eins und verwenden Sie die Einrichtung bei ausgeschalteter Darstellung oder ein ausreichend langes VBlank-Fenster. Diese Hilfsfunktionen schalten die Darstellung nicht aus und warten nicht.
Eine synchrone Übertragung von 1024 Bytes gehört gewöhnlich in die Einrichtung bei ausgeschalteter Darstellung. Die Hilfsfunktion verteilt sie nicht auf mehrere Frames.
Anwendungsbeispiel
nes_nametable_apply_now(0x2000,empty,table);Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Kombinieren Sie Zeilen-, Rechteck-, Füll- und vollständige Tabellenübertragungen. Zwei rote 32×8-Balken erscheinen über einem blauen 16×16-Quadrat und roten 16×24/32×24-Rechtecken. Direkte und eingereihte Übertragungen zeichnen an unterschiedlichen Positionen.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\batch3_nametable.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch3_nametable.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chrImplementierung und Quelltext
kitaqfc/lib/nametable_asset.h:41
Upload 960 tile bytes followed by 64 attribute bytes. This bulk operation does not disable rendering or wait for VBlank on its own.
kitaqfc/lib/nametable_asset.c:178
void nes_nametable_apply_now(unsigned short nt_base, unsigned char* nam960, unsigned char* attr64)
{
nes_ppu_stream_write(nt_base, nam960, 960);
nes_ppu_stream_write(nes_attr_base_from_nt(nt_base), attr64, 64);
}nes_nt_base_from_index
Berechnet eine logische Nametable-Basis aus den unteren zwei Indexbits.
Syntax
unsigned short nes_nt_base_from_index(unsigned char index);Parameter
indexIndex; 0..3 wählen Tabellen, größere Werte werden auf die unteren zwei Bits reduziert.
Rückgabewert
Gibt $2000 + (index & 3)*$400 zurück.
Anwendungsbeispiel
result[0]=nes_nt_base_from_index(5);Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Kombinieren Sie Zeilen-, Rechteck-, Füll- und vollständige Tabellenübertragungen. Zwei rote 32×8-Balken erscheinen über einem blauen 16×16-Quadrat und roten 16×24/32×24-Rechtecken. Direkte und eingereihte Übertragungen zeichnen an unterschiedlichen Positionen.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\batch3_nametable.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch3_nametable.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chrImplementierung und Quelltext
kitaqfc/lib/nametable_asset.h:9
Mask the index to the four logical nametables and return its PPU base. Physical storage still depends on the cartridge's mirroring configuration.
kitaqfc/lib/nametable_asset.c:22
unsigned short nes_nt_base_from_index(unsigned char index)
{
index = (unsigned char)(index & 3);
return (unsigned short)(0x2000 + ((unsigned short)index << 10));
}nes_nt_queue_fill_rect
Reiht für jede Rechteckzeile das Füllen mit einer Kachel-ID ein.
Syntax
unsigned char nes_nt_queue_fill_rect(unsigned short nt_base, unsigned char tile_x, unsigned char tile_y, unsigned char width, unsigned char height, unsigned char value);Parameter
nt_baseLogische Nametable-Basis $2000/$2400/$2800/$2C00; die Spiegelung bestimmt die physische Unabhängigkeit.
tile_xLinke Kachelspalte, sichtbarer Bereich 0..31.
tile_yObere Kachelzeile, sichtbarer Bereich 0..29.
widthBreite in Kacheln.
heightHöhe in Kacheln.
valueKachel-ID zum Füllen, 0..255.
Rückgabewert
Gibt nach allen Zeilen oder bei Höhe null 1 zurück, bei fehlgeschlagener Aufnahme 0.
Bedingungen und Grenzen
Binden Sie runtime.c ein. Die Warteschlange kopiert Nutzdaten für eine spätere NMI oder eine sichere Übertragung bei ausgeschalteter Darstellung. Serialisieren Sie Erzeugung und Verbrauch. Geht bei mehreren Zeilen die Kapazität aus, bleiben zuvor aufgenommene Zeilen eingereiht.
Halten Sie Koordinaten und Ausdehnungen innerhalb der sichtbaren Nametable; gewöhnlich gilt pitch≥width. Es findet kein Clipping statt. Eingereihte Zeilen dürfen höchstens 127 lang sein; ein gewöhnliches Nametable-Rechteck ist höchstens 32 Kacheln breit.
Anwendungsbeispiel
result[10]=nes_nt_queue_fill_rect(0x2000,16,8,4,3,1);result[11]=nes_vram_queue_used;nes_vram_queue_nmi_flush();Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Kombinieren Sie Zeilen-, Rechteck-, Füll- und vollständige Tabellenübertragungen. Zwei rote 32×8-Balken erscheinen über einem blauen 16×16-Quadrat und roten 16×24/32×24-Rechtecken. Direkte und eingereihte Übertragungen zeichnen an unterschiedlichen Positionen.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\batch3_nametable.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch3_nametable.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chrImplementierung und Quelltext
kitaqfc/lib/nametable_asset.h:38
Queue one fill record per row, stopping on failure while retaining previously queued rows. The runtime fill-length and rectangle bounds requirements apply.
kitaqfc/lib/nametable_asset.c:157
unsigned char nes_nt_queue_fill_rect(unsigned short nt_base, unsigned char tile_x, unsigned char tile_y, unsigned char width, unsigned char height, unsigned char value)
{
unsigned char row;
unsigned short ppu_addr;
row = 0;
while (row != height)
{
ppu_addr = (unsigned short)(nt_base + ((unsigned short)(tile_y + row) << 5) + tile_x);
if (nes_vram_queue_try_fill(ppu_addr, value, width) == 0)
{
return 0;
}
row = (unsigned char)(row + 1);
}
return 1;
}nes_nt_queue_rect
Kopiert für jede Rechteckzeile die Quelldaten in die Warteschlange.
Syntax
unsigned char nes_nt_queue_rect(unsigned short nt_base, unsigned char tile_x, unsigned char tile_y, unsigned char width, unsigned char height, unsigned char pitch, unsigned char* src);Parameter
nt_baseLogische Nametable-Basis $2000/$2400/$2800/$2C00; die Spiegelung bestimmt die physische Unabhängigkeit.
tile_xLinke Kachelspalte, sichtbarer Bereich 0..31.
tile_yObere Kachelzeile, sichtbarer Bereich 0..29.
widthBreite in Kacheln.
heightHöhe in Kacheln.
pitchByte-Abstand zwischen den Quellzeilenanfängen; kann abschließende Füllbytes überspringen.
srcLesbare Quelle mit mindestens (height−1)*pitch+width Bytes.
Rückgabewert
Gibt nach allen Zeilen oder bei Höhe null 1 zurück, bei fehlgeschlagener Aufnahme 0.
Bedingungen und Grenzen
Binden Sie runtime.c ein. Die Warteschlange kopiert Nutzdaten für eine spätere NMI oder eine sichere Übertragung bei ausgeschalteter Darstellung. Serialisieren Sie Erzeugung und Verbrauch. Geht bei mehreren Zeilen die Kapazität aus, bleiben zuvor aufgenommene Zeilen eingereiht.
Halten Sie Koordinaten und Ausdehnungen innerhalb der sichtbaren Nametable; gewöhnlich gilt pitch≥width. Es findet kein Clipping statt. Eingereihte Zeilen dürfen höchstens 127 lang sein; ein gewöhnliches Nametable-Rechteck ist höchstens 32 Kacheln breit.
Anwendungsbeispiel
result[8]=nes_nt_queue_rect(0x2000,10,8,2,3,4,patch);result[9]=nes_vram_queue_used;nes_vram_queue_nmi_flush();Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Kombinieren Sie Zeilen-, Rechteck-, Füll- und vollständige Tabellenübertragungen. Zwei rote 32×8-Balken erscheinen über einem blauen 16×16-Quadrat und roten 16×24/32×24-Rechtecken. Direkte und eingereihte Übertragungen zeichnen an unterschiedlichen Positionen.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\batch3_nametable.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch3_nametable.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chrImplementierung und Quelltext
kitaqfc/lib/nametable_asset.h:35
Copy rows into the runtime queue until complete or full. Failure leaves earlier rows queued; it does not roll back a partially admitted rectangle. Widths must respect the queue literal-record limit. Pitch is source bytes per row. Each copied literal record costs width+3 queue bytes; check total admission needs when partial updates are unacceptable.
kitaqfc/lib/nametable_asset.c:137
unsigned char nes_nt_queue_rect(unsigned short nt_base, unsigned char tile_x, unsigned char tile_y, unsigned char width, unsigned char height, unsigned char pitch, unsigned char* src)
{
unsigned char row;
unsigned short ppu_addr;
row = 0;
while (row != height)
{
ppu_addr = (unsigned short)(nt_base + ((unsigned short)(tile_y + row) << 5) + tile_x);
if (nes_vram_queue_try_write(ppu_addr, src, width) == 0)
{
return 0;
}
src = src + pitch;
row = (unsigned char)(row + 1);
}
return 1;
}nes_nt_queue_row
Kopiert eine vollständige Zeile aus 32 Kacheln in die Warteschlange.
Syntax
unsigned char nes_nt_queue_row(unsigned short nt_base, unsigned char row, unsigned char* src32);Parameter
nt_baseLogische Nametable-Basis $2000/$2400/$2800/$2C00; die Spiegelung bestimmt die physische Unabhängigkeit.
rowZeile 0..29; wird nicht auf Bereichsgrenzen geprüft.
src3232 lesbare Kachel-IDs.
Rückgabewert
Gibt bei Aufnahme 1 zurück, bei voller Warteschlange 0; benötigt 35 Warteschlangenbytes.
Bedingungen und Grenzen
Binden Sie runtime.c ein. Die Warteschlange kopiert Nutzdaten für eine spätere NMI oder eine sichere Übertragung bei ausgeschalteter Darstellung. Serialisieren Sie Erzeugung und Verbrauch. Geht bei mehreren Zeilen die Kapazität aus, bleiben zuvor aufgenommene Zeilen eingereiht.
Anwendungsbeispiel
result[7]=nes_nt_queue_row(0x2000,4,row);nes_vram_queue_nmi_flush();Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Kombinieren Sie Zeilen-, Rechteck-, Füll- und vollständige Tabellenübertragungen. Zwei rote 32×8-Balken erscheinen über einem blauen 16×16-Quadrat und roten 16×24/32×24-Rechtecken. Direkte und eingereihte Übertragungen zeichnen an unterschiedlichen Positionen.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\batch3_nametable.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch3_nametable.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chrImplementierung und Quelltext
kitaqfc/lib/nametable_asset.h:26
Copy one complete nametable row into the runtime queue.
kitaqfc/lib/nametable_asset.c:111
unsigned char nes_nt_queue_row(unsigned short nt_base, unsigned char row, unsigned char* src32)
{
unsigned short ppu_addr;
ppu_addr = (unsigned short)(nt_base + ((unsigned short)row << 5));
return nes_vram_queue_try_write(ppu_addr, src32, 32);
}nes_nt_stream_rect
Liest jede Rechteckzeile anhand des Quellzeilenabstands und überträgt sie direkt an die PPU.
Syntax
void nes_nt_stream_rect(unsigned short nt_base, unsigned char tile_x, unsigned char tile_y, unsigned char width, unsigned char height, unsigned char pitch, unsigned char* src);Parameter
nt_baseLogische Nametable-Basis $2000/$2400/$2800/$2C00; die Spiegelung bestimmt die physische Unabhängigkeit.
tile_xLinke Kachelspalte, sichtbarer Bereich 0..31.
tile_yObere Kachelzeile, sichtbarer Bereich 0..29.
widthBreite in Kacheln.
heightHöhe in Kacheln.
pitchByte-Abstand zwischen den Quellzeilenanfängen; kann abschließende Füllbytes überspringen.
srcLesbare Quelle mit mindestens (height−1)*pitch+width Bytes.
Rückgabewert
Kein Rückgabewert.
Bedingungen und Grenzen
Setzen Sie bei direkten Übertragungen das PPUCTRL-Inkrement auf eins und verwenden Sie die Einrichtung bei ausgeschalteter Darstellung oder ein ausreichend langes VBlank-Fenster. Diese Hilfsfunktionen schalten die Darstellung nicht aus und warten nicht.
Halten Sie Koordinaten und Ausdehnungen innerhalb der sichtbaren Nametable; gewöhnlich gilt pitch≥width. Es findet kein Clipping statt. Eingereihte Zeilen dürfen höchstens 127 lang sein; ein gewöhnliches Nametable-Rechteck ist höchstens 32 Kacheln breit.
Anwendungsbeispiel
// A pitch of four skips two source bytes at the end of each row.
nes_nt_stream_rect(0x2000,4,8,2,2,4,patch);Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Kombinieren Sie Zeilen-, Rechteck-, Füll- und vollständige Tabellenübertragungen. Zwei rote 32×8-Balken erscheinen über einem blauen 16×16-Quadrat und roten 16×24/32×24-Rechtecken. Direkte und eingereihte Übertragungen zeichnen an unterschiedlichen Positionen.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\batch3_nametable.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch3_nametable.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chrImplementierung und Quelltext
kitaqfc/lib/nametable_asset.h:29
Write each rectangle row immediately, advancing source by pitch rather than width. Caller-provided coordinates, storage and timing are not clipped or checked.
kitaqfc/lib/nametable_asset.c:120
void nes_nt_stream_rect(unsigned short nt_base, unsigned char tile_x, unsigned char tile_y, unsigned char width, unsigned char height, unsigned char pitch, unsigned char* src)
{
unsigned char row;
unsigned short ppu_addr;
row = 0;
while (row != height)
{
ppu_addr = (unsigned short)(nt_base + ((unsigned short)(tile_y + row) << 5) + tile_x);
nes_ppu_stream_write(ppu_addr, src, width);
src = src + pitch;
row = (unsigned char)(row + 1);
}
}nes_nt_stream_row
Kopiert eine vollständige Zeile aus 32 Kacheln direkt in die PPU.
Syntax
void nes_nt_stream_row(unsigned short nt_base, unsigned char row, unsigned char* src32);Parameter
nt_baseLogische Nametable-Basis $2000/$2400/$2800/$2C00; die Spiegelung bestimmt die physische Unabhängigkeit.
rowZeile 0..29; wird nicht auf Bereichsgrenzen geprüft.
src3232 lesbare Kachel-IDs.
Rückgabewert
Kein Rückgabewert.
Bedingungen und Grenzen
Setzen Sie bei direkten Übertragungen das PPUCTRL-Inkrement auf eins und verwenden Sie die Einrichtung bei ausgeschalteter Darstellung oder ein ausreichend langes VBlank-Fenster. Diese Hilfsfunktionen schalten die Darstellung nicht aus und warten nicht.
Anwendungsbeispiel
nes_nt_stream_row(0x2000,2,row);Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Kombinieren Sie Zeilen-, Rechteck-, Füll- und vollständige Tabellenübertragungen. Zwei rote 32×8-Balken erscheinen über einem blauen 16×16-Quadrat und roten 16×24/32×24-Rechtecken. Direkte und eingereihte Übertragungen zeichnen an unterschiedlichen Positionen.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\batch3_nametable.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch3_nametable.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chrImplementierung und Quelltext
kitaqfc/lib/nametable_asset.h:24
Write one complete 32-tile row directly. The caller validates the row and PPU timing.
kitaqfc/lib/nametable_asset.c:103
void nes_nt_stream_row(unsigned short nt_base, unsigned char row, unsigned char* src32)
{
unsigned short ppu_addr;
ppu_addr = (unsigned short)(nt_base + ((unsigned short)row << 5));
nes_ppu_stream_write(ppu_addr, src32, 32);
}nes_game.h — Operationsmakros für Spiele
nes_game.h bietet lesbare Makronamen für VRAM-Warteschlangen, OAM und Metasprites, Controller-Abfragen, Mapper-Interrupts, geteiltes Scrolling und FDS-Operationen. Jedes Makro expandiert zu einem Compiler-Intrinsic, sodass Diagnosemeldungen und KUROSAKI-Metadaten die zugrunde liegende Hardwareoperation erfassen. Die Warteschlangenmakros nutzen die Intrinsic-Warteschlange; das OAM-DMA-Makro hat keine Parameter.
Wählen Sie die Header bewusst: nes_game.h und der Sammelheader fc.h definieren die Makros. Für die C-Funktionen binden Sie runtime.h beziehungsweise metasprite.h samt Implementierungen ohne diese Makros ein, oder entfernen Sie die gleichnamigen Makros zuvor mit #undef. Das parameterlose DMA-Makro akzeptiert das Argument page der C-Funktion nicht.
nes_fds_farcall
FDS-Hilfsmakro für bankübergreifende Aufrufe in nes_game.h. Expandiert zu __fds_overlay_farcall((bank), (func)).
Syntax
#define nes_fds_farcall(bank, func) __fds_overlay_farcall((bank), (func))Parameter
bankAusdruck für die Bank. Er wird vor dem Aufruf einmal ausgewertet; die tatsächlich geladene Bank ergibt sich jedoch aus der gelinkten Platzierung von func. Damit wird keine Adresse in einer beliebig zur Laufzeit gewählten Bank aufgerufen. Übergeben Sie einen passenden Wert wie
__bankof(func).funcName einer deklarierten Funktion ohne Parameter. Das Beispiel übergibt
u8 overlay_answer(void). Numerische Adressen, Laufzeit-Funktionszeiger und Funktionen mit erforderlichen Argumenten werden abgewiesen. Verwenden Sie bei benötigten Argumenten einen normalen Aufruf wietarget(a, b).
Rückgabewert
Acht-Bit-Ergebnis der Zielfunktion. Schlägt das Laden fehl, lässt sich aber die vorherige Bank wiederherstellen, wird die Zielfunktion nicht aufgerufen; stattdessen kommt das Ladefehlerbyte zurück. Legen Sie die Rückgabekonvention so fest, dass Fehler von normalen Ergebnissen unterscheidbar sind.
Bedingungen und Grenzen
Verwenden Sie dies mit --mapper=fds --fds-layout=fds32. Bank 0 enthält gemeinsamen Code bei $A000–$DFFF. Beim Start belegt Bank 1 den Bereich $6000–$9FFF; Banken ab 2 sind Overlays, die in dasselbe 16-KiB-Fenster geladen werden. Platzieren Sie Overlaycode oder -daten mit Direktiven wie #pragma fixed_bank 2.
Bank 1 wird aus einer separaten Boot-PRG-Datei mit 16.384 Bytes bei $6000 wiederhergestellt. Ohne Manifest sind die Standard-IDs 0 für Bank 1, 1 für gemeinsamen Code und 2 für CHR. Ein eigenes Manifest muss das Boot-PRG in 16.384-Byte-Dateien bei $6000 und $A000 aufteilen. Für Banken ab 2 lautet die Datei-ID --fds-overlay-start-id (standardmäßig 32) + Banknummer − 2.
Bei einem Aufruf in eine andere Bank wird die vorherige Bank gespeichert und vor der Rückkehr wiederhergestellt. Für verschachtelte Aufrufe gilt dasselbe. Auch nach einem teilweise fehlgeschlagenen Transfer wird eine Wiederherstellung versucht. Scheitert diese selbst, hält die Ausführung im gemeinsamen Code an, statt zu überschriebenem Code zurückzukehren. Ziele in der gemeinsamen Bank und Aufrufe innerhalb derselben Bank vermeiden unnötige Transfers.
BIOS-Aufrufe sind synchron. Diese API hält während des Ladens die Spielschleife nicht einmal pro Frame am Laufen. Verwenden Sie sie aus normalem Steuercode in der gemeinsamen Bank, nicht aus einem Interrupt-Handler. Bild- und Audiokontinuität sowie das Zusammenspiel mit dem echten BIOS müssen separat geprüft werden.
Diese Aufnahmen nutzen einen eigens geschriebenen Test für die LoadFiles-Aufrufkonvention, um kompilierten CPU-Code, Speichertransfers und jedes angezeigte Pixel zu prüfen. Echtes BIOS, Diskettentransfer-Timing, CRC und Hardwarestart werden damit nicht geprüft. KUROSAKI bildet den FDS-Controller nur teilweise nach. Eine gewöhnliche Ausführung ohne diesen Testbaustein belegt nicht dieselben Übertragungsergebnisse.
Der erste Compilerbefehl unten baut das herunterladbare Beispiel. Das Python-Prüfprogramm baut alle fünf Lektionen mit und ohne Optimierung und prüft sie anschließend in KUROSAKI. Es erstellt und entfernt einen temporären Testbaustein aus scripts/fds_abi_fixture.py; für diese Prüfungen ist kein externes BIOS nötig. Der Testbaustein ist kein BIOS für normale Spiele.
Anwendungsbeispiel
#pragma fixed_bank 0
#include "fc_fds_scene.h"
u8 choose_overlay(void){fds_result[2]++;return 2;}
#pragma fixed_bank 2
u8 overlay_answer(void){fds_result[1]++;fds_result[3]=__fds_current_bank();return 42;}
#pragma fixed_bank 0
void main(void) {
__irq_disable();fds_result[1]=0;fds_result[2]=0;
fds_result[0]=nes_fds_farcall(choose_overlay(),overlay_answer);
fds_result[4]=__fds_current_bank();fds_result[15]=165;
fds_call_screen();while(1){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
Mit dem eigens geschriebenen LoadFiles-ABI-Test ist RETURN VALUE 042; CALLBACK COUNT und BANK EXPR COUNT sind jeweils 001; BANK IN CALLBACK ist 002 und BANK AFTER RETURN 001. Funktion und Bankausdruck liefen jeweils einmal, und Bank 1 wurde nach dem Aufruf von Bank 2 wiederhergestellt. Dies ist keine Aufnahme eines echten Diskettentransfertests.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\fds_call_alias.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\fds_call_alias.fds --mapper=fds --fds-layout=fds32 --fds-no-license-bypass --fds-overlay-trim --nes-chr=.\kitaq-docs\samples\font.chr --no-cache --no-disasm
python .\kitaq-docs\tools\check_fds_load_examples.pyImplementierung und Quelltext
kitaqfc/lib/nes_game.h:41
nes_fds_load_bank
Makroschreibweise von __fds_load_bank() in nes_game.h, um über den Spielhilfsheader eine logische Bank ausdrücklich zu laden.
Syntax
#define nes_fds_load_bank(bank) __fds_load_bank((bank))Parameter
bankZu ladende logische Bank, 1 bis 254. Bank 0 ist gemeinsamer Code und kein ladbares Fenster; 255 ist für unbekannte Bankbelegung reserviert. Bei Banken ab 2 muss auch die berechnete Datei-ID in 0 bis 254 liegen.
Rückgabewert
Bei Erfolg null. Gibt 255 für Bank 0 oder 255, einen Datei-ID-Überlauf oder Bank 1 ohne Wiederherstellungsdatei zurück. Ein fehlgeschlagener BIOS-Transfer liefert dessen Fehlerbyte. Argumentfehler vor dem Transfer bewahren den Belegungsvermerk; fehlgeschlagene BIOS-Transfers setzen ihn auf 255 (unbekannt).
Bedingungen und Grenzen
Verwenden Sie dies mit --mapper=fds --fds-layout=fds32. Bank 0 enthält gemeinsamen Code bei $A000–$DFFF. Beim Start belegt Bank 1 den Bereich $6000–$9FFF; Banken ab 2 sind Overlays, die in dasselbe 16-KiB-Fenster geladen werden. Platzieren Sie Overlaycode oder -daten mit Direktiven wie #pragma fixed_bank 2.
Expandiert zu __fds_load_bank((bank)), ohne bank mehrfach auszuwerten. Argumentgrenzen, Belegungsprüfung und Fehlerverhalten entsprechen dem Intrinsic.
Bank 1 wird aus einer separaten Boot-PRG-Datei mit 16.384 Bytes bei $6000 wiederhergestellt. Ohne Manifest sind die Standard-IDs 0 für Bank 1, 1 für gemeinsamen Code und 2 für CHR. Ein eigenes Manifest muss das Boot-PRG in 16.384-Byte-Dateien bei $6000 und $A000 aufteilen. Für Banken ab 2 lautet die Datei-ID --fds-overlay-start-id (standardmäßig 32) + Banknummer − 2.
Mit der standardmäßigen Belegungsprüfung gibt eine bereits vermerkte Bank ohne Diskettenzugriff null zurück. --fds-no-overlay-guard deaktiviert diese Abkürzung in __fds_load_bank(). Ein erfolgreicher Ladevorgang vermerkt die angeforderte Bank. Dieser Vermerk ist keine Prüfung des Speicherinhalts.
Das direkte Laden einer anderen Bank aus Code im Fenster $6000–$9FFF kann die laufende Funktion oder deren Rücksprungadresse überschreiben. Das Beispiel legt Aufrufer und Anzeigecode in #pragma fixed_bank 0 ab. Um eine Funktion in einer anderen Bank aufzurufen und zurückzukehren, verwenden Sie __fds_overlay_farcall() oder einen normalen typisierten Funktionsaufruf.
BIOS-Aufrufe sind synchron. Diese API hält während des Ladens die Spielschleife nicht einmal pro Frame am Laufen. Verwenden Sie sie aus normalem Steuercode in der gemeinsamen Bank, nicht aus einem Interrupt-Handler. Bild- und Audiokontinuität sowie das Zusammenspiel mit dem echten BIOS müssen separat geprüft werden.
Diese Aufnahmen nutzen einen eigens geschriebenen Test für die LoadFiles-Aufrufkonvention, um kompilierten CPU-Code, Speichertransfers und jedes angezeigte Pixel zu prüfen. Echtes BIOS, Diskettentransfer-Timing, CRC und Hardwarestart werden damit nicht geprüft. KUROSAKI bildet den FDS-Controller nur teilweise nach. Eine gewöhnliche Ausführung ohne diesen Testbaustein belegt nicht dieselben Übertragungsergebnisse.
Der erste Compilerbefehl unten baut das herunterladbare Beispiel. Das Python-Prüfprogramm baut alle fünf Lektionen mit und ohne Optimierung und prüft sie anschließend in KUROSAKI. Es erstellt und entfernt einen temporären Testbaustein aus scripts/fds_abi_fixture.py; für diese Prüfungen ist kein externes BIOS nötig. Der Testbaustein ist kein BIOS für normale Spiele.
Anwendungsbeispiel
#pragma fixed_bank 0
#include "fc_fds_scene.h"
#pragma fixed_bank 2
__prg_rom u8 bank_payload[4]={11,22,33,44};
#pragma fixed_bank 0
void main(void) {
__irq_disable();
fds_result[0]=__fds_load_bank(2);
fds_result[1]=__fds_current_bank();
fds_result[2]=__fds_require_bank(2);
fds_result[3]=bank_payload[0];fds_result[4]=bank_payload[3];
fds_result[5]=nes_fds_load_bank(1);
fds_result[6]=__fds_current_bank();
fds_result[7]=__fds_require_bank(1);
fds_result[8]=__fds_load_bank(0);
fds_result[9]=__fds_load_bank(255);
fds_result[15]=165;
m_init();m_text(2,2,"FDS DATA WINDOW");m_wait();
m_text(2,5,"LOAD BANK 2 STATUS");fds_number(25,5,fds_result[0]);m_wait();
m_text(2,7,"FIRST / LAST BYTE");fds_number(21,7,fds_result[3]);fds_number(25,7,fds_result[4]);m_wait();
m_text(2,9,"REQUIRE SAME BANK");fds_number(25,9,fds_result[2]);m_wait();
m_text(2,11,"RESTORE BANK 1");fds_number(25,11,fds_result[5]);m_wait();
m_text(2,13,"RESIDENT BANK");fds_number(25,13,fds_result[6]);m_wait();
m_text(2,16,"INVALID BANKS 0 / 255");m_wait();
fds_number(2,18,fds_result[8]);fds_number(8,18,fds_result[9]);m_wait();
while(1){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
Mit dem eigens geschriebenen LoadFiles-ABI-Test sind LOAD BANK 2 STATUS, REQUIRE SAME BANK und RESTORE BANK 1 jeweils 000. FIRST / LAST BYTE zeigt 011 und 044 aus den vier übertragenen Bytes; RESIDENT BANK ist nach der Wiederherstellung 001. Die ungültigen Banken 0 und 255 liefern jeweils 255. Das Anfordern derselben Bank löst keinen weiteren Ladevorgang aus: Die geprüften Dateianforderungen sind 32 und danach 0.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\fds_bank_load.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\fds_bank_load.fds --mapper=fds --fds-layout=fds32 --fds-no-license-bypass --fds-overlay-trim --nes-chr=.\kitaq-docs\samples\font.chr --no-cache --no-disasm
python .\kitaq-docs\tools\check_fds_load_examples.pyImplementierung und Quelltext
kitaqfc/lib/nes_game.h:40
nes_fds_wave_load
Makro, das sein Array an __fds_wave_load zum Laden einer 64-Byte-Welle weiterreicht.
Syntax
#define nes_fds_wave_load(wave64) __fds_wave_load((wave64))Parameter
wave64Vierundsechzig FDS-Wellenbytes mit je einer Sechsbitamplitude 0..63. NULL wird nicht geprüft.
Rückgabewert
Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.
Bedingungen und Grenzen
Erstellen Sie mit --mapper=fds ein .fds-Abbild. Diese Lektion verwendet Sound ohne Datenträger-I/O. Die Aufnahme nutzt KUROSAKIs direkten RAM-Start und Audiomodell. Die leere Testfirmware implementiert keine BIOS-Routinen und wird nicht verteilt. Normaler Diskettenstart und echte Hardware benötigen eine passende Startumgebung.
Anwendungsbeispiel
// Mapper 20 sound lesson: original 64-step triangle and two sustained pitches.
#include "fc_sound_example.h"
#include "fds_sound.h"
#include "nes_game.h"
__location(0x4087) u8 mod_control;
__location(0x4085) u8 mod_counter;
u8 triangle[64]; u8 modulation[32];
void main(void) {
u8 i;
sound_begin("FDS WAVE AND VOLUME");
for(i=0;i<32;i++) { triangle[i]=(u8)(i*2); triangle[63-i]=(u8)(i*2); modulation[i]=0; }
__fds_sound_enable();
// Halt/reset modulation before writing the 32 values (each writes two slots).
mod_control=0x80; mod_counter=0;
__fds_mod_load(modulation);
__fds_wave_load(triangle);
sound_result[0]=*((u8*)0x4040); sound_result[1]=*((u8*)0x405F);
__fds_freq_set(1031);
__fds_volume_set(24);
sound_wait(60);
__fds_volume_set(0); sound_wait(30);
// This macro forwards the same 64-byte load. Use raw envelope registers.
nes_fds_wave_load(triangle);
__fds_env_set(0x98,0x80,0);
__fds_freq_set(1545);
sound_wait(60);
__fds_volume_set(0); sound_wait(30);
sound_end();
}Erwartetes Ergebnis
Ein eigenes 64-stufiges Dreieck spielt bei etwa 440 Hz, pausiert, spielt bei etwa 660 Hz und stoppt. Die zweite Note nutzt nes_fds_wave_load und rohe Hüllkurveneinstellungen. Geprüft werden Audiomodell und Direktstart, nicht BIOS-gesteuerter Diskettenstart.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\sound_fds.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\fc-fds.fds --mapper=fds --nes-chr=.\kitaq-docs\samples\font.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/nes_game.h:39
#define nes_fds_wave_load(wave64) __fds_wave_load((wave64))nes_mapper_irq_ack
Quittierungsmakro für Handler aus nes_game.h. Expandiert zu __mapper_irq_ack() und löscht sowie deaktiviert die Anforderung zugleich.
Syntax
#define nes_mapper_irq_ack() __mapper_irq_ack()Rückgabewert
Kein Rückgabewert.
Bedingungen und Grenzen
Die Intrinsic-Deklarationen stehen in intrinsics.h. Binden Sie für die Makros nes_mapper_irq_* den Header nes_game.h ein. Wählen Sie die Platine beim Build mit --mapper.
Nur MMC3. Erforderlich sind ein __nes_irq-Handler, qualifizierte PPU-A12-Übergänge, Mapper-IRQ-Freigabe und CPU-__irq_enable(). Das Beispiel aktiviert die Darstellung mit Hintergrundmustern bei $0000 und Spritemustern bei $1000. Die Lektion prüft keine Synchronisierung auf eine exakte Zeile echter Hardware.
MMC3-Quittierung und -Deaktivierung schreiben beide nach $E000. Das löscht die aktuelle Anforderung und deaktiviert weitere. Rufen Sie zum gewünschten Zeitpunkt erneut __mapper_irq_enable() auf, um einen weiteren Interrupt freizugeben. Beide Vorgänge ändern weder CPU-Interruptmaske noch NMI-Freigabe.
Der Compiler erzeugt RTI für eigene Interrupt-Handler. Der Handler muss aber alle von ihm geänderten A/X/Y-Register und gemeinsamen temporären Speicher sichern. Das Beispiel sichert A/X/Y und verwendet nur ein Byteinkrement sowie eine argumentlose Quittierung. Prüfen Sie bei zusätzlichen C-Aufrufen auch deren gemeinsam genutzten Speicher.
Anwendungsbeispiel
void __nes_irq(void) {
__asm {
PHA
TXA
PHA
TYA
PHA
}
irq_count++;
if (irq_phase == 1) { nes_mapper_irq_ack(); }
else { __mapper_irq_ack(); }
__asm {
PLA
TAY
PLA
TAX
PLA
}
}Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Das MMC3-Beispiel zeigt CHR-Marker 19/20, 21/22 und 23/24. CIRAM-Lesewerte ergeben A B A B bei vertikaler Spiegelung und A A B B bei horizontaler. Die IRQ-Zählerstände sind 01→02→03→03: Jede der ersten drei ausdrücklichen Freigaben erlaubt einen Interrupt; nach Deaktivierung bleibt der Stand gleich. Jede Stufe wartet sechs Frames.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\mapper_controls.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\mapper_controls.nes --mapper=mmc3 --nes-chr=.\kitaq-docs\samples\mapper_banks.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/nes_game.h:36
nes_mapper_irq_disable
Deaktiviert MMC3-IRQ und löscht die ausstehende Anforderung über nes_game.h. Expandiert zu __mapper_irq_disable().
Syntax
#define nes_mapper_irq_disable() __mapper_irq_disable()Rückgabewert
Kein Rückgabewert.
Bedingungen und Grenzen
Die Intrinsic-Deklarationen stehen in intrinsics.h. Binden Sie für die Makros nes_mapper_irq_* den Header nes_game.h ein. Wählen Sie die Platine beim Build mit --mapper.
Nur MMC3. Erforderlich sind ein __nes_irq-Handler, qualifizierte PPU-A12-Übergänge, Mapper-IRQ-Freigabe und CPU-__irq_enable(). Das Beispiel aktiviert die Darstellung mit Hintergrundmustern bei $0000 und Spritemustern bei $1000. Die Lektion prüft keine Synchronisierung auf eine exakte Zeile echter Hardware.
MMC3-Quittierung und -Deaktivierung schreiben beide nach $E000. Das löscht die aktuelle Anforderung und deaktiviert weitere. Rufen Sie zum gewünschten Zeitpunkt erneut __mapper_irq_enable() auf, um einen weiteren Interrupt freizugeben. Beide Vorgänge ändern weder CPU-Interruptmaske noch NMI-Freigabe.
Der Compiler erzeugt RTI für eigene Interrupt-Handler. Der Handler muss aber alle von ihm geänderten A/X/Y-Register und gemeinsamen temporären Speicher sichern. Das Beispiel sichert A/X/Y und verwendet nur ein Byteinkrement sowie eine argumentlose Quittierung. Prüfen Sie bei zusätzlichen C-Aufrufen auch deren gemeinsam genutzten Speicher.
Anwendungsbeispiel
nes_mapper_irq_disable();
for (i=0;i<6;i++) { m_wait(); }
mapper_result[18]=irq_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 MMC3-Beispiel zeigt CHR-Marker 19/20, 21/22 und 23/24. CIRAM-Lesewerte ergeben A B A B bei vertikaler Spiegelung und A A B B bei horizontaler. Die IRQ-Zählerstände sind 01→02→03→03: Jede der ersten drei ausdrücklichen Freigaben erlaubt einen Interrupt; nach Deaktivierung bleibt der Stand gleich. Jede Stufe wartet sechs Frames.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\mapper_controls.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\mapper_controls.nes --mapper=mmc3 --nes-chr=.\kitaq-docs\samples\mapper_banks.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/nes_game.h:35
nes_mapper_irq_enable
Aktiviert MMC3-IRQ über nes_game.h. Expandiert zu __mapper_irq_enable(), ohne die CPU-Interruptmaske zu ändern.
Syntax
#define nes_mapper_irq_enable() __mapper_irq_enable()Rückgabewert
Kein Rückgabewert.
Bedingungen und Grenzen
Die Intrinsic-Deklarationen stehen in intrinsics.h. Binden Sie für die Makros nes_mapper_irq_* den Header nes_game.h ein. Wählen Sie die Platine beim Build mit --mapper.
Nur MMC3. Erforderlich sind ein __nes_irq-Handler, qualifizierte PPU-A12-Übergänge, Mapper-IRQ-Freigabe und CPU-__irq_enable(). Das Beispiel aktiviert die Darstellung mit Hintergrundmustern bei $0000 und Spritemustern bei $1000. Die Lektion prüft keine Synchronisierung auf eine exakte Zeile echter Hardware.
MMC3-Quittierung und -Deaktivierung schreiben beide nach $E000. Das löscht die aktuelle Anforderung und deaktiviert weitere. Rufen Sie zum gewünschten Zeitpunkt erneut __mapper_irq_enable() auf, um einen weiteren Interrupt freizugeben. Beide Vorgänge ändern weder CPU-Interruptmaske noch NMI-Freigabe.
Der Compiler erzeugt RTI für eigene Interrupt-Handler. Der Handler muss aber alle von ihm geänderten A/X/Y-Register und gemeinsamen temporären Speicher sichern. Das Beispiel sichert A/X/Y und verwendet nur ein Byteinkrement sowie eine argumentlose Quittierung. Prüfen Sie bei zusätzlichen C-Aufrufen auch deren gemeinsam genutzten Speicher.
Anwendungsbeispiel
nes_mapper_irq_set(15); nes_mapper_irq_enable();
for (i=0;i<6;i++) { m_wait(); }
mapper_result[16]=irq_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 MMC3-Beispiel zeigt CHR-Marker 19/20, 21/22 und 23/24. CIRAM-Lesewerte ergeben A B A B bei vertikaler Spiegelung und A A B B bei horizontaler. Die IRQ-Zählerstände sind 01→02→03→03: Jede der ersten drei ausdrücklichen Freigaben erlaubt einen Interrupt; nach Deaktivierung bleibt der Stand gleich. Jede Stufe wartet sechs Frames.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\mapper_controls.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\mapper_controls.nes --mapper=mmc3 --nes-chr=.\kitaq-docs\samples\mapper_banks.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/nes_game.h:34
nes_mapper_irq_set
MMC3-Latchmakro aus nes_game.h. Übergibt sein Argument einmal an __mapper_irq_set und fordert Nachladen an.
Syntax
#define nes_mapper_irq_set(scanline) __mapper_irq_set((scanline))Parameter
scanlineAcht-Bit-Latchwert des Zählers von 0 bis 255, keine absolute Bildschirm-Y-Koordinate. Nachladezeitpunkt und qualifizierte PPU-A12-Übergänge bestimmen die Auslösung. Null ist gültig und bedeutet nicht „Interrupts deaktivieren“.
Rückgabewert
Kein Rückgabewert.
Bedingungen und Grenzen
Die Intrinsic-Deklarationen stehen in intrinsics.h. Binden Sie für die Makros nes_mapper_irq_* den Header nes_game.h ein. Wählen Sie die Platine beim Build mit --mapper.
Nur MMC3. Erforderlich sind ein __nes_irq-Handler, qualifizierte PPU-A12-Übergänge, Mapper-IRQ-Freigabe und CPU-__irq_enable(). Das Beispiel aktiviert die Darstellung mit Hintergrundmustern bei $0000 und Spritemustern bei $1000. Die Lektion prüft keine Synchronisierung auf eine exakte Zeile echter Hardware.
MMC3-Quittierung und -Deaktivierung schreiben beide nach $E000. Das löscht die aktuelle Anforderung und deaktiviert weitere. Rufen Sie zum gewünschten Zeitpunkt erneut __mapper_irq_enable() auf, um einen weiteren Interrupt freizugeben. Beide Vorgänge ändern weder CPU-Interruptmaske noch NMI-Freigabe.
Der Compiler erzeugt RTI für eigene Interrupt-Handler. Der Handler muss aber alle von ihm geänderten A/X/Y-Register und gemeinsamen temporären Speicher sichern. Das Beispiel sichert A/X/Y und verwendet nur ein Byteinkrement sowie eine argumentlose Quittierung. Prüfen Sie bei zusätzlichen C-Aufrufen auch deren gemeinsam genutzten Speicher.
Anwendungsbeispiel
nes_mapper_irq_set(15); nes_mapper_irq_enable();
for (i=0;i<6;i++) { m_wait(); }
mapper_result[16]=irq_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 MMC3-Beispiel zeigt CHR-Marker 19/20, 21/22 und 23/24. CIRAM-Lesewerte ergeben A B A B bei vertikaler Spiegelung und A A B B bei horizontaler. Die IRQ-Zählerstände sind 01→02→03→03: Jede der ersten drei ausdrücklichen Freigaben erlaubt einen Interrupt; nach Deaktivierung bleibt der Stand gleich. Jede Stufe wartet sechs Frames.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\mapper_controls.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\mapper_controls.nes --mapper=mmc3 --nes-chr=.\kitaq-docs\samples\mapper_banks.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/nes_game.h:33
nes_oam_clear
Makro aus nes_game.h: Es wird zum in der Syntax gezeigten Intrinsic expandiert. Binden Sie diesen Header ein; für diese Operation ist keine C-Implementierungsdatei erforderlich.
Blendet alle 64 Sprites im Schattenpuffer der Seite 02 aus, indem jedes Y-Byte auf 0xF0 gesetzt wird. Kachelnummern, Attribute und X-Koordinaten bleiben erhalten.
Syntax
#define nes_oam_clear() __oam_clear()Rückgabewert
Keiner (void).
Bedingungen und Grenzen
Diese Operationen ändern den CPU-RAM bei 0x0200–0x02FF, nicht sofort das Hardware-OAM. Übertragen Sie die fertige Seite mit __oam_dma. Belegungsflags, Koordinatenfelder und Zähler der Sprite-Bibliothek werden nicht mitgeführt. Interrupt-Routinen dürfen eine noch unvollständige Seite weder ändern noch übertragen.
Anwendungsbeispiel
nes_sprite_set(63,144,111,128,0); // Seed the CLEAR row with a visible entry.
nes_oam_clear(); // Set every Y byte to 240; tile, attributes and X are retained.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 zeigt jede Operation in einer beschrifteten Zeile. SET und MOVE zeigen 8×8-Pfeile nach rechts bei (144,16) und (144,32), TILE ein grünes Quadrat bei (144,48) und ATTR den in beiden Achsen gespiegelten Pfeil bei (144,64). HIDE bei (144,80) und CLEAR bei (144,112) müssen leer bleiben. META zeigt zwei Pfeile bei (136,96) und (144,96), den zweiten horizontal gespiegelt. NEXT 07 bezeichnet die nächste Position nach den Einträgen 5 und 6. Die Ränder sind rot, der Schaft grün und die Spitzendetails blau. Geprüft werden 8.704 Pixel je Bild und die übertragenen OAM-Bytes; echte Hardware wurde nicht getestet.
Das Programm ALIASES bereitet die beschrifteten Zeilen mit Makros aus nes_game.h vor und sendet Seite 02 mit nes_oam_dma(). TRANSFER zeigt den 8×8-Pfeil bei (144,128). Das Beispiel verwendet die Makros, ohne runtime.c oder metasprite.c einzubinden.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\oam_aliases.c -I .\kitaqfc\lib -I .\kitaq-docs\samples --nes-chr=.\kitaq-docs\samples\sprite_example.chr -o .\out\oam_aliases.nes --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/nes_game.h:21
#define nes_oam_clear() __oam_clear()nes_oam_dma
Diesen Namen gibt es in zwei Formen. Das parameterlose Makro nes_oam_dma() überträgt Seite 02 über __oam_dma(). Die C-Funktion nes_oam_dma(page) überträgt die angegebene 256-Byte-Seite des CPU-Speichers. Beide setzen OAMADDR auf null und übertragen die ganze Seite, ohne die Quelle zu verändern.
Syntax
#define nes_oam_dma() __oam_dma()
// C function declared in runtime.h:
void nes_oam_dma(unsigned char page);Parameter
page (C)Oberes Byte der CPU-Quelladresse: Übergeben Sie für
0x0400–0x04FFden Wert4, nicht0x0400. Stellen Sie eine vollständige lesbare Seite mit 256 Byte bereit und halten Sie die nötige Bank eingeblendet. Vermeiden Sie Seiten mit E/A-Registern, deren Lesezugriffe Nebenwirkungen haben können. Die Quelle wird nicht geprüft.
Rückgabewert
Keiner (void).
Bedingungen und Grenzen
Wählen Sie die Header bewusst: nes_game.h und der Sammelheader fc.h definieren die Makros. Für die C-Funktionen binden Sie runtime.h beziehungsweise metasprite.h samt Implementierungen ohne diese Makros ein, oder entfernen Sie die gleichnamigen Makros zuvor mit #undef. Das parameterlose DMA-Makro akzeptiert das Argument page der C-Funktion nicht.
Die C-Metasprite-Funktionen benötigen nes_oam_shadow[256]. runtime.c definiert diesen Puffer bei 0x0200, reserviert zusätzlich 0x0300–0x03BF für seine VRAM-Warteschlange und stellt __nes_nmi bereit. Binden Sie jede Implementierung nur einmal ein und stimmen Sie die Interruptbehandlung mit dem übrigen Programm ab.
Rufen Sie DMA während VBlank oder bei abgeschalteter Bildausgabe auf. Keine der beiden Formen wartet auf VBlank. Bereiten Sie zuerst die gesamte Quellseite vor und übertragen Sie sie anschließend; Interrupts dürfen die Seite während der Vorbereitung nicht verändern.
Anwendungsbeispiel
m_wait();nes_oam_dma(); // Expand to the page-02 compiler intrinsic.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 zeigt jede Operation in einer beschrifteten Zeile. SET und MOVE zeigen 8×8-Pfeile nach rechts bei (144,16) und (144,32), TILE ein grünes Quadrat bei (144,48) und ATTR den in beiden Achsen gespiegelten Pfeil bei (144,64). HIDE bei (144,80) und CLEAR bei (144,112) müssen leer bleiben. META zeigt zwei Pfeile bei (136,96) und (144,96), den zweiten horizontal gespiegelt. NEXT 07 bezeichnet die nächste Position nach den Einträgen 5 und 6. Die Ränder sind rot, der Schaft grün und die Spitzendetails blau. Geprüft werden 8.704 Pixel je Bild und die übertragenen OAM-Bytes; echte Hardware wurde nicht getestet.
Das Programm ALIASES bereitet die beschrifteten Zeilen mit Makros aus nes_game.h vor und sendet Seite 02 mit nes_oam_dma(). TRANSFER zeigt den 8×8-Pfeil bei (144,128). Das Beispiel verwendet die Makros, ohne runtime.c oder metasprite.c einzubinden.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\oam_aliases.c -I .\kitaqfc\lib -I .\kitaq-docs\samples --nes-chr=.\kitaq-docs\samples\sprite_example.chr -o .\out\oam_aliases.nes --no-cache --no-disasmAnwendungsbeispiel
m_wait();nes_oam_dma(4); // C function: source address high byte, 0x0400 -> 4.Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
C-RUNTIME kombiniert die C-Funktionen. PAIR zeigt zwei 8×8-Pfeile bei (144,32) und (152,32), den zweiten horizontal gespiegelt. Ein weiteres Paar bei y=64 wird ausgeblendet; HIDE RANGE muss daher leer bleiben. Die beiden Zeichenaufrufe verwenden die Slots 4–5 und 6–7 und ergeben NEXT 08. Seite 02 wird nach Seite 04 kopiert; nur Slot 8 wechselt vom Pfeil-Tile 128 zum Quadrat-Tile 129. nes_oam_dma(4) muss neben PAGE 04 bei (144,96) ein grünes Quadrat anzeigen, während Seite 02 Tile 128 behält.
Die Pfeile haben rote Ränder, grüne Schäfte und blaue Details an der Spitze; das Quadrat-Tile 129 ist grün. Die Prüfung vergleicht pro Bild 8.704 Farbpixel, alle 256 übertragenen OAM-Bytes und die Beschriftungen. Physische Hardware wurde nicht getestet.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\oam_c_helpers.c -I .\kitaqfc\lib -I .\kitaq-docs\samples --nes-chr=.\kitaq-docs\samples\sprite_example.chr -o .\out\oam_c_helpers.nes --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/nes_game.h:23
kitaqfc/lib/runtime.c:245
void nes_oam_dma(unsigned char page)
{
OAMADDR = 0;
OAMDMA = page;
}nes_pad1
Funktionsähnliches Makro, das exakt zu __pad_read1_safe() expandiert. Liest Controller 1 und liefert dessen rohe NES-Maske; kein Alias für den gespeicherten Zustand von input_current().
Syntax
#define nes_pad1() __pad_read1_safe()Rückgabewert
Eine 8-Bit-Haltemaske in roher NES-Reihenfolge. Jedes gesetzte Bit steht für eine gedrückte Taste, 0 für keine. Kein auf 0/1 normalisierter Wahrheitswert.
Bedingungen und Grenzen
Rohes NES-Format: A=0x01, B=0x02, SELECT=0x04, START=0x08, UP=0x10, DOWN=0x20, LEFT=0x40, RIGHT=0x80. Ein gesetztes Bit bedeutet gedrückt. Verwende diese Werte mit nes_pad_* und rohen __pad_*-Ergebnissen, nicht die gemeinsamen BTN_*-Masken aus input.h.
Dieser Aufruf liest einen neuen Hardwarezustand. Er aktualisiert weder den gespeicherten input_*- noch den nes_pad1_*-Zustand und erzeugt keine Druck-, Loslass- oder Wiederholungsereignisse. Speichere das Ergebnis und vergleiche es bei Bedarf mit deiner vorherigen Maske.
Die sichere Abfrage wiederholt Paare vollständiger Lesevorgänge, bis beide Masken übereinstimmen. Jeder Lesevorgang strobt $4016 und setzt die serielle Leseposition beider Controller zurück. Die Zahl der Versuche ist unbegrenzt. Diese Prüfung belegt keine Kompatibilität mit sämtlichen DMC-/Peripheriekombinationen.
Anwendungsbeispiel
alias1=nes_pad1(); // Macro for __pad_read1_safe(), using NES raw bits.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 vergleicht beide Controlleranschlüsse, einfache und auf Übereinstimmung geprüfte Lesevorgänge, Maskenfilter und Kurzmakros. Halten Sie A + Rechts auf Controller 1 und B + Links auf Controller 2 gedrückt. RAW P1, SAFE P1 und ALIAS P1 sind 129; die drei P2-Werte sind 66. BUTTONS P1 ist 1 und DIRS P1 ist 128: Der Richtungsfilter behält die oberen Bitpositionen bei. FAILED CHECKS muss 0 sein. Die erfassten Werte bleiben sichtbar.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\input_raw.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\input_raw.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr --no-disasm --no-cacheImplementierung und Quelltext
kitaqfc/lib/nes_game.h:30
nes_pad2
Funktionsähnliches Makro, das exakt zu __pad_read2_safe() expandiert. Liest Controller 2 und liefert dessen rohe NES-Maske; kein Alias für den gespeicherten Zustand von input_current().
Syntax
#define nes_pad2() __pad_read2_safe()Rückgabewert
Eine 8-Bit-Haltemaske in roher NES-Reihenfolge. Jedes gesetzte Bit steht für eine gedrückte Taste, 0 für keine. Kein auf 0/1 normalisierter Wahrheitswert.
Bedingungen und Grenzen
Rohes NES-Format: A=0x01, B=0x02, SELECT=0x04, START=0x08, UP=0x10, DOWN=0x20, LEFT=0x40, RIGHT=0x80. Ein gesetztes Bit bedeutet gedrückt. Verwende diese Werte mit nes_pad_* und rohen __pad_*-Ergebnissen, nicht die gemeinsamen BTN_*-Masken aus input.h.
Dieser Aufruf liest einen neuen Hardwarezustand. Er aktualisiert weder den gespeicherten input_*- noch den nes_pad1_*-Zustand und erzeugt keine Druck-, Loslass- oder Wiederholungsereignisse. Speichere das Ergebnis und vergleiche es bei Bedarf mit deiner vorherigen Maske.
Die sichere Abfrage wiederholt Paare vollständiger Lesevorgänge, bis beide Masken übereinstimmen. Jeder Lesevorgang strobt $4016 und setzt die serielle Leseposition beider Controller zurück. Die Zahl der Versuche ist unbegrenzt. Diese Prüfung belegt keine Kompatibilität mit sämtlichen DMC-/Peripheriekombinationen.
Anwendungsbeispiel
alias2=nes_pad2(); // Macro for __pad_read2_safe(), using NES raw bits.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 vergleicht beide Controlleranschlüsse, einfache und auf Übereinstimmung geprüfte Lesevorgänge, Maskenfilter und Kurzmakros. Halten Sie A + Rechts auf Controller 1 und B + Links auf Controller 2 gedrückt. RAW P1, SAFE P1 und ALIAS P1 sind 129; die drei P2-Werte sind 66. BUTTONS P1 ist 1 und DIRS P1 ist 128: Der Richtungsfilter behält die oberen Bitpositionen bei. FAILED CHECKS muss 0 sein. Die erfassten Werte bleiben sichtbar.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\input_raw.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\input_raw.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr --no-disasm --no-cacheImplementierung und Quelltext
kitaqfc/lib/nes_game.h:31
nes_split_scroll_sprite0
Bildschirmteilungsmakro aus nes_game.h. Übergibt X und Y je einmal an __split_scroll_sprite0 und führt dieselben Warte- und Scrollzugriffe aus.
Syntax
#define nes_split_scroll_sprite0(x,y) __split_scroll_sprite0((x),(y))Parameter
xHorizontaler Scrollwert 0..255, keine Objekt-Bildschirm-X-Koordinate. Das Beispiel nutzt 32, um den unteren Teil desselben Hintergrunds 32 Pixel nach links zu verschieben.
yVorübergehender vertikaler Scrollwert 0..255; üblicher sichtbarer Bereich 0..239. Die Hilfe schreibt $2005 und ändert daher während der Darstellung die laufende Vertikalposition nicht sofort. Das horizontale Teilungsbeispiel übergibt null.
Rückgabewert
Kein Rückgabewert.
Bedingungen und Grenzen
Überlagern Sie ein deckendes Pixel von OAM-Sprite 0 mit einem deckenden Hintergrundpixel bei aktivierten Ebenen. Die Priorität hinter dem Hintergrund erlaubt weiterhin einen Treffer. Die linken acht Pixel erfordern die jeweiligen Ebenenfreigaben; Überlappung bei X=255 löst keinen Treffer aus.
Fragt PPUSTATUS ($2002), Bit 6 ab, bis es gelöscht und danach gesetzt ist. Bei bereits erfolgtem Treffer wartet der Aufruf auf einen neuen im nächsten Frame. Lesen quittiert das Flag nicht; die PPU löscht es während Pre-Render.
Keine Zeitbegrenzung oder Fehlerrückgabe. Verstecktes Sprite 0, transparenter Hintergrund, deaktivierte Darstellung oder sonst fehlende Überlappung lassen den Aufruf blockieren. Stellen Sie vorher einen Treffer sicher. CPU-IRQ-Freigabe ist nicht nötig, NMI wird nicht aktiviert. Das Beispiel aktiviert NMI für seine separate Framewartefunktion.
Lesen von $2002 beeinflusst auch das gemeinsame PPU-Adress-/Scrollschreiblatch und das VBlank-Flag. Fügen Sie diesen Aufruf nicht zwischen die beiden Schreibzugriffe einer $2005-/$2006-Operation ein. Nutzen Sie Hauptcode, keinen NMI-/IRQ-Handler.
Nach dem Treffer wird $2002 gelesen und X, dann Y nach $2005 geschrieben. Fein-X wirkt sofort, Grob-X beim nächsten horizontalen Nachladen. Y wirkt normalerweise beim nächsten Pre-Render-Nachladen, sofern kein anderer Scrollzugriff es vorher ersetzt. Dies ist keine sofortige beliebige X/Y-Rasterneupositionierung.
Polling und Befehlsausführung verzögern die Schreibzugriffe. KUROSAKI rendert zeilenweise; die Aufnahmen belegen daher keine punktgenaue Hardwaregrenze. Das Beispiel legt den Wechsel in das weiße Band Y=96..103, abseits der blauen und roten Balken.
Der gemeinsame Header fc_sprite0_scene.h bereitet eigene blaue/rote Balken und ein weißes horizontales Band vor. Sprite 0 liegt bei (16,96) hinter dem Hintergrund; sein rohes OAM-Y ist 95, da Anzeige-Y=OAM-Y+1. Jeder Frame setzt während VBlank den oberen Scroll auf null zurück und wartet dann auf den Treffer.
NESdev: PPU-Referenz für Programmierer
Anwendungsbeispiel
void main(void) {
s0_prepare();
while (1) {
s0_frame();
nes_split_scroll_sprite0(32,0);
s0_completed++;
}
}Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Über dem weißen Band liegt Blau bei X=64..95 und Rot bei X=160..191. Darunter ab Y=104 liegt Blau bei X=32..63, Rot bei X=128..159; nur der untere Bereich wandert 32 Pixel nach links. Das Band liegt bei Y=96..103, die Balken enden bei Y=207. Geprüft werden ein Abschluss pro Frame sowie Position und Farbe jedes Bildpixels.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\sprite0_split_alias.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\sprite0_split_alias.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\sprite0_scene.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/nes_game.h:37
nes_sprite_hide
Makro aus nes_game.h: Es wird zum in der Syntax gezeigten Intrinsic expandiert. Binden Sie diesen Header ein; für diese Operation ist keine C-Implementierungsdatei erforderlich.
Blendet einen Sprite im Schattenpuffer aus, indem Y auf 0xF0 gesetzt wird. X, Kachel und Attribute bleiben zur Wiederverwendung erhalten. Die Funktion gibt keinen Platz frei und ändert den Belegungszähler der Sprite-Bibliothek nicht.
Syntax
#define nes_sprite_hide(i) __sprite_hide((i))Parameter
iSprite-Index von 0 bis 63, kein Byte-Offset. Intern wird er mit vier multipliziert und als 8-Bit-Position gespeichert. Werte außerhalb des Bereichs werden modulo 64 umgebrochen und können einen anderen Eintrag überschreiben. Eine Belegungsprüfung findet nicht statt.
Rückgabewert
Keiner (void).
Bedingungen und Grenzen
Diese Operationen ändern den CPU-RAM bei 0x0200–0x02FF, nicht sofort das Hardware-OAM. Übertragen Sie die fertige Seite mit __oam_dma. Belegungsflags, Koordinatenfelder und Zähler der Sprite-Bibliothek werden nicht mitgeführt. Interrupt-Routinen dürfen eine noch unvollständige Seite weder ändern noch übertragen.
Anwendungsbeispiel
nes_sprite_hide(4); // The HIDE row remains empty after DMA.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 zeigt jede Operation in einer beschrifteten Zeile. SET und MOVE zeigen 8×8-Pfeile nach rechts bei (144,16) und (144,32), TILE ein grünes Quadrat bei (144,48) und ATTR den in beiden Achsen gespiegelten Pfeil bei (144,64). HIDE bei (144,80) und CLEAR bei (144,112) müssen leer bleiben. META zeigt zwei Pfeile bei (136,96) und (144,96), den zweiten horizontal gespiegelt. NEXT 07 bezeichnet die nächste Position nach den Einträgen 5 und 6. Die Ränder sind rot, der Schaft grün und die Spitzendetails blau. Geprüft werden 8.704 Pixel je Bild und die übertragenen OAM-Bytes; echte Hardware wurde nicht getestet.
Das Programm ALIASES bereitet die beschrifteten Zeilen mit Makros aus nes_game.h vor und sendet Seite 02 mit nes_oam_dma(). TRANSFER zeigt den 8×8-Pfeil bei (144,128). Das Beispiel verwendet die Makros, ohne runtime.c oder metasprite.c einzubinden.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\oam_aliases.c -I .\kitaqfc\lib -I .\kitaq-docs\samples --nes-chr=.\kitaq-docs\samples\sprite_example.chr -o .\out\oam_aliases.nes --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/nes_game.h:26
#define nes_sprite_hide(i) __sprite_hide((i))nes_sprite_move
Makro aus nes_game.h: Es wird zum in der Syntax gezeigten Intrinsic expandiert. Binden Sie diesen Header ein; für diese Operation ist keine C-Implementierungsdatei erforderlich.
Ändert nur die X- und Y-Bytes eines Sprites im Schattenpuffer. Kachelnummer und Attribute bleiben erhalten; dieselbe Grafik wird ohne Änderung der Palette oder Spiegelung verschoben.
Syntax
#define nes_sprite_move(i,x,y) __sprite_move((i),(x),(y))Parameter
iSprite-Index von 0 bis 63, kein Byte-Offset. Intern wird er mit vier multipliziert und als 8-Bit-Position gespeichert. Werte außerhalb des Bereichs werden modulo 64 umgebrochen und können einen anderen Eintrag überschreiben. Eine Belegungsprüfung findet nicht statt.
xHorizontale Position in Pixeln als vorzeichenloses Byte; keine Tile-Koordinate.
yY-Byte des OAM. Für eine Oberkante unterhalb der Zeile null wird ihre Position minus eins übergeben; 239..255 liegen außerhalb der 240 sichtbaren Zeilen.
Rückgabewert
Keiner (void).
Bedingungen und Grenzen
Diese Operationen ändern den CPU-RAM bei 0x0200–0x02FF, nicht sofort das Hardware-OAM. Übertragen Sie die fertige Seite mit __oam_dma. Belegungsflags, Koordinatenfelder und Zähler der Sprite-Bibliothek werden nicht mitgeführt. Interrupt-Routinen dürfen eine noch unvollständige Seite weder ändern noch übertragen.
Anwendungsbeispiel
nes_sprite_move(1,144,31); // Move to (144,32), retaining tile 128 and attributes 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 zeigt jede Operation in einer beschrifteten Zeile. SET und MOVE zeigen 8×8-Pfeile nach rechts bei (144,16) und (144,32), TILE ein grünes Quadrat bei (144,48) und ATTR den in beiden Achsen gespiegelten Pfeil bei (144,64). HIDE bei (144,80) und CLEAR bei (144,112) müssen leer bleiben. META zeigt zwei Pfeile bei (136,96) und (144,96), den zweiten horizontal gespiegelt. NEXT 07 bezeichnet die nächste Position nach den Einträgen 5 und 6. Die Ränder sind rot, der Schaft grün und die Spitzendetails blau. Geprüft werden 8.704 Pixel je Bild und die übertragenen OAM-Bytes; echte Hardware wurde nicht getestet.
Das Programm ALIASES bereitet die beschrifteten Zeilen mit Makros aus nes_game.h vor und sendet Seite 02 mit nes_oam_dma(). TRANSFER zeigt den 8×8-Pfeil bei (144,128). Das Beispiel verwendet die Makros, ohne runtime.c oder metasprite.c einzubinden.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\oam_aliases.c -I .\kitaqfc\lib -I .\kitaq-docs\samples --nes-chr=.\kitaq-docs\samples\sprite_example.chr -o .\out\oam_aliases.nes --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/nes_game.h:25
#define nes_sprite_move(i,x,y) __sprite_move((i),(x),(y))nes_sprite_set
Makro aus nes_game.h: Es wird zum in der Syntax gezeigten Intrinsic expandiert. Binden Sie diesen Header ein; für diese Operation ist keine C-Implementierungsdatei erforderlich.
Schreibt alle vier Felder eines Sprites in den Schattenpuffer der Seite 02. Die Argumente lauten Index, X, Y, Kachel und Attribute; gespeichert wird in der Reihenfolge Y, Kachel, Attribute, X.
Syntax
#define nes_sprite_set(i,x,y,t,a) __sprite_set((i),(x),(y),(t),(a))Parameter
iSprite-Index von 0 bis 63, kein Byte-Offset. Intern wird er mit vier multipliziert und als 8-Bit-Position gespeichert. Werte außerhalb des Bereichs werden modulo 64 umgebrochen und können einen anderen Eintrag überschreiben. Eine Belegungsprüfung findet nicht statt.
xHorizontale Position in Pixeln als vorzeichenloses Byte; keine Tile-Koordinate.
yY-Byte des OAM. Für eine Oberkante unterhalb der Zeile null wird ihre Position minus eins übergeben; 239..255 liegen außerhalb der 240 sichtbaren Zeilen.
t8-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.
aVollständiges Attributbyte: Bits 0–1 wählen Palette 0–3; Bit 5 legt undurchsichtige Sprite-Pixel hinter undurchsichtige Hintergrundpixel; Bits 6 und 7 spiegeln horizontal beziehungsweise vertikal. Bits 2–4 müssen null bleiben. Kombinieren Sie Flags mit bitweisem ODER; das Byte ersetzt sämtliche bisherigen Attribute.
Rückgabewert
Keiner (void).
Bedingungen und Grenzen
Diese Operationen ändern den CPU-RAM bei 0x0200–0x02FF, nicht sofort das Hardware-OAM. Übertragen Sie die fertige Seite mit __oam_dma. Belegungsflags, Koordinatenfelder und Zähler der Sprite-Bibliothek werden nicht mitgeführt. Interrupt-Routinen dürfen eine noch unvollständige Seite weder ändern noch übertragen.
Anwendungsbeispiel
nes_sprite_set(0,144,15,128,0); // An 8x8 arrow at visible position (144,16).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 zeigt jede Operation in einer beschrifteten Zeile. SET und MOVE zeigen 8×8-Pfeile nach rechts bei (144,16) und (144,32), TILE ein grünes Quadrat bei (144,48) und ATTR den in beiden Achsen gespiegelten Pfeil bei (144,64). HIDE bei (144,80) und CLEAR bei (144,112) müssen leer bleiben. META zeigt zwei Pfeile bei (136,96) und (144,96), den zweiten horizontal gespiegelt. NEXT 07 bezeichnet die nächste Position nach den Einträgen 5 und 6. Die Ränder sind rot, der Schaft grün und die Spitzendetails blau. Geprüft werden 8.704 Pixel je Bild und die übertragenen OAM-Bytes; echte Hardware wurde nicht getestet.
Das Programm ALIASES bereitet die beschrifteten Zeilen mit Makros aus nes_game.h vor und sendet Seite 02 mit nes_oam_dma(). TRANSFER zeigt den 8×8-Pfeil bei (144,128). Das Beispiel verwendet die Makros, ohne runtime.c oder metasprite.c einzubinden.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\oam_aliases.c -I .\kitaqfc\lib -I .\kitaq-docs\samples --nes-chr=.\kitaq-docs\samples\sprite_example.chr -o .\out\oam_aliases.nes --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/nes_game.h:24
#define nes_sprite_set(i,x,y,t,a) __sprite_set((i),(x),(y),(t),(a))nes_vram_clear_queue
Makro aus nes_game.h: Es wird zum in der Syntax gezeigten Intrinsic expandiert. Binden Sie diesen Header ein; für diese Operation ist keine C-Implementierungsdatei erforderlich.
Verwirft alle ausstehenden Einträge und setzt Länge sowie Bereit-Flag auf 0. Schreibt nicht ins VRAM und löscht die Überlaufmeldung nicht. Rufen Sie dafür gesondert __vramq_clear_overflow auf.
Syntax
#define nes_vram_clear_queue() __vramq_clear()Rückgabewert
Keiner (void).
Bedingungen und Grenzen
FC zählt codierte Befehlsbytes in einem festen intrinsischen 128-Byte-Puffer. Ein Tile-Schreibbefehl braucht 4 Bytes, ein Fülleintrag 5 und eine Zeigerkopie 6 einschließlich Metadaten. NMI kann eine bereite Warteschlange verarbeiten; prüfen und befüllen Sie sie vor der Freigabe und koordinieren Sie Erzeuger und Verbraucher.
Diese Makros verwenden die Intrinsic-Befehlswarteschlange des Compilers, die auch lib/vram.c nutzt. Sie wählen nicht den C-Laufzeitpuffer nes_vram_queue_*. Mit __vramq_len() lesen Sie die Zahl ausstehender codierter Bytes, mit __vramq_overflow() erkennen Sie Kapazitätsfehler; __vramq_clear_overflow() löscht das Fehlerflag.
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
nes_vram_clear_queue();
if (__vramq_len()!=0 || __vramq_overflow()!=1) failures++;
// Clearing queued work deliberately leaves the overflow latch set.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 verwendet Makros aus nes_game.h zum Einreihen einzelner Bytes, Kopieren, Füllen, Freigeben und Leeren der Warteschlange. Zusätzlich prüfen die Abfrage- und Ausführungs-Intrinsics __vramq_* deren Wirkung. Der Titel lautet VRAM QUEUE MACROS. Große Übertragungen laufen bei abgeschalteter Bildausgabe; ihre Freigabe garantiert nicht, dass sie innerhalb von VBlank abgeschlossen werden.
Das Programm zeigt Kapazität, gespeicherte Zeiger, getrennte Rücksetzfunktionen sowie direkte und NMI-Ausführung. Erwartet werden CAPACITY 128, ENCODED BYTES 030, AFTER EXEC 000, OVERFLOW SEEN 001 und FAILED CHECKS 000. Sechs Einträge belegen 30 Bytes und führen 512 Byte-Schreibzugriffe aus. OVERFLOW SEEN speichert die frühere absichtliche Ablehnung; es bedeutet nicht, dass am Ende noch ein Überlauf gemeldet wird.
Die blaue Kopie beginnt bei Pixel (0,16), die grüne Füllung bei (0,88). Jeder Bereich umfasst sieben vollständige Kachelzeilen mit 256 Pixeln Breite und 248 Pixel der achten: insgesamt 255 Kacheln. Das letzte Feld von 8 × 8 bleibt schwarz. Die Kopie wiederholt volle, links halbvolle und dreieckige Muster; das erste ist ein Dreieck, weil die Quelle nach dem Einreihen geändert wird. Die Füllung bleibt trotz geänderter Aufrufervariable voll. Form und Farbe werden geprüft.
Bei y=160 werden ein volles rotes Quadrat bei x=16, eine rote linke Halbkachel bei x=224 und ein volles rotes Quadrat bei x=240 erwartet. Das erste übersteht Einträge mit Länge null, das mittlere belegt die NMI-Verarbeitung, das letzte einen einzelnen Put. Das verworfene Feld bei (248,160) bleibt schwarz. Lange Transfers laufen bei abgeschaltetem Rendering und NMI; nur der letzte kleine Schreibzugriff nutzt NMI. Dies ist ein NROM-Emulatortest, kein Test auf echter Hardware.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\vram_queue_macros.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\vram_queue_macros.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/nes_game.h:19
#define nes_vram_clear_queue() __vramq_clear()nes_vram_commit
Makro aus nes_game.h: Es wird zum in der Syntax gezeigten Intrinsic expandiert. Binden Sie diesen Header ein; für diese Operation ist keine C-Implementierungsdatei erforderlich.
Setzt das Bereit-Flag auf 1 und erlaubt damit die Verarbeitung. Kopiert keine Nutzdaten, schreibt nicht in die PPU und wartet nicht auf NMI. Halten Sie Warteschlange und gespeicherte Quellen nach der Freigabe bis zum Abschluss unverändert. Bei aktiviertem NMI kann der Standardhandler sie asynchron verarbeiten.
Syntax
#define nes_vram_commit() __vramq_commit()Rückgabewert
Keiner (void).
Bedingungen und Grenzen
FC zählt codierte Befehlsbytes in einem festen intrinsischen 128-Byte-Puffer. Ein Tile-Schreibbefehl braucht 4 Bytes, ein Fülleintrag 5 und eine Zeigerkopie 6 einschließlich Metadaten. NMI kann eine bereite Warteschlange verarbeiten; prüfen und befüllen Sie sie vor der Freigabe und koordinieren Sie Erzeuger und Verbraucher.
Diese Makros verwenden die Intrinsic-Befehlswarteschlange des Compilers, die auch lib/vram.c nutzt. Sie wählen nicht den C-Laufzeitpuffer nes_vram_queue_*. Mit __vramq_len() lesen Sie die Zahl ausstehender codierter Bytes, mit __vramq_overflow() erkennen Sie Kapazitätsfehler; __vramq_clear_overflow() löscht das Fehlerflag.
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
nes_vram_commit(); // NMI is disabled here: this only marks the queue ready.
if (__vramq_len()!=30) 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 verwendet Makros aus nes_game.h zum Einreihen einzelner Bytes, Kopieren, Füllen, Freigeben und Leeren der Warteschlange. Zusätzlich prüfen die Abfrage- und Ausführungs-Intrinsics __vramq_* deren Wirkung. Der Titel lautet VRAM QUEUE MACROS. Große Übertragungen laufen bei abgeschalteter Bildausgabe; ihre Freigabe garantiert nicht, dass sie innerhalb von VBlank abgeschlossen werden.
Das Programm zeigt Kapazität, gespeicherte Zeiger, getrennte Rücksetzfunktionen sowie direkte und NMI-Ausführung. Erwartet werden CAPACITY 128, ENCODED BYTES 030, AFTER EXEC 000, OVERFLOW SEEN 001 und FAILED CHECKS 000. Sechs Einträge belegen 30 Bytes und führen 512 Byte-Schreibzugriffe aus. OVERFLOW SEEN speichert die frühere absichtliche Ablehnung; es bedeutet nicht, dass am Ende noch ein Überlauf gemeldet wird.
Die blaue Kopie beginnt bei Pixel (0,16), die grüne Füllung bei (0,88). Jeder Bereich umfasst sieben vollständige Kachelzeilen mit 256 Pixeln Breite und 248 Pixel der achten: insgesamt 255 Kacheln. Das letzte Feld von 8 × 8 bleibt schwarz. Die Kopie wiederholt volle, links halbvolle und dreieckige Muster; das erste ist ein Dreieck, weil die Quelle nach dem Einreihen geändert wird. Die Füllung bleibt trotz geänderter Aufrufervariable voll. Form und Farbe werden geprüft.
Bei y=160 werden ein volles rotes Quadrat bei x=16, eine rote linke Halbkachel bei x=224 und ein volles rotes Quadrat bei x=240 erwartet. Das erste übersteht Einträge mit Länge null, das mittlere belegt die NMI-Verarbeitung, das letzte einen einzelnen Put. Das verworfene Feld bei (248,160) bleibt schwarz. Lange Transfers laufen bei abgeschaltetem Rendering und NMI; nur der letzte kleine Schreibzugriff nutzt NMI. Dies ist ein NROM-Emulatortest, kein Test auf echter Hardware.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\vram_queue_macros.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\vram_queue_macros.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/nes_game.h:18
#define nes_vram_commit() __vramq_commit()nes_vram_copy
Makro aus nes_game.h: Es wird zum in der Syntax gezeigten Intrinsic expandiert. Binden Sie diesen Header ein; für diese Operation ist keine C-Implementierungsdatei erforderlich.
Fügt einen Sechs-Byte-Eintrag an, der bei der Ausführung len Bytes von src nach ppu_addr kopiert. Gespeichert wird der Zeiger, nicht der Inhalt. Selbst eine Kopie von 255 Bytes belegt nur sechs Pufferbytes. Die Quelle wird aufsteigend gelesen; für ein fortlaufendes Ziel wählen Sie PPU-Schrittweite 1.
Syntax
#define nes_vram_copy(addr, src, len) __vramq_copy((addr), (src), (len))Parameter
addrPPU-Byteadresse (
0x0000–0x3FFF), kein CPU-Zeiger. Das Ziel muss beschreibbar sein: Musteränderungen benötigen CHR-RAM statt CHR-ROM. PPU-Adressabbildung und Spiegelung gelten weiterhin. Wählen Sie für fortlaufendes Kopieren und Füllen die Schrittweite 1 in PPUCTRL. Führen Sie Befehle zu einem sicheren PPU-Zeitpunkt aus und stellen Sie danach den Scrollzustand her; der Ausführer schreibt PPUADDR und PPUDATA, ohne Scrolleinstellungen wiederherzustellen.srcNahzeiger 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.
lenByteanzahl von 0 bis 255. Ein Eintrag verarbeitet die gesamte Anzahl ohne Aufteilung in 127-Byte-Abschnitte. Auch null belegt einen Kopier- oder Fülleintrag. Bei dessen Ausführung wird die PPU-Adresse gesetzt, aber kein Byte nach PPUDATA geschrieben. 256 liegt außerhalb des Argumentbereichs.
Rückgabewert
Keiner (void).
Bedingungen und Grenzen
Das Einfügen liefert keinen Erfolgswert. Passt der vollständige Eintrag nicht, wird __vramq_overflow() auf 1 gesetzt; vorhandene Einträge und Länge bleiben erhalten. Genau passender Platz wird akzeptiert. Eine frühere Überlaufmeldung verhindert keinen passenden Eintrag; behandeln oder löschen Sie sie vor der Bewertung eines neuen Stapels. Mehrere Einfügevorgänge bilden keine Transaktion.
FC zählt codierte Befehlsbytes in einem festen intrinsischen 128-Byte-Puffer. Ein Tile-Schreibbefehl braucht 4 Bytes, ein Fülleintrag 5 und eine Zeigerkopie 6 einschließlich Metadaten. NMI kann eine bereite Warteschlange verarbeiten; prüfen und befüllen Sie sie vor der Freigabe und koordinieren Sie Erzeuger und Verbraucher.
Diese Makros verwenden die Intrinsic-Befehlswarteschlange des Compilers, die auch lib/vram.c nutzt. Sie wählen nicht den C-Laufzeitpuffer nes_vram_queue_*. Mit __vramq_len() lesen Sie die Zahl ausstehender codierter Bytes, mit __vramq_overflow() erkennen Sie Kapazitätsfehler; __vramq_clear_overflow() löscht das Fehlerflag.
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
nes_vram_copy(0x2040,source_bytes,255);
source_bytes[0]=3; // The executor must see this change through its retained pointer.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 verwendet Makros aus nes_game.h zum Einreihen einzelner Bytes, Kopieren, Füllen, Freigeben und Leeren der Warteschlange. Zusätzlich prüfen die Abfrage- und Ausführungs-Intrinsics __vramq_* deren Wirkung. Der Titel lautet VRAM QUEUE MACROS. Große Übertragungen laufen bei abgeschalteter Bildausgabe; ihre Freigabe garantiert nicht, dass sie innerhalb von VBlank abgeschlossen werden.
Das Programm zeigt Kapazität, gespeicherte Zeiger, getrennte Rücksetzfunktionen sowie direkte und NMI-Ausführung. Erwartet werden CAPACITY 128, ENCODED BYTES 030, AFTER EXEC 000, OVERFLOW SEEN 001 und FAILED CHECKS 000. Sechs Einträge belegen 30 Bytes und führen 512 Byte-Schreibzugriffe aus. OVERFLOW SEEN speichert die frühere absichtliche Ablehnung; es bedeutet nicht, dass am Ende noch ein Überlauf gemeldet wird.
Die blaue Kopie beginnt bei Pixel (0,16), die grüne Füllung bei (0,88). Jeder Bereich umfasst sieben vollständige Kachelzeilen mit 256 Pixeln Breite und 248 Pixel der achten: insgesamt 255 Kacheln. Das letzte Feld von 8 × 8 bleibt schwarz. Die Kopie wiederholt volle, links halbvolle und dreieckige Muster; das erste ist ein Dreieck, weil die Quelle nach dem Einreihen geändert wird. Die Füllung bleibt trotz geänderter Aufrufervariable voll. Form und Farbe werden geprüft.
Bei y=160 werden ein volles rotes Quadrat bei x=16, eine rote linke Halbkachel bei x=224 und ein volles rotes Quadrat bei x=240 erwartet. Das erste übersteht Einträge mit Länge null, das mittlere belegt die NMI-Verarbeitung, das letzte einen einzelnen Put. Das verworfene Feld bei (248,160) bleibt schwarz. Lange Transfers laufen bei abgeschaltetem Rendering und NMI; nur der letzte kleine Schreibzugriff nutzt NMI. Dies ist ein NROM-Emulatortest, kein Test auf echter Hardware.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\vram_queue_macros.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\vram_queue_macros.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/nes_game.h:16
#define nes_vram_copy(addr, src, len) __vramq_copy((addr), (src), (len))nes_vram_fill
Makro aus nes_game.h: Es wird zum in der Syntax gezeigten Intrinsic expandiert. Binden Sie diesen Header ein; für diese Operation ist keine C-Implementierungsdatei erforderlich.
Fügt einen Fünf-Byte-Eintrag an, der das Byte value bei len PPU-Schreibzugriffen wiederholt. Der Wert wird gespeichert; spätere Änderungen der Aufrufervariablen ändern den eingereihten Füllwert nicht. Wiederholt wird ein Byte, kein mehrteiliges Kachelmuster.
Syntax
#define nes_vram_fill(addr, value, len) __vramq_fill((addr), (value), (len))Parameter
addrPPU-Byteadresse (
0x0000–0x3FFF), kein CPU-Zeiger. Das Ziel muss beschreibbar sein: Musteränderungen benötigen CHR-RAM statt CHR-ROM. PPU-Adressabbildung und Spiegelung gelten weiterhin. Wählen Sie für fortlaufendes Kopieren und Füllen die Schrittweite 1 in PPUCTRL. Führen Sie Befehle zu einem sicheren PPU-Zeitpunkt aus und stellen Sie danach den Scrollzustand her; der Ausführer schreibt PPUADDR und PPUDATA, ohne Scrolleinstellungen wiederherzustellen.valueEin 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.
lenByteanzahl von 0 bis 255. Ein Eintrag verarbeitet die gesamte Anzahl ohne Aufteilung in 127-Byte-Abschnitte. Auch null belegt einen Kopier- oder Fülleintrag. Bei dessen Ausführung wird die PPU-Adresse gesetzt, aber kein Byte nach PPUDATA geschrieben. 256 liegt außerhalb des Argumentbereichs.
Rückgabewert
Keiner (void).
Bedingungen und Grenzen
Das Einfügen liefert keinen Erfolgswert. Passt der vollständige Eintrag nicht, wird __vramq_overflow() auf 1 gesetzt; vorhandene Einträge und Länge bleiben erhalten. Genau passender Platz wird akzeptiert. Eine frühere Überlaufmeldung verhindert keinen passenden Eintrag; behandeln oder löschen Sie sie vor der Bewertung eines neuen Stapels. Mehrere Einfügevorgänge bilden keine Transaktion.
FC zählt codierte Befehlsbytes in einem festen intrinsischen 128-Byte-Puffer. Ein Tile-Schreibbefehl braucht 4 Bytes, ein Fülleintrag 5 und eine Zeigerkopie 6 einschließlich Metadaten. NMI kann eine bereite Warteschlange verarbeiten; prüfen und befüllen Sie sie vor der Freigabe und koordinieren Sie Erzeuger und Verbraucher.
Diese Makros verwenden die Intrinsic-Befehlswarteschlange des Compilers, die auch lib/vram.c nutzt. Sie wählen nicht den C-Laufzeitpuffer nes_vram_queue_*. Mit __vramq_len() lesen Sie die Zahl ausstehender codierter Bytes, mit __vramq_overflow() erkennen Sie Kapazitätsfehler; __vramq_clear_overflow() löscht das Fehlerflag.
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
nes_vram_fill(0x2160,fill_value,255); // Seven complete rows and 31 tiles in the eighth.
fill_value=3; // The queued value stays 1, so the green block remains solid.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 verwendet Makros aus nes_game.h zum Einreihen einzelner Bytes, Kopieren, Füllen, Freigeben und Leeren der Warteschlange. Zusätzlich prüfen die Abfrage- und Ausführungs-Intrinsics __vramq_* deren Wirkung. Der Titel lautet VRAM QUEUE MACROS. Große Übertragungen laufen bei abgeschalteter Bildausgabe; ihre Freigabe garantiert nicht, dass sie innerhalb von VBlank abgeschlossen werden.
Das Programm zeigt Kapazität, gespeicherte Zeiger, getrennte Rücksetzfunktionen sowie direkte und NMI-Ausführung. Erwartet werden CAPACITY 128, ENCODED BYTES 030, AFTER EXEC 000, OVERFLOW SEEN 001 und FAILED CHECKS 000. Sechs Einträge belegen 30 Bytes und führen 512 Byte-Schreibzugriffe aus. OVERFLOW SEEN speichert die frühere absichtliche Ablehnung; es bedeutet nicht, dass am Ende noch ein Überlauf gemeldet wird.
Die blaue Kopie beginnt bei Pixel (0,16), die grüne Füllung bei (0,88). Jeder Bereich umfasst sieben vollständige Kachelzeilen mit 256 Pixeln Breite und 248 Pixel der achten: insgesamt 255 Kacheln. Das letzte Feld von 8 × 8 bleibt schwarz. Die Kopie wiederholt volle, links halbvolle und dreieckige Muster; das erste ist ein Dreieck, weil die Quelle nach dem Einreihen geändert wird. Die Füllung bleibt trotz geänderter Aufrufervariable voll. Form und Farbe werden geprüft.
Bei y=160 werden ein volles rotes Quadrat bei x=16, eine rote linke Halbkachel bei x=224 und ein volles rotes Quadrat bei x=240 erwartet. Das erste übersteht Einträge mit Länge null, das mittlere belegt die NMI-Verarbeitung, das letzte einen einzelnen Put. Das verworfene Feld bei (248,160) bleibt schwarz. Lange Transfers laufen bei abgeschaltetem Rendering und NMI; nur der letzte kleine Schreibzugriff nutzt NMI. Dies ist ein NROM-Emulatortest, kein Test auf echter Hardware.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\vram_queue_macros.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\vram_queue_macros.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/nes_game.h:17
#define nes_vram_fill(addr, value, len) __vramq_fill((addr), (value), (len))nes_vram_put
Makro aus nes_game.h: Es wird zum in der Syntax gezeigten Intrinsic expandiert. Binden Sie diesen Header ein; für diese Operation ist keine C-Implementierungsdatei erforderlich.
Fügt eine PPU-Adresse und einen Bytewert als Vier-Byte-Eintrag an. Der Wert wird sofort in die Warteschlange kopiert und erst bei deren Ausführung geschrieben. Dies eignet sich etwa für eine Nametable-Kachel oder ein anderes beschreibbares PPU-Byte.
Syntax
#define nes_vram_put(addr, value) __vramq_put((addr), (value))Parameter
addrPPU-Byteadresse (
0x0000–0x3FFF), kein CPU-Zeiger. Das Ziel muss beschreibbar sein: Musteränderungen benötigen CHR-RAM statt CHR-ROM. PPU-Adressabbildung und Spiegelung gelten weiterhin. Wählen Sie für fortlaufendes Kopieren und Füllen die Schrittweite 1 in PPUCTRL. Führen Sie Befehle zu einem sicheren PPU-Zeitpunkt aus und stellen Sie danach den Scrollzustand her; der Ausführer schreibt PPUADDR und PPUDATA, ohne Scrolleinstellungen wiederherzustellen.valueEin 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.
Rückgabewert
Keiner (void).
Bedingungen und Grenzen
Das Einfügen liefert keinen Erfolgswert. Passt der vollständige Eintrag nicht, wird __vramq_overflow() auf 1 gesetzt; vorhandene Einträge und Länge bleiben erhalten. Genau passender Platz wird akzeptiert. Eine frühere Überlaufmeldung verhindert keinen passenden Eintrag; behandeln oder löschen Sie sie vor der Bewertung eines neuen Stapels. Mehrere Einfügevorgänge bilden keine Transaktion.
FC zählt codierte Befehlsbytes in einem festen intrinsischen 128-Byte-Puffer. Ein Tile-Schreibbefehl braucht 4 Bytes, ein Fülleintrag 5 und eine Zeigerkopie 6 einschließlich Metadaten. NMI kann eine bereite Warteschlange verarbeiten; prüfen und befüllen Sie sie vor der Freigabe und koordinieren Sie Erzeuger und Verbraucher.
Diese Makros verwenden die Intrinsic-Befehlswarteschlange des Compilers, die auch lib/vram.c nutzt. Sie wählen nicht den C-Laufzeitpuffer nes_vram_queue_*. Mit __vramq_len() lesen Sie die Zahl ausstehender codierter Bytes, mit __vramq_overflow() erkennen Sie Kapazitätsfehler; __vramq_clear_overflow() löscht das Fehlerflag.
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
nes_vram_put(0x2282,1); // Red 8x8 sentinel at pixel (16,160).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 verwendet Makros aus nes_game.h zum Einreihen einzelner Bytes, Kopieren, Füllen, Freigeben und Leeren der Warteschlange. Zusätzlich prüfen die Abfrage- und Ausführungs-Intrinsics __vramq_* deren Wirkung. Der Titel lautet VRAM QUEUE MACROS. Große Übertragungen laufen bei abgeschalteter Bildausgabe; ihre Freigabe garantiert nicht, dass sie innerhalb von VBlank abgeschlossen werden.
Das Programm zeigt Kapazität, gespeicherte Zeiger, getrennte Rücksetzfunktionen sowie direkte und NMI-Ausführung. Erwartet werden CAPACITY 128, ENCODED BYTES 030, AFTER EXEC 000, OVERFLOW SEEN 001 und FAILED CHECKS 000. Sechs Einträge belegen 30 Bytes und führen 512 Byte-Schreibzugriffe aus. OVERFLOW SEEN speichert die frühere absichtliche Ablehnung; es bedeutet nicht, dass am Ende noch ein Überlauf gemeldet wird.
Die blaue Kopie beginnt bei Pixel (0,16), die grüne Füllung bei (0,88). Jeder Bereich umfasst sieben vollständige Kachelzeilen mit 256 Pixeln Breite und 248 Pixel der achten: insgesamt 255 Kacheln. Das letzte Feld von 8 × 8 bleibt schwarz. Die Kopie wiederholt volle, links halbvolle und dreieckige Muster; das erste ist ein Dreieck, weil die Quelle nach dem Einreihen geändert wird. Die Füllung bleibt trotz geänderter Aufrufervariable voll. Form und Farbe werden geprüft.
Bei y=160 werden ein volles rotes Quadrat bei x=16, eine rote linke Halbkachel bei x=224 und ein volles rotes Quadrat bei x=240 erwartet. Das erste übersteht Einträge mit Länge null, das mittlere belegt die NMI-Verarbeitung, das letzte einen einzelnen Put. Das verworfene Feld bei (248,160) bleibt schwarz. Lange Transfers laufen bei abgeschaltetem Rendering und NMI; nur der letzte kleine Schreibzugriff nutzt NMI. Dies ist ein NROM-Emulatortest, kein Test auf echter Hardware.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\vram_queue_macros.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\vram_queue_macros.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/nes_game.h:15
#define nes_vram_put(addr, value) __vramq_put((addr), (value))oam_fair.h — Wechselnder Spritevorrang mit Prioritäten
Hängt aktive Einträge aus einem Software-Pool mit 64 Elementen an den OAM-Schattenpuffer an. Vor jedem Durchlauf wird der Startindex um 13 modulo 64 erhöht. Wiederholte Aufrufe verteilen durch wechselnde OAM-Priorität das Sprite-Flackern; die Hardwaregrenze wird dadurch nicht erhöht.
Definieren Sie die Arrays X, Y, active und shadow sowie den used-Zeiger selbst; binden Sie oam_fair_impl.h einmal in einer festen PRG-Bank ein. Rufen Sie die Routine aus der Hauptschleife im 8×8-Sprite-Modus auf. Koordinaten laufen modulo 256 über, ohne Clipping. Die Routine überträgt kein OAM: Nutzen Sie DMA mit der Seite des shadow-Puffers. Die Hardwaregrenzen bleiben 64 OAM-Sprites und acht Sprites pro Bildzeile.
OAM_FairDraw
Hängt aktive Einträge aus einem Software-Pool mit 64 Elementen an den OAM-Schattenpuffer an. Vor jedem Durchlauf wird der Startindex um 13 modulo 64 erhöht. Wiederholte Aufrufe verteilen durch wechselnde OAM-Priorität das Sprite-Flackern; die Hardwaregrenze wird dadurch nicht erhöht.
Syntax
void OAM_FairDraw(void);Rückgabewert
Kein C-Rückgabewert. oam_fair_drawn enthält die Zahl der angehängten Einträge, oam_fair_used den aktualisierten Bytezeiger und oam_fair_phase den Startindex des Durchlaufs. Die Phase wird auch ohne gezeichneten Eintrag weitergeschaltet; oam_fair_drawn ist dann null.
Bedingungen und Grenzen
Die Funktion hat keine Parameter; konfigurieren Sie die gemeinsamen Variablen. oam_fair_x[64] und oam_fair_y[64] enthalten die Mittelpunkte der 8×8-Sprites in Pixeln: OAM-X ist Mittelpunkt X−4, OAM-Y ist Mittelpunkt Y−5. Einträge mit einem Wert ungleich null in oam_fair_active[64] werden ausgewählt. Alle ausgegebenen Einträge verwenden das gemeinsame Tile und Attributbyte aus oam_fair_tile und oam_fair_attr.
Setzen Sie oam_fair_used auf den nächsten freien Byteoffset in oam_fair_shadow[256], ausgerichtet auf vier Bytes. oam_fair_limit begrenzt die Zahl der in diesem Aufruf angehängten Einträge. Es werden höchstens 64 Pool-Einträge geprüft; ab Byteoffset 252 wird nicht mehr geschrieben, sodass Slot 63 frei bleibt. Frühere Einträge bleiben erhalten; unbenutzte Einträge am Ende müssen separat ausgeblendet werden.
Definieren Sie die Arrays X, Y, active und shadow sowie den used-Zeiger selbst; binden Sie oam_fair_impl.h einmal in einer festen PRG-Bank ein. Rufen Sie die Routine aus der Hauptschleife im 8×8-Sprite-Modus auf. Koordinaten laufen modulo 256 über, ohne Clipping. Die Routine überträgt kein OAM: Nutzen Sie DMA mit der Seite des shadow-Puffers. Die Hardwaregrenzen bleiben 64 OAM-Sprites und acht Sprites pro Bildzeile.
Anwendungsbeispiel
oam_fair_used=4; // Byte cursor: reserve the already prepared slot 0.
OAM_FairDraw(); // Phase becomes 13; append pool entries 13, 14 and 15.Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
FAIR-POOL erhält ein grünes 8×8-Quadrat bei (144,32) in Slot 0 und hängt drei Pfeile mit den Mittelpunkten (148,68), (164,68) und (180,68) an. Ihre sichtbaren linken oberen Ecken müssen bei (144,64), (160,64) und (176,64) liegen. Mit phase=0 und used=4 entstehen PHASE 13, DRAWN 03 und BYTES 16. Das Standbild prüft Position und Erhaltung; ein separater Zustandstest mit 64 Aufrufen prüft, dass jeder Pool-Eintrag genau einmal Startpunkt ist.
Die Pfeile haben rote Ränder, grüne Schäfte und blaue Details an der Spitze; das Quadrat-Tile 129 ist grün. Die Prüfung vergleicht pro Bild 8.704 Farbpixel, alle 256 übertragenen OAM-Bytes und die Beschriftungen. Physische Hardware wurde nicht getestet.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\oam_fair.c -I .\kitaqfc\lib -I .\kitaq-docs\samples --nes-chr=.\kitaq-docs\samples\sprite_example.chr -o .\out\oam_fair.nes --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/oam_fair.h:24
Append active pool entries using the configured common tile/attributes. The emitter stops at byte cursor 252, leaving slot 63 unused to avoid cursor wrap. Hide unused trailing OAM entries separately before DMA.
kitaqfc/lib/oam_fair_impl.h:12
void OAM_FairDraw(void) {
__asm {
LDA oam_fair_phase
CLC
ADC #13
AND #63
STA oam_fair_phase
TAX
LDY oam_fair_used
LDA #0
STA oam_fair_drawn
STA oam_fair_scanned
// Visit each pool entry at most once, preserving already-written OAM entries
// and sharing the configured tile/attribute values across emitted sprites.
kq_fair_loop:
LDA oam_fair_active,X
BEQ kq_fair_next
LDA oam_fair_drawn
CMP oam_fair_limit
BCS kq_fair_done
// Reserve the final four-byte slot so advancing this byte cursor cannot wrap to zero.
CPY #252
BCS kq_fair_done
// Convert the 8x8 center to raw OAM coordinates; Y also needs the hardware minus-one bias.
LDA oam_fair_y,X
SEC
SBC #5
STA oam_fair_shadow,Y
LDA oam_fair_tile
STA oam_fair_shadow+1,Y
LDA oam_fair_attr
STA oam_fair_shadow+2,Y
LDA oam_fair_x,X
SEC
SBC #4
STA oam_fair_shadow+3,Y
INY
INY
INY
INY
INC oam_fair_drawn
// Advance cyclically and stop after returning to this frame's starting entry.
kq_fair_next:
TXA
CLC
ADC #1
AND #63
TAX
CPX oam_fair_phase
BNE kq_fair_loop
// Publish the updated byte cursor for later OAM writers and the VBlank DMA path.
kq_fair_done:
STY oam_fair_used
}
}pad.h — NES-Controllereingaben
pad.h und pad.c speichern Controller 1 in NES-Bitreihenfolge. Die Abfrage berechnet vorherigen Zustand, Halten, neue Tastendrücke und Loslassen, aber keine Wiederholung. Für einstellbare Wiederholung pro Taste zusätzlich input_repeat.c linken. Controller 2 liest du mit einer Port-2-Intrinsic; den vorherigen Zustand verwaltet dein Spiel.
Rohes NES-Format: A=0x01, B=0x02, SELECT=0x04, START=0x08, UP=0x10, DOWN=0x20, LEFT=0x40, RIGHT=0x80. Ein gesetztes Bit bedeutet gedrückt. Verwende diese Werte mit nes_pad_* und rohen __pad_*-Ergebnissen, nicht die gemeinsamen BTN_*-Masken aus input.h.
Initialisiere die vier nes_pad1_*-Zustandsbytes vor der ersten Abfrage mit 0. Danach einmal pro Eingabetakt abfragen. pressed = current & ~previous und released = previous & ~current beschreiben die letzte Abfrage. Der Wiederholungszustand wird separat durch nes_pad_repeat_step() aktualisiert.
nes_pad_poll
Strobt $4016, liest die acht seriellen D0-Bits von Controller 1 und aktualisiert nes_pad1_prev, nes_pad1_cur, nes_pad1_pressed und nes_pad1_released. Es erfolgt nur ein Lesevorgang, ohne die Wiederholungsprüfung der sicheren Funktionen. Der abschließende Zugriff auf $4017 speichert keinen Zustand für Controller 2.
Syntax
void nes_pad_poll(void);Rückgabewert
Keiner (void).
Bedingungen und Grenzen
Rohes NES-Format: A=0x01, B=0x02, SELECT=0x04, START=0x08, UP=0x10, DOWN=0x20, LEFT=0x40, RIGHT=0x80. Ein gesetztes Bit bedeutet gedrückt. Verwende diese Werte mit nes_pad_* und rohen __pad_*-Ergebnissen, nicht die gemeinsamen BTN_*-Masken aus input.h.
Initialisiere die vier nes_pad1_*-Zustandsbytes vor der ersten Abfrage mit 0. Danach einmal pro Eingabetakt abfragen. pressed = current & ~previous und released = previous & ~current beschreiben die letzte Abfrage. Der Wiederholungszustand wird separat durch nes_pad_repeat_step() aktualisiert.
Anwendungsbeispiel
nes_pad_poll(); // Read controller 1 and update its held/pressed/released snapshots.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 erklärt die Reihenfolge Einlesen → Wiederholung aktualisieren → Zustand abfragen und zeigt, dass die NES-Abfragen maskierte Bits statt des Wahrheitswerts 1 liefern. Verwenden Sie nes_pad_repeat_config(3, 1), halten Sie B für 40 Aktualisierungen gedrückt und lassen Sie los. FIRST HELD, FIRST TRIGGER und FIRST REPEAT sind 2; HELD TICKS ist 40, PULSE COUNT ist 19 und RELEASE BITS ist 2. Die erste Wiederholung folgt vier Aktualisierungen nach dem ersten Impuls; danach beträgt der Abstand zwei Aktualisierungen. FAILED CHECKS muss 0 sein. Eine andere Haltedauer verändert die Impulszahl.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\pad.c .\kitaqfc\lib\input_repeat.c .\kitaq-docs\samples\api-examples\fc\pad_repeat.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\pad_repeat.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chr --no-disasm --no-cacheImplementierung und Quelltext
kitaqfc/lib/pad.h:16
Latch controller input with a 1-to-0 strobe and shift eight controller-1 bits into held/pressed/released masks. This direct path does not perform repeated reads for DMC interference; the final JOY2 read does not populate player-2 state.
kitaqfc/lib/pad.c:21
void nes_pad_poll(void)
{
unsigned char state;
unsigned char mask;
unsigned char sample;
nes_pad1_prev = nes_pad1_cur;
JOY1 = 1;
JOY1 = 0;
state = 0;
mask = 1;
while (mask != 0)
{
sample = JOY1;
if ((sample & 1) != 0)
{
state = state | mask;
}
mask = mask + mask;
}
nes_pad1_cur = state;
nes_pad1_pressed = (unsigned char)(state & (unsigned char)(state ^ nes_pad1_prev));
nes_pad1_released = (unsigned char)(nes_pad1_prev & (unsigned char)(state ^ nes_pad1_prev));
sample = JOY2;
sample = sample;
}palette.h — NES-Paletten
Verwaltet Hintergrund- und Spritefarben mit einem 32-Byte-CPU-Schattenpuffer und sofortigen oder eingereihten Übertragungen. PPU-Palettenadressen enthalten Aliase.
nes_palette_apply_now
Kopiert 32 Farben in den Schattenpuffer und überträgt sie anschließend direkt an die PPU.
Syntax
void nes_palette_apply_now(unsigned char* src32);Parameter
src32Lesbare 32-Byte-Palette: 16 Hintergrundfarben, gefolgt von 16 Spritefarben; verwenden Sie Farbcodes von 0–63.
Rückgabewert
Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.
Bedingungen und Grenzen
Der Schattenpuffer reserviert die CPU-Adressen 0x03C0–0x03DF. Die PPU-Adressen 0x3F10/14/18/1C sind Aliase von 0x3F00/04/08/0C. Die 32 rohen Schattenbytes müssen daher nicht mit 32 unabhängigen PPU-Lesewerten übereinstimmen. Verwenden Sie PPU-Inkrement eins in einem sicheren VBlank-Zeitfenster oder bei ausgeschalteter Darstellung. Die Hilfsfunktion wartet nicht, maskiert keine Interrupts und stellt das Scrolling nicht wieder her.
Anwendungsbeispiel
nes_palette_apply_now(colors);Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Zeigen Sie rote, blaue und grüne 32×32-Hintergrundrechtecke bei (16,32), (80,32) und (144,32) sowie 8×8-Spritequadrate bei (16,96), (80,96) und (144,96) in derselben Farbreihenfolge. Getrennte Hintergrund- und Spritepaletten demonstrieren direkte und eingereihte Übertragungen.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\batch2_palette.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch2_palette.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chrImplementierung und Quelltext
kitaqfc/lib/palette.h:11
Replace shadow palette data and upload all 32 bytes immediately. The caller provides a safe PPU access period; this helper does not wait for VBlank.
kitaqfc/lib/palette.c:28
void nes_palette_apply_now(unsigned char* src32)
{
nes_palette_copy(src32);
nes_ppu_stream_write(0x3F00, nes_palette_shadow, 32);
}nes_palette_apply_shadow_now
Überträgt die aktuellen 32 Farben des Schattenpuffers direkt an die PPU.
Syntax
void nes_palette_apply_shadow_now(void);Rückgabewert
Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.
Bedingungen und Grenzen
Der Schattenpuffer reserviert die CPU-Adressen 0x03C0–0x03DF. Die PPU-Adressen 0x3F10/14/18/1C sind Aliase von 0x3F00/04/08/0C. Die 32 rohen Schattenbytes müssen daher nicht mit 32 unabhängigen PPU-Lesewerten übereinstimmen. Verwenden Sie PPU-Inkrement eins in einem sicheren VBlank-Zeitfenster oder bei ausgeschalteter Darstellung. Die Hilfsfunktion wartet nicht, maskiert keine Interrupts und stellt das Scrolling nicht wieder her.
Anwendungsbeispiel
nes_palette_apply_shadow_now();Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Zeigen Sie rote, blaue und grüne 32×32-Hintergrundrechtecke bei (16,32), (80,32) und (144,32) sowie 8×8-Spritequadrate bei (16,96), (80,96) und (144,96) in derselben Farbreihenfolge. Getrennte Hintergrund- und Spritepaletten demonstrieren direkte und eingereihte Übertragungen.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\batch2_palette.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch2_palette.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chrImplementierung und Quelltext
kitaqfc/lib/palette.h:13
Upload the current palette shadow directly, with timing controlled by the caller.
kitaqfc/lib/palette.c:35
void nes_palette_apply_shadow_now(void)
{
nes_ppu_stream_write(0x3F00, nes_palette_shadow, 32);
}nes_palette_copy
Kopiert 32 Palettenbytes in den CPU-Schattenpuffer, ohne sie an die PPU zu übertragen.
Syntax
void nes_palette_copy(unsigned char* src32);Parameter
src32Lesbare 32-Byte-Palette: 16 Hintergrundfarben, gefolgt von 16 Spritefarben; verwenden Sie Farbcodes von 0–63.
Rückgabewert
Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.
Bedingungen und Grenzen
Der Schattenpuffer reserviert die CPU-Adressen 0x03C0–0x03DF. Die PPU-Adressen 0x3F10/14/18/1C sind Aliase von 0x3F00/04/08/0C. Die 32 rohen Schattenbytes müssen daher nicht mit 32 unabhängigen PPU-Lesewerten übereinstimmen.
Anwendungsbeispiel
nes_palette_copy(colors);result[0]=nes_palette_shadow[5];Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Zeigen Sie rote, blaue und grüne 32×32-Hintergrundrechtecke bei (16,32), (80,32) und (144,32) sowie 8×8-Spritequadrate bei (16,96), (80,96) und (144,96) in derselben Farbreihenfolge. Getrennte Hintergrund- und Spritepaletten demonstrieren direkte und eingereihte Übertragungen.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\batch2_palette.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch2_palette.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chrImplementierung und Quelltext
kitaqfc/lib/palette.h:8
Copy exactly 32 palette bytes to the fixed shadow buffer without writing the PPU.
kitaqfc/lib/palette.c:19
void nes_palette_copy(unsigned char* src32)
{
__memcpy(nes_palette_shadow, src32, 32);
}nes_palette_queue_all
Ersetzt alle 32 Schattenfarben und kopiert sie in die VRAM-Warteschlange der Laufzeitumgebung.
Syntax
unsigned char nes_palette_queue_all(unsigned char* src32);Parameter
src32Lesbare 32-Byte-Palette: 16 Hintergrundfarben, gefolgt von 16 Spritefarben; verwenden Sie Farbcodes von 0–63.
Rückgabewert
1 bei erfolgreicher Einreihung, 0 bei unzureichender Kapazität. Die neuen Schattenwerte bleiben auch bei einem Fehlschlag erhalten. Erfolg bedeutet nicht, dass die PPU bereits aktualisiert wurde.
Bedingungen und Grenzen
Der Schattenpuffer reserviert die CPU-Adressen 0x03C0–0x03DF. Die PPU-Adressen 0x3F10/14/18/1C sind Aliase von 0x3F00/04/08/0C. Die 32 rohen Schattenbytes müssen daher nicht mit 32 unabhängigen PPU-Lesewerten übereinstimmen. Die Warteschlange kopiert die Werte; nach erfolgreicher Aufnahme darf die Quelle geändert werden. Verhindern Sie konkurrierende Zugriffe zwischen dem Befüllen der Warteschlange und ihrem NMI-Verbraucher.
Anwendungsbeispiel
nes_vram_queue_clear();result[1]=nes_palette_queue_all(colors);result[2]=nes_vram_queue_used;nes_vram_queue_nmi_flush();Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Zeigen Sie rote, blaue und grüne 32×32-Hintergrundrechtecke bei (16,32), (80,32) und (144,32) sowie 8×8-Spritequadrate bei (16,96), (80,96) und (144,96) in derselben Farbreihenfolge. Getrennte Hintergrund- und Spritepaletten demonstrieren direkte und eingereihte Übertragungen.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\batch2_palette.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch2_palette.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chrImplementierung und Quelltext
kitaqfc/lib/palette.h:18
Update the shadow and copy all colors into the runtime queue. A queue failure leaves the new shadow contents in place. Return one if the runtime queue accepted the copied payload, zero if it was full. Admission does not mean the NMI consumer has already updated the PPU.
kitaqfc/lib/palette.c:42
unsigned char nes_palette_queue_all(unsigned char* src32)
{
nes_palette_copy(src32);
return nes_vram_queue_try_write(0x3F00, nes_palette_shadow, 32);
}nes_palette_queue_bg4
Aktualisiert die vier Farben einer Hintergrundpalette im Schattenpuffer und kopiert sie in die VRAM-Warteschlange.
Syntax
unsigned char nes_palette_queue_bg4(unsigned char pal_index, unsigned char* src4);Parameter
pal_indexPalettenindex 0–3; die Funktion prüft ihn nicht.
src4Vier Bytes für die gewählte Palette; verwenden Sie Farbcodes von 0–63.
Rückgabewert
1 bei erfolgreicher Einreihung, 0 bei unzureichender Kapazität. Die neuen Schattenwerte bleiben auch bei einem Fehlschlag erhalten. Erfolg bedeutet nicht, dass die PPU bereits aktualisiert wurde.
Bedingungen und Grenzen
Der Schattenpuffer reserviert die CPU-Adressen 0x03C0–0x03DF. Die PPU-Adressen 0x3F10/14/18/1C sind Aliase von 0x3F00/04/08/0C. Die 32 rohen Schattenbytes müssen daher nicht mit 32 unabhängigen PPU-Lesewerten übereinstimmen. Die Warteschlange kopiert die Werte; nach erfolgreicher Aufnahme darf die Quelle geändert werden. Verhindern Sie konkurrierende Zugriffe zwischen dem Befüllen der Warteschlange und ihrem NMI-Verbraucher.
Anwendungsbeispiel
result[3]=nes_palette_queue_bg4(3,four);nes_vram_queue_nmi_flush();Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Zeigen Sie rote, blaue und grüne 32×32-Hintergrundrechtecke bei (16,32), (80,32) und (144,32) sowie 8×8-Spritequadrate bei (16,96), (80,96) und (144,96) in derselben Farbreihenfolge. Getrennte Hintergrund- und Spritepaletten demonstrieren direkte und eingereihte Übertragungen.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\batch2_palette.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch2_palette.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chrImplementierung und Quelltext
kitaqfc/lib/palette.h:21
Update and queue four background palette bytes. pal_index must be 0..3; there is no range check before writing the shadow.
kitaqfc/lib/palette.c:50
unsigned char nes_palette_queue_bg4(unsigned char pal_index, unsigned char* src4)
{
unsigned char dst;
dst = pal_index + pal_index;
dst = dst + dst;
__memcpy(nes_palette_shadow + dst, src4, 4);
return nes_vram_queue_try_write((unsigned short)(0x3F00 + dst), nes_palette_shadow + dst, 4);
}nes_palette_queue_sprite4
Aktualisiert die vier Farben einer Spritepalette im Schattenpuffer und kopiert sie in die VRAM-Warteschlange.
Syntax
unsigned char nes_palette_queue_sprite4(unsigned char pal_index, unsigned char* src4);Parameter
pal_indexPalettenindex 0–3; die Funktion prüft ihn nicht.
src4Vier Bytes für die gewählte Palette; verwenden Sie Farbcodes von 0–63.
Rückgabewert
1 bei erfolgreicher Einreihung, 0 bei unzureichender Kapazität. Die neuen Schattenwerte bleiben auch bei einem Fehlschlag erhalten. Erfolg bedeutet nicht, dass die PPU bereits aktualisiert wurde.
Bedingungen und Grenzen
Der Schattenpuffer reserviert die CPU-Adressen 0x03C0–0x03DF. Die PPU-Adressen 0x3F10/14/18/1C sind Aliase von 0x3F00/04/08/0C. Die 32 rohen Schattenbytes müssen daher nicht mit 32 unabhängigen PPU-Lesewerten übereinstimmen. Die Warteschlange kopiert die Werte; nach erfolgreicher Aufnahme darf die Quelle geändert werden. Verhindern Sie konkurrierende Zugriffe zwischen dem Befüllen der Warteschlange und ihrem NMI-Verbraucher.
Anwendungsbeispiel
result[4]=nes_palette_queue_sprite4(2,four);nes_vram_queue_nmi_flush();Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Zeigen Sie rote, blaue und grüne 32×32-Hintergrundrechtecke bei (16,32), (80,32) und (144,32) sowie 8×8-Spritequadrate bei (16,96), (80,96) und (144,96) in derselben Farbreihenfolge. Getrennte Hintergrund- und Spritepaletten demonstrieren direkte und eingereihte Übertragungen.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\batch2_palette.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch2_palette.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chrImplementierung und Quelltext
kitaqfc/lib/palette.h:24
Update and queue four sprite palette bytes at the 0x3F10 region. The caller supplies pal_index 0..3; NES palette mirroring still applies.
kitaqfc/lib/palette.c:61
unsigned char nes_palette_queue_sprite4(unsigned char pal_index, unsigned char* src4)
{
unsigned char dst;
dst = pal_index + pal_index;
dst = dst + dst;
__memcpy(nes_palette_shadow + (unsigned char)(0x10 + dst), src4, 4);
return nes_vram_queue_try_write((unsigned short)(0x3F10 + dst), nes_palette_shadow + (unsigned char)(0x10 + dst), 4);
}Eigene Bewegung mit Q5.3-Datentypen
Neben den world/body-Funktionen definiert physics2d.h Typen und Konstanten für eigene Bewegungen mit Nachkommaanteil. Dieses Beispiel implementiert game_step mit der Q5.3-Datenkonvention. Das ist ein anderer Ansatz als die world/body-Integration.
KQ2DPosition speichert die ganzzahlige Pixelposition (0..255), KQ2DFraction den Rest (0..7), KQ2DSpeed den Bewegungsbetrag pro Tick in Achtelpixeln (0..255) und KQ2DDirection die Richtung. Alle vier Typen sind u8. Die Richtung wird getrennt von der Geschwindigkeit gespeichert, nicht als Vorzeichen.
Verwenden Sie KQ2D_SUBPIXEL_BITS=3, ONE=8 und MASK=7, um position*8+fraction in einem 16-Bit-Zwischenwert zusammenzufassen. Richtung NONE=0 bedeutet Stillstand, NEGATIVE=1 Subtraktion und POSITIVE=2 Addition. Das Spiel muss die Grenzen so behandeln, dass die Subtraktion nicht negativ wird und die resultierende Ganzzahlposition im Bereich 0..255 bleibt.
KQ2D_DRAG_BRAKE=1, STUN=2, COAST=3 und THRUST=4 kennzeichnen vom Spiel definierte Verhaltensweisen für Bremsen, Betäubung, Ausrollen und Schub. Die reine Zuweisung eines Wertes wendet keine Beschleunigung oder Reibung an. Definieren Sie jeden Effekt und seine Dauer in Ihrer Aktualisierungsroutine.
Beispiel: Halbpixelbewegungen aufsummieren
Das obere rote 16×16-Pixel-Quadrat beginnt bei X=24; das untere zeigt X=32 nach 16 Ticks. Geschwindigkeit 4 bedeutet 4/8=0.5 Pixel pro Tick, also acht Pixel in 16 Ticks. Unterschiedliche Y-Positionen trennen die beiden Zustände zum Vergleich. Eine anschließende numerische Prüfung geht acht Ticks zurück und erhält X=28 mit Nachkommaanteil 0.
void game_step() {
u16 total;
total=(u16)position*KQ2D_SUBPIXEL_ONE+fraction;
if(direction==KQ2D_DIR_POSITIVE) total=total+speed;
else if(direction==KQ2D_DIR_NEGATIVE) total=total-speed;
position=(KQ2DPosition)(total>>KQ2D_SUBPIXEL_BITS);
fraction=(KQ2DFraction)(total&KQ2D_SUBPIXEL_MASK);
}
// Initial state: position=24; fraction=0; speed=4;
// direction=KQ2D_DIR_POSITIVE; call game_step() 16 times.
Vollständiges Beispielprogramm
Build
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\physics_subpixel.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\physics_subpixel.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chr --no-cache --no-disasmphysics2d
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.
Binden Sie nicht nur Header ein, sondern kompilieren Sie auch die Implementierungsdateien. Für 2D benötigen Sie fixed.c und physics2d.c, für 3D zusätzlich physics3d.c. Die Beispiele nutzen MMC3, CHR-RAM und Zeichenspeicher im PRG-RAM bei $6800–$6FFF. Dieser Zeichenpuffer ist keine Voraussetzung der Physikbibliothek selbst.
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
void kq2d_world_init(KQWorld2D* world, KQBody2D* bodies, u8 body_count);Parameter
worldZeiger auf die Welt mit dem Körperarray und den Simulationseinstellungen.
bodiesAnfang eines vom aufrufenden Code gehaltenen Körperarrays mit body_count Elementen.
body_countAnzahl 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.
Binden Sie nicht nur Header ein, sondern kompilieren Sie auch die Implementierungsdateien. Für 2D benötigen Sie fixed.c und physics2d.c, für 3D zusätzlich physics3d.c. Die Beispiele nutzen MMC3, CHR-RAM und Zeichenspeicher im PRG-RAM bei $6800–$6FFF. Dieser Zeichenpuffer ist keine Voraussetzung der Physikbibliothek selbst.
Anwendungsbeispiel
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 einen Tick später. Ein rotes 16×16-Quadrat mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden ist seine Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). RAM-Prüfungen decken auch Initialisierung, Setzfunktionen, Integration, Rechteck- und Punktabfragen sowie vorzeichenbehaftete Skalierung ab.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\physics_body2d.c -I .\kitaqfc\lib -I .\kitaq-docs\samples --mapper=mmc3 --nes-chr-ram -o .\out\physics_body2d.nes --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/physics2d.h:36
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.
kitaqfc/lib/physics2d.c:351
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;
}kq2d_step
Integriert aktive dynamische Körper und löst anschließend Kontakte zwischen aktiven Arrayeinträgen auf.
Syntax
void kq2d_step(KQWorld2D* world);Parameter
worldZeiger 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.
Binden Sie nicht nur Header ein, sondern kompilieren Sie auch die Implementierungsdateien. Für 2D benötigen Sie fixed.c und physics2d.c, für 3D zusätzlich physics3d.c. Die Beispiele nutzen MMC3, CHR-RAM und Zeichenspeicher im PRG-RAM bei $6800–$6FFF. Dieser Zeichenpuffer ist keine Voraussetzung der Physikbibliothek selbst.
Anwendungsbeispiel
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 einen Tick später. Ein rotes 16×16-Quadrat mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden ist seine Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). RAM-Prüfungen decken auch Initialisierung, Setzfunktionen, Integration, Rechteck- und Punktabfragen sowie vorzeichenbehaftete Skalierung ab.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\physics_body2d.c -I .\kitaqfc\lib -I .\kitaq-docs\samples --mapper=mmc3 --nes-chr-ram -o .\out\physics_body2d.nes --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/physics2d.h:41
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 uses non-reentrant helper scratch. This is discrete integration; fast bodies can pass through thin obstacles.
kitaqfc/lib/physics2d.c:581
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[(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_value();
kq2d_asm_limit = world->max_speed;
kq2d__clamp_value();
b->vx = kq2d_asm_value;
kq2d_asm_value = b->vy;
kq2d_asm_operand = world->gravity_y;
kq2d__add_value();
kq2d_asm_limit = world->max_speed;
kq2d__clamp_value();
b->vy = kq2d_asm_value;
kq2d_asm_value = b->x;
kq2d_asm_operand = b->vx;
kq2d__add_value();
b->x = kq2d_asm_value;
kq2d_asm_value = b->y;
kq2d_asm_operand = b->vy;
kq2d__add_value();
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[(u8)i];
if (a->active == 0) continue;
u8 j;
for (j = (u8)(i + 1); j < count; j++)
{
KQBody2D* b = &bodies[(u8)j];
if (b->active == 0) continue;
kq2d__resolve_pair(a, b);
}
}
}
}kq2d_integrate_body
Wendet Weltschwerkraft und Geschwindigkeitsgrenzen pro Achse auf einen dynamischen Körper an und addiert anschließend die Geschwindigkeit zur Position.
Syntax
void kq2d_integrate_body(KQWorld2D* world, KQBody2D* body);Parameter
worldZeiger auf die Welt mit dem Körperarray und den Simulationseinstellungen.
bodyZeiger 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.
Binden Sie nicht nur Header ein, sondern kompilieren Sie auch die Implementierungsdateien. Für 2D benötigen Sie fixed.c und physics2d.c, für 3D zusätzlich physics3d.c. Die Beispiele nutzen MMC3, CHR-RAM und Zeichenspeicher im PRG-RAM bei $6800–$6FFF. Dieser Zeichenpuffer ist keine Voraussetzung der Physikbibliothek selbst.
Anwendungsbeispiel
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 einen Tick später. Ein rotes 16×16-Quadrat mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden ist seine Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). RAM-Prüfungen decken auch Initialisierung, Setzfunktionen, Integration, Rechteck- und Punktabfragen sowie vorzeichenbehaftete Skalierung ab.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\physics_body2d.c -I .\kitaqfc\lib -I .\kitaq-docs\samples --mapper=mmc3 --nes-chr-ram -o .\out\physics_body2d.nes --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/physics2d.h:45
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.
kitaqfc/lib/physics2d.c:451
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_value();
kq2d_asm_limit = world->max_speed;
kq2d__clamp_value();
body->vx = kq2d_asm_value;
kq2d_asm_value = body->vy;
kq2d_asm_operand = world->gravity_y;
kq2d__add_value();
kq2d_asm_limit = world->max_speed;
kq2d__clamp_value();
body->vy = kq2d_asm_value;
kq2d_asm_value = body->x;
kq2d_asm_operand = body->vx;
kq2d__add_value();
body->x = kq2d_asm_value;
kq2d_asm_value = body->y;
kq2d_asm_operand = body->vy;
kq2d__add_value();
body->y = kq2d_asm_value;
}kq2d_overlap_aabb
Prüft zwei über ihren Mittelpunkt definierte Boxen auf echte Überlappung entlang X und Y.
Syntax
u8 kq2d_overlap_aabb(const KQBody2D* a, const KQBody2D* b);Parameter
aGültiger Körperzeiger. Die Abfrage ignoriert Aktivität, Masse und Flags.
bGü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.
Binden Sie nicht nur Header ein, sondern kompilieren Sie auch die Implementierungsdateien. Für 2D benötigen Sie fixed.c und physics2d.c, für 3D zusätzlich physics3d.c. Die Beispiele nutzen MMC3, CHR-RAM und Zeichenspeicher im PRG-RAM bei $6800–$6FFF. Dieser Zeichenpuffer ist keine Voraussetzung der Physikbibliothek selbst.
Anwendungsbeispiel
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 einen Tick später. Ein rotes 16×16-Quadrat mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden ist seine Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). RAM-Prüfungen decken auch Initialisierung, Setzfunktionen, Integration, Rechteck- und Punktabfragen sowie vorzeichenbehaftete Skalierung ab.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\physics_body2d.c -I .\kitaqfc\lib -I .\kitaq-docs\samples --mapper=mmc3 --nes-chr-ram -o .\out\physics_body2d.nes --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/physics2d.h:49
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.
kitaqfc/lib/physics2d.c:366
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_body_init
Initialisiert eine über ihren Mittelpunkt definierte Box mit den angegebenen halben Ausdehnungen, Geschwindigkeit null, inverser Masse 256 und aktivem Zustand.
Syntax
void kq2d_body_init(KQBody2D* body, s16 x, s16 y, s16 half_x, s16 half_y);Parameter
bodyZeiger auf den zu ändernden Körper. Von dieser Operation nicht verwendete Felder bleiben erhalten.
xX-Koordinate des Mittelpunkts oder Punkts, im Beispiel in Pixeln.
yY-Koordinate des Mittelpunkts oder Punkts; im Beispiel zeigen positive Werte nach unten.
half_xHalbe Ausdehnung entlang X; die gesamte Boxbreite ist doppelt so groß.
half_yHalbe 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.
Binden Sie nicht nur Header ein, sondern kompilieren Sie auch die Implementierungsdateien. Für 2D benötigen Sie fixed.c und physics2d.c, für 3D zusätzlich physics3d.c. Die Beispiele nutzen MMC3, CHR-RAM und Zeichenspeicher im PRG-RAM bei $6800–$6FFF. Dieser Zeichenpuffer ist keine Voraussetzung der Physikbibliothek selbst.
Anwendungsbeispiel
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 einen Tick später. Ein rotes 16×16-Quadrat mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden ist seine Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). RAM-Prüfungen decken auch Initialisierung, Setzfunktionen, Integration, Rechteck- und Punktabfragen sowie vorzeichenbehaftete Skalierung ab.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\physics_body2d.c -I .\kitaqfc\lib -I .\kitaq-docs\samples --mapper=mmc3 --nes-chr-ram -o .\out\physics_body2d.nes --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/physics2d.h:52
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.
kitaqfc/lib/physics2d.c:384
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_set_pos
Ersetzt nur den Körpermittelpunkt; Geschwindigkeit, Ausdehnungen und Aktivitätszustand bleiben erhalten.
Syntax
void kq2d_body_set_pos(KQBody2D* body, s16 x, s16 y);Parameter
bodyZeiger auf den zu ändernden Körper. Von dieser Operation nicht verwendete Felder bleiben erhalten.
xX-Koordinate des Mittelpunkts oder Punkts, im Beispiel in Pixeln.
yY-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.
Binden Sie nicht nur Header ein, sondern kompilieren Sie auch die Implementierungsdateien. Für 2D benötigen Sie fixed.c und physics2d.c, für 3D zusätzlich physics3d.c. Die Beispiele nutzen MMC3, CHR-RAM und Zeichenspeicher im PRG-RAM bei $6800–$6FFF. Dieser Zeichenpuffer ist keine Voraussetzung der Physikbibliothek selbst.
Anwendungsbeispiel
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 einen Tick später. Ein rotes 16×16-Quadrat mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden ist seine Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). RAM-Prüfungen decken auch Initialisierung, Setzfunktionen, Integration, Rechteck- und Punktabfragen sowie vorzeichenbehaftete Skalierung ab.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\physics_body2d.c -I .\kitaqfc\lib -I .\kitaq-docs\samples --mapper=mmc3 --nes-chr-ram -o .\out\physics_body2d.nes --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/physics2d.h:54
Replace the center without altering velocity, extents or activity. Null is ignored.
kitaqfc/lib/physics2d.c:399
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
void kq2d_body_set_velocity(KQBody2D* body, s16 vx, s16 vy);Parameter
bodyZeiger auf den zu ändernden Körper. Von dieser Operation nicht verwendete Felder bleiben erhalten.
vxX-Verschiebung pro Simulationstakt, in derselben Einheit wie die Position.
vyY-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.
Binden Sie nicht nur Header ein, sondern kompilieren Sie auch die Implementierungsdateien. Für 2D benötigen Sie fixed.c und physics2d.c, für 3D zusätzlich physics3d.c. Die Beispiele nutzen MMC3, CHR-RAM und Zeichenspeicher im PRG-RAM bei $6800–$6FFF. Dieser Zeichenpuffer ist keine Voraussetzung der Physikbibliothek selbst.
Anwendungsbeispiel
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 einen Tick später. Ein rotes 16×16-Quadrat mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden ist seine Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). RAM-Prüfungen decken auch Initialisierung, Setzfunktionen, Integration, Rechteck- und Punktabfragen sowie vorzeichenbehaftete Skalierung ab.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\physics_body2d.c -I .\kitaqfc\lib -I .\kitaq-docs\samples --mapper=mmc3 --nes-chr-ram -o .\out\physics_body2d.nes --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/physics2d.h:56
Replace velocity without clamping or checking activity/mass. Null is ignored.
kitaqfc/lib/physics2d.c:407
void kq2d_body_set_velocity(KQBody2D* body, s16 vx, s16 vy)
{
if (body == 0) return;
body->vx = vx;
body->vy = vy;
}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
void kq2d_body_apply_gravity(KQBody2D* body, s16 gravity_x, s16 gravity_y, s16 max_speed);Parameter
bodyZeiger auf den zu ändernden Körper. Von dieser Operation nicht verwendete Felder bleiben erhalten.
gravity_xBeschleunigung, die dieser Aufruf zur X-Geschwindigkeit addiert.
gravity_yBeschleunigung, die dieser Aufruf zur Y-Geschwindigkeit addiert.
max_speedGeschwindigkeitsgrenze. 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.
Binden Sie nicht nur Header ein, sondern kompilieren Sie auch die Implementierungsdateien. Für 2D benötigen Sie fixed.c und physics2d.c, für 3D zusätzlich physics3d.c. Die Beispiele nutzen MMC3, CHR-RAM und Zeichenspeicher im PRG-RAM bei $6800–$6FFF. Dieser Zeichenpuffer ist keine Voraussetzung der Physikbibliothek selbst.
Anwendungsbeispiel
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 einen Tick später. Ein rotes 16×16-Quadrat mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden ist seine Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). RAM-Prüfungen decken auch Initialisierung, Setzfunktionen, Integration, Rechteck- und Punktabfragen sowie vorzeichenbehaftete Skalierung ab.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\physics_body2d.c -I .\kitaqfc\lib -I .\kitaq-docs\samples --mapper=mmc3 --nes-chr-ram -o .\out\physics_body2d.nes --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/physics2d.h:60
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.
kitaqfc/lib/physics2d.c:417
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_value();
kq2d_asm_limit = max_speed;
kq2d__clamp_value();
body->vx = kq2d_asm_value;
kq2d_asm_value = body->vy;
kq2d_asm_operand = gravity_y;
kq2d__add_value();
kq2d_asm_limit = max_speed;
kq2d__clamp_value();
body->vy = kq2d_asm_value;
}kq2d_body_apply_friction
Skaliert beide Geschwindigkeitskomponenten mit einem vorzeichenbehafteten Bytekoeffizienten geteilt durch 256, ohne Position oder Aktivität zu prüfen.
Syntax
void kq2d_body_apply_friction(KQBody2D* body, u8 friction_q8);Parameter
bodyZeiger auf den zu ändernden Körper. Von dieser Operation nicht verwendete Felder bleiben erhalten.
friction_q8Von 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.
Binden Sie nicht nur Header ein, sondern kompilieren Sie auch die Implementierungsdateien. Für 2D benötigen Sie fixed.c und physics2d.c, für 3D zusätzlich physics3d.c. Die Beispiele nutzen MMC3, CHR-RAM und Zeichenspeicher im PRG-RAM bei $6800–$6FFF. Dieser Zeichenpuffer ist keine Voraussetzung der Physikbibliothek selbst.
Anwendungsbeispiel
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 einen Tick später. Ein rotes 16×16-Quadrat mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden ist seine Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). RAM-Prüfungen decken auch Initialisierung, Setzfunktionen, Integration, Rechteck- und Punktabfragen sowie vorzeichenbehaftete Skalierung ab.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\physics_body2d.c -I .\kitaqfc\lib -I .\kitaq-docs\samples --mapper=mmc3 --nes-chr-ram -o .\out\physics_body2d.nes --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/physics2d.h:64
Scale both velocities by a signed eight-bit coefficient divided by 256. Despite the unsigned parameter, values 128..255 become negative coefficients; this is not a full-range unsigned Q8 damping helper. Null is ignored.
kitaqfc/lib/physics2d.c:441
void kq2d_body_apply_friction(KQBody2D* body, u8 friction_q8)
{
if (body == 0) return;
body->vx = kq2d_scale_q8(body->vx, (s16)(s8)friction_q8);
body->vy = kq2d_scale_q8(body->vy, (s16)(s8)friction_q8);
}kq2d_rect_intersect
Prüft die Innenbereiche zweier Rechtecke auf Überlappung. Die Rechtecke werden durch linke obere Ecke und Größe angegeben.
Syntax
u8 kq2d_rect_intersect(KQRect a, KQRect b);Parameter
aKQRect-Wert mit den Koordinaten der linken oberen Ecke sowie positiver Breite und Höhe.
bKQRect-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.
Binden Sie nicht nur Header ein, sondern kompilieren Sie auch die Implementierungsdateien. Für 2D benötigen Sie fixed.c und physics2d.c, für 3D zusätzlich physics3d.c. Die Beispiele nutzen MMC3, CHR-RAM und Zeichenspeicher im PRG-RAM bei $6800–$6FFF. Dieser Zeichenpuffer ist keine Voraussetzung der Physikbibliothek selbst.
Anwendungsbeispiel
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 einen Tick später. Ein rotes 16×16-Quadrat mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden ist seine Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). RAM-Prüfungen decken auch Initialisierung, Setzfunktionen, Integration, Rechteck- und Punktabfragen sowie vorzeichenbehaftete Skalierung ab.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\physics_body2d.c -I .\kitaqfc\lib -I .\kitaq-docs\samples --mapper=mmc3 --nes-chr-ram -o .\out\physics_body2d.nes --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/physics2d.h:67
Delegate strict rectangle overlap to the fixed-point utility; edge-only contact is false. Coordinate-plus-size sums must remain representable as s16.
kitaqfc/lib/physics2d.c:485
u8 kq2d_rect_intersect(KQRect a, KQRect b)
{
return kq_rect_intersect(a, b);
}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
u8 kq2d_point_in_rect(s16 x, s16 y, KQRect r);Parameter
xX-Koordinate des Mittelpunkts oder Punkts, im Beispiel in Pixeln.
yY-Koordinate des Mittelpunkts oder Punkts; im Beispiel zeigen positive Werte nach unten.
rKQRect-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.
Binden Sie nicht nur Header ein, sondern kompilieren Sie auch die Implementierungsdateien. Für 2D benötigen Sie fixed.c und physics2d.c, für 3D zusätzlich physics3d.c. Die Beispiele nutzen MMC3, CHR-RAM und Zeichenspeicher im PRG-RAM bei $6800–$6FFF. Dieser Zeichenpuffer ist keine Voraussetzung der Physikbibliothek selbst.
Anwendungsbeispiel
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 einen Tick später. Ein rotes 16×16-Quadrat mit Mittelpunkt (24,24) und Geschwindigkeit (4,16) erreicht (28,36); auf dem blauen Boden ist seine Y-Geschwindigkeit null. Die Panelursprünge liegen bei den Bildschirmkoordinaten (8,48) und (88,48). RAM-Prüfungen decken auch Initialisierung, Setzfunktionen, Integration, Rechteck- und Punktabfragen sowie vorzeichenbehaftete Skalierung ab.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\physics_body2d.c -I .\kitaqfc\lib -I .\kitaq-docs\samples --mapper=mmc3 --nes-chr-ram -o .\out\physics_body2d.nes --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/physics2d.h:70
Delegate the half-open point test: include left/top and exclude right/bottom. Coordinate-plus-size sums must remain representable as s16.
kitaqfc/lib/physics2d.c:492
u8 kq2d_point_in_rect(s16 x, s16 y, KQRect r)
{
return kq_point_in_rect(x, y, r);
}kq2d_scale_q8
Multipliziert mit einem vorzeichenbehafteten Koeffizienten geteilt durch 256 und schneidet bei beiden Vorzeichen gegen null ab.
Syntax
s16 kq2d_scale_q8(s16 value, s16 coefficient);Parameter
valueVorzeichenbehafteter 16-Bit-Wert, auf den der Skalierungsfaktor angewendet wird.
coefficientVorzeichenbehafteter 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.
Binden Sie nicht nur Header ein, sondern kompilieren Sie auch die Implementierungsdateien. Für 2D benötigen Sie fixed.c und physics2d.c, für 3D zusätzlich physics3d.c. Die Beispiele nutzen MMC3, CHR-RAM und Zeichenspeicher im PRG-RAM bei $6800–$6FFF. Dieser Zeichenpuffer ist keine Voraussetzung der Physikbibliothek selbst.
Anwendungsbeispiel
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 seinem Platz. Seine grüne Geschwindigkeitslinie wechselt von (8,16) links zu (2,−8) rechts und zeigt Rückprall und tangentiale Reibung an der blauen Fläche. Die Panelursprünge liegen auf dem Bildschirm bei (8,48) und (88,48), der Körpermittelpunkt lokal bei (24,40). Die Auftreffgeschwindigkeit beträgt 16; das Beispiel zur Überquerungszeit gibt 192/256 zurück. Ein separater Aufruf zur Geschwindigkeitsbegrenzung reduziert (300,400) auf (147,196).

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\physics_surface.c -I .\kitaqfc\lib -I .\kitaq-docs\samples --mapper=mmc3 --nes-chr-ram -o .\out\physics_surface.nes --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/physics2d.h:86
Truncates toward zero, including negative values; coefficient is -256..256.
kitaqfc/lib/physics2d.c:8
s16 kq2d_scale_q8(s16 value,s16 coefficient) {
u16 magnitude;u16 product;u8 factor;u8 negative;
__asm {
LDA value
ORA value+1
BEQ kqfc_scale_zero
LDA coefficient
BNE kqfc_scale_fraction
LDA coefficient+1
BEQ kqfc_scale_zero
BMI kqfc_scale_negate_value
LDA value
LDX value+1
RTS
kqfc_scale_negate_value:
SEC
LDA #0
SBC value
STA product
LDA #0
SBC value+1
TAX
LDA product
RTS
kqfc_scale_zero:
LDA #0
LDX #0
RTS
kqfc_scale_fraction:
LDA value+1
EOR coefficient+1
AND #128
STA negative
LDA value
STA magnitude
LDA value+1
STA magnitude+1
BPL kqfc_scale_value_positive
SEC
LDA #0
SBC magnitude
STA magnitude
LDA #0
SBC magnitude+1
STA magnitude+1
kqfc_scale_value_positive:
LDA coefficient
STA factor
LDA coefficient+1
BPL kqfc_scale_factor_positive
SEC
LDA #0
SBC factor
STA factor
kqfc_scale_factor_positive:
LDA #0
STA product
STA product+1
// Process coefficient bit 0; carry is the product's seventeenth bit.
LSR factor
BCC kqfc_scale_shift_0
CLC
LDA product
ADC magnitude
STA product
LDA product+1
ADC magnitude+1
STA product+1
kqfc_scale_shift_0:
ROR product+1
ROR product
// Process coefficient bit 1; carry is the product's seventeenth bit.
LSR factor
BCC kqfc_scale_shift_1
CLC
LDA product
ADC magnitude
STA product
LDA product+1
ADC magnitude+1
STA product+1
kqfc_scale_shift_1:
ROR product+1
ROR product
// Process coefficient bit 2; carry is the product's seventeenth bit.
LSR factor
BCC kqfc_scale_shift_2
CLC
LDA product
ADC magnitude
STA product
LDA product+1
ADC magnitude+1
STA product+1
kqfc_scale_shift_2:
ROR product+1
ROR product
// Process coefficient bit 3; carry is the product's seventeenth bit.
LSR factor
BCC kqfc_scale_shift_3
CLC
LDA product
ADC magnitude
STA product
LDA product+1
ADC magnitude+1
STA product+1
kqfc_scale_shift_3:
ROR product+1
ROR product
// Process coefficient bit 4; carry is the product's seventeenth bit.
LSR factor
BCC kqfc_scale_shift_4
CLC
LDA product
ADC magnitude
STA product
LDA product+1
ADC magnitude+1
STA product+1
kqfc_scale_shift_4:
ROR product+1
ROR product
// Process coefficient bit 5; carry is the product's seventeenth bit.
LSR factor
BCC kqfc_scale_shift_5
CLC
LDA product
ADC magnitude
STA product
LDA product+1
ADC magnitude+1
STA product+1
kqfc_scale_shift_5:
ROR product+1
ROR product
// Process coefficient bit 6; carry is the product's seventeenth bit.
LSR factor
BCC kqfc_scale_shift_6
CLC
LDA product
ADC magnitude
STA product
LDA product+1
ADC magnitude+1
STA product+1
kqfc_scale_shift_6:
ROR product+1
ROR product
// Process coefficient bit 7; carry is the product's seventeenth bit.
LSR factor
BCC kqfc_scale_shift_7
CLC
LDA product
ADC magnitude
STA product
LDA product+1
ADC magnitude+1
STA product+1
kqfc_scale_shift_7:
ROR product+1
ROR product
LDA negative
BEQ kqfc_scale_positive
SEC
LDA #0
SBC product
STA product
LDA #0
SBC product+1
TAX
LDA product
RTS
kqfc_scale_positive:
LDA product
LDX product+1
RTS
}
}kq2d_body_limit_speed
Schätzt die Vektorlänge konservativ und skaliert beide Achsen gemeinsam, um die Gesamtgeschwindigkeit zu begrenzen.
Syntax
void kq2d_body_limit_speed(KQBody2D* body, s16 max_speed);Parameter
bodyZeiger auf den zu ändernden Körper. Von dieser Operation nicht verwendete Felder bleiben erhalten.
max_speedGeschwindigkeitsgrenze. 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.
Binden Sie nicht nur Header ein, sondern kompilieren Sie auch die Implementierungsdateien. Für 2D benötigen Sie fixed.c und physics2d.c, für 3D zusätzlich physics3d.c. Die Beispiele nutzen MMC3, CHR-RAM und Zeichenspeicher im PRG-RAM bei $6800–$6FFF. Dieser Zeichenpuffer ist keine Voraussetzung der Physikbibliothek selbst.
Anwendungsbeispiel
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 seinem Platz. Seine grüne Geschwindigkeitslinie wechselt von (8,16) links zu (2,−8) rechts und zeigt Rückprall und tangentiale Reibung an der blauen Fläche. Die Panelursprünge liegen auf dem Bildschirm bei (8,48) und (88,48), der Körpermittelpunkt lokal bei (24,40). Die Auftreffgeschwindigkeit beträgt 16; das Beispiel zur Überquerungszeit gibt 192/256 zurück. Ein separater Aufruf zur Geschwindigkeitsbegrenzung reduziert (300,400) auf (147,196).

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\physics_surface.c -I .\kitaqfc\lib -I .\kitaq-docs\samples --mapper=mmc3 --nes-chr-ram -o .\out\physics_surface.nes --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/physics2d.h:90
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.
kitaqfc/lib/physics2d.c:214
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[(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
Nutzt die Geschwindigkeit relativ zu einer bewegten Oberfläche, um normalen Rückprall, eine minimale Rückprallgeschwindigkeit und tangentiale Reibung anzuwenden.
Syntax
s16 kq2d_body_resolve_surface(KQBody2D* body, const KQSurface2D* surface);Parameter
bodyZeiger auf den zu ändernden Körper. Von dieser Operation nicht verwendete Felder bleiben erhalten.
surfaceZeiger 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.
Binden Sie nicht nur Header ein, sondern kompilieren Sie auch die Implementierungsdateien. Für 2D benötigen Sie fixed.c und physics2d.c, für 3D zusätzlich physics3d.c. Die Beispiele nutzen MMC3, CHR-RAM und Zeichenspeicher im PRG-RAM bei $6800–$6FFF. Dieser Zeichenpuffer ist keine Voraussetzung der Physikbibliothek selbst.
Anwendungsbeispiel
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 seinem Platz. Seine grüne Geschwindigkeitslinie wechselt von (8,16) links zu (2,−8) rechts und zeigt Rückprall und tangentiale Reibung an der blauen Fläche. Die Panelursprünge liegen auf dem Bildschirm bei (8,48) und (88,48), der Körpermittelpunkt lokal bei (24,40). Die Auftreffgeschwindigkeit beträgt 16; das Beispiel zur Überquerungszeit gibt 192/256 zurück. Ein separater Aufruf zur Geschwindigkeitsbegrenzung reduziert (300,400) auf (147,196).

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\physics_surface.c -I .\kitaqfc\lib -I .\kitaq-docs\samples --mapper=mmc3 --nes-chr-ram -o .\out\physics_surface.nes --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/physics2d.h:93
Kinematic surface response; returns incoming normal speed, or zero if separating. Caller resolves penetration separately. Relative components must fit +/-8191.
kitaqfc/lib/physics2d.c:268
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_surface_toi_q8
Schätzt bei linearer Bewegung den Übertrittszeitpunkt innerhalb des Takts anhand der vorzeichenbehafteten Start- und Endabstände.
Syntax
u16 kq2d_surface_toi_q8(s16 start_gap, s16 end_gap);Parameter
start_gapVorzeichenbehafteter Abstand zu Beginn des Takts; positiv bedeutet außerhalb der Oberfläche.
end_gapVorzeichenbehafteter 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.
Binden Sie nicht nur Header ein, sondern kompilieren Sie auch die Implementierungsdateien. Für 2D benötigen Sie fixed.c und physics2d.c, für 3D zusätzlich physics3d.c. Die Beispiele nutzen MMC3, CHR-RAM und Zeichenspeicher im PRG-RAM bei $6800–$6FFF. Dieser Zeichenpuffer ist keine Voraussetzung der Physikbibliothek selbst.
Anwendungsbeispiel
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 seinem Platz. Seine grüne Geschwindigkeitslinie wechselt von (8,16) links zu (2,−8) rechts und zeigt Rückprall und tangentiale Reibung an der blauen Fläche. Die Panelursprünge liegen auf dem Bildschirm bei (8,48) und (88,48), der Körpermittelpunkt lokal bei (24,40). Die Auftreffgeschwindigkeit beträgt 16; das Beispiel zur Überquerungszeit gibt 192/256 zurück. Ein separater Aufruf zur Geschwindigkeitsbegrenzung reduziert (300,400) auf (147,196).

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\physics_surface.c -I .\kitaqfc\lib -I .\kitaq-docs\samples --mapper=mmc3 --nes-chr-ram -o .\out\physics_surface.nes --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/physics2d.h:96
Linear crossing time in Q8 (0..256); positive separation is outside. Returns 0 for initial overlap, 256 for no crossing. Gaps must fit +/-8191.
kitaqfc/lib/physics2d.c:245
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));
}physics3d
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.
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.
Binden Sie nicht nur Header ein, sondern kompilieren Sie auch die Implementierungsdateien. Für 2D benötigen Sie fixed.c und physics2d.c, für 3D zusätzlich physics3d.c. Die Beispiele nutzen MMC3, CHR-RAM und Zeichenspeicher im PRG-RAM bei $6800–$6FFF. Dieser Zeichenpuffer ist keine Voraussetzung der Physikbibliothek selbst.
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
void kq3d_world_init(KQWorld3D* world, KQBody3D* bodies, u8 body_count);Parameter
worldZeiger auf die Welt mit dem Körperarray und den Simulationseinstellungen.
bodiesAnfang eines vom aufrufenden Code gehaltenen Körperarrays mit body_count Elementen.
body_countAnzahl 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.
Binden Sie nicht nur Header ein, sondern kompilieren Sie auch die Implementierungsdateien. Für 2D benötigen Sie fixed.c und physics2d.c, für 3D zusätzlich physics3d.c. Die Beispiele nutzen MMC3, CHR-RAM und Zeichenspeicher im PRG-RAM bei $6800–$6FFF. Dieser Zeichenpuffer ist keine Voraussetzung der Physikbibliothek selbst.
Anwendungsbeispiel
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 steht die X/Y-Vorderansicht, rechts die X/Z-Draufsicht. Grüne Umrisse markieren die Anfangsposition (24,24,16), rote Kästen zeigen (36,24,24) nach einem Tick, blaue Bereiche das statische Hindernis. Die X-Geschwindigkeit wechselt von 16 auf −14, während die Z-Geschwindigkeit bei 8 bleibt. Der Aufprallwert beträgt 16, die Flags bleiben aber selbst mit break_speed=1 null. Die Panelursprünge liegen auf dem Bildschirm bei (8,48) und (88,48).

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\physics_body3d.c -I .\kitaqfc\lib -I .\kitaq-docs\samples --mapper=mmc3 --nes-chr-ram -o .\out\physics_body3d.nes --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/physics3d.h:47
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.
kitaqfc/lib/physics3d.c:125
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;
}kq3d_body_init
Initialisiert 3D-Mittelpunkt, halbe Ausdehnungen und Masse; setzt Geschwindigkeit, Beschleunigung, Aufprallwert und Flags auf null und aktiviert den Körper.
Syntax
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
bodyZeiger auf den zu ändernden Körper. Von dieser Operation nicht verwendete Felder bleiben erhalten.
xX-Koordinate des Mittelpunkts oder Punkts, im Beispiel in Pixeln.
yY-Koordinate des Mittelpunkts oder Punkts; im Beispiel zeigen positive Werte nach unten.
zZ-Koordinate des Mittelpunkts, in der Draufsicht des Beispiels vertikal dargestellt.
half_xHalbe Ausdehnung entlang X; die gesamte Boxbreite ist doppelt so groß.
half_yHalbe Ausdehnung entlang Y; die gesamte Boxhöhe ist doppelt so groß.
half_zHalbe Ausdehnung entlang Z; die gesamte Tiefe ist doppelt so groß.
mass_q8Massenwert, 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.
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.
Binden Sie nicht nur Header ein, sondern kompilieren Sie auch die Implementierungsdateien. Für 2D benötigen Sie fixed.c und physics2d.c, für 3D zusätzlich physics3d.c. Die Beispiele nutzen MMC3, CHR-RAM und Zeichenspeicher im PRG-RAM bei $6800–$6FFF. Dieser Zeichenpuffer ist keine Voraussetzung der Physikbibliothek selbst.
Anwendungsbeispiel
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 steht die X/Y-Vorderansicht, rechts die X/Z-Draufsicht. Grüne Umrisse markieren die Anfangsposition (24,24,16), rote Kästen zeigen (36,24,24) nach einem Tick, blaue Bereiche das statische Hindernis. Die X-Geschwindigkeit wechselt von 16 auf −14, während die Z-Geschwindigkeit bei 8 bleibt. Der Aufprallwert beträgt 16, die Flags bleiben aber selbst mit break_speed=1 null. Die Panelursprünge liegen auf dem Bildschirm bei (8,48) und (88,48).

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\physics_body3d.c -I .\kitaqfc\lib -I .\kitaq-docs\samples --mapper=mmc3 --nes-chr-ram -o .\out\physics_body3d.nes --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/physics3d.h:51
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.
kitaqfc/lib/physics3d.c:161
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
void kq3d_body_set_mass(KQBody3D* body, s16 mass_q8);Parameter
bodyZeiger auf den zu ändernden Körper. Von dieser Operation nicht verwendete Felder bleiben erhalten.
mass_q8Massenwert, 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
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.
Binden Sie nicht nur Header ein, sondern kompilieren Sie auch die Implementierungsdateien. Für 2D benötigen Sie fixed.c und physics2d.c, für 3D zusätzlich physics3d.c. Die Beispiele nutzen MMC3, CHR-RAM und Zeichenspeicher im PRG-RAM bei $6800–$6FFF. Dieser Zeichenpuffer ist keine Voraussetzung der Physikbibliothek selbst.
Anwendungsbeispiel
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 steht die X/Y-Vorderansicht, rechts die X/Z-Draufsicht. Grüne Umrisse markieren die Anfangsposition (24,24,16), rote Kästen zeigen (36,24,24) nach einem Tick, blaue Bereiche das statische Hindernis. Die X-Geschwindigkeit wechselt von 16 auf −14, während die Z-Geschwindigkeit bei 8 bleibt. Der Aufprallwert beträgt 16, die Flags bleiben aber selbst mit break_speed=1 null. Die Panelursprünge liegen auf dem Bildschirm bei (8,48) und (88,48).

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\physics_body3d.c -I .\kitaqfc\lib -I .\kitaq-docs\samples --mapper=mmc3 --nes-chr-ram -o .\out\physics_body3d.nes --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/physics3d.h:56
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.
kitaqfc/lib/physics3d.c:142
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_step
Integriert aktive dynamische Körper und verarbeitet Kontaktkorrektur, Rückprall und Aufprallwerte zwischen aktiven Welteinträgen.
Syntax
void kq3d_step(KQWorld3D* world);Parameter
worldZeiger 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.
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.
Binden Sie nicht nur Header ein, sondern kompilieren Sie auch die Implementierungsdateien. Für 2D benötigen Sie fixed.c und physics2d.c, für 3D zusätzlich physics3d.c. Die Beispiele nutzen MMC3, CHR-RAM und Zeichenspeicher im PRG-RAM bei $6800–$6FFF. Dieser Zeichenpuffer ist keine Voraussetzung der Physikbibliothek selbst.
Anwendungsbeispiel
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 steht die X/Y-Vorderansicht, rechts die X/Z-Draufsicht. Grüne Umrisse markieren die Anfangsposition (24,24,16), rote Kästen zeigen (36,24,24) nach einem Tick, blaue Bereiche das statische Hindernis. Die X-Geschwindigkeit wechselt von 16 auf −14, während die Z-Geschwindigkeit bei 8 bleibt. Der Aufprallwert beträgt 16, die Flags bleiben aber selbst mit break_speed=1 null. Die Panelursprünge liegen auf dem Bildschirm bei (8,48) und (88,48).

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\physics_body3d.c -I .\kitaqfc\lib -I .\kitaq-docs\samples --mapper=mmc3 --nes-chr-ram -o .\out\physics_body3d.nes --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/physics3d.h:62
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 uses non-reentrant helper scratch and can miss fast crossings.
kitaqfc/lib/physics3d.c:323
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[(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_value();
kq3d_asm_operand = b->ax;
kq3d__add_value();
kq3d_asm_limit = world->max_speed;
kq3d__clamp_value();
b->vx = kq3d_asm_value;
kq3d_asm_value = b->vy;
kq3d_asm_operand = world->gravity_y;
kq3d__add_value();
kq3d_asm_operand = b->ay;
kq3d__add_value();
kq3d_asm_limit = world->max_speed;
kq3d__clamp_value();
b->vy = kq3d_asm_value;
kq3d_asm_value = b->vz;
kq3d_asm_operand = world->gravity_z;
kq3d__add_value();
kq3d_asm_operand = b->az;
kq3d__add_value();
kq3d_asm_limit = world->max_speed;
kq3d__clamp_value();
b->vz = kq3d_asm_value;
kq3d_asm_value = b->x;
kq3d_asm_operand = b->vx;
kq3d__add_value();
b->x = kq3d_asm_value;
kq3d_asm_value = b->y;
kq3d_asm_operand = b->vy;
kq3d__add_value();
b->y = kq3d_asm_value;
kq3d_asm_value = b->z;
kq3d_asm_operand = b->vz;
kq3d__add_value();
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[(u8)i];
if (a->active == 0) continue;
u8 j;
for (j = (u8)(i + 1); j < count; j++)
{
KQBody3D* b = &bodies[(u8)j];
if (b->active == 0) continue;
kq3d__resolve_pair(a, b);
}
}
}
}kq3d_integrate_body
Setzt den Aufprallwert eines aktiven dynamischen Körpers zurück, addiert Weltschwerkraft und Körperbeschleunigung, begrenzt jede Geschwindigkeitsachse und aktualisiert die Position.
Syntax
void kq3d_integrate_body(KQWorld3D* world, KQBody3D* body);Parameter
worldZeiger auf die Welt mit dem Körperarray und den Simulationseinstellungen.
bodyZeiger 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.
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.
Binden Sie nicht nur Header ein, sondern kompilieren Sie auch die Implementierungsdateien. Für 2D benötigen Sie fixed.c und physics2d.c, für 3D zusätzlich physics3d.c. Die Beispiele nutzen MMC3, CHR-RAM und Zeichenspeicher im PRG-RAM bei $6800–$6FFF. Dieser Zeichenpuffer ist keine Voraussetzung der Physikbibliothek selbst.
Anwendungsbeispiel
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 steht die X/Y-Vorderansicht, rechts die X/Z-Draufsicht. Grüne Umrisse markieren die Anfangsposition (24,24,16), rote Kästen zeigen (36,24,24) nach einem Tick, blaue Bereiche das statische Hindernis. Die X-Geschwindigkeit wechselt von 16 auf −14, während die Z-Geschwindigkeit bei 8 bleibt. Der Aufprallwert beträgt 16, die Flags bleiben aber selbst mit break_speed=1 null. Die Panelursprünge liegen auf dem Bildschirm bei (8,48) und (88,48).

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\physics_body3d.c -I .\kitaqfc\lib -I .\kitaq-docs\samples --mapper=mmc3 --nes-chr-ram -o .\out\physics_body3d.nes --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/physics3d.h:67
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.
kitaqfc/lib/physics3d.c:267
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_value();
kq3d_asm_operand = body->ax;
kq3d__add_value();
kq3d_asm_limit = world->max_speed;
kq3d__clamp_value();
body->vx = kq3d_asm_value;
kq3d_asm_value = body->vy;
kq3d_asm_operand = world->gravity_y;
kq3d__add_value();
kq3d_asm_operand = body->ay;
kq3d__add_value();
kq3d_asm_limit = world->max_speed;
kq3d__clamp_value();
body->vy = kq3d_asm_value;
kq3d_asm_value = body->vz;
kq3d_asm_operand = world->gravity_z;
kq3d__add_value();
kq3d_asm_operand = body->az;
kq3d__add_value();
kq3d_asm_limit = world->max_speed;
kq3d__clamp_value();
body->vz = kq3d_asm_value;
kq3d_asm_value = body->x;
kq3d_asm_operand = body->vx;
kq3d__add_value();
body->x = kq3d_asm_value;
kq3d_asm_value = body->y;
kq3d_asm_operand = body->vy;
kq3d__add_value();
body->y = kq3d_asm_value;
kq3d_asm_value = body->z;
kq3d_asm_operand = body->vz;
kq3d__add_value();
body->z = kq3d_asm_value;
}kq3d_overlap_aabb
Prüft zwei über ihren Mittelpunkt definierte Boxen auf echte Überlappung entlang aller drei Achsen.
Syntax
u8 kq3d_overlap_aabb(const KQBody3D* a, const KQBody3D* b);Parameter
aGültiger Körperzeiger. Die Abfrage ignoriert Aktivität, Masse und Flags.
bGü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.
Binden Sie nicht nur Header ein, sondern kompilieren Sie auch die Implementierungsdateien. Für 2D benötigen Sie fixed.c und physics2d.c, für 3D zusätzlich physics3d.c. Die Beispiele nutzen MMC3, CHR-RAM und Zeichenspeicher im PRG-RAM bei $6800–$6FFF. Dieser Zeichenpuffer ist keine Voraussetzung der Physikbibliothek selbst.
Anwendungsbeispiel
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 steht die X/Y-Vorderansicht, rechts die X/Z-Draufsicht. Grüne Umrisse markieren die Anfangsposition (24,24,16), rote Kästen zeigen (36,24,24) nach einem Tick, blaue Bereiche das statische Hindernis. Die X-Geschwindigkeit wechselt von 16 auf −14, während die Z-Geschwindigkeit bei 8 bleibt. Der Aufprallwert beträgt 16, die Flags bleiben aber selbst mit break_speed=1 null. Die Panelursprünge liegen auf dem Bildschirm bei (8,48) und (88,48).

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\physics_body3d.c -I .\kitaqfc\lib -I .\kitaq-docs\samples --mapper=mmc3 --nes-chr-ram -o .\out\physics_body3d.nes --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/physics3d.h:71
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.
kitaqfc/lib/physics3d.c:188
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_dot_q8_8
Teilt jedes der drei vorzeichenbehafteten Produkte durch 256, schneidet jeden Term gegen null ab und addiert anschließend die Terme.
Syntax
s16 kq3d_dot_q8_8(s16 x, s16 y, s16 z, s8 ax, s8 ay, s8 az);Parameter
xVorzeichenbehaftete 16-Bit-Komponente, die mit dem zugehörigen Koeffizienten multipliziert wird; sie kann Position oder Geschwindigkeit darstellen.
yVorzeichenbehaftete 16-Bit-Komponente, die mit dem zugehörigen Koeffizienten multipliziert wird; sie kann Position oder Geschwindigkeit darstellen.
zVorzeichenbehaftete 16-Bit-Komponente, die mit dem zugehörigen Koeffizienten multipliziert wird; sie kann Position oder Geschwindigkeit darstellen.
axVorzeichenbehafteter Bytekoeffizient für diese Achse (-128..127), mit Faktor 1/256 angewendet.
ayVorzeichenbehafteter Bytekoeffizient für diese Achse (-128..127), mit Faktor 1/256 angewendet.
azVorzeichenbehafteter 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
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.
Binden Sie nicht nur Header ein, sondern kompilieren Sie auch die Implementierungsdateien. Für 2D benötigen Sie fixed.c und physics2d.c, für 3D zusätzlich physics3d.c. Die Beispiele nutzen MMC3, CHR-RAM und Zeichenspeicher im PRG-RAM bei $6800–$6FFF. Dieser Zeichenpuffer ist keine Voraussetzung der Physikbibliothek selbst.
Anwendungsbeispiel
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 steht die X/Y-Vorderansicht, rechts die X/Z-Draufsicht. Grüne Umrisse markieren die Anfangsposition (24,24,16), rote Kästen zeigen (36,24,24) nach einem Tick, blaue Bereiche das statische Hindernis. Die X-Geschwindigkeit wechselt von 16 auf −14, während die Z-Geschwindigkeit bei 8 bleibt. Der Aufprallwert beträgt 16, die Flags bleiben aber selbst mit break_speed=1 null. Die Panelursprünge liegen auf dem Bildschirm bei (8,48) und (88,48).

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\physics_body3d.c -I .\kitaqfc\lib -I .\kitaq-docs\samples --mapper=mmc3 --nes-chr-ram -o .\out\physics_body3d.nes --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/physics3d.h:75
Sum three signed products, dividing each by 256 (toward zero) before addition. Coefficients are signed bytes scaled by 1/256; the 16-bit sum is not saturated.
kitaqfc/lib/physics3d.c:407
s16 kq3d_dot_q8_8(s16 x, s16 y, s16 z, s8 ax, s8 ay, s8 az)
{
return (s16)(kq2d_scale_q8(x,(s16)ax) + kq2d_scale_q8(y,(s16)ay) + kq2d_scale_q8(z,(s16)az));
}ppu.h — Deklarationen zur PPU-Anzeige
Binden oder kompilieren Sie ppu.c genau einmal und ohne runtime.c. Rufen Sie vor dessen Funktionen mit zwei Adressbytes __ppu_read_status() auf, um den gemeinsamen Latch zurückzusetzen. ppu.h deklariert diese Funktionen nicht; seine vier Deklarationen für Bildausgabe, Palette und Nametable besitzen in dieser Distribution keine Implementierung. Die hier gezeigten Funktionen stammen aus ppu.c; ppu.h allein reicht nicht aus.
nes_ppu_clear_nt
nes_ppu_clear_nt(nt_base, tile, attr) ist in dieser Distribution nicht implementiert. Das ausführbare Beispiel leert Nametable 0 in zwei Schritten: __nametable_rect_nt(0,0,0,32,30,0) beschreibt die 960 Kachelzellen, __vram_fill(0x23C0,0,64) löscht die 64 gepackten Attributbytes. Beide Aufrufe erfolgen bei ausgeschalteter Bildausgabe und Schrittweite 1. Logische Nametables können durch die Spiegelung der Cartridge denselben Speicher verwenden.
Syntax
void nes_ppu_clear_nt(unsigned short nt_base, unsigned char tile, unsigned char attr);Parameter
nt_base / tile / attrDer Prototyp deklariert
nt_baseals vorzeichenlosen 16-Bit-Wert undtile/attrals vorzeichenlose 8-Bit-Werte. Es gibt keinen Funktionskörper für Adresswahl, Füllen oder Prüfung dieser Parameter. Die Alternative wählt ausdrücklich die logische Nametable 0 und übergibt Kachel- und gepackte Attributwerte getrennt.
Rückgabewert
Deklarierter Rückgabetyp: void. Es ist keine Implementierung eingebunden; für diesen Namen gibt es daher kein ausführbares Rückkehrverhalten.
Bedingungen und Grenzen
Das Beispiel zeigt implementierte Alternativen und keinen erfolgreichen Aufruf der Deklaration. Die Prüfung umfasst den erwarteten Buildfehler wegen eines unaufgelösten Symbols für jeden fehlenden Namen sowie separate Emulatorprüfungen der Alternativen. Stellen Sie zum Aufruf des deklarierten Namens eine passende eigene Implementierung bereit; ein weiteres Header-Include liefert keinen Funktionskörper.
Anwendungsbeispiel
nes_ppu_clear_nt(0x2000,0,0); // All 960 tiles and 64 packed attribute bytes.
// Nametable reads are buffered: discard one read, then inspect all 1024 bytes.
__ppu_addr(0x2000);discarded_read=sample_ppudata;
for(i=0;i<1024;i++)if(sample_ppudata!=0)failures=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 ausführbare Alternative bereitet den Bildschirm bei ausgeschalteter Bildausgabe vor, setzt Paletten, löscht Kacheln und Attribute und zeichnet das Testbild. Bei (0,16) beginnt ein blaues Muster aus vollen Kacheln, linken Halbflächen und Dreiecken, bei (0,96) ein grüner Vollblock. Jeder Bereich ist 256×64 Pixel groß; die letzte 8×8-Zelle bei (248,72) beziehungsweise (248,152) bleibt wegen der Übertragung von 255 Kachelbytes schwarz. Bei y=208 stehen ein rotes 8×8-Quadrat an x=16, ein linker 4×8-Balken an x=224 und ein achtzeiliges Dreieck an x=240. FAILED CHECKS zeigt 0. Separate Zustandsprüfungen bestätigen beide Steuerregister, die 32 Palettenbytes und alle 1.024 gelöschten Nametable-Bytes. Die vier deklarierten Aufrufe müssen beim Linken scheitern.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\ppu_implemented.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\ppu_implemented.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/ppu.h:14
Fill 960 tiles and 64 packed attributes; preserve PPUCTRL. Accept exactly $2000/$2400/$2800/$2C00; invalid bases are ignored.
kitaqfc/lib/ppu.c:60
void nes_ppu_clear_nt(unsigned short nt_base, unsigned char tile, unsigned char attr)
{
unsigned char table;
unsigned char saved_ctrl;
if (nt_base != 0x2000 && nt_base != 0x2400 && nt_base != 0x2800 && nt_base != 0x2C00) return;
table = (unsigned char)((nt_base - 0x2000) >> 10);
saved_ctrl=__ppu_ctrl_get();
__ppu_ctrl_set((u8)(saved_ctrl & 0xFB));
__nametable_rect_nt(table,0,0,32,30,tile);
__vram_fill((u16)(nt_base+0x3C0),attr,64);
__ppu_ctrl_set(saved_ctrl);
}nes_ppu_fill
Setzt die Adresse mit hi und lo und schreibt value anschließend count-mal nach PPUDATA. Diese Funktion aus ppu.c füllt sofort mit einer 8-Bit-Anzahl; der Aufrufer setzt vorher den Latch zurück. Zeilen- oder Rechteckgrenzen begrenzen die Schreibzugriffe nicht.
Syntax
void nes_ppu_fill(unsigned char hi, unsigned char lo, unsigned char value, unsigned char count);Parameter
hi / lohiundlosind das obere und untere Byte einer PPU-Adresse:0x23, 0x42steht beispielsweise für0x2342. Es sind Adressbytes und keine Kachelkoordinaten. Die üblichen Adressmasken und Spiegelungen der PPU gelten weiterhin.valueEin 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.
countByteanzahl
0..255als vorzeichenloser 8-Bit-Wert. Null setzt die Adresse, ohne Daten zu schreiben. Der gemeinsame Latch wird auch bei null nicht zurückgesetzt; bereiten Sie ihn vor dem Aufruf vor.
Rückgabewert
Keiner (void).
Bedingungen und Grenzen
Binden oder kompilieren Sie ppu.c genau einmal und ohne runtime.c. Rufen Sie vor dessen Funktionen mit zwei Adressbytes __ppu_read_status() auf, um den gemeinsamen Latch zurückzusetzen. ppu.h deklariert diese Funktionen nicht; seine vier Deklarationen für Bildausgabe, Palette und Nametable besitzen in dieser Distribution keine Implementierung. Die hier gezeigten Funktionen stammen aus ppu.c; ppu.h allein reicht nicht aus.
Direkter PPU-Zugriff erfordert ausgeschaltete Bildausgabe oder einen sicheren VBlank-Zeitraum, in den die gesamte Operation passt. Diese Funktionen warten nicht, legen keine Aufträge an, sperren NMI nicht und stellen den Bildlauf nicht wieder her. Verhindern Sie, dass Interrupts während des Aufrufs den gemeinsamen Latch oder die Adresse verändern. PPUCTRL-Bit 2 wählt eine Zieladressschrittweite von 1 oder 32 pro Byte. Spiegelung und Adressumlauf übernimmt die PPU; CHR-ROM ist nicht beschreibbar. Stellen Sie nach dem Zugriff vor der Bildausgabe den gewünschten Bildlauf ein.
Anwendungsbeispiel
__ppu_read_status();nes_ppu_fill(0x21,0x80,1,255);Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Das separate Beispiel mit zwei Adressbytes zeigt die ausdrückliche Latch-Vorbereitung und 8-Bit-Übertragungsanzahlen. Blauer und grüner Bereich verwenden jeweils 255 Bytes; die letzten 8×8-Zellen bei (248,72) und (248,152) bleiben schwarz. Die roten Markierungen besitzen dieselben Positionen und Formen wie im Laufzeitbeispiel. FAILED CHECKS zeigt 0; dieses Programm prüft die Wartefunktionen der Laufzeitbibliothek nicht.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\ppu_address_pair.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\ppu_address_pair.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/ppu.c:27
Set the address and issue count identical PPUDATA writes without waiting for VBlank.
kitaqfc/lib/ppu.c:27
void nes_ppu_fill(unsigned char hi, unsigned char lo, unsigned char value, unsigned char count)
{
unsigned char i;
nes_ppu_seek_bytes(hi, lo);
for (i = 0; i != count; ++i)
kq_ppu_data_register = value;
}nes_ppu_load_palette
Für nes_ppu_load_palette(pal32) existiert nur eine Deklaration, keine implementierte Palettenübertragung. Das lauffähige Beispiel überträgt bei ausgeschalteter Bildausgabe und Adressschrittweite 1 mit __palette_bg_load 16 Hintergrundbytes und mit __palette_sp_load 16 Spritebytes. Die Hardware-Palettenaliase gelten weiterhin; ein Schreibzugriff auf die Spritepalette kann auch einen Hintergrundfarbeintrag ändern.
Syntax
void nes_ppu_load_palette(unsigned char* pal32);Parameter
pal32pal32ist als Zeiger auf vorzeichenlose Bytes deklariert. Der Name stellt keine implementierte 32-Byte-Übertragung bereit. Übergeben Sie für die lauffähige Alternative jedem Paletten-Intrinsic 16 lesbare Bytes und halten Sie die Quellbank bis zur Rückkehr eingeblendet.
Rückgabewert
Deklarierter Rückgabetyp: void. Es ist keine Implementierung eingebunden; für diesen Namen gibt es daher kein ausführbares Rückkehrverhalten.
Bedingungen und Grenzen
Das Beispiel zeigt implementierte Alternativen und keinen erfolgreichen Aufruf der Deklaration. Die Prüfung umfasst den erwarteten Buildfehler wegen eines unaufgelösten Symbols für jeden fehlenden Namen sowie separate Emulatorprüfungen der Alternativen. Stellen Sie zum Aufruf des deklarierten Namens eine passende eigene Implementierung bereit; ein weiteres Header-Include liefert keinen Funktionskörper.
Anwendungsbeispiel
nes_ppu_load_palette(stream_palette); // Sixteen BG bytes followed by sixteen sprite bytes.
// Palette reads are immediate; both halves use the same original sample palette.
__ppu_addr(0x3F00);
for(i=0;i<32;i++)if(sample_ppudata!=stream_palette[(u8)(i&15)])failures=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 ausführbare Alternative bereitet den Bildschirm bei ausgeschalteter Bildausgabe vor, setzt Paletten, löscht Kacheln und Attribute und zeichnet das Testbild. Bei (0,16) beginnt ein blaues Muster aus vollen Kacheln, linken Halbflächen und Dreiecken, bei (0,96) ein grüner Vollblock. Jeder Bereich ist 256×64 Pixel groß; die letzte 8×8-Zelle bei (248,72) beziehungsweise (248,152) bleibt wegen der Übertragung von 255 Kachelbytes schwarz. Bei y=208 stehen ein rotes 8×8-Quadrat an x=16, ein linker 4×8-Balken an x=224 und ein achtzeiliges Dreieck an x=240. FAILED CHECKS zeigt 0. Separate Zustandsprüfungen bestätigen beide Steuerregister, die 32 Palettenbytes und alle 1.024 gelöschten Nametable-Bytes. Die vier deklarierten Aufrufe müssen beim Linken scheitern.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\ppu_implemented.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\ppu_implemented.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/ppu.h:11
Copy 32 bytes into $3F00..$3F1F with increment one; preserve PPUCTRL. Null is ignored. Hardware palette mirrors apply; source bank must stay mapped.
kitaqfc/lib/ppu.c:48
void nes_ppu_load_palette(unsigned char* pal32)
{
u8 saved_ctrl;
if (pal32 == 0) return;
saved_ctrl=__ppu_ctrl_get();
__ppu_ctrl_set((u8)(saved_ctrl & 0xFB));
__palette_bg_load(pal32);
__palette_sp_load(pal32 + 16);
__ppu_ctrl_set(saved_ctrl);
}nes_ppu_screen_off
nes_ppu_screen_off ist in ppu.h deklariert, besitzt in dieser Distribution aber keinen Funktionskörper. Ein direkter Aufruf lässt sich nicht linken. Das ausführbare Beispiel stoppt die Bildausgabe mit __ppu_off(), das PPUMASK und dessen Softwarekopie auf null setzt. NMI wird dabei nicht deaktiviert; für die umfangreiche Bildschirmvorbereitung setzt das Beispiel PPUCTRL zusätzlich auf null.
Syntax
void nes_ppu_screen_off(void);Rückgabewert
Deklarierter Rückgabetyp: void. Es ist keine Implementierung eingebunden; für diesen Namen gibt es daher kein ausführbares Rückkehrverhalten.
Bedingungen und Grenzen
Das Beispiel zeigt implementierte Alternativen und keinen erfolgreichen Aufruf der Deklaration. Die Prüfung umfasst den erwarteten Buildfehler wegen eines unaufgelösten Symbols für jeden fehlenden Namen sowie separate Emulatorprüfungen der Alternativen. Stellen Sie zum Aufruf des deklarierten Namens eine passende eigene Implementierung bereit; ein weiteres Header-Include liefert keinen Funktionskörper.
Anwendungsbeispiel
nes_ppu_screen_off();__ppu_ctrl_set(0); // Disable NMI during this bulk preparation.Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Die ausführbare Alternative bereitet den Bildschirm bei ausgeschalteter Bildausgabe vor, setzt Paletten, löscht Kacheln und Attribute und zeichnet das Testbild. Bei (0,16) beginnt ein blaues Muster aus vollen Kacheln, linken Halbflächen und Dreiecken, bei (0,96) ein grüner Vollblock. Jeder Bereich ist 256×64 Pixel groß; die letzte 8×8-Zelle bei (248,72) beziehungsweise (248,152) bleibt wegen der Übertragung von 255 Kachelbytes schwarz. Bei y=208 stehen ein rotes 8×8-Quadrat an x=16, ein linker 4×8-Balken an x=224 und ein achtzeiliges Dreieck an x=240. FAILED CHECKS zeigt 0. Separate Zustandsprüfungen bestätigen beide Steuerregister, die 32 Palettenbytes und alle 1.024 gelöschten Nametable-Bytes. Die vier deklarierten Aufrufe müssen beim Linken scheitern.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\ppu_implemented.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\ppu_implemented.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/ppu.h:6
Link ppu.c. Bulk palette/nametable transfers require rendering to be disabled. Disable background and sprite rendering, preserving other PPUMASK bits.
kitaqfc/lib/ppu.c:36
void nes_ppu_screen_off(void) { __ppu_mask_set((u8)(__ppu_mask_get() & 0xE7)); }nes_ppu_screen_on
nes_ppu_screen_on(ctrl, mask) ist eine Deklaration ohne Implementierung und kann die Bildausgabe nicht selbst einschalten. Das lauffähige Beispiel stellt den Bildlauf ein und ruft __ppu_ctrl_set(0x80) sowie __ppu_mask_set(0x0A) auf. Das aktiviert NMI und den Hintergrund einschließlich der linken acht Pixel, aber keine Sprites. Wählen Sie die Registerwerte passend zu Ihrem Spiel.
Syntax
void nes_ppu_screen_on(unsigned char ctrl, unsigned char mask);Parameter
ctrl / maskDie Deklaration gibt
ctrlundmaskvorzeichenlose 8-Bit-Typen. Ein Funktionskörper, der ihr Laufzeitverhalten festlegt, fehlt. Die lauffähige Alternative schreibt die gewünschten PPUCTRL- und PPUMASK-Werte durch getrennte Intrinsic-Aufrufe.
Rückgabewert
Deklarierter Rückgabetyp: void. Es ist keine Implementierung eingebunden; für diesen Namen gibt es daher kein ausführbares Rückkehrverhalten.
Bedingungen und Grenzen
Das Beispiel zeigt implementierte Alternativen und keinen erfolgreichen Aufruf der Deklaration. Die Prüfung umfasst den erwarteten Buildfehler wegen eines unaufgelösten Symbols für jeden fehlenden Namen sowie separate Emulatorprüfungen der Alternativen. Stellen Sie zum Aufruf des deklarierten Namens eine passende eigene Implementierung bereit; ein weiteres Header-Include liefert keinen Funktionskörper.
Anwendungsbeispiel
nes_ppu_screen_on(0x80,0x0A);
// NMI and background rendering are now enabled, with left-edge background visible.Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Die ausführbare Alternative bereitet den Bildschirm bei ausgeschalteter Bildausgabe vor, setzt Paletten, löscht Kacheln und Attribute und zeichnet das Testbild. Bei (0,16) beginnt ein blaues Muster aus vollen Kacheln, linken Halbflächen und Dreiecken, bei (0,96) ein grüner Vollblock. Jeder Bereich ist 256×64 Pixel groß; die letzte 8×8-Zelle bei (248,72) beziehungsweise (248,152) bleibt wegen der Übertragung von 255 Kachelbytes schwarz. Bei y=208 stehen ein rotes 8×8-Quadrat an x=16, ein linker 4×8-Balken an x=224 und ein achtzeiliges Dreieck an x=240. FAILED CHECKS zeigt 0. Separate Zustandsprüfungen bestätigen beide Steuerregister, die 32 Palettenbytes und alle 1.024 gelöschten Nametable-Bytes. Die vier deklarierten Aufrufe müssen beim Linken scheitern.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\ppu_implemented.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\ppu_implemented.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/ppu.h:8
Set scroll to (0,0), then apply the requested PPUCTRL and PPUMASK values.
kitaqfc/lib/ppu.c:39
void nes_ppu_screen_on(unsigned char ctrl, unsigned char mask)
{
__ppu_read_status();
__scroll_set(0,0);
__ppu_ctrl_set(ctrl);
__ppu_mask_set(mask);
}nes_ppu_seek_bytes
Setzt durch Lesen von PPUSTATUS das gemeinsame PPU-Adresslatch zurück und setzt anschließend die Adresse aus getrennten hi- und lo-Bytes. Diese Form ist nützlich, wenn das Spiel die Adresse bereits als zwei Bytes speichert.
Syntax
void nes_ppu_seek_bytes(unsigned char hi, unsigned char lo);Parameter
hi / lohiundlosind das obere und untere Byte einer PPU-Adresse:0x23, 0x42steht beispielsweise für0x2342. Es sind Adressbytes und keine Kachelkoordinaten. Die üblichen Adressmasken und Spiegelungen der PPU gelten weiterhin.
Rückgabewert
Keiner (void).
Bedingungen und Grenzen
Binden oder kompilieren Sie ppu.c genau einmal und ohne runtime.c. Rufen Sie vor dessen Funktionen mit zwei Adressbytes __ppu_read_status() auf, um den gemeinsamen Latch zurückzusetzen. ppu.h deklariert diese Funktionen nicht; seine vier Deklarationen für Bildausgabe, Palette und Nametable besitzen in dieser Distribution keine Implementierung. Die hier gezeigten Funktionen stammen aus ppu.c; ppu.h allein reicht nicht aus.
Direkter PPU-Zugriff erfordert ausgeschaltete Bildausgabe oder einen sicheren VBlank-Zeitraum, in den die gesamte Operation passt. Diese Funktionen warten nicht, legen keine Aufträge an, sperren NMI nicht und stellen den Bildlauf nicht wieder her. Verhindern Sie, dass Interrupts während des Aufrufs den gemeinsamen Latch oder die Adresse verändern. PPUCTRL-Bit 2 wählt eine Zieladressschrittweite von 1 oder 32 pro Byte. Spiegelung und Adressumlauf übernimmt die PPU; CHR-ROM ist nicht beschreibbar. Stellen Sie nach dem Zugriff vor der Bildausgabe den gewünschten Bildlauf ein.
Anwendungsbeispiel
nes_ppu_seek_bytes(0x23,0x42);
PPUDATA=1; // Red 8x8 marker at pixel (16,208).Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Das separate Beispiel mit zwei Adressbytes zeigt die ausdrückliche Latch-Vorbereitung und 8-Bit-Übertragungsanzahlen. Blauer und grüner Bereich verwenden jeweils 255 Bytes; die letzten 8×8-Zellen bei (248,72) und (248,152) bleiben schwarz. Die roten Markierungen besitzen dieselben Positionen und Formen wie im Laufzeitbeispiel. FAILED CHECKS zeigt 0; dieses Programm prüft die Wartefunktionen der Laufzeitbibliothek nicht.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\ppu_address_pair.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\ppu_address_pair.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/ppu.c:8
Reset the shared scroll/address latch before writing the address byte pair.
kitaqfc/lib/ppu.c:8
void nes_ppu_seek_bytes(unsigned char hi, unsigned char lo)
{
__ppu_read_status();
kq_ppu_addr_register = hi;
kq_ppu_addr_register = lo;
}nes_ppu_write_bytes
Schreibt nach dem Setzen der Adresse mit hi und lo direkt count aufeinanderfolgende Quellbytes nach PPUDATA. Diese Funktion aus ppu.c nimmt eine 8-Bit-Anzahl entgegen; der Aufrufer muss den Adress-Latch zurücksetzen. Die Übertragung endet vor der Rückkehr und verwendet keine Warteschlange.
Syntax
void nes_ppu_write_bytes(unsigned char hi, unsigned char lo, const unsigned char* src, unsigned char count);Parameter
hi / lohiundlosind das obere und untere Byte einer PPU-Adresse:0x23, 0x42steht beispielsweise für0x2342. Es sind Adressbytes und keine Kachelkoordinaten. Die üblichen Adressmasken und Spiegelungen der PPU gelten weiterhin.srcCPU-Zeiger auf mindestens die angeforderte Anzahl lesbarer Bytes. Halten Sie die Quelle bis zur Rückkehr dieser synchronen Übertragung eingeblendet und unverändert. Es gibt keine Bankumschaltung, Speicherung des Zeigers in einer Warteschlange oder Prüfung der Quelllänge. Bei Anzahl null wird der Zeiger nicht dereferenziert.
countByteanzahl
0..255als vorzeichenloser 8-Bit-Wert. Null setzt die Adresse, ohne Daten zu schreiben. Der gemeinsame Latch wird auch bei null nicht zurückgesetzt; bereiten Sie ihn vor dem Aufruf vor.
Rückgabewert
Keiner (void).
Bedingungen und Grenzen
Binden oder kompilieren Sie ppu.c genau einmal und ohne runtime.c. Rufen Sie vor dessen Funktionen mit zwei Adressbytes __ppu_read_status() auf, um den gemeinsamen Latch zurückzusetzen. ppu.h deklariert diese Funktionen nicht; seine vier Deklarationen für Bildausgabe, Palette und Nametable besitzen in dieser Distribution keine Implementierung. Die hier gezeigten Funktionen stammen aus ppu.c; ppu.h allein reicht nicht aus.
Direkter PPU-Zugriff erfordert ausgeschaltete Bildausgabe oder einen sicheren VBlank-Zeitraum, in den die gesamte Operation passt. Diese Funktionen warten nicht, legen keine Aufträge an, sperren NMI nicht und stellen den Bildlauf nicht wieder her. Verhindern Sie, dass Interrupts während des Aufrufs den gemeinsamen Latch oder die Adresse verändern. PPUCTRL-Bit 2 wählt eine Zieladressschrittweite von 1 oder 32 pro Byte. Spiegelung und Adressumlauf übernimmt die PPU; CHR-ROM ist nicht beschreibbar. Stellen Sie nach dem Zugriff vor der Bildausgabe den gewünschten Bildlauf ein.
Anwendungsbeispiel
__ppu_read_status();nes_ppu_write_bytes(0x20,0x40,source_bytes,255);
source_bytes[0]=3; // The completed transfer retains tile 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 separate Beispiel mit zwei Adressbytes zeigt die ausdrückliche Latch-Vorbereitung und 8-Bit-Übertragungsanzahlen. Blauer und grüner Bereich verwenden jeweils 255 Bytes; die letzten 8×8-Zellen bei (248,72) und (248,152) bleiben schwarz. Die roten Markierungen besitzen dieselben Positionen und Formen wie im Laufzeitbeispiel. FAILED CHECKS zeigt 0; dieses Programm prüft die Wartefunktionen der Laufzeitbibliothek nicht.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\ppu_address_pair.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\ppu_address_pair.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/ppu.c:18
Set the address and write count bytes directly through PPUDATA. The current PPUCTRL increment mode determines how the destination advances. count is 0..255; zero still changes PPU address/latch state. No bank switch or payload copy is performed.
kitaqfc/lib/ppu.c:18
void nes_ppu_write_bytes(unsigned char hi, unsigned char lo, const unsigned char* src, unsigned char count)
{
unsigned char i;
nes_ppu_seek_bytes(hi, lo);
for (i = 0; i != count; ++i)
kq_ppu_data_register = src[i];
}runtime.h — C-Hilfsfunktionen für NMI, OAM und PPU-Übertragungen
Verwenden Sie die Deklarationen aus runtime.h und binden oder kompilieren Sie runtime.c genau einmal. Neben dieser Warteschlange stellt die Datei __nes_nmi, den Laufzeit-Bildzähler, direkte PPU-Hilfsfunktionen und OAM-Speicher auf Seite 02 bereit. Stimmen Sie die NMI-Behandlung mit Ihrem Programm ab; eine Funktionsdeklaration allein bindet keine Implementierung ein.
Dies ist eine separate 192-Byte-Warteschlange aus runtime.c an den CPU-Adressen 0x0300–0x03BF. Ein Dateneintrag belegt 3+len Bytes, ein Fülleintrag vier. nes_vram_queue_used zählt codierte Bytes, nicht ausstehende PPU-Schreibzugriffe oder freien VRAM. Die Intrinsic-Warteschlange __vramq_* verwendet ein anderes Format; diese Funktionen leeren, prüfen oder verarbeiten sie nicht.
Trennen Sie Aufbau und Verarbeitung der Pakete; Sperren oder doppelte Puffer sind nicht vorgesehen. Für eine eindeutige Vorbereitung deaktivieren Sie NMI beim Anhängen und verarbeiten die Einträge bei abgeschalteter Bildausgabe, oder aktivieren NMI für ein Paket, das in VBlank passt. runtime.c verarbeitet eine nicht leere Warteschlange automatisch aus __nes_nmi, ohne Freigabeaufruf. Es gibt weder Zeitbudget noch Aufteilung oder Wiederherstellung des Scrollzustands. Freier Warteschlangenplatz garantiert keine sichere VBlank-Dauer.
nes_ppu_seek
Setzt die PPU-Adresse für nachfolgende PPUDATA-Zugriffe. nes_ppu_seek(ppu_addr) aus runtime.c liest PPUSTATUS, setzt damit den gemeinsamen Schreib-Latch zurück und schreibt anschließend das obere und untere Adressbyte. Die separate Funktion nes_ppu_seek(hi, lo) aus ppu.c setzt den Latch nicht zurück. Trotz gleichem Namen unterscheiden sich Parameter und Verhalten; binden Sie nur eine der beiden Implementierungen ein.
Syntax
void nes_ppu_seek(unsigned short ppu_addr);Parameter
ppu_addrPPU-Byteadresse (
0x0000–0x3FFF), kein CPU-Zeiger. Das Ziel muss beschreibbar sein: Musteränderungen benötigen CHR-RAM statt CHR-ROM. PPU-Adressabbildung und Spiegelung gelten weiterhin. Wählen Sie für fortlaufendes Kopieren und Füllen die Schrittweite 1 in PPUCTRL. Führen Sie Befehle zu einem sicheren PPU-Zeitpunkt aus und stellen Sie danach den Scrollzustand her; der Ausführer schreibt PPUADDR und PPUDATA, ohne Scrolleinstellungen wiederherzustellen.
Rückgabewert
Keiner (void).
Bedingungen und Grenzen
Verwenden Sie die Deklarationen aus runtime.h und binden oder kompilieren Sie runtime.c genau einmal. Neben dieser Warteschlange stellt die Datei __nes_nmi, den Laufzeit-Bildzähler, direkte PPU-Hilfsfunktionen und OAM-Speicher auf Seite 02 bereit. Stimmen Sie die NMI-Behandlung mit Ihrem Programm ab; eine Funktionsdeklaration allein bindet keine Implementierung ein.
Direkter PPU-Zugriff erfordert ausgeschaltete Bildausgabe oder einen sicheren VBlank-Zeitraum, in den die gesamte Operation passt. Diese Funktionen warten nicht, legen keine Aufträge an, sperren NMI nicht und stellen den Bildlauf nicht wieder her. Verhindern Sie, dass Interrupts während des Aufrufs den gemeinsamen Latch oder die Adresse verändern. PPUCTRL-Bit 2 wählt eine Zieladressschrittweite von 1 oder 32 pro Byte. Spiegelung und Adressumlauf übernimmt die PPU; CHR-ROM ist nicht beschreibbar. Stellen Sie nach dem Zugriff vor der Bildausgabe den gewünschten Bildlauf ein.
Anwendungsbeispiel
PPUADDR=0x21; // Deliberately leave the shared address latch half-written.
nes_ppu_seek(0x2342); // This runtime function resets the latch itself.
PPUDATA=1; // Red 8x8 marker at pixel (16,208).Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Das Laufzeitbeispiel zeigt direkte Übertragung und beide Wartemethoden. Bei (0,16) erscheint ein blaues Muster aus vollen Kacheln, linken Halbflächen und Dreiecken; bei (0,96) ein gefüllter grüner Block. Jeder Block ist 256×64 Pixel groß und entsteht aus 256 Kachelbytes. Die erste blaue Kachel bleibt nach Änderung der Quelle gefüllt. Bei y=208 markieren rote Formen an x=16, 224 und 240 Adresssetzung, Schreiben mit Länge null und Füllen mit Länge null: ein 8×8-Quadrat, ein linker 4×8-Balken und ein achtzeiliges Dreieck. Beide Warteanzeigen zeigen 1, FAILED CHECKS zeigt 0.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\runtime_ppu.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\runtime_ppu.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/runtime.h:28
Reset the PPU address latch with a status read, then write the high/low address bytes.
kitaqfc/lib/runtime.c:207
void nes_ppu_seek(unsigned short ppu_addr)
{
unsigned char latch;
latch = PPUSTATUS;
PPUADDR = (unsigned char)(ppu_addr >> 8);
PPUADDR = (unsigned char)ppu_addr;
latch = latch;
}nes_ppu_stream_fill
Setzt ppu_addr und schreibt anschließend dasselbe Byte value genau len-mal nach PPUDATA. Das direkte Füllen ist bei der Rückkehr abgeschlossen. Kachelmaße, Attribute und Rechteckgrenzen werden dabei nicht ausgewertet.
Syntax
void nes_ppu_stream_fill(unsigned short ppu_addr, unsigned char value, unsigned short len);Parameter
ppu_addrPPU-Byteadresse (
0x0000–0x3FFF), kein CPU-Zeiger. Das Ziel muss beschreibbar sein: Musteränderungen benötigen CHR-RAM statt CHR-ROM. PPU-Adressabbildung und Spiegelung gelten weiterhin. Wählen Sie für fortlaufendes Kopieren und Füllen die Schrittweite 1 in PPUCTRL. Führen Sie Befehle zu einem sicheren PPU-Zeitpunkt aus und stellen Sie danach den Scrollzustand her; der Ausführer schreibt PPUADDR und PPUDATA, ohne Scrolleinstellungen wiederherzustellen.valueEin 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.
lenByteanzahl von
0..65535als vorzeichenloser 16-Bit-Wert. Auch null setzt die PPU-Adresse und den Latch zurück, schreibt aber nicht nach PPUDATA. Zielgröße und Aufteilung der Übertragung werden nicht geprüft; große Werte können den PPU-Adressraum umlaufen.
Rückgabewert
Keiner (void).
Bedingungen und Grenzen
Verwenden Sie die Deklarationen aus runtime.h und binden oder kompilieren Sie runtime.c genau einmal. Neben dieser Warteschlange stellt die Datei __nes_nmi, den Laufzeit-Bildzähler, direkte PPU-Hilfsfunktionen und OAM-Speicher auf Seite 02 bereit. Stimmen Sie die NMI-Behandlung mit Ihrem Programm ab; eine Funktionsdeklaration allein bindet keine Implementierung ein.
Direkter PPU-Zugriff erfordert ausgeschaltete Bildausgabe oder einen sicheren VBlank-Zeitraum, in den die gesamte Operation passt. Diese Funktionen warten nicht, legen keine Aufträge an, sperren NMI nicht und stellen den Bildlauf nicht wieder her. Verhindern Sie, dass Interrupts während des Aufrufs den gemeinsamen Latch oder die Adresse verändern. PPUCTRL-Bit 2 wählt eine Zieladressschrittweite von 1 oder 32 pro Byte. Spiegelung und Adressumlauf übernimmt die PPU; CHR-ROM ist nicht beschreibbar. Stellen Sie nach dem Zugriff vor der Bildausgabe den gewünschten Bildlauf ein.
Anwendungsbeispiel
nes_ppu_stream_fill(0x2180,1,256); // Eight complete rows of solid green tiles.Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Das Laufzeitbeispiel zeigt direkte Übertragung und beide Wartemethoden. Bei (0,16) erscheint ein blaues Muster aus vollen Kacheln, linken Halbflächen und Dreiecken; bei (0,96) ein gefüllter grüner Block. Jeder Block ist 256×64 Pixel groß und entsteht aus 256 Kachelbytes. Die erste blaue Kachel bleibt nach Änderung der Quelle gefüllt. Bei y=208 markieren rote Formen an x=16, 224 und 240 Adresssetzung, Schreiben mit Länge null und Füllen mit Länge null: ein 8×8-Quadrat, ein linker 4×8-Balken und ein achtzeiliges Dreieck. Beide Warteanzeigen zeigen 1, FAILED CHECKS zeigt 0.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\runtime_ppu.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\runtime_ppu.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/runtime.h:34
Write value repeatedly through PPUDATA, using the current PPU address increment mode. This routine does not wait for VBlank or disable rendering.
kitaqfc/lib/runtime.c:232
void nes_ppu_stream_fill(unsigned short ppu_addr, unsigned char value, unsigned short len)
{
nes_ppu_seek(ppu_addr);
while (len != 0)
{
PPUDATA = value;
len = len - 1;
}
}nes_ppu_stream_write
Schreibt ab ppu_addr direkt len aufeinanderfolgende Quellbytes nach PPUDATA. Die Adresse wird einmal gesetzt; nach jedem Schreibzugriff wird die lokale Kopie des Quellzeigers erhöht. Bei der Rückkehr ist die Übertragung abgeschlossen. Spätere Änderungen der Quelle verändern die VRAM-Daten nicht. Die Zeigervariable des Aufrufers bleibt unverändert.
Syntax
void nes_ppu_stream_write(unsigned short ppu_addr, unsigned char* src, unsigned short len);Parameter
ppu_addrPPU-Byteadresse (
0x0000–0x3FFF), kein CPU-Zeiger. Das Ziel muss beschreibbar sein: Musteränderungen benötigen CHR-RAM statt CHR-ROM. PPU-Adressabbildung und Spiegelung gelten weiterhin. Wählen Sie für fortlaufendes Kopieren und Füllen die Schrittweite 1 in PPUCTRL. Führen Sie Befehle zu einem sicheren PPU-Zeitpunkt aus und stellen Sie danach den Scrollzustand her; der Ausführer schreibt PPUADDR und PPUDATA, ohne Scrolleinstellungen wiederherzustellen.srcCPU-Zeiger auf mindestens die angeforderte Anzahl lesbarer Bytes. Halten Sie die Quelle bis zur Rückkehr dieser synchronen Übertragung eingeblendet und unverändert. Es gibt keine Bankumschaltung, Speicherung des Zeigers in einer Warteschlange oder Prüfung der Quelllänge. Bei Anzahl null wird der Zeiger nicht dereferenziert.
lenByteanzahl von
0..65535als vorzeichenloser 16-Bit-Wert. Auch null setzt die PPU-Adresse und den Latch zurück, schreibt aber nicht nach PPUDATA. Zielgröße und Aufteilung der Übertragung werden nicht geprüft; große Werte können den PPU-Adressraum umlaufen.
Rückgabewert
Keiner (void).
Bedingungen und Grenzen
Verwenden Sie die Deklarationen aus runtime.h und binden oder kompilieren Sie runtime.c genau einmal. Neben dieser Warteschlange stellt die Datei __nes_nmi, den Laufzeit-Bildzähler, direkte PPU-Hilfsfunktionen und OAM-Speicher auf Seite 02 bereit. Stimmen Sie die NMI-Behandlung mit Ihrem Programm ab; eine Funktionsdeklaration allein bindet keine Implementierung ein.
Direkter PPU-Zugriff erfordert ausgeschaltete Bildausgabe oder einen sicheren VBlank-Zeitraum, in den die gesamte Operation passt. Diese Funktionen warten nicht, legen keine Aufträge an, sperren NMI nicht und stellen den Bildlauf nicht wieder her. Verhindern Sie, dass Interrupts während des Aufrufs den gemeinsamen Latch oder die Adresse verändern. PPUCTRL-Bit 2 wählt eine Zieladressschrittweite von 1 oder 32 pro Byte. Spiegelung und Adressumlauf übernimmt die PPU; CHR-ROM ist nicht beschreibbar. Stellen Sie nach dem Zugriff vor der Bildausgabe den gewünschten Bildlauf ein.
Anwendungsbeispiel
// Rendering/NMI are off; PPUCTRL increment is 1. Transfer 256 bytes now.
nes_ppu_stream_write(0x2040,source_bytes,256);
source_bytes[0]=3; // VRAM already holds tile 1 at the first blue cell.Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Das Laufzeitbeispiel zeigt direkte Übertragung und beide Wartemethoden. Bei (0,16) erscheint ein blaues Muster aus vollen Kacheln, linken Halbflächen und Dreiecken; bei (0,96) ein gefüllter grüner Block. Jeder Block ist 256×64 Pixel groß und entsteht aus 256 Kachelbytes. Die erste blaue Kachel bleibt nach Änderung der Quelle gefüllt. Bei y=208 markieren rote Formen an x=16, 224 und 240 Adresssetzung, Schreiben mit Länge null und Füllen mit Länge null: ein 8×8-Quadrat, ein linker 4×8-Balken und ein achtzeiliges Dreieck. Beide Warteanzeigen zeigen 1, FAILED CHECKS zeigt 0.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\runtime_ppu.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\runtime_ppu.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/runtime.h:31
Write len source bytes directly through PPUDATA. Call only during an appropriate PPU access period; the address increment mode comes from the current PPUCTRL.
kitaqfc/lib/runtime.c:219
void nes_ppu_stream_write(unsigned short ppu_addr, unsigned char* src, unsigned short len)
{
nes_ppu_seek(ppu_addr);
while (len != 0)
{
PPUDATA = *src;
src = src + 1;
len = len - 1;
}
}nes_vblank_wait
Fragt Bit 7 von PPUSTATUS ab, verbraucht zunächst eine bereits gesetzte Meldung und wartet dann auf eine neue VBlank-Meldung. Funktioniert auch bei deaktiviertem NMI, führt aber keine Warteschlange aus und ändert den NMI-Zähler der Laufzeitbibliothek nicht. Jeder Statuslesezugriff löscht das VBlank-Flag und setzt den gemeinsamen Schreib-Latch für Bildlauf und Adresse zurück. Verwenden Sie diese Abfrage getrennt von der NMI-gesteuerten Ablaufplanung, da Statuszugriffe das NMI-Timing beeinflussen können. Zeitlimit, Datenübertragung und Wiederherstellung des Bildlaufs sind nicht enthalten.
Syntax
void nes_vblank_wait(void);Rückgabewert
Keiner (void).
Bedingungen und Grenzen
Verwenden Sie die Deklarationen aus runtime.h und binden oder kompilieren Sie runtime.c genau einmal. Neben dieser Warteschlange stellt die Datei __nes_nmi, den Laufzeit-Bildzähler, direkte PPU-Hilfsfunktionen und OAM-Speicher auf Seite 02 bereit. Stimmen Sie die NMI-Behandlung mit Ihrem Programm ab; eine Funktionsdeklaration allein bindet keine Implementierung ein.
Anwendungsbeispiel
// With NMI disabled, poll a new PPU VBlank flag. No queued work is flushed.
nes_vblank_wait();blank_seen=1;
if((PPUSTATUS&0x80)!=0)failures++; // The wait's status read cleared the flag.Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Das Laufzeitbeispiel zeigt direkte Übertragung und beide Wartemethoden. Bei (0,16) erscheint ein blaues Muster aus vollen Kacheln, linken Halbflächen und Dreiecken; bei (0,96) ein gefüllter grüner Block. Jeder Block ist 256×64 Pixel groß und entsteht aus 256 Kachelbytes. Die erste blaue Kachel bleibt nach Änderung der Quelle gefüllt. Bei y=208 markieren rote Formen an x=16, 224 und 240 Adresssetzung, Schreiben mit Länge null und Füllen mit Länge null: ein 8×8-Quadrat, ein linker 4×8-Balken und ein achtzeiliges Dreieck. Beide Warteanzeigen zeigen 1, FAILED CHECKS zeigt 0.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\runtime_ppu.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\runtime_ppu.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/runtime.h:26
Wait for the current VBlank to end, then for the next one to begin. Each PPUSTATUS read has hardware side effects, including clearing the VBlank flag.
kitaqfc/lib/runtime.c:196
void nes_vblank_wait(void)
{
while ((PPUSTATUS & 0x80) != 0)
{
}
while ((PPUSTATUS & 0x80) == 0)
{
}
}nes_vram_queue_clear
Verwirft alle ausstehenden Einträge der C-Laufzeitwarteschlange und setzt nes_vram_queue_used sowie nes_vram_queue_overflow auf null. Es erfolgen keine PPU-Schreibzugriffe; die gespeicherten Nutzdatenbytes werden nicht gelöscht. Die Intrinsic-Warteschlange des Compilers bleibt unverändert.
Syntax
void nes_vram_queue_clear(void);Rückgabewert
Keiner (void).
Bedingungen und Grenzen
Dies ist eine separate 192-Byte-Warteschlange aus runtime.c an den CPU-Adressen 0x0300–0x03BF. Ein Dateneintrag belegt 3+len Bytes, ein Fülleintrag vier. nes_vram_queue_used zählt codierte Bytes, nicht ausstehende PPU-Schreibzugriffe oder freien VRAM. Die Intrinsic-Warteschlange __vramq_* verwendet ein anderes Format; diese Funktionen leeren, prüfen oder verarbeiten sie nicht.
Verwenden Sie die Deklarationen aus runtime.h und binden oder kompilieren Sie runtime.c genau einmal. Neben dieser Warteschlange stellt die Datei __nes_nmi, den Laufzeit-Bildzähler, direkte PPU-Hilfsfunktionen und OAM-Speicher auf Seite 02 bereit. Stimmen Sie die NMI-Behandlung mit Ihrem Programm ab; eine Funktionsdeklaration allein bindet keine Implementierung ein.
Trennen Sie Aufbau und Verarbeitung der Pakete; Sperren oder doppelte Puffer sind nicht vorgesehen. Für eine eindeutige Vorbereitung deaktivieren Sie NMI beim Anhängen und verarbeiten die Einträge bei abgeschalteter Bildausgabe, oder aktivieren NMI für ein Paket, das in VBlank passt. runtime.c verarbeitet eine nicht leere Warteschlange automatisch aus __nes_nmi, ohne Freigabeaufruf. Es gibt weder Zeitbudget noch Aufteilung oder Wiederherstellung des Scrollzustands. Freier Warteschlangenplatz garantiert keine sichere VBlank-Dauer.
Anwendungsbeispiel
nes_vram_queue_clear(); // Discard all records AND clear the overflow latch.
if(nes_vram_queue_used!=0 || nes_vram_queue_overflow!=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 Beispiel füllt zunächst alle 192 Warteschlangenbytes und lässt einen weiteren Eintrag absichtlich ablehnen. Es verwirft dieses Paket, prüft die Ablehnung von Länge 128 und reiht dann fünf Einträge ein: 145 Bytes für 255 PPU-Schreibzugriffe. Erwartet werden CAPACITY 192, ENCODED BYTES 145, AFTER FLUSH 000, REJECTED LENGTH 001, OVERFLOW SEEN 001 und FAILED CHECKS 000. Die Ablehnungsanzeigen speichern Beobachtungen aus vorherigen Programmschritten, nicht den abschließenden Flagzustand.
Die blau kopierten Tiles beginnen bei (0,16), die grüne Füllung bei (0,64). Jeder Bereich enthält 127 Tiles: drei volle Reihen und 31 Tiles in der vierten; die letzte 8×8-Zelle bleibt schwarz. Die blaue Folge wiederholt volle, halbbreite und dreieckige Tiles; das erste bleibt trotz geänderter Quelle voll. Bei y=112 bleibt das rote Quadrat bei x=16 nach Aufträgen der Länge null erhalten, das rote halbe Tile bei x=224 belegt die automatische NMI-Verarbeitung, und die verworfene Zelle bei x=248 bleibt schwarz. Geprüft werden 18.432 Pixel sowie das Ausbleiben von VRAM-Schreibzugriffen während aktiver Bildausgabe. Physische Hardware wurde nicht getestet.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\runtime_queue.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\runtime_queue.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/runtime.h:40
Discard pending VRAM commands and clear the overflow latch; no PPU writes occur.
kitaqfc/lib/runtime.c:31
void nes_vram_queue_clear(void)
{
nes_vram_queue_used = 0;
nes_vram_queue_overflow = 0;
}nes_vram_queue_nmi_flush
Arbeitet alle ausstehenden Einträge der C-Laufzeitwarteschlange der Reihe nach ab, ohne Freigabeflag. Setzt für jeden Eintrag die PPU-Adresse und überträgt die gespeicherten Daten oder wiederholt das Füllbyte. Danach wird nes_vram_queue_used auf null gesetzt; das Überlaufflag bleibt erhalten. Bei leerer Warteschlange erfolgt kein PPU-Zugriff.
Syntax
void nes_vram_queue_nmi_flush(void);Rückgabewert
Keiner (void).
Bedingungen und Grenzen
Dies ist eine separate 192-Byte-Warteschlange aus runtime.c an den CPU-Adressen 0x0300–0x03BF. Ein Dateneintrag belegt 3+len Bytes, ein Fülleintrag vier. nes_vram_queue_used zählt codierte Bytes, nicht ausstehende PPU-Schreibzugriffe oder freien VRAM. Die Intrinsic-Warteschlange __vramq_* verwendet ein anderes Format; diese Funktionen leeren, prüfen oder verarbeiten sie nicht.
Verwenden Sie die Deklarationen aus runtime.h und binden oder kompilieren Sie runtime.c genau einmal. Neben dieser Warteschlange stellt die Datei __nes_nmi, den Laufzeit-Bildzähler, direkte PPU-Hilfsfunktionen und OAM-Speicher auf Seite 02 bereit. Stimmen Sie die NMI-Behandlung mit Ihrem Programm ab; eine Funktionsdeklaration allein bindet keine Implementierung ein.
Trennen Sie Aufbau und Verarbeitung der Pakete; Sperren oder doppelte Puffer sind nicht vorgesehen. Für eine eindeutige Vorbereitung deaktivieren Sie NMI beim Anhängen und verarbeiten die Einträge bei abgeschalteter Bildausgabe, oder aktivieren NMI für ein Paket, das in VBlank passt. runtime.c verarbeitet eine nicht leere Warteschlange automatisch aus __nes_nmi, ohne Freigabeaufruf. Es gibt weder Zeitbudget noch Aufteilung oder Wiederherstellung des Scrollzustands. Freier Warteschlangenplatz garantiert keine sichere VBlank-Dauer.
PPU-Byteadresse (0x0000–0x3FFF), kein CPU-Zeiger. Das Ziel muss beschreibbar sein: Musteränderungen benötigen CHR-RAM statt CHR-ROM. PPU-Adressabbildung und Spiegelung gelten weiterhin. Wählen Sie für fortlaufendes Kopieren und Füllen die Schrittweite 1 in PPUCTRL. Führen Sie Befehle zu einem sicheren PPU-Zeitpunkt aus und stellen Sie danach den Scrollzustand her; der Ausführer schreibt PPUADDR und PPUDATA, ohne Scrolleinstellungen wiederherzustellen.
Anwendungsbeispiel
// Rendering and NMI are disabled; PPUCTRL selects increment 1.
nes_vram_queue_nmi_flush(); // No commit flag: consume all queued records now.
after_flush=nes_vram_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 Beispiel füllt zunächst alle 192 Warteschlangenbytes und lässt einen weiteren Eintrag absichtlich ablehnen. Es verwirft dieses Paket, prüft die Ablehnung von Länge 128 und reiht dann fünf Einträge ein: 145 Bytes für 255 PPU-Schreibzugriffe. Erwartet werden CAPACITY 192, ENCODED BYTES 145, AFTER FLUSH 000, REJECTED LENGTH 001, OVERFLOW SEEN 001 und FAILED CHECKS 000. Die Ablehnungsanzeigen speichern Beobachtungen aus vorherigen Programmschritten, nicht den abschließenden Flagzustand.
Die blau kopierten Tiles beginnen bei (0,16), die grüne Füllung bei (0,64). Jeder Bereich enthält 127 Tiles: drei volle Reihen und 31 Tiles in der vierten; die letzte 8×8-Zelle bleibt schwarz. Die blaue Folge wiederholt volle, halbbreite und dreieckige Tiles; das erste bleibt trotz geänderter Quelle voll. Bei y=112 bleibt das rote Quadrat bei x=16 nach Aufträgen der Länge null erhalten, das rote halbe Tile bei x=224 belegt die automatische NMI-Verarbeitung, und die verworfene Zelle bei x=248 bleibt schwarz. Geprüft werden 18.432 Pixel sowie das Ausbleiben von VRAM-Schreibzugriffen während aktiver Bildausgabe. Physische Hardware wurde nicht getestet.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\runtime_queue.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\runtime_queue.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/runtime.h:51
Consume complete records in order during a safe PPU access period. Reading PPUSTATUS resets the shared address latch before each address pair. The caller is responsible for ensuring the transfer fits its NMI/VBlank time budget.
kitaqfc/lib/runtime.c:127
void nes_vram_queue_nmi_flush(void)
{
unsigned char i;
unsigned char cmd;
unsigned char len;
unsigned char data_index;
unsigned char latch;
i = 0;
while (i != nes_vram_queue_used)
{
latch = PPUSTATUS;
PPUADDR = nes_vram_queue_data[i];
PPUADDR = nes_vram_queue_data[(unsigned char)(i + 1)];
cmd = nes_vram_queue_data[(unsigned char)(i + 2)];
if ((cmd & 0x80) != 0)
{
len = (unsigned char)(cmd & 0x7F);
data_index = nes_vram_queue_data[(unsigned char)(i + 3)];
while (len != 0)
{
PPUDATA = data_index;
len = len - 1;
}
i = (unsigned char)(i + 4);
}
else
{
len = cmd;
data_index = (unsigned char)(i + 3);
while (len != 0)
{
PPUDATA = nes_vram_queue_data[data_index];
data_index = data_index + 1;
len = len - 1;
}
i = data_index;
}
latch = latch;
}
nes_vram_queue_used = 0;
}nes_vram_queue_try_fill
Hängt einen Fülleintrag aus vier Bytes an die C-Laufzeitwarteschlange an. Bei der Ausführung wird value genau len-mal in PPUDATA geschrieben. Das Byte wird sofort gespeichert; spätere Änderungen der aufrufenden Variablen beeinflussen die Füllung nicht. Wiederholt wird ein Byte, kein Tile-Muster.
Syntax
unsigned char nes_vram_queue_try_fill(unsigned short ppu_addr, unsigned char value, unsigned char len);Parameter
ppu_addrPPU-Byteadresse (
0x0000–0x3FFF), kein CPU-Zeiger. Das Ziel muss beschreibbar sein: Musteränderungen benötigen CHR-RAM statt CHR-ROM. PPU-Adressabbildung und Spiegelung gelten weiterhin. Wählen Sie für fortlaufendes Kopieren und Füllen die Schrittweite 1 in PPUCTRL. Führen Sie Befehle zu einem sicheren PPU-Zeitpunkt aus und stellen Sie danach den Scrollzustand her; der Ausführer schreibt PPUADDR und PPUDATA, ohne Scrolleinstellungen wiederherzustellen.valueEin 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.
lenAnzahl der PPU-Bytes von 0 bis 127. Bit 7 des Längenbytes kennzeichnet Fülleinträge, daher werden 128–255 abgewiesen. Ein Schreibauftrag der Länge null belegt drei Warteschlangenbytes, ein leerer Füllauftrag vier. Beide setzen beim Abarbeiten die PPU-Adresse, schreiben aber nicht in PPUDATA.
Rückgabewert
Gibt 1 zurück, wenn der vollständige Eintrag angenommen wurde, sonst 0 bei ungültiger Länge oder Platzmangel. Eine Ablehnung setzt nes_vram_queue_overflow auf 1; vorhandene Einträge und belegte Länge bleiben unverändert. Das Fehlerflag bleibt bis zum Löschen gesetzt, verhindert aber keinen späteren Eintrag, der noch hineinpasst. Prüfen Sie jeden Rückgabewert.
Bedingungen und Grenzen
Dies ist eine separate 192-Byte-Warteschlange aus runtime.c an den CPU-Adressen 0x0300–0x03BF. Ein Dateneintrag belegt 3+len Bytes, ein Fülleintrag vier. nes_vram_queue_used zählt codierte Bytes, nicht ausstehende PPU-Schreibzugriffe oder freien VRAM. Die Intrinsic-Warteschlange __vramq_* verwendet ein anderes Format; diese Funktionen leeren, prüfen oder verarbeiten sie nicht.
Verwenden Sie die Deklarationen aus runtime.h und binden oder kompilieren Sie runtime.c genau einmal. Neben dieser Warteschlange stellt die Datei __nes_nmi, den Laufzeit-Bildzähler, direkte PPU-Hilfsfunktionen und OAM-Speicher auf Seite 02 bereit. Stimmen Sie die NMI-Behandlung mit Ihrem Programm ab; eine Funktionsdeklaration allein bindet keine Implementierung ein.
Trennen Sie Aufbau und Verarbeitung der Pakete; Sperren oder doppelte Puffer sind nicht vorgesehen. Für eine eindeutige Vorbereitung deaktivieren Sie NMI beim Anhängen und verarbeiten die Einträge bei abgeschalteter Bildausgabe, oder aktivieren NMI für ein Paket, das in VBlank passt. runtime.c verarbeitet eine nicht leere Warteschlange automatisch aus __nes_nmi, ohne Freigabeaufruf. Es gibt weder Zeitbudget noch Aufteilung oder Wiederherstellung des Scrollzustands. Freier Warteschlangenplatz garantiert keine sichere VBlank-Dauer.
Anwendungsbeispiel
if(nes_vram_queue_try_fill(0x2100,fill_value,127)!=1)failures++;
fill_value=3; // The queued fill remains the solid tile 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 füllt zunächst alle 192 Warteschlangenbytes und lässt einen weiteren Eintrag absichtlich ablehnen. Es verwirft dieses Paket, prüft die Ablehnung von Länge 128 und reiht dann fünf Einträge ein: 145 Bytes für 255 PPU-Schreibzugriffe. Erwartet werden CAPACITY 192, ENCODED BYTES 145, AFTER FLUSH 000, REJECTED LENGTH 001, OVERFLOW SEEN 001 und FAILED CHECKS 000. Die Ablehnungsanzeigen speichern Beobachtungen aus vorherigen Programmschritten, nicht den abschließenden Flagzustand.
Die blau kopierten Tiles beginnen bei (0,16), die grüne Füllung bei (0,64). Jeder Bereich enthält 127 Tiles: drei volle Reihen und 31 Tiles in der vierten; die letzte 8×8-Zelle bleibt schwarz. Die blaue Folge wiederholt volle, halbbreite und dreieckige Tiles; das erste bleibt trotz geänderter Quelle voll. Bei y=112 bleibt das rote Quadrat bei x=16 nach Aufträgen der Länge null erhalten, das rote halbe Tile bei x=224 belegt die automatische NMI-Verarbeitung, und die verworfene Zelle bei x=248 bleibt schwarz. Geprüft werden 18.432 Pixel sowie das Ausbleiben von VRAM-Schreibzugriffen während aktiver Bildausgabe. Physische Hardware wurde nicht getestet.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\runtime_queue.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\runtime_queue.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/runtime.h:47
Queue a four-byte fill record: address high/low, length with bit 7 set, value. Reject lengths above 127 and latch overflow on any capacity/format failure.
kitaqfc/lib/runtime.c:90
unsigned char nes_vram_queue_try_fill(unsigned short ppu_addr, unsigned char value, unsigned char len)
{
unsigned char used;
unsigned char need;
used = nes_vram_queue_used;
need = 4;
if ((unsigned char)(used + need) < used)
{
nes_vram_queue_overflow = 1;
return 0;
}
if ((unsigned char)(used + need) > 192)
{
nes_vram_queue_overflow = 1;
return 0;
}
if ((len & 0x80) != 0)
{
nes_vram_queue_overflow = 1;
return 0;
}
nes_vram_queue_data[used] = (unsigned char)(ppu_addr >> 8);
nes_vram_queue_data[(unsigned char)(used + 1)] = (unsigned char)ppu_addr;
nes_vram_queue_data[(unsigned char)(used + 2)] = (unsigned char)(len | 0x80);
nes_vram_queue_data[(unsigned char)(used + 3)] = value;
nes_vram_queue_used = (unsigned char)(used + need);
return 1;
}nes_vram_queue_try_write
Hängt einen Eintrag mit Nutzdaten an die C-Laufzeitwarteschlange an. Kopiert während dieses Aufrufs len Quellbytes in den Puffer und veröffentlicht anschließend die neue belegte Länge. Die PPU-Übertragung erfolgt beim Abarbeiten der Warteschlange. Änderungen oder Wiederverwendung der Quelle nach einem erfolgreichen Aufruf verändern die eingereihten Daten nicht.
Syntax
unsigned char nes_vram_queue_try_write(unsigned short ppu_addr, unsigned char* src, unsigned char len);Parameter
ppu_addrPPU-Byteadresse (
0x0000–0x3FFF), kein CPU-Zeiger. Das Ziel muss beschreibbar sein: Musteränderungen benötigen CHR-RAM statt CHR-ROM. PPU-Adressabbildung und Spiegelung gelten weiterhin. Wählen Sie für fortlaufendes Kopieren und Füllen die Schrittweite 1 in PPUCTRL. Führen Sie Befehle zu einem sicheren PPU-Zeitpunkt aus und stellen Sie danach den Scrollzustand her; der Ausführer schreibt PPUADDR und PPUDATA, ohne Scrolleinstellungen wiederherzustellen.srcZeiger auf mindestens
lenlesbare Bytes im aktuell eingeblendeten Speicher. Die Quelle muss nur während dieses Aufrufs gültig bleiben: Der Inhalt wird kopiert, niemals verändert. Bei Länge null werden keine Quellbytes gelesen.lenAnzahl der PPU-Bytes von 0 bis 127. Bit 7 des Längenbytes kennzeichnet Fülleinträge, daher werden 128–255 abgewiesen. Ein Schreibauftrag der Länge null belegt drei Warteschlangenbytes, ein leerer Füllauftrag vier. Beide setzen beim Abarbeiten die PPU-Adresse, schreiben aber nicht in PPUDATA.
Rückgabewert
Gibt 1 zurück, wenn der vollständige Eintrag angenommen wurde, sonst 0 bei ungültiger Länge oder Platzmangel. Eine Ablehnung setzt nes_vram_queue_overflow auf 1; vorhandene Einträge und belegte Länge bleiben unverändert. Das Fehlerflag bleibt bis zum Löschen gesetzt, verhindert aber keinen späteren Eintrag, der noch hineinpasst. Prüfen Sie jeden Rückgabewert.
Bedingungen und Grenzen
Dies ist eine separate 192-Byte-Warteschlange aus runtime.c an den CPU-Adressen 0x0300–0x03BF. Ein Dateneintrag belegt 3+len Bytes, ein Fülleintrag vier. nes_vram_queue_used zählt codierte Bytes, nicht ausstehende PPU-Schreibzugriffe oder freien VRAM. Die Intrinsic-Warteschlange __vramq_* verwendet ein anderes Format; diese Funktionen leeren, prüfen oder verarbeiten sie nicht.
Verwenden Sie die Deklarationen aus runtime.h und binden oder kompilieren Sie runtime.c genau einmal. Neben dieser Warteschlange stellt die Datei __nes_nmi, den Laufzeit-Bildzähler, direkte PPU-Hilfsfunktionen und OAM-Speicher auf Seite 02 bereit. Stimmen Sie die NMI-Behandlung mit Ihrem Programm ab; eine Funktionsdeklaration allein bindet keine Implementierung ein.
Trennen Sie Aufbau und Verarbeitung der Pakete; Sperren oder doppelte Puffer sind nicht vorgesehen. Für eine eindeutige Vorbereitung deaktivieren Sie NMI beim Anhängen und verarbeiten die Einträge bei abgeschalteter Bildausgabe, oder aktivieren NMI für ein Paket, das in VBlank passt. runtime.c verarbeitet eine nicht leere Warteschlange automatisch aus __nes_nmi, ohne Freigabeaufruf. Es gibt weder Zeitbudget noch Aufteilung oder Wiederherstellung des Scrollzustands. Freier Warteschlangenplatz garantiert keine sichere VBlank-Dauer.
Anwendungsbeispiel
if(nes_vram_queue_try_write(0x2040,source_bytes,127)!=1)failures++;
source_bytes[0]=3; // The queued first tile stays 1: payload was copied immediately.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 füllt zunächst alle 192 Warteschlangenbytes und lässt einen weiteren Eintrag absichtlich ablehnen. Es verwirft dieses Paket, prüft die Ablehnung von Länge 128 und reiht dann fünf Einträge ein: 145 Bytes für 255 PPU-Schreibzugriffe. Erwartet werden CAPACITY 192, ENCODED BYTES 145, AFTER FLUSH 000, REJECTED LENGTH 001, OVERFLOW SEEN 001 und FAILED CHECKS 000. Die Ablehnungsanzeigen speichern Beobachtungen aus vorherigen Programmschritten, nicht den abschließenden Flagzustand.
Die blau kopierten Tiles beginnen bei (0,16), die grüne Füllung bei (0,64). Jeder Bereich enthält 127 Tiles: drei volle Reihen und 31 Tiles in der vierten; die letzte 8×8-Zelle bleibt schwarz. Die blaue Folge wiederholt volle, halbbreite und dreieckige Tiles; das erste bleibt trotz geänderter Quelle voll. Bei y=112 bleibt das rote Quadrat bei x=16 nach Aufträgen der Länge null erhalten, das rote halbe Tile bei x=224 belegt die automatische NMI-Verarbeitung, und die verworfene Zelle bei x=248 bleibt schwarz. Geprüft werden 18.432 Pixel sowie das Ausbleiben von VRAM-Schreibzugriffen während aktiver Bildausgabe. Physische Hardware wurde nicht getestet.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\runtime_queue.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\runtime_queue.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/runtime.h:44
Copy a literal payload into the queue and publish its new used length last. Accept lengths 0..127; reject larger lengths and latch overflow without changing the queue. The caller must ensure queue production cannot race its NMI consumer.
kitaqfc/lib/runtime.c:40
unsigned char nes_vram_queue_try_write(unsigned short ppu_addr, unsigned char* src, unsigned char len)
{
unsigned char used;
unsigned char need;
unsigned char i;
unsigned char dst_index;
// Bit 7 selects a fill record; accepting it here would misdecode a literal
// and lengths 253..255 would also wrap the byte-sized allocation cost.
if ((len & 0x80) != 0)
{
nes_vram_queue_overflow = 1;
return 0;
}
used = nes_vram_queue_used;
// Each literal record costs three header bytes plus len payload bytes.
need = (unsigned char)(len + 3);
if ((unsigned char)(used + need) < used)
{
nes_vram_queue_overflow = 1;
return 0;
}
if ((unsigned char)(used + need) > 192)
{
nes_vram_queue_overflow = 1;
return 0;
}
nes_vram_queue_data[used] = (unsigned char)(ppu_addr >> 8);
nes_vram_queue_data[(unsigned char)(used + 1)] = (unsigned char)ppu_addr;
nes_vram_queue_data[(unsigned char)(used + 2)] = len;
i = 0;
dst_index = (unsigned char)(used + 3);
while (i != len)
{
nes_vram_queue_data[dst_index] = src[i];
dst_index = dst_index + 1;
i = i + 1;
}
nes_vram_queue_used = (unsigned char)(used + need);
return 1;
}nes_wait_nmi
Wartet, bis nes_nmi_counter vom beim Eintritt gespeicherten Wert abweicht. __nes_nmi aus runtime.c erhöht diesen 8-Bit-Zähler nach dem Abarbeiten seiner Warteschlange. Der Ungleichheitsvergleich erfasst auch den Überlauf von 255 auf 0. Aktivieren Sie NMI und verwenden Sie diesen Handler oder eine gleichwertige Zähleraktualisierung. Die Schleife hat kein Zeitlimit, aktiviert NMI nicht, stellt den Bildlauf nicht wieder her und garantiert keine exakt eine Bildperiode lange Wartezeit.
Syntax
void nes_wait_nmi(void);Rückgabewert
Keiner (void).
Bedingungen und Grenzen
Verwenden Sie die Deklarationen aus runtime.h und binden oder kompilieren Sie runtime.c genau einmal. Neben dieser Warteschlange stellt die Datei __nes_nmi, den Laufzeit-Bildzähler, direkte PPU-Hilfsfunktionen und OAM-Speicher auf Seite 02 bereit. Stimmen Sie die NMI-Behandlung mit Ihrem Programm ab; eine Funktionsdeklaration allein bindet keine Implementierung ein.
Anwendungsbeispiel
__scroll_set(0,0);start_counter=nes_nmi_counter;
__ppu_ctrl_set(0x80); // Enable runtime.c's NMI handler before waiting.
nes_wait_nmi(); // Returns after the runtime completion counter changes.
nmi_seen=(u8)(nes_nmi_counter!=start_counter);
if(nmi_seen!=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 Laufzeitbeispiel zeigt direkte Übertragung und beide Wartemethoden. Bei (0,16) erscheint ein blaues Muster aus vollen Kacheln, linken Halbflächen und Dreiecken; bei (0,96) ein gefüllter grüner Block. Jeder Block ist 256×64 Pixel groß und entsteht aus 256 Kachelbytes. Die erste blaue Kachel bleibt nach Änderung der Quelle gefüllt. Bei y=208 markieren rote Formen an x=16, 224 und 240 Adresssetzung, Schreiben mit Länge null und Füllen mit Länge null: ein 8×8-Quadrat, ein linker 4×8-Balken und ein achtzeiliges Dreieck. Beide Warteanzeigen zeigen 1, FAILED CHECKS zeigt 0.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\runtime_ppu.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\runtime_ppu.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/runtime.h:23
Wait until the NMI handler advances its counter. NMI must already be enabled and able to execute; this polling loop has no timeout.
kitaqfc/lib/runtime.c:185
void nes_wait_nmi(void)
{
unsigned char start;
start = nes_nmi_counter;
while (nes_nmi_counter == start)
{
}
}scene.h — Szenenregistrierung, -wechsel und -aktualisierung
Überträgt Szenengrafik über einen gemeinsamen Übertragungszustand in die VRAM-Warteschlange. Unterscheiden Sie das Ende von step vom Abschluss der PPU-Schreibzugriffe des Warteschlangenverbrauchers.
Ruft die Handler enter, update, draw und exit einer Szenentabelle auf, um zwischen Bildschirmen wie Titelanzeige und Spiel zu wechseln.
nes_scene_stream_begin
Speichert Ziel, Quelle, Länge und Blockgröße und markiert den gemeinsamen Datenstrom als aktiv.
Syntax
void nes_scene_stream_begin(unsigned short ppu_addr, unsigned char* src, unsigned short len, unsigned char chunk);Parameter
ppu_addrPPU-Zieladresse, keine CPU-Adresse.
srcQuelle mit
lenBytes; halten Sie sie lesbar, bis alle Bytes eingereiht wurden.lenByte-Anzahl, 0–65535; der aufrufende Code prüft auch die Grenzen des Zielbereichs.
chunkMaximale Nutzdatenmenge je Warteschlangeneintrag: Null bedeutet 32; Werte über 127 werden auf 127 begrenzt. Dies ist keine Gesamtgrenze für einen step-Aufruf.
Rückgabewert
Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.
Bedingungen und Grenzen
Es wird nur ein Datenstrom verwaltet. Ein begin-Aufruf ersetzt ihn, storniert aber keine bereits in die Warteschlange kopierten Daten. Halten Sie Quellspeicher und ROM-Zuordnung gültig und steuern Sie step-Aufrufe sowie Warteschlangenverbrauch im aufrufenden Code.
Anwendungsbeispiel
nes_scene_stream_begin(0x2100,small,4,2);result[0]=nes_scene_stream_state.remaining;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 zeigt, wie ein Datenstrom in Warteschlangenblöcke kopiert und anschließend an die PPU übertragen wird. Übertragen Sie 960 Kachelbytes, 64 Attributbytes und 32 Palettenbytes für ein rotes 64×32-Rechteck bei (16,32). Ein begin-Aufruf allein aktualisiert die Anzeige nicht.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\batch2_stream.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch2_stream.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chrImplementierung und Quelltext
kitaqfc/lib/scene.h:47
Replace the single active transfer and retain its source pointer. Keep the source storage and any required ROM bank readable until all bytes are queued.
kitaqfc/lib/scene.c:86
void nes_scene_stream_begin(unsigned short ppu_addr, unsigned char* src, unsigned short len, unsigned char chunk)
{
nes_scene_stream_state.ppu_addr = ppu_addr;
nes_scene_stream_state.src = src;
nes_scene_stream_state.remaining = len;
nes_scene_stream_state.chunk = chunk;
nes_scene_stream_state.active = 1;
}nes_scene_stream_begin_attr
Bereitet 64 Attributbytes für Nametable-Basis+0x03C0 mit Warteschlangeneinträgen zu je 16 Bytes vor.
Syntax
void nes_scene_stream_begin_attr(unsigned short nt_base, unsigned char* src64);Parameter
nt_basePPU-Basisadresse der Nametable, beispielsweise 0x2000.
src6464 Attributbytes; bewahren Sie sie bis zur vollständigen Einreihung auf.
Rückgabewert
Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.
Bedingungen und Grenzen
Es wird nur ein Datenstrom verwaltet. Ein begin-Aufruf ersetzt ihn, storniert aber keine bereits in die Warteschlange kopierten Daten. Halten Sie Quellspeicher und ROM-Zuordnung gültig und steuern Sie step-Aufrufe sowie Warteschlangenverbrauch im aufrufenden Code.
Anwendungsbeispiel
nes_scene_stream_begin_attr(0x2000,attrs);while(nes_scene_stream_step()!=0){nes_vram_queue_nmi_flush();}nes_vram_queue_nmi_flush();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 zeigt, wie ein Datenstrom in Warteschlangenblöcke kopiert und anschließend an die PPU übertragen wird. Übertragen Sie 960 Kachelbytes, 64 Attributbytes und 32 Palettenbytes für ein rotes 64×32-Rechteck bei (16,32). Ein begin-Aufruf allein aktualisiert die Anzeige nicht.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\batch2_stream.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch2_stream.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chrImplementierung und Quelltext
kitaqfc/lib/scene.h:51
Prepare the 64-byte attribute table at nametable base + 0x03C0.
kitaqfc/lib/scene.c:102
void nes_scene_stream_begin_attr(unsigned short nt_base, unsigned char* src64)
{
nes_scene_stream_begin((unsigned short)(nt_base + 0x03C0), src64, 64, 16);
}nes_scene_stream_begin_nametable
Bereitet die Übertragung von 960 Nametable-Kachelbytes mit Warteschlangeneinträgen zu je 32 Bytes vor.
Syntax
void nes_scene_stream_begin_nametable(unsigned short nt_base, unsigned char* src960);Parameter
nt_basePPU-Basisadresse der Nametable, beispielsweise 0x2000.
src960960 Kachelbytes einer Nametable ohne ihre 64 Attributbytes.
Rückgabewert
Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.
Bedingungen und Grenzen
Es wird nur ein Datenstrom verwaltet. Ein begin-Aufruf ersetzt ihn, storniert aber keine bereits in die Warteschlange kopierten Daten. Halten Sie Quellspeicher und ROM-Zuordnung gültig und steuern Sie step-Aufrufe sowie Warteschlangenverbrauch im aufrufenden Code.
Anwendungsbeispiel
nes_scene_stream_begin_nametable(0x2000,tiles960);while(nes_scene_stream_step()!=0){nes_vram_queue_nmi_flush();}nes_vram_queue_nmi_flush();result[4]=nes_scene_stream_state.remaining;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 zeigt, wie ein Datenstrom in Warteschlangenblöcke kopiert und anschließend an die PPU übertragen wird. Übertragen Sie 960 Kachelbytes, 64 Attributbytes und 32 Palettenbytes für ein rotes 64×32-Rechteck bei (16,32). Ein begin-Aufruf allein aktualisiert die Anzeige nicht.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\batch2_stream.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch2_stream.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chrImplementierung und Quelltext
kitaqfc/lib/scene.h:49
Prepare the 960-byte tile portion of a nametable using 32-byte queue records.
kitaqfc/lib/scene.c:96
void nes_scene_stream_begin_nametable(unsigned short nt_base, unsigned char* src960)
{
nes_scene_stream_begin(nt_base, src960, 960, 32);
}nes_scene_stream_begin_palette
Bereitet 32 Palettenbytes für PPU-Adresse 0x3F00 mit Warteschlangeneinträgen zu je 16 Bytes vor.
Syntax
void nes_scene_stream_begin_palette(unsigned char* src32);Parameter
src3232 Palettenbytes: 16 Hintergrund- und 16 Spritefarben; beachten Sie Farbcodegrenzen und PPU-Spiegelung.
Rückgabewert
Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.
Bedingungen und Grenzen
Es wird nur ein Datenstrom verwaltet. Ein begin-Aufruf ersetzt ihn, storniert aber keine bereits in die Warteschlange kopierten Daten. Halten Sie Quellspeicher und ROM-Zuordnung gültig und steuern Sie step-Aufrufe sowie Warteschlangenverbrauch im aufrufenden Code.
Anwendungsbeispiel
nes_scene_stream_begin_palette(colors);while(nes_scene_stream_step()!=0){nes_vram_queue_nmi_flush();}nes_vram_queue_nmi_flush();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 zeigt, wie ein Datenstrom in Warteschlangenblöcke kopiert und anschließend an die PPU übertragen wird. Übertragen Sie 960 Kachelbytes, 64 Attributbytes und 32 Palettenbytes für ein rotes 64×32-Rechteck bei (16,32). Ein begin-Aufruf allein aktualisiert die Anzeige nicht.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\batch2_stream.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch2_stream.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chrImplementierung und Quelltext
kitaqfc/lib/scene.h:53
Prepare a 32-byte palette transfer to PPU address 0x3F00.
kitaqfc/lib/scene.c:108
void nes_scene_stream_begin_palette(unsigned char* src32)
{
nes_scene_stream_begin(0x3F00, src32, 32, 16);
}nes_scene_stream_step
Kopiert die verbleibenden Daten in so viele Blöcke, wie die VRAM-Warteschlange der Laufzeitumgebung aufnehmen kann.
Syntax
unsigned char nes_scene_stream_step(void);Rückgabewert
1, wenn wegen begrenzter Kapazität Daten übrig bleiben; 0, wenn alles eingereiht oder der Datenstrom inaktiv ist. Ein abgelehnter Block verschiebt weder Quelle noch Ziel, sodass ein erneuter Versuch möglich ist. Auch bei Rückgabe null können PPU-Übertragungen noch ausstehen.
Bedingungen und Grenzen
Es wird nur ein Datenstrom verwaltet. Ein begin-Aufruf ersetzt ihn, storniert aber keine bereits in die Warteschlange kopierten Daten. Halten Sie Quellspeicher und ROM-Zuordnung gültig und steuern Sie step-Aufrufe sowie Warteschlangenverbrauch im aufrufenden Code.
Anwendungsbeispiel
result[1]=nes_scene_stream_step();result[2]=nes_scene_stream_state.active;result[3]=nes_vram_queue_used;nes_vram_queue_nmi_flush();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 zeigt, wie ein Datenstrom in Warteschlangenblöcke kopiert und anschließend an die PPU übertragen wird. Übertragen Sie 960 Kachelbytes, 64 Attributbytes und 32 Palettenbytes für ein rotes 64×32-Rechteck bei (16,32). Ein begin-Aufruf allein aktualisiert die Anzeige nicht.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\batch2_stream.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch2_stream.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chrImplementierung und Quelltext
kitaqfc/lib/scene.h:57
Queue as many chunks as available capacity allows, capped at 127 bytes each. Return one when queue exhaustion requires a later retry, zero when all data has been queued. Zero does not mean the NMI consumer has already written the PPU.
kitaqfc/lib/scene.c:116
unsigned char nes_scene_stream_step(void)
{
unsigned char chunk;
while (nes_scene_stream_state.active != 0)
{
if (nes_scene_stream_state.remaining == 0)
{
nes_scene_stream_state.active = 0;
return 0;
}
// A step may enqueue several chunks; chunk limits record size, not the total bytes or time per frame.
chunk = nes_scene_stream_state.chunk;
if (chunk == 0)
{
chunk = 32;
}
if ((unsigned short)chunk > nes_scene_stream_state.remaining)
{
chunk = (unsigned char)nes_scene_stream_state.remaining;
}
if (chunk > 127)
{
chunk = 127;
}
// A failed enqueue leaves this chunk pending so a later step can retry after the queue drains.
if (nes_vram_queue_try_write(nes_scene_stream_state.ppu_addr, nes_scene_stream_state.src, chunk) == 0)
{
return 1;
}
nes_scene_stream_state.ppu_addr = (unsigned short)(nes_scene_stream_state.ppu_addr + chunk);
nes_scene_stream_state.src = nes_scene_stream_state.src + chunk;
nes_scene_stream_state.remaining = (unsigned short)(nes_scene_stream_state.remaining - chunk);
}
return 0;
}scene_change
Verlässt die aktive Szene, sofern vorhanden, und betritt die angeforderte Szene.
Syntax
void scene_change(u8 scene_id);Parameter
scene_idIndex 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.
Anwendungsbeispiel
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\batch_services.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch_services.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/scene.h:33
Ignore invalid IDs; otherwise exit the current scene and enter the requested one. Selecting the current ID still performs exit/enter. Callbacks run synchronously.
kitaqfc/lib/scene.c:28
void scene_change(u8 scene_id)
{
SceneFunc fn;
if (scene_id >= kq_scene_count) return;
// Exit/enter handlers must not recursively change scenes or replace this shared table.
if (kq_scene_has_current != 0) {
fn = kq_scene_table[(__safe_index u8)kq_scene_current].exit;
if (fn != 0) fn();
}
kq_scene_current = scene_id;
kq_scene_has_current = 1;
kq_scene_changed = 1;
fn = kq_scene_table[(__safe_index u8)kq_scene_current].enter;
if (fn != 0) fn();
}scene_draw
Ruft den draw-Callback der aktiven Szene einmal auf.
Syntax
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.
Anwendungsbeispiel
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\batch_services.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch_services.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/scene.h:38
Call the active scene's draw handler if one exists; no current scene is a no-op.
kitaqfc/lib/scene.c:61
void scene_draw()
{
SceneFunc fn;
if (kq_scene_has_current == 0) return;
fn = kq_scene_table[(__safe_index u8)kq_scene_current].draw;
if (fn != 0) fn();
}scene_get_current
Liest die gespeicherte aktuelle Szenen-ID.
Syntax
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.
Anwendungsbeispiel
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\batch_services.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch_services.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/scene.h:40
Return the stored scene ID; zero is also returned before the first transition.
kitaqfc/lib/scene.c:71
u8 scene_get_current()
{
return kq_scene_current;
}scene_init
Registriert eine Szenentabelle, ohne eine Szene zu aktivieren.
Syntax
void scene_init(const SceneDef* scenes, u8 count);Parameter
scenesArray aus
SceneDef-Einträgen mit den Callbacks enter, update, draw und exit.countAnzahl 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.
Anwendungsbeispiel
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\batch_services.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch_services.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/scene.h:28
Attach the caller-owned scene table and clear current-scene state without invoking callbacks.
kitaqfc/lib/scene.c:11
void scene_init(const SceneDef* scenes, u8 count)
{
kq_scene_table = scenes;
kq_scene_count = count;
kq_scene_current = 0;
kq_scene_changed = 0;
kq_scene_has_current = 0;
}scene_set_table
Ersetzt die Szenentabelle und lässt keine Szene aktiv.
Syntax
void scene_set_table(const SceneDef* scenes, u8 count);Parameter
scenesArray aus
SceneDef-Einträgen mit den Callbacks enter, update, draw und exit.countAnzahl 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.
Anwendungsbeispiel
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\batch_services.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch_services.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/scene.h:30
Replace the table by resetting scene state; this does not call the old scene's exit handler.
kitaqfc/lib/scene.c:21
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
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.
Anwendungsbeispiel
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\batch_services.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch_services.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/scene.h:36
Clear the change flag before calling the active scene's update handler, so a transition made during that handler is visible afterward.
kitaqfc/lib/scene.c:50
void scene_update()
{
SceneFunc fn;
if (kq_scene_has_current == 0) return;
kq_scene_changed = 0;
fn = kq_scene_table[(__safe_index u8)kq_scene_current].update;
if (fn != 0) fn();
}scene_was_changed
Prüft, ob derzeit ein Szenenwechsel vermerkt ist.
Syntax
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.
Anwendungsbeispiel
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\batch_services.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch_services.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/scene.h:42
Read the transition flag, which is cleared at the start of an active scene update.
kitaqfc/lib/scene.c:77
u8 scene_was_changed()
{
return kq_scene_changed;
}scroll.h — Hintergrund, Fenster und geteiltes Scrollen
Erzeugt die PPUCTRL-Nametable-Auswahl und PPUSCROLL aus 16-Bit-Weltkoordinaten. Auch Y wird in 256er-Bereiche aufgeteilt; berücksichtigen Sie daher die Bildschirmhöhe von 240 Pixeln.
nes_camera_follow_center
Zieht den Bildschirmanker von der Weltposition des Ziels ab und speichert das Ergebnis als Kamerakoordinaten.
Syntax
void nes_camera_follow_center(unsigned short target_x, unsigned short target_y, unsigned char center_x, unsigned char center_y);Parameter
target_xWelt-X des Ziels in Pixeln, 0–65535.
target_yWelt-Y des Ziels in Pixeln, 0–65535.
center_xGewünschtes Bildschirm-X des Ziels, 0–255.
center_yGewünschtes Bildschirm-Y des Ziels, 0–255.
Rückgabewert
Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.
Bedingungen und Grenzen
Es wird ein Koordinatenpaar gemeinsam genutzt. Rufen Sie nes_scroll_apply zum Aktualisieren der Hardware auf. Negative Subtraktionsergebnisse laufen in u16 um; begrenzen Sie die Weltkanten im Spiel.
Anwendungsbeispiel
nes_camera_follow_center(300,260,128,120);result[4]=nes_scroll_camera_x;result[5]=nes_scroll_camera_y;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 zeigt, wie gespeicherte 16-Bit-Koordinaten PPUCTRL und Scrollwerte ergeben. Der Grundsteuerwert ist 144; Anwenden von (264,272) ergibt 147. Das Verfolgen von Ziel (300,260) mit Anker (128,120) ergibt Kamera (172,140). Separate Zustandsprüfungen untersuchen die tatsächlichen PPU-Schreibzugriffe.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch2_scroll.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch2_scroll.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrAnwendungsbeispiel
nes_scroll_set_base_ctrl(0);
nes_scroll_set(264,16);
nes_scroll_apply();Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Zeigen Sie auf NROM mit vertikaler Spiegelung Nametable 1 an. Ein rotes 32×16-Rechteck an Weltposition (288,32) erscheint bei Kamera (264,16) an Bildschirmposition (24,16). Dies zeigt die Tabellenauswahl über Bit 8 und das Scrolling über das untere Byte.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch2_scroll_view.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch2_scroll_view.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chr --mirroring=verticalImplementierung und Quelltext
kitaqfc/lib/scroll.h:21
Subtract the screen anchor from the world point into unsigned camera coordinates. Underflow wraps; world-edge clamping belongs to the game.
kitaqfc/lib/scroll.c:56
void nes_camera_follow_center(unsigned short target_x, unsigned short target_y, unsigned char center_x, unsigned char center_y)
{
nes_scroll_camera_x = target_x - center_x;
nes_scroll_camera_y = target_y - center_y;
}nes_scroll_apply
Kombiniert gespeicherte Koordinaten mit dem PPUCTRL-Grundwert, setzt das Latch zurück und schreibt PPUCTRL sowie X/Y-Scrollwerte.
Syntax
void nes_scroll_apply(void);Rückgabewert
Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.
Bedingungen und Grenzen
Bit 8 jeder Achse wählt eine Nametable; das untere Byte liefert den Scrollwert. Y-Werte von 240–255 sind keine gewöhnlichen vertikalen Scrollpositionen. Das gesamte PPUCTRL-Register wird ersetzt; initialisieren Sie NMI und die übrigen Grundbits daher bewusst. Es wird nicht auf VBlank gewartet; das Lesen von PPUSTATUS beeinflusst auch das VBlank-Flag und das gemeinsame Latch.
Anwendungsbeispiel
nes_scroll_apply();result[3]=nes_scroll_ctrl_base|((nes_scroll_camera_x>>8)&1)|((nes_scroll_camera_y>>7)&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 zeigt, wie gespeicherte 16-Bit-Koordinaten PPUCTRL und Scrollwerte ergeben. Der Grundsteuerwert ist 144; Anwenden von (264,272) ergibt 147. Das Verfolgen von Ziel (300,260) mit Anker (128,120) ergibt Kamera (172,140). Separate Zustandsprüfungen untersuchen die tatsächlichen PPU-Schreibzugriffe.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch2_scroll.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch2_scroll.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrAnwendungsbeispiel
nes_scroll_set_base_ctrl(0);
nes_scroll_set(264,16);
nes_scroll_apply();Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Zeigen Sie auf NROM mit vertikaler Spiegelung Nametable 1 an. Ein rotes 32×16-Rechteck an Weltposition (288,32) erscheint bei Kamera (264,16) an Bildschirmposition (24,16). Dies zeigt die Tabellenauswahl über Bit 8 und das Scrolling über das untere Byte.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch2_scroll_view.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch2_scroll_view.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chr --mirroring=verticalImplementierung und Quelltext
kitaqfc/lib/scroll.h:18
Combine bit 8 of each camera coordinate with base PPUCTRL, reset the latch by reading PPUSTATUS, and write low-byte X/Y scroll. This uses 256-unit wrapping on both axes rather than normalizing Y to a 240-pixel nametable height. Initialize base control to the intended PPUCTRL value, including NMI enable, before applying. Only coordinate bits 0..8 are used; arrange safe PPU timing in the caller.
kitaqfc/lib/scroll.c:34
void nes_scroll_apply(void)
{
unsigned char ctrl;
unsigned char x_hi;
unsigned char y_hi;
unsigned char latch;
x_hi = (unsigned char)((nes_scroll_camera_x >> 8) & 1);
y_hi = (unsigned char)((nes_scroll_camera_y >> 8) & 1);
ctrl = (unsigned char)(nes_scroll_ctrl_base | x_hi | (unsigned char)(y_hi << 1));
// Replace the whole control register, so the saved base also determines NMI and increment mode.
PPUCTRL = ctrl;
latch = PPUSTATUS;
PPUSCROLL = (unsigned char)nes_scroll_camera_x;
PPUSCROLL = (unsigned char)nes_scroll_camera_y;
latch = latch;
}nes_scroll_set
Speichert 16-Bit-Kamerakoordinaten, ohne in die PPU zu schreiben.
Syntax
void nes_scroll_set(unsigned short camera_x, unsigned short camera_y);Parameter
camera_xHorizontale Koordinate in ganzen Pixeln; beim Anwenden werden die unteren neun Bits verwendet.
camera_yVertikale Koordinate; beim Anwenden werden die unteren neun Bits verwendet, ohne auf die Nametable-Höhe von 240 Pixeln zu normieren.
Rückgabewert
Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.
Bedingungen und Grenzen
Es wird ein Koordinatenpaar gemeinsam genutzt. Rufen Sie nes_scroll_apply zum Aktualisieren der Hardware auf. Negative Subtraktionsergebnisse laufen in u16 um; begrenzen Sie die Weltkanten im Spiel.
Anwendungsbeispiel
nes_scroll_set(264,272);result[1]=nes_scroll_camera_x;result[2]=nes_scroll_camera_y;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 zeigt, wie gespeicherte 16-Bit-Koordinaten PPUCTRL und Scrollwerte ergeben. Der Grundsteuerwert ist 144; Anwenden von (264,272) ergibt 147. Das Verfolgen von Ziel (300,260) mit Anker (128,120) ergibt Kamera (172,140). Separate Zustandsprüfungen untersuchen die tatsächlichen PPU-Schreibzugriffe.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch2_scroll.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch2_scroll.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrAnwendungsbeispiel
nes_scroll_set_base_ctrl(0);
nes_scroll_set(264,16);
nes_scroll_apply();Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Zeigen Sie auf NROM mit vertikaler Spiegelung Nametable 1 an. Ein rotes 32×16-Rechteck an Weltposition (288,32) erscheint bei Kamera (264,16) an Bildschirmposition (24,16). Dies zeigt die Tabellenauswahl über Bit 8 und das Scrolling über das untere Byte.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch2_scroll_view.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch2_scroll_view.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chr --mirroring=verticalImplementierung und Quelltext
kitaqfc/lib/scroll.h:12
Store camera coordinates without touching hardware registers.
kitaqfc/lib/scroll.c:25
void nes_scroll_set(unsigned short camera_x, unsigned short camera_y)
{
nes_scroll_camera_x = camera_x;
nes_scroll_camera_y = camera_y;
}nes_scroll_set_base_ctrl
Speichert den PPUCTRL-Grundwert mit gelöschten zwei Bits zur Nametable-Auswahl.
Syntax
void nes_scroll_set_base_ctrl(unsigned char ctrl);Parameter
ctrlPPUCTRL-Wert mit NMI-, Mustertabellen- und Inkrementeinstellungen; die unteren zwei Bits werden aus den Koordinaten abgeleitet.
Rückgabewert
Kein Rückgabewert. Der betroffene Zustand und der Zeitpunkt der Wirkung werden in diesem Eintrag beschrieben.
Bedingungen und Grenzen
Es wird ein Koordinatenpaar gemeinsam genutzt. Rufen Sie nes_scroll_apply zum Aktualisieren der Hardware auf. Negative Subtraktionsergebnisse laufen in u16 um; begrenzen Sie die Weltkanten im Spiel.
Anwendungsbeispiel
nes_scroll_set_base_ctrl(0x93);result[0]=nes_scroll_ctrl_base;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 zeigt, wie gespeicherte 16-Bit-Koordinaten PPUCTRL und Scrollwerte ergeben. Der Grundsteuerwert ist 144; Anwenden von (264,272) ergibt 147. Das Verfolgen von Ziel (300,260) mit Anker (128,120) ergibt Kamera (172,140). Separate Zustandsprüfungen untersuchen die tatsächlichen PPU-Schreibzugriffe.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch2_scroll.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch2_scroll.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrAnwendungsbeispiel
nes_scroll_set_base_ctrl(0);
nes_scroll_set(264,16);
nes_scroll_apply();Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Zeigen Sie auf NROM mit vertikaler Spiegelung Nametable 1 an. Ein rotes 32×16-Rechteck an Weltposition (288,32) erscheint bei Kamera (264,16) an Bildschirmposition (24,16). Dies zeigt die Tabellenauswahl über Bit 8 und das Scrolling über das untere Byte.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch2_scroll_view.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch2_scroll_view.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chr --mirroring=verticalImplementierung und Quelltext
kitaqfc/lib/scroll.h:10
Store PPUCTRL bits other than the two nametable-selection bits for later application.
kitaqfc/lib/scroll.c:19
void nes_scroll_set_base_ctrl(unsigned char ctrl)
{
nes_scroll_ctrl_base = (unsigned char)(ctrl & 0xFC);
}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.
FC-Attribute: Bits 0..1 wählen eine von vier Paletten, Bit 5 legt das Sprite hinter Hintergrundpixel mit Index ungleich null, Bits 6/7 spiegeln X/Y. Unbenutzte Bits 2..4 bleiben null. Die Werte unterscheiden sich von GB; verwenden Sie die Konstanten der jeweiligen Plattform.
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
u8 anim_update(SpriteAnim* anim);Parameter
animBeschreibbarer 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.
Anwendungsbeispiel
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\sprite_shapes.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.nes --nes-chr=.\kitaq-docs\samples\sprite_example.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/sprite.h:74
Advance animation ticks and wrap the frame index, returning the selected tile. Zero ticks-per-frame freezes advancement; null state returns zero.
kitaqfc/lib/sprite.c:174
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 = (u8)(anim->ticks + 1);
if (anim->ticks >= anim->ticks_per_frame) {
anim->ticks = 0;
anim->frame = (u8)(anim->frame + 1);
if (anim->frame >= anim->frame_count) anim->frame = 0;
}
return (u8)(anim->first_tile + anim->frame);
}metasprite_draw
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
u8 metasprite_draw(u8 first_id, u8 x, u8 y, const MetaSpritePart* parts, u8 count);Parameter
first_idEintrags-ID von 0 bis SPRITE_MAX-1, standardmäßig 0..39 auf GB und 0..63 auf FC. Ungültige IDs werden ignoriert.
xHorizontale Position in Pixeln als vorzeichenloses Byte; keine Tile-Koordinate.
yY-Byte des OAM. Für eine Oberkante unterhalb der Zeile null wird ihre Position minus eins übergeben; 239..255 liegen außerhalb der 240 sichtbaren Zeilen.
partsLesbares 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.
countAnzahl 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.
Anwendungsbeispiel
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\sprite_shapes.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.nes --nes-chr=.\kitaq-docs\samples\sprite_example.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/sprite.h:71
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.
kitaqfc/lib/sprite.c:152
u8 metasprite_draw(u8 first_id, u8 x, u8 y, const MetaSpritePart* parts, u8 count)
{
u8 i;
i = 0;
while (i < count) {
u8 id;
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(id, (u8)(x + parts[i].dx), (u8)(y + parts[i].dy), parts[i].tile, parts[i].flags);
kq_sprite_x[id] = (u8)(x + parts[i].dx);
kq_sprite_y[id] = (u8)(y + parts[i].dy);
i = (u8)(i + 1);
}
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
u8 sprite_alloc(void);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.
Anwendungsbeispiel
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\sprite_shapes.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.nes --nes-chr=.\kitaq-docs\samples\sprite_example.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/sprite.h:45
Claim and hide the first free slot, or return 0xFF if all slots are active.
kitaqfc/lib/sprite.c:35
u8 sprite_alloc(void)
{
u8 i;
i = 0;
while (i < SPRITE_MAX) {
if (kq_sprite_active[i] == 0) {
kq_sprite_active[i] = 1;
kq_sprite_used = (u8)(kq_sprite_used + 1);
sprite_hide(i);
return i;
}
i = (u8)(i + 1);
}
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
u8 sprite_count_used(void);Rückgabewert
Vorzeichenloser Bytewert von 0 bis SPRITE_MAX.
Anwendungsbeispiel
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\sprite_shapes.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.nes --nes-chr=.\kitaq-docs\samples\sprite_example.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/sprite.h:62
Return the number of active slots, including slots activated by metasprite_draw. Hidden allocated slots remain active until sprite_free releases them.
kitaqfc/lib/sprite.c:108
u8 sprite_count_used(void)
{
return kq_sprite_used;
}sprite_flush_oam
Wartet auf den nächsten Stand des NMI-Bildzählers und überträgt dann die 256 Byte große OAM-Seite. NMI muss aktiviert sein, und der Handler muss diesen Zähler aktualisieren.
Syntax
void sprite_flush_oam(void);Rückgabewert
Keiner (void).
Bedingungen und Grenzen
Die FC-Routine setzt OAMADDR auf null und startet DMA aus CPU-Seite $02 ($0200–$02FF). Verwenden Sie sie während VBlank oder bei abgeschalteter Darstellung; vermeiden Sie gleichzeitige Änderungen derselben Seite durch Interrupt-Code.
Anwendungsbeispiel
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\sprite_shapes.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.nes --nes-chr=.\kitaq-docs\samples\sprite_example.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/sprite.h:59
Wait for NMI before requesting OAM DMA.
kitaqfc/lib/sprite.c:100
void sprite_flush_oam(void)
{
__nmi_wait();
__oam_dma();
}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
void sprite_flush_oam_now(void);Rückgabewert
Keiner (void).
Bedingungen und Grenzen
Die FC-Routine setzt OAMADDR auf null und startet DMA aus CPU-Seite $02 ($0200–$02FF). Verwenden Sie sie während VBlank oder bei abgeschalteter Darstellung; vermeiden Sie gleichzeitige Änderungen derselben Seite durch Interrupt-Code.
Anwendungsbeispiel
// 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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\sprite_shapes.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.nes --nes-chr=.\kitaq-docs\samples\sprite_example.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/sprite.h:57
Transfer intrinsic shadow OAM immediately; this wrapper does not wait for VBlank.
kitaqfc/lib/sprite.c:94
void sprite_flush_oam_now(void)
{
__oam_dma();
}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
void sprite_free(u8 id);Parameter
idEintrags-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.
Anwendungsbeispiel
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\sprite_shapes.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.nes --nes-chr=.\kitaq-docs\samples\sprite_example.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/sprite.h:47
Release an active valid slot and hide it; invalid/repeated frees are ignored.
kitaqfc/lib/sprite.c:52
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 = (u8)(kq_sprite_used - 1);
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
void sprite_hide(u8 id);Parameter
idEintrags-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.
Anwendungsbeispiel
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\sprite_shapes.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.nes --nes-chr=.\kitaq-docs\samples\sprite_example.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/sprite.h:55
Mark the software position off screen and hide its OAM entry without freeing it.
kitaqfc/lib/sprite.c:85
void sprite_hide(u8 id)
{
if (sprite_valid(id) == 0) return;
kq_sprite_x[id] = 0;
kq_sprite_y[id] = 0xF0;
__sprite_hide(id);
}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
void sprite_init(void);Rückgabewert
Keiner (void).
Bedingungen und Grenzen
Auf FC werden Reservierungen und verwaltete Koordinaten zurückgesetzt; beim Ausblenden bleiben Tile- und Attributbytes erhalten. SPRITE_MAX muss zwischen 1 und 64 liegen.
Anwendungsbeispiel
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\sprite_shapes.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.nes --nes-chr=.\kitaq-docs\samples\sprite_example.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/sprite.h:43
Reset allocation/position state and hide each OAM slot through the intrinsic. The software height defaults to eight; hardware sprite size is configured elsewhere.
kitaqfc/lib/sprite.c:19
void sprite_init(void)
{
u8 i;
kq_sprite_used = 0;
kq_sprite_height = 8;
i = 0;
while (i < SPRITE_MAX) {
kq_sprite_active[i] = 0;
kq_sprite_x[i] = 0;
kq_sprite_y[i] = 0;
__sprite_hide(i);
i = (u8)(i + 1);
}
}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
u8 sprite_max_scanline_count(void);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.
Anwendungsbeispiel
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\sprite_shapes.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.nes --nes-chr=.\kitaq-docs\samples\sprite_example.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/sprite.h:67
Estimate peak overlap across 240 lines from software Y/height values. This does not model pixel transparency, OAM priority or every hardware overflow quirk.
kitaqfc/lib/sprite.c:117
u8 sprite_max_scanline_count(void)
{
u8 line;
u8 best;
line = 0;
best = 0;
while (line < 240) {
u8 i;
u8 count;
i = 0;
count = 0;
while (i < SPRITE_MAX) {
if (kq_sprite_active[i] != 0) {
if (line > kq_sprite_y[i] && (u8)(line - kq_sprite_y[i]) <= kq_sprite_height) {
count = (u8)(count + 1);
}
}
i = (u8)(i + 1);
}
if (count > best) best = count;
line = (u8)(line + 1);
}
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
void sprite_set_flags(u8 id, u8 flags);Parameter
idEintrags-ID von 0 bis SPRITE_MAX-1, standardmäßig 0..39 auf GB und 0..63 auf FC. Ungültige IDs werden ignoriert.
flagsVollstä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.
FC-Attribute: Bits 0..1 wählen eine von vier Paletten, Bit 5 legt das Sprite hinter Hintergrundpixel mit Index ungleich null, Bits 6/7 spiegeln X/Y. Unbenutzte Bits 2..4 bleiben null. Die Werte unterscheiden sich von GB; verwenden Sie die Konstanten der jeweiligen Plattform.
Anwendungsbeispiel
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\sprite_shapes.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.nes --nes-chr=.\kitaq-docs\samples\sprite_example.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/sprite.h:53
Replace the hardware attribute byte of a valid OAM slot.
kitaqfc/lib/sprite.c:78
void sprite_set_flags(u8 id, u8 flags)
{
if (sprite_valid(id) == 0) return;
__sprite_attr(id, flags);
}sprite_set_pos
Aktualisiert die verwaltete Position und die OAM-Koordinaten des FC-Sprites. X ist die Bildschirmposition; Y ist der OAM-Bytewert. Für eine sichtbare Oberkante bei Pixel 32 wird Y=31 übergeben.
Syntax
void sprite_set_pos(u8 id, u8 x, u8 y);Parameter
idEintrags-ID von 0 bis SPRITE_MAX-1, standardmäßig 0..39 auf GB und 0..63 auf FC. Ungültige IDs werden ignoriert.
xHorizontale Position in Pixeln als vorzeichenloses Byte; keine Tile-Koordinate.
yY-Byte des OAM. Für eine Oberkante unterhalb der Zeile null wird ihre Position minus eins übergeben; 239..255 liegen außerhalb der 240 sichtbaren Zeilen.
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.
Anwendungsbeispiel
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\sprite_shapes.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.nes --nes-chr=.\kitaq-docs\samples\sprite_example.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/sprite.h:49
Update software coordinates and the intrinsic OAM position for a valid slot.
kitaqfc/lib/sprite.c:62
void sprite_set_pos(u8 id, u8 x, u8 y)
{
if (sprite_valid(id) == 0) return;
kq_sprite_x[id] = x;
kq_sprite_y[id] = y;
__sprite_move(id, x, y);
}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
void sprite_set_tile(u8 id, u8 tile);Parameter
idEintrags-ID von 0 bis SPRITE_MAX-1, standardmäßig 0..39 auf GB und 0..63 auf FC. Ungültige IDs werden ignoriert.
tile8-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.
Anwendungsbeispiel
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\sprite_shapes.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.nes --nes-chr=.\kitaq-docs\samples\sprite_example.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/sprite.h:51
Replace the tile byte of a valid OAM slot without changing allocation state.
kitaqfc/lib/sprite.c:71
void sprite_set_tile(u8 id, u8 tile)
{
if (sprite_valid(id) == 0) return;
__sprite_tile(id, 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
u8 sprite_warn_scanline_overflow(void);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.
Anwendungsbeispiel
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\sprite_shapes.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.nes --nes-chr=.\kitaq-docs\samples\sprite_example.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/sprite.h:64
Flag software overlap estimates above eight sprites on one scanline.
kitaqfc/lib/sprite.c:143
u8 sprite_warn_scanline_overflow(void)
{
return (u8)(sprite_max_scanline_count() > 8);
}system.h — Start, Bildzähler, Wartefunktionen und Interrupts
Verwaltet Frame-Wartezähler, Callbacks nach dem Warten und die Steuerung maskierbarer CPU-Interrupts.
fc_frame_count
fc_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
u16 fc_frame_count(void);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.
Die FC-Initialisierung aktiviert NMI. Das Warten setzt eine funktionierende NMI-Zustellung voraus. Das Maskieren von CPU-IRQs hält NMI nicht an.
Anwendungsbeispiel
result[3]=fc_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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\system_aliases.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\system_aliases.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/system.h:30
#define fc_frame_count system_get_framekitaqfc/lib/system.c:30
u16 system_get_frame(void)
{
return kq_system_frame;
}fc_init
fc_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
void fc_init(void);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.
Die FC-Initialisierung aktiviert NMI. Das Warten setzt eine funktionierende NMI-Zustellung voraus. Das Maskieren von CPU-IRQs hält NMI nicht an.
Anwendungsbeispiel
fc_init();result[0]=fc_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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\system_aliases.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\system_aliases.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/system.h:27
#define fc_init system_initkitaqfc/lib/system.c:7
void system_init(void)
{
kq_system_frame = 0;
system_vblank_callback = 0;
// NMI waits require a running PPU and its enabled NMI source, independently of the CPU IRQ mask.
__nmi_enable();
}fc_set_vblank_callback
fc_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
void fc_set_vblank_callback(SystemCallback callback);Parameter
callbackAufzurufende 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.
Die FC-Initialisierung aktiviert NMI. Das Warten setzt eine funktionierende NMI-Zustellung voraus. Das Maskieren von CPU-IRQs hält NMI nicht an.
Anwendungsbeispiel
fc_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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\system_aliases.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\system_aliases.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/system.h:29
#define fc_set_vblank_callback system_set_vblank_callbackkitaqfc/lib/system.c:24
void system_set_vblank_callback(SystemCallback callback)
{
system_vblank_callback = callback;
}fc_wait_vblank
fc_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
void fc_wait_vblank(void);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.
Die FC-Initialisierung aktiviert NMI. Das Warten setzt eine funktionierende NMI-Zustellung voraus. Das Maskieren von CPU-IRQs hält NMI nicht an.
Anwendungsbeispiel
fc_wait_vblank();fc_wait_vblank();fc_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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\system_aliases.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\system_aliases.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/system.h:28
#define fc_wait_vblank system_wait_vblankkitaqfc/lib/system.c:16
void system_wait_vblank(void)
{
__nmi_wait();
kq_system_frame = (u16)(kq_system_frame + 1);
if (system_vblank_callback != 0) system_vblank_callback();
}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
u16 gb_frame_count(void);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.
Dies ist die von der FC-Bibliothek angebotene gb_-Schreibweise. Sie ruft die FC-Implementierung system_* auf, keine Game-Boy-Hardware. Der entsprechende fc_-Name ruft dieselbe FC-Implementierung auf.
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.
Die FC-Initialisierung aktiviert NMI. Das Warten setzt eine funktionierende NMI-Zustellung voraus. Das Maskieren von CPU-IRQs hält NMI nicht an.
Anwendungsbeispiel
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\system_gb_aliases.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\system_gb_aliases.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/system.h:34
#define gb_frame_count system_get_framekitaqfc/lib/system.c:30
u16 system_get_frame(void)
{
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
void gb_init(void);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 die von der FC-Bibliothek angebotene gb_-Schreibweise. Sie ruft die FC-Implementierung system_* auf, keine Game-Boy-Hardware. Der entsprechende fc_-Name ruft dieselbe FC-Implementierung auf.
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.
Die FC-Initialisierung aktiviert NMI. Das Warten setzt eine funktionierende NMI-Zustellung voraus. Das Maskieren von CPU-IRQs hält NMI nicht an.
Anwendungsbeispiel
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\system_gb_aliases.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\system_gb_aliases.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/system.h:31
#define gb_init system_initkitaqfc/lib/system.c:7
void system_init(void)
{
kq_system_frame = 0;
system_vblank_callback = 0;
// NMI waits require a running PPU and its enabled NMI source, independently of the CPU IRQ mask.
__nmi_enable();
}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
void gb_set_vblank_callback(SystemCallback callback);Parameter
callbackAufzurufende 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 die von der FC-Bibliothek angebotene gb_-Schreibweise. Sie ruft die FC-Implementierung system_* auf, keine Game-Boy-Hardware. Der entsprechende fc_-Name ruft dieselbe FC-Implementierung auf.
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.
Die FC-Initialisierung aktiviert NMI. Das Warten setzt eine funktionierende NMI-Zustellung voraus. Das Maskieren von CPU-IRQs hält NMI nicht an.
Anwendungsbeispiel
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\system_gb_aliases.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\system_gb_aliases.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/system.h:33
#define gb_set_vblank_callback system_set_vblank_callbackkitaqfc/lib/system.c:24
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
void gb_wait_vblank(void);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 die von der FC-Bibliothek angebotene gb_-Schreibweise. Sie ruft die FC-Implementierung system_* auf, keine Game-Boy-Hardware. Der entsprechende fc_-Name ruft dieselbe FC-Implementierung auf.
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.
Die FC-Initialisierung aktiviert NMI. Das Warten setzt eine funktionierende NMI-Zustellung voraus. Das Maskieren von CPU-IRQs hält NMI nicht an.
Anwendungsbeispiel
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\system_gb_aliases.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\system_gb_aliases.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/system.h:32
#define gb_wait_vblank system_wait_vblankkitaqfc/lib/system.c:16
void system_wait_vblank(void)
{
__nmi_wait();
kq_system_frame = (u16)(kq_system_frame + 1);
if (system_vblank_callback != 0) system_vblank_callback();
}system_disable_interrupts
Deaktiviert maskierbare CPU-Interrupts.
Syntax
void system_disable_interrupts(void);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.
Die FC-Initialisierung aktiviert NMI. Das Warten setzt eine funktionierende NMI-Zustellung voraus. Das Maskieren von CPU-IRQs hält NMI nicht an.
Anwendungsbeispiel
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\batch_services.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch_services.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/system.h:25
Disable maskable CPU IRQs; this does not disable the PPU's NMI source.
kitaqfc/lib/system.c:48
void system_disable_interrupts(void)
{
__irq_disable();
}system_enable_interrupts
Aktiviert maskierbare CPU-Interrupts.
Syntax
void system_enable_interrupts(void);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.
Die FC-Initialisierung aktiviert NMI. Das Warten setzt eine funktionierende NMI-Zustellung voraus. Das Maskieren von CPU-IRQs hält NMI nicht an.
Anwendungsbeispiel
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\batch_services.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch_services.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/system.h:23
Enable maskable CPU IRQs through the intrinsic; NMI is controlled separately.
kitaqfc/lib/system.c:42
void system_enable_interrupts(void)
{
__irq_enable();
}system_get_frame
Liest den 16-Bit-Zähler der Frame-Wartefunktion.
Syntax
u16 system_get_frame(void);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.
Die FC-Initialisierung aktiviert NMI. Das Warten setzt eine funktionierende NMI-Zustellung voraus. Das Maskieren von CPU-IRQs hält NMI nicht an.
Anwendungsbeispiel
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\batch_services.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch_services.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/system.h:19
Return the wrapping 16-bit count of completed waits through this wrapper.
kitaqfc/lib/system.c:30
u16 system_get_frame(void)
{
return kq_system_frame;
}system_get_frame8
Liest für kurze Wiederholungsintervalle die unteren acht Bits des Frame-Zählers.
Syntax
u8 system_get_frame8(void);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.
Die FC-Initialisierung aktiviert NMI. Das Warten setzt eine funktionierende NMI-Zustellung voraus. Das Maskieren von CPU-IRQs hält NMI nicht an.
Anwendungsbeispiel
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\batch_services.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch_services.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/system.h:21
Return the low byte of the software frame counter.
kitaqfc/lib/system.c:36
u8 system_get_frame8(void)
{
return (u8)kq_system_frame;
}system_init
Initialisiert die Frame-Verwaltung, indem Zähler und registrierter Callback gelöscht werden.
Syntax
void system_init(void);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.
Die FC-Initialisierung aktiviert NMI. Das Warten setzt eine funktionierende NMI-Zustellung voraus. Das Maskieren von CPU-IRQs hält NMI nicht an.
Anwendungsbeispiel
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\batch_services.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch_services.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/system.h:13
Reset the software frame counter and callback storage, then enable NMI.
kitaqfc/lib/system.c:7
void system_init(void)
{
kq_system_frame = 0;
system_vblank_callback = 0;
// NMI waits require a running PPU and its enabled NMI source, independently of the CPU IRQ mask.
__nmi_enable();
}system_set_vblank_callback
Registriert, ersetzt oder entfernt die nach einem Frame-Wartevorgang aufgerufene Funktion.
Syntax
void system_set_vblank_callback(SystemCallback callback);Parameter
callbackAufzurufende 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.
Die FC-Initialisierung aktiviert NMI. Das Warten setzt eine funktionierende NMI-Zustellung voraus. Das Maskieren von CPU-IRQs hält NMI nicht an.
Anwendungsbeispiel
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\batch_services.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch_services.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/system.h:17
Replace the per-wait callback; null disables callback dispatch.
kitaqfc/lib/system.c:24
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
void system_wait_vblank(void);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.
Die FC-Initialisierung aktiviert NMI. Das Warten setzt eine funktionierende NMI-Zustellung voraus. Das Maskieren von CPU-IRQs hält NMI nicht an.
Anwendungsbeispiel
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.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\runtime.c .\kitaq-docs\samples\api-examples\fc\batch_services.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch_services.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/system.h:15
Wait for NMI, count the completed wait, then invoke the registered callback.
kitaqfc/lib/system.c:16
void system_wait_vblank(void)
{
__nmi_wait();
kq_system_frame = (u16)(kq_system_frame + 1);
if (system_vblank_callback != 0) system_vblank_callback();
}tilemap.h — Rechteckige Operationen auf Kachelkarten
Liest ein zeilenweises Kachelarray und prüft Solidität über einen ID-Schwellenwert. Rechtecktests prüfen nur die vier Ecken, nicht den gesamten Innenraum.
nes_tilemap_get
Liest die Kachel-ID und gibt bei Koordinaten außerhalb der Karte 255 zurück.
Syntax
unsigned char nes_tilemap_get(struct NesTilemap* map, unsigned char tx, unsigned char ty);Parameter
mapGültige Karte mit zeilenweisem Kachelarray, Abmessungen und Soliditätsschwelle; der Speicher muss während des Aufrufs lesbar bleiben.
txKachel-X-Koordinate; eine Einheit entspricht acht Pixeln.
tyKachel-Y-Koordinate; eine Einheit entspricht acht Pixeln.
Rückgabewert
Kachelbyte oder 255; eine gespeicherte 255 lässt sich nicht von einem Ergebnis außerhalb der Karte unterscheiden.
Bedingungen und Grenzen
Benötigt eine gültige Karte und ein nichtleeres lesbares Array. Die Eigenschaft „solide“ wird über einen Schwellenwert der Kachel-ID bestimmt, nicht über eine separate Kollisionsmaske.
Anwendungsbeispiel
result[1]=nes_tilemap_get(&map,2,1);result[2]=nes_tilemap_get(&map,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
Setzen Sie die solide Kachel 5 bei (2,1) in eine 5×3-Karte: Ihr Array-Index ist 7, eine Abfrage außerhalb liefert 255. Berührt eine Ecke das Hindernis, ist das Ergebnis 1. Ein 40×24-Rechteck, das es nur im Inneren einschließt, liefert 0 und zeigt damit die Beschränkung auf die Eckprüfung.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch2_tilemap.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch2_tilemap.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/tilemap.h:19
Return a tile byte, or 0xFF when coordinates exceed map dimensions. The map/storage pointers must be valid; 0xFF may also be an actual stored tile.
kitaqfc/lib/tilemap.c:32
unsigned char nes_tilemap_get(struct NesTilemap* map, unsigned char tx, unsigned char ty)
{
if (tx >= map->width)
{
return 0xFF;
}
if (ty >= map->height)
{
return 0xFF;
}
return map->tiles[nes_tilemap_index(map, tx, ty)];
}nes_tilemap_index
Wandelt Kachelkoordinaten in den zeilenweisen Byte-Offset ty*width+tx um.
Syntax
unsigned short nes_tilemap_index(struct NesTilemap* map, unsigned char tx, unsigned char ty);Parameter
mapGültige Karte mit zeilenweisem Kachelarray, Abmessungen und Soliditätsschwelle; der Speicher muss während des Aufrufs lesbar bleiben.
txKachel-X-Koordinate; eine Einheit entspricht acht Pixeln.
tyKachel-Y-Koordinate; eine Einheit entspricht acht Pixeln.
Rückgabewert
Berechneter 16-Bit-Offset; die Koordinaten werden nicht auf Bereichsgrenzen geprüft.
Bedingungen und Grenzen
Benötigt eine gültige Karte und ein nichtleeres lesbares Array. Die Eigenschaft „solide“ wird über einen Schwellenwert der Kachel-ID bestimmt, nicht über eine separate Kollisionsmaske.
Anwendungsbeispiel
result[0]=nes_tilemap_index(&map,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
Setzen Sie die solide Kachel 5 bei (2,1) in eine 5×3-Karte: Ihr Array-Index ist 7, eine Abfrage außerhalb liefert 255. Berührt eine Ecke das Hindernis, ist das Ergebnis 1. Ein 40×24-Rechteck, das es nur im Inneren einschließt, liefert 0 und zeigt damit die Beschränkung auf die Eckprüfung.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch2_tilemap.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch2_tilemap.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/tilemap.h:16
Compute a row-major byte offset by adding the row stride ty times. This internal arithmetic helper does not validate coordinates.
kitaqfc/lib/tilemap.c:14
unsigned short nes_tilemap_index(struct NesTilemap* map, unsigned char tx, unsigned char ty)
{
unsigned short index;
unsigned char y;
index = tx;
y = 0;
while (y != ty)
{
index = (unsigned short)(index + map->width);
y = y + 1;
}
return index;
}nes_tilemap_point_solid
Prüft eine Kachel gegen solid_from; Kachel 255 und Koordinaten außerhalb der Karte gelten immer als solide.
Syntax
unsigned char nes_tilemap_point_solid(struct NesTilemap* map, unsigned char tx, unsigned char ty);Parameter
mapGültige Karte mit zeilenweisem Kachelarray, Abmessungen und Soliditätsschwelle; der Speicher muss während des Aufrufs lesbar bleiben.
txKachel-X-Koordinate; eine Einheit entspricht acht Pixeln.
tyKachel-Y-Koordinate; eine Einheit entspricht acht Pixeln.
Rückgabewert
1 für solide, andernfalls 0.
Bedingungen und Grenzen
Benötigt eine gültige Karte und ein nichtleeres lesbares Array. Die Eigenschaft „solide“ wird über einen Schwellenwert der Kachel-ID bestimmt, nicht über eine separate Kollisionsmaske.
Anwendungsbeispiel
result[3]=nes_tilemap_point_solid(&map,2,1);result[4]=nes_tilemap_point_solid(&map,0,0);result[5]=nes_tilemap_point_solid(&map,5,0);Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Setzen Sie die solide Kachel 5 bei (2,1) in eine 5×3-Karte: Ihr Array-Index ist 7, eine Abfrage außerhalb liefert 255. Berührt eine Ecke das Hindernis, ist das Ergebnis 1. Ein 40×24-Rechteck, das es nur im Inneren einschließt, liefert 0 und zeigt damit die Beschränkung auf die Eckprüfung.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch2_tilemap.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch2_tilemap.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/tilemap.h:22
Treat out-of-bounds/0xFF tiles as solid, then compare other tile IDs with the map's solid_from threshold.
kitaqfc/lib/tilemap.c:47
unsigned char nes_tilemap_point_solid(struct NesTilemap* map, unsigned char tx, unsigned char ty)
{
unsigned char tile;
tile = nes_tilemap_get(map, tx, ty);
if (tile == 0xFF)
{
return 1;
}
if (tile >= map->solid_from)
{
return 1;
}
return 0;
}nes_tilemap_world_box_solid
Prüft die linke obere, rechte obere, linke untere und rechte untere Ecke eines Weltrechtecks.
Syntax
unsigned char nes_tilemap_world_box_solid(struct NesTilemap* map, unsigned short world_x, unsigned short world_y, unsigned char width, unsigned char height);Parameter
mapGültige Karte mit zeilenweisem Kachelarray, Abmessungen und Soliditätsschwelle; der Speicher muss während des Aufrufs lesbar bleiben.
world_xWelt-X in ganzen Pixeln; halten Sie den Wert unter 2048, um einen Umlauf zu vermeiden.
world_yWelt-Y in ganzen Pixeln; halten Sie den Wert unter 2048, um einen Umlauf zu vermeiden.
widthRechteckbreite, 1–255 Pixel; die gegenüberliegende Kante
world_x+width-1muss unter 2048 bleiben.heightRechteckhöhe, 1–255 Pixel; die gegenüberliegende Kante
world_y+height-1muss unter 2048 bleiben.
Rückgabewert
1, wenn mindestens eine Ecke solide ist, andernfalls 0.
Bedingungen und Grenzen
Breite und Höhe dürfen nicht null sein. Kanten zwischen den Ecken und der Innenraum werden nicht abgesucht; große Rechtecke können daher Hindernisse übersehen. Das Beispiel liefert bei einem Hindernis in der Mitte null, wenn alle vier Ecken frei sind.
Anwendungsbeispiel
result[12]=nes_tilemap_world_box_solid(&map,8,8,16,8);result[13]=nes_tilemap_world_box_solid(&map,0,0,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
Setzen Sie die solide Kachel 5 bei (2,1) in eine 5×3-Karte: Ihr Array-Index ist 7, eine Abfrage außerhalb liefert 255. Berührt eine Ecke das Hindernis, ist das Ergebnis 1. Ein 40×24-Rechteck, das es nur im Inneren einschließt, liefert 0 und zeigt damit die Beschränkung auf die Eckprüfung.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch2_tilemap.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch2_tilemap.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/tilemap.h:33
Test only the four corners of a nonempty world box. Interior/edge tiles between the corners are not scanned, so large boxes can miss obstacles. Width/height must be nonzero and endpoint arithmetic must not overflow.
kitaqfc/lib/tilemap.c:86
unsigned char nes_tilemap_world_box_solid(struct NesTilemap* map, unsigned short world_x, unsigned short world_y, unsigned char width, unsigned char height)
{
unsigned short x2;
unsigned short y2;
x2 = (unsigned short)(world_x + width - 1);
y2 = (unsigned short)(world_y + height - 1);
if (nes_tilemap_world_point_solid(map, world_x, world_y) != 0)
{
return 1;
}
if (nes_tilemap_world_point_solid(map, x2, world_y) != 0)
{
return 1;
}
if (nes_tilemap_world_point_solid(map, world_x, y2) != 0)
{
return 1;
}
if (nes_tilemap_world_point_solid(map, x2, y2) != 0)
{
return 1;
}
return 0;
}nes_tilemap_world_point_solid
Wandelt einen Weltpunkt in Koordinaten von Acht-Pixel-Kacheln um und prüft auf Solidität.
Syntax
unsigned char nes_tilemap_world_point_solid(struct NesTilemap* map, unsigned short world_x, unsigned short world_y);Parameter
mapGültige Karte mit zeilenweisem Kachelarray, Abmessungen und Soliditätsschwelle; der Speicher muss während des Aufrufs lesbar bleiben.
world_xWelt-X in ganzen Pixeln; halten Sie den Wert unter 2048, um einen Umlauf zu vermeiden.
world_yWelt-Y in ganzen Pixeln; halten Sie den Wert unter 2048, um einen Umlauf zu vermeiden.
Rückgabewert
1, wenn die entsprechende Kachel solide ist, andernfalls 0.
Bedingungen und Grenzen
Benötigt eine gültige Karte und ein nichtleeres lesbares Array. Die Eigenschaft „solide“ wird über einen Schwellenwert der Kachel-ID bestimmt, nicht über eine separate Kollisionsmaske.
Anwendungsbeispiel
result[10]=nes_tilemap_world_point_solid(&map,16,8);result[11]=nes_tilemap_world_point_solid(&map,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
Setzen Sie die solide Kachel 5 bei (2,1) in eine 5×3-Karte: Ihr Array-Index ist 7, eine Abfrage außerhalb liefert 255. Berührt eine Ecke das Hindernis, ist das Ergebnis 1. Ein 40×24-Rechteck, das es nur im Inneren einschließt, liefert 0 und zeigt damit die Beschränkung auf die Eckprüfung.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch2_tilemap.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch2_tilemap.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/tilemap.h:29
Convert a world point to tile coordinates and apply the tile solidity rule.
kitaqfc/lib/tilemap.c:77
unsigned char nes_tilemap_world_point_solid(struct NesTilemap* map, unsigned short world_x, unsigned short world_y)
{
return nes_tilemap_point_solid(map, nes_world_to_tile8_x(world_x), nes_world_to_tile8_y(world_y));
}nes_world_to_tile8_x
Teilt Welt-X durch acht und begrenzt das Ergebnis auf ein Kachelkoordinaten-Byte.
Syntax
unsigned char nes_world_to_tile8_x(unsigned short world_x);Parameter
world_xWelt-X in ganzen Pixeln; halten Sie den Wert unter 2048, um einen Umlauf zu vermeiden.
Rückgabewert
Die unteren acht Bits von world_x >> 3; läuft alle 2048 Pixel um.
Bedingungen und Grenzen
Benötigt eine gültige Karte und ein nichtleeres lesbares Array. Die Eigenschaft „solide“ wird über einen Schwellenwert der Kachel-ID bestimmt, nicht über eine separate Kollisionsmaske.
Anwendungsbeispiel
result[6]=nes_world_to_tile8_x(23);result[7]=nes_world_to_tile8_x(24);Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Setzen Sie die solide Kachel 5 bei (2,1) in eine 5×3-Karte: Ihr Array-Index ist 7, eine Abfrage außerhalb liefert 255. Berührt eine Ecke das Hindernis, ist das Ergebnis 1. Ein 40×24-Rechteck, das es nur im Inneren einschließt, liefert 0 und zeigt damit die Beschränkung auf die Eckprüfung.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch2_tilemap.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch2_tilemap.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/tilemap.h:25
Convert pixels to eight-pixel tile X and narrow to a byte. Keep world X below 2048 when wraparound is not intended.
kitaqfc/lib/tilemap.c:65
unsigned char nes_world_to_tile8_x(unsigned short world_x)
{
return (unsigned char)(world_x >> 3);
}nes_world_to_tile8_y
Teilt Welt-Y durch acht und begrenzt das Ergebnis auf ein Kachelkoordinaten-Byte.
Syntax
unsigned char nes_world_to_tile8_y(unsigned short world_y);Parameter
world_yWelt-Y in ganzen Pixeln; halten Sie den Wert unter 2048, um einen Umlauf zu vermeiden.
Rückgabewert
Die unteren acht Bits von world_y >> 3; läuft alle 2048 Pixel um.
Bedingungen und Grenzen
Benötigt eine gültige Karte und ein nichtleeres lesbares Array. Die Eigenschaft „solide“ wird über einen Schwellenwert der Kachel-ID bestimmt, nicht über eine separate Kollisionsmaske.
Anwendungsbeispiel
result[8]=nes_world_to_tile8_y(15);result[9]=nes_world_to_tile8_y(16);Dieser Ausschnitt zeigt den Aufruf. Beachten Sie beim Einbau in ein vollständiges Programm die angegebenen Anforderungen an Initialisierung und Puffer.
Erwartetes Ergebnis
Setzen Sie die solide Kachel 5 bei (2,1) in eine 5×3-Karte: Ihr Array-Index ist 7, eine Abfrage außerhalb liefert 255. Berührt eine Ecke das Hindernis, ist das Ergebnis 1. Ein 40×24-Rechteck, das es nur im Inneren einschließt, liefert 0 und zeigt damit die Beschränkung auf die Eckprüfung.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\batch2_tilemap.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\batch2_tilemap.nes --no-cache --no-disasm --mapper=nrom --nes-chr=.\kitaq-docs\samples\font.chrImplementierung und Quelltext
kitaqfc/lib/tilemap.h:27
Convert pixels to eight-pixel tile Y with the same byte-coordinate limit.
kitaqfc/lib/tilemap.c:71
unsigned char nes_world_to_tile8_y(unsigned short world_y)
{
return (unsigned char)(world_y >> 3);
}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.
FC zählt codierte Befehlsbytes in einem festen intrinsischen 128-Byte-Puffer. Ein Tile-Schreibbefehl braucht 4 Bytes, ein Fülleintrag 5 und eine Zeigerkopie 6 einschließlich Metadaten. NMI kann eine bereite Warteschlange verarbeiten; prüfen und befüllen Sie sie vor der Freigabe und koordinieren Sie Erzeuger und Verbraucher.
Gibt die intrinsische Warteschlange mit __vramq_commit frei und wartet mit __nmi_wait auf den NMI-Pfad. Der Standardhandler verarbeitet die bereite Warteschlange. NMI und Handler müssen aktiv bleiben; große Übertragungen werden durch diesen Aufruf nicht auf mehrere VBlanks verteilt.
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
void vram_clear_queue(void);Rückgabewert
Keiner (void).
Bedingungen und Grenzen
FC zählt codierte Befehlsbytes in einem festen intrinsischen 128-Byte-Puffer. Ein Tile-Schreibbefehl braucht 4 Bytes, ein Fülleintrag 5 und eine Zeigerkopie 6 einschließlich Metadaten. NMI kann eine bereite Warteschlange verarbeiten; prüfen und befüllen Sie sie vor der Freigabe und koordinieren Sie Erzeuger und Verbraucher.
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
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.
Auf FC kennzeichnet Rot die beiden oberen Quadrate, die Kopie aus drei Mustern und das letzte VBlank-Quadrat. Blau kennzeichnet das Rechteck von 32 × 24 und die Kopie aus zwei Mustern. Grün kennzeichnet den Block aus 3 × 2 Kacheln und den Balken von 40 × 8. Der Hintergrund ist schwarz; Position und Farbe jedes gezeichneten Pixels werden geprüft.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\vram.c .\kitaq-docs\samples\api-examples\fc\vram_queue_shapes.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/vram.h:15
Discard queued commands and explicitly reset the overflow latch.
kitaqfc/lib/vram.c:17
void vram_clear_queue(void)
{
__vramq_clear();
__vramq_clear_overflow();
}vram_flush
Gibt die intrinsische Warteschlange mit __vramq_commit frei und wartet mit __nmi_wait auf den NMI-Pfad. Der Standardhandler verarbeitet die bereite Warteschlange. NMI und Handler müssen aktiv bleiben; große Übertragungen werden durch diesen Aufruf nicht auf mehrere VBlanks verteilt.
Syntax
void vram_flush(void);Rückgabewert
Keiner (void).
Bedingungen und Grenzen
FC zählt codierte Befehlsbytes in einem festen intrinsischen 128-Byte-Puffer. Ein Tile-Schreibbefehl braucht 4 Bytes, ein Fülleintrag 5 und eine Zeigerkopie 6 einschließlich Metadaten. NMI kann eine bereite Warteschlange verarbeiten; prüfen und befüllen Sie sie vor der Freigabe und koordinieren Sie Erzeuger und Verbraucher.
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.
PPU-Byteadresse (0x0000–0x3FFF), kein CPU-Zeiger. Das Ziel muss beschreibbar sein: Musteränderungen benötigen CHR-RAM statt CHR-ROM. PPU-Adressabbildung und Spiegelung gelten weiterhin. Wählen Sie für fortlaufendes Kopieren und Füllen die Schrittweite 1 in PPUCTRL. Führen Sie Befehle zu einem sicheren PPU-Zeitpunkt aus und stellen Sie danach den Scrollzustand her; der Ausführer schreibt PPUADDR und PPUDATA, ohne Scrolleinstellungen wiederherzustellen.
Anwendungsbeispiel
vram_flush(); // One small write through the VBlank/NMI path.
__scroll_set(0,0);
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.
Auf FC kennzeichnet Rot die beiden oberen Quadrate, die Kopie aus drei Mustern und das letzte VBlank-Quadrat. Blau kennzeichnet das Rechteck von 32 × 24 und die Kopie aus zwei Mustern. Grün kennzeichnet den Block aus 3 × 2 Kacheln und den Balken von 40 × 8. Der Hintergrund ist schwarz; Position und Farbe jedes gezeichneten Pixels werden geprüft.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\vram.c .\kitaq-docs\samples\api-examples\fc\vram_queue_shapes.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/vram.h:41
Commit queued records for consumption and wait for the NMI path.
kitaqfc/lib/vram.c:115
void vram_flush(void)
{
__vramq_commit();
__nmi_wait();
}vram_flush_now
Ruft sofort __vramq_exec auf. Ausgeführt wird nur bei durch __vramq_commit gesetztem Bereit-Flag; eine nicht freigegebene Warteschlange bleibt unverändert. Nach der Ausführung werden Länge und Bereit-Flag gelöscht, die Überlaufmeldung bleibt. Diese Funktion gibt die Warteschlange weder frei noch wartet sie auf einen sicheren PPU-Zeitpunkt.
Syntax
void vram_flush_now(void);Rückgabewert
Keiner (void).
Bedingungen und Grenzen
FC zählt codierte Befehlsbytes in einem festen intrinsischen 128-Byte-Puffer. Ein Tile-Schreibbefehl braucht 4 Bytes, ein Fülleintrag 5 und eine Zeigerkopie 6 einschließlich Metadaten. NMI kann eine bereite Warteschlange verarbeiten; prüfen und befüllen Sie sie vor der Freigabe und koordinieren Sie Erzeuger und Verbraucher.
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.
PPU-Byteadresse (0x0000–0x3FFF), kein CPU-Zeiger. Das Ziel muss beschreibbar sein: Musteränderungen benötigen CHR-RAM statt CHR-ROM. PPU-Adressabbildung und Spiegelung gelten weiterhin. Wählen Sie für fortlaufendes Kopieren und Füllen die Schrittweite 1 in PPUCTRL. Führen Sie Befehle zu einem sicheren PPU-Zeitpunkt aus und stellen Sie danach den Scrollzustand her; der Ausführer schreibt PPUADDR und PPUDATA, ohne Scrolleinstellungen wiederherzustellen.
Anwendungsbeispiel
// Rendering is stopped here. On FC, commit readiness before direct execution.
__vramq_commit();
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.
Auf FC kennzeichnet Rot die beiden oberen Quadrate, die Kopie aus drei Mustern und das letzte VBlank-Quadrat. Blau kennzeichnet das Rechteck von 32 × 24 und die Kopie aus zwei Mustern. Grün kennzeichnet den Block aus 3 × 2 Kacheln und den Balken von 40 × 8. Der Hintergrund ist schwarz; Position und Farbe jedes gezeichneten Pixels werden geprüft.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\vram.c .\kitaq-docs\samples\api-examples\fc\vram_queue_shapes.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/vram.h:39
Invoke the queue executor directly. Its ready flag must already be set by commit, and the caller supplies appropriate PPU timing.
kitaqfc/lib/vram.c:109
void vram_flush_now(void)
{
__vramq_exec();
}vram_get_overflowed
Liest das Überlaufflag, ohne es zu löschen; es kann einen früheren Fehler festhalten.
Syntax
u8 vram_get_overflowed(void);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
FC zählt codierte Befehlsbytes in einem festen intrinsischen 128-Byte-Puffer. Ein Tile-Schreibbefehl braucht 4 Bytes, ein Fülleintrag 5 und eine Zeigerkopie 6 einschließlich Metadaten. NMI kann eine bereite Warteschlange verarbeiten; prüfen und befüllen Sie sie vor der Freigabe und koordinieren Sie Erzeuger und Verbraucher.
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
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.
Auf FC kennzeichnet Rot die beiden oberen Quadrate, die Kopie aus drei Mustern und das letzte VBlank-Quadrat. Blau kennzeichnet das Rechteck von 32 × 24 und die Kopie aus zwei Mustern. Grün kennzeichnet den Block aus 3 × 2 Kacheln und den Balken von 40 × 8. Der Hintergrund ist schwarz; Position und Farbe jedes gezeichneten Pixels werden geprüft.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\vram.c .\kitaq-docs\samples\api-examples\fc\vram_queue_shapes.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/vram.h:52
Read the overflow latch without clearing it.
kitaqfc/lib/vram.c:144
u8 vram_get_overflowed(void)
{
return __vramq_overflow();
}vram_get_queue_capacity
Gibt die Gesamtkapazität des Befehlspuffers unabhängig von seiner aktuellen Belegung zurück.
Syntax
u8 vram_get_queue_capacity(void);Rückgabewert
Ein vorzeichenloses Byte in den hier beschriebenen plattformspezifischen Einheiten. Die Abfrage verändert oder verarbeitet die Warteschlange nicht.
Bedingungen und Grenzen
FC zählt codierte Befehlsbytes in einem festen intrinsischen 128-Byte-Puffer. Ein Tile-Schreibbefehl braucht 4 Bytes, ein Fülleintrag 5 und eine Zeigerkopie 6 einschließlich Metadaten. NMI kann eine bereite Warteschlange verarbeiten; prüfen und befüllen Sie sie vor der Freigabe und koordinieren Sie Erzeuger und Verbraucher.
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
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.
Auf FC kennzeichnet Rot die beiden oberen Quadrate, die Kopie aus drei Mustern und das letzte VBlank-Quadrat. Blau kennzeichnet das Rechteck von 32 × 24 und die Kopie aus zwei Mustern. Grün kennzeichnet den Block aus 3 × 2 Kacheln und den Balken von 40 × 8. Der Hintergrund ist schwarz; Position und Farbe jedes gezeichneten Pixels werden geprüft.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\vram.c .\kitaq-docs\samples\api-examples\fc\vram_queue_shapes.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/vram.h:50
Return the queue's total capacity in bytes, independent of its current usage. This describes the command buffer, not free space in PPU VRAM.
kitaqfc/lib/vram.c:138
u8 vram_get_queue_capacity(void)
{
return __vramq_capacity();
}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
u8 vram_get_queue_free(void);Rückgabewert
Ein vorzeichenloses Byte in den hier beschriebenen plattformspezifischen Einheiten. Die Abfrage verändert oder verarbeitet die Warteschlange nicht.
Bedingungen und Grenzen
FC zählt codierte Befehlsbytes in einem festen intrinsischen 128-Byte-Puffer. Ein Tile-Schreibbefehl braucht 4 Bytes, ein Fülleintrag 5 und eine Zeigerkopie 6 einschließlich Metadaten. NMI kann eine bereite Warteschlange verarbeiten; prüfen und befüllen Sie sie vor der Freigabe und koordinieren Sie Erzeuger und Verbraucher.
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
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.
Auf FC kennzeichnet Rot die beiden oberen Quadrate, die Kopie aus drei Mustern und das letzte VBlank-Quadrat. Blau kennzeichnet das Rechteck von 32 × 24 und die Kopie aus zwei Mustern. Grün kennzeichnet den Block aus 3 × 2 Kacheln und den Balken von 40 × 8. Der Hintergrund ist schwarz; Position und Farbe jedes gezeichneten Pixels werden geprüft.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\vram.c .\kitaq-docs\samples\api-examples\fc\vram_queue_shapes.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/vram.h:47
Return the remaining command-buffer capacity in bytes. A command requires space for its complete encoded record, including its address and metadata. Read before committing: NMI may consume a committed queue asynchronously.
kitaqfc/lib/vram.c:131
u8 vram_get_queue_free(void)
{
return (u8)(__vramq_capacity() - __vramq_len());
}vram_get_queue_used
Gibt den von ausstehenden Befehlen belegten Pufferumfang zurück, nicht die Bytezahl der späteren Videodaten.
Syntax
u8 vram_get_queue_used(void);Rückgabewert
Ein vorzeichenloses Byte in den hier beschriebenen plattformspezifischen Einheiten. Die Abfrage verändert oder verarbeitet die Warteschlange nicht.
Bedingungen und Grenzen
FC zählt codierte Befehlsbytes in einem festen intrinsischen 128-Byte-Puffer. Ein Tile-Schreibbefehl braucht 4 Bytes, ein Fülleintrag 5 und eine Zeigerkopie 6 einschließlich Metadaten. NMI kann eine bereite Warteschlange verarbeiten; prüfen und befüllen Sie sie vor der Freigabe und koordinieren Sie Erzeuger und Verbraucher.
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
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.
Auf FC kennzeichnet Rot die beiden oberen Quadrate, die Kopie aus drei Mustern und das letzte VBlank-Quadrat. Blau kennzeichnet das Rechteck von 32 × 24 und die Kopie aus zwei Mustern. Grün kennzeichnet den Block aus 3 × 2 Kacheln und den Balken von 40 × 8. Der Hintergrund ist schwarz; Position und Farbe jedes gezeichneten Pixels werden geprüft.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\vram.c .\kitaq-docs\samples\api-examples\fc\vram_queue_shapes.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/vram.h:43
Return the encoded queue length in bytes, not the number of commands.
kitaqfc/lib/vram.c:122
u8 vram_get_queue_used(void)
{
return __vramq_len();
}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
void vram_init(void);Rückgabewert
Keiner (void).
Bedingungen und Grenzen
FC zählt codierte Befehlsbytes in einem festen intrinsischen 128-Byte-Puffer. Ein Tile-Schreibbefehl braucht 4 Bytes, ein Fülleintrag 5 und eine Zeigerkopie 6 einschließlich Metadaten. NMI kann eine bereite Warteschlange verarbeiten; prüfen und befüllen Sie sie vor der Freigabe und koordinieren Sie Erzeuger und Verbraucher.
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
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.
Auf FC kennzeichnet Rot die beiden oberen Quadrate, die Kopie aus drei Mustern und das letzte VBlank-Quadrat. Blau kennzeichnet das Rechteck von 32 × 24 und die Kopie aus zwei Mustern. Grün kennzeichnet den Block aus 3 × 2 Kacheln und den Balken von 40 × 8. Der Hintergrund ist schwarz; Position und Farbe jedes gezeichneten Pixels werden geprüft.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\vram.c .\kitaq-docs\samples\api-examples\fc\vram_queue_shapes.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/vram.h:13
Clear the intrinsic queue and its overflow latch.
kitaqfc/lib/vram.c:10
void vram_init(void)
{
__vramq_clear();
__vramq_clear_overflow();
}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
u8 vram_queue_bg_block(u16 base, u8 x, u8 y, u8 w, u8 h, const u8* src);Parameter
baseKachel- und Rechteckbefehle verwenden das zur Übersetzung festgelegte
VRAM_NT_BASE, standardmäßig0x2000. Blockübertragungen verwenden die angegebene Nametable-Basis (0x2000,0x2400,0x2800oder0x2C00); Nametable-Spiegelung gilt weiterhin. Adressen werden beim Einreihen mit 32 Bytes je Zeile berechnet. Bleiben Sie innerhalb von 32 × 30 Kacheln, um Attributbytes nicht zu überschreiben.x, yLinke obere Position in 8×8-Tiles, nicht Pixeln. Es erfolgt kein Abschneiden. Halten Sie
x + w <= 32und auf GBy + h <= 32, im Tile-Bereich einer FC-Nametable<= 30ein. Ein einzelnes Tile hat Breite und Höhe 1.w, hBreite und Höhe in Tiles als vorzeichenlose Bytes. Der Quellblock enthält zeilenweise
w * hBytes. Nullabmessungen erzeugen keine sichtbaren Schreibzugriffe; der Platzbedarf folgt dennoch den Plattformregeln.srcNahzeiger 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 nach dem Versuch keine Überlaufmeldung gesetzt ist, andernfalls 0. Auch bei passendem aktuellem Eintrag kann ein früherer Überlauf 0 verursachen. Mehrteilige Operationen können teilweise eingereiht bleiben; ein Rückgängigmachen erfolgt nicht. Selbst eine Länge von null kann wegen einer vorhandenen Meldung 0 liefern.
Bedingungen und Grenzen
FC zählt codierte Befehlsbytes in einem festen intrinsischen 128-Byte-Puffer. Ein Tile-Schreibbefehl braucht 4 Bytes, ein Fülleintrag 5 und eine Zeigerkopie 6 einschließlich Metadaten. NMI kann eine bereite Warteschlange verarbeiten; prüfen und befüllen Sie sie vor der Freigabe und koordinieren Sie Erzeuger und Verbraucher.
Dieser Aufruf benötigt 6 * h Befehlspuffer-Bytes für die vollständige Operation. Die Formel zählt codierte Einträge einschließlich Metadaten, nicht die übertragenen Nutzdaten. Prüfen Sie vor mehrteiligen Operationen den freien Platz.
Kachel- und Rechteckbefehle verwenden das zur Übersetzung festgelegte VRAM_NT_BASE, standardmäßig 0x2000. Blockübertragungen verwenden die angegebene Nametable-Basis (0x2000, 0x2400, 0x2800 oder 0x2C00); Nametable-Spiegelung gilt weiterhin. Adressen werden beim Einreihen mit 32 Bytes je Zeile berechnet. Bleiben Sie innerhalb von 32 × 30 Kacheln, um Attributbytes nicht zu überschreiben.
Jede Zeile verwendet einen Eintrag. Höhe 0 fügt keinen hinzu; Breite 0 fügt weiterhin einen je Zeile hinzu, schreibt aber keine Bytes. Zeilenkoordinaten werden in u8 umgewandelt; y + row läuft bei 256 um. Begrenzung und Rücknahme teilweiser Einträge erfolgen nicht.
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
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.
Auf FC kennzeichnet Rot die beiden oberen Quadrate, die Kopie aus drei Mustern und das letzte VBlank-Quadrat. Blau kennzeichnet das Rechteck von 32 × 24 und die Kopie aus zwei Mustern. Grün kennzeichnet den Block aus 3 × 2 Kacheln und den Balken von 40 × 8. Der Hintergrund ist schwarz; Position und Farbe jedes gezeichneten Pixels werden geprüft.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\vram.c .\kitaq-docs\samples\api-examples\fc\vram_queue_shapes.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/vram.h:27
Queue each tightly packed source row as a pointer-based copy record. Keep source storage and its ROM bank accessible until queue execution finishes; partial queuing remains possible on overflow.
kitaqfc/lib/vram.c:54
u8 vram_queue_bg_block(u16 base, u8 x, u8 y, u8 w, u8 h, const u8* src)
{
u8 row;
row = 0;
while (row < h) {
__vramq_copy(vram_xy_addr(base, x, (u8)(y + row)), src, w);
src = src + w;
row = (u8)(row + 1);
}
return (u8)(__vramq_overflow() == 0);
}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
u8 vram_queue_bg_rect(u8 x, u8 y, u8 w, u8 h, u8 tile);Parameter
x, yLinke obere Position in 8×8-Tiles, nicht Pixeln. Es erfolgt kein Abschneiden. Halten Sie
x + w <= 32und auf GBy + h <= 32, im Tile-Bereich einer FC-Nametable<= 30ein. Ein einzelnes Tile hat Breite und Höhe 1.w, hBreite und Höhe in Tiles als vorzeichenlose Bytes. Der Quellblock enthält zeilenweise
w * hBytes. Nullabmessungen erzeugen keine sichtbaren Schreibzugriffe; der Platzbedarf folgt dennoch den Plattformregeln.tileTile-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 nach dem Versuch keine Überlaufmeldung gesetzt ist, andernfalls 0. Auch bei passendem aktuellem Eintrag kann ein früherer Überlauf 0 verursachen. Mehrteilige Operationen können teilweise eingereiht bleiben; ein Rückgängigmachen erfolgt nicht. Selbst eine Länge von null kann wegen einer vorhandenen Meldung 0 liefern.
Bedingungen und Grenzen
FC zählt codierte Befehlsbytes in einem festen intrinsischen 128-Byte-Puffer. Ein Tile-Schreibbefehl braucht 4 Bytes, ein Fülleintrag 5 und eine Zeigerkopie 6 einschließlich Metadaten. NMI kann eine bereite Warteschlange verarbeiten; prüfen und befüllen Sie sie vor der Freigabe und koordinieren Sie Erzeuger und Verbraucher.
Dieser Aufruf benötigt 5 * h Befehlspuffer-Bytes für die vollständige Operation. Die Formel zählt codierte Einträge einschließlich Metadaten, nicht die übertragenen Nutzdaten. Prüfen Sie vor mehrteiligen Operationen den freien Platz.
Kachel- und Rechteckbefehle verwenden das zur Übersetzung festgelegte VRAM_NT_BASE, standardmäßig 0x2000. Blockübertragungen verwenden die angegebene Nametable-Basis (0x2000, 0x2400, 0x2800 oder 0x2C00); Nametable-Spiegelung gilt weiterhin. Adressen werden beim Einreihen mit 32 Bytes je Zeile berechnet. Bleiben Sie innerhalb von 32 × 30 Kacheln, um Attributbytes nicht zu überschreiben.
Jede Zeile verwendet einen Eintrag. Höhe 0 fügt keinen hinzu; Breite 0 fügt weiterhin einen je Zeile hinzu, schreibt aber keine Bytes. Zeilenkoordinaten werden in u8 umgewandelt; y + row läuft bei 256 um. Begrenzung und Rücknahme teilweiser Einträge erfolgen nicht.
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
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.
Auf FC kennzeichnet Rot die beiden oberen Quadrate, die Kopie aus drei Mustern und das letzte VBlank-Quadrat. Blau kennzeichnet das Rechteck von 32 × 24 und die Kopie aus zwei Mustern. Grün kennzeichnet den Block aus 3 × 2 Kacheln und den Balken von 40 × 8. Der Hintergrund ist schwarz; Position und Farbe jedes gezeichneten Pixels werden geprüft.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\vram.c .\kitaq-docs\samples\api-examples\fc\vram_queue_shapes.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/vram.h:23
Queue one fill per row. This is not transactional: capacity exhaustion can leave earlier rows queued, and the loop continues attempting later rows.
kitaqfc/lib/vram.c:40
u8 vram_queue_bg_rect(u8 x, u8 y, u8 w, u8 h, u8 tile)
{
u8 row;
row = 0;
while (row < h) {
__vramq_fill(vram_xy_addr(VRAM_NT_BASE, x, (u8)(y + row)), tile, w);
row = (u8)(row + 1);
}
return (u8)(__vramq_overflow() == 0);
}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
u8 vram_queue_bg_tile(u8 x, u8 y, u8 tile);Parameter
x, yLinke obere Position in 8×8-Tiles, nicht Pixeln. Es erfolgt kein Abschneiden. Halten Sie
x + w <= 32und auf GBy + h <= 32, im Tile-Bereich einer FC-Nametable<= 30ein. Ein einzelnes Tile hat Breite und Höhe 1.tileTile-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 nach dem Versuch keine Überlaufmeldung gesetzt ist, andernfalls 0. Auch bei passendem aktuellem Eintrag kann ein früherer Überlauf 0 verursachen. Mehrteilige Operationen können teilweise eingereiht bleiben; ein Rückgängigmachen erfolgt nicht. Selbst eine Länge von null kann wegen einer vorhandenen Meldung 0 liefern.
Bedingungen und Grenzen
FC zählt codierte Befehlsbytes in einem festen intrinsischen 128-Byte-Puffer. Ein Tile-Schreibbefehl braucht 4 Bytes, ein Fülleintrag 5 und eine Zeigerkopie 6 einschließlich Metadaten. NMI kann eine bereite Warteschlange verarbeiten; prüfen und befüllen Sie sie vor der Freigabe und koordinieren Sie Erzeuger und Verbraucher.
Dieser Aufruf benötigt 4 Befehlspuffer-Bytes für die vollständige Operation. Die Formel zählt codierte Einträge einschließlich Metadaten, nicht die übertragenen Nutzdaten. Prüfen Sie vor mehrteiligen Operationen den freien Platz.
Kachel- und Rechteckbefehle verwenden das zur Übersetzung festgelegte VRAM_NT_BASE, standardmäßig 0x2000. Blockübertragungen verwenden die angegebene Nametable-Basis (0x2000, 0x2400, 0x2800 oder 0x2C00); Nametable-Spiegelung gilt weiterhin. Adressen werden beim Einreihen mit 32 Bytes je Zeile berechnet. Bleiben Sie innerhalb von 32 × 30 Kacheln, um Attributbytes nicht zu überschreiben.
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
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.
Auf FC kennzeichnet Rot die beiden oberen Quadrate, die Kopie aus drei Mustern und das letzte VBlank-Quadrat. Blau kennzeichnet das Rechteck von 32 × 24 und die Kopie aus zwei Mustern. Grün kennzeichnet den Block aus 3 × 2 Kacheln und den Balken von 40 × 8. Der Hintergrund ist schwarz; Position und Farbe jedes gezeichneten Pixels werden geprüft.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\vram.c .\kitaq-docs\samples\api-examples\fc\vram_queue_shapes.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/vram.h:18
Queue one tile at the default nametable base. Return the current overflow status, which may include a failure from an earlier operation.
kitaqfc/lib/vram.c:25
u8 vram_queue_bg_tile(u8 x, u8 y, u8 tile)
{
__vramq_put(vram_xy_addr(VRAM_NT_BASE, x, y), tile);
return (u8)(__vramq_overflow() == 0);
}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
u8 vram_queue_memcpy(u16 dst, const void* src, u16 len);Parameter
dstPPU-Byteadresse (
0x0000–0x3FFF), kein CPU-Zeiger. Das Ziel muss beschreibbar sein: Musteränderungen benötigen CHR-RAM statt CHR-ROM. PPU-Adressabbildung und Spiegelung gelten weiterhin. Wählen Sie für fortlaufendes Kopieren und Füllen die Schrittweite 1 in PPUCTRL. Führen Sie Befehle zu einem sicheren PPU-Zeitpunkt aus und stellen Sie danach den Scrollzustand her; der Ausführer schreibt PPUADDR und PPUDATA, ohne Scrolleinstellungen wiederherzustellen.srcNahzeiger 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.
lenAnzahl 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 nach dem Versuch keine Überlaufmeldung gesetzt ist, andernfalls 0. Auch bei passendem aktuellem Eintrag kann ein früherer Überlauf 0 verursachen. Mehrteilige Operationen können teilweise eingereiht bleiben; ein Rückgängigmachen erfolgt nicht. Selbst eine Länge von null kann wegen einer vorhandenen Meldung 0 liefern.
Bedingungen und Grenzen
FC zählt codierte Befehlsbytes in einem festen intrinsischen 128-Byte-Puffer. Ein Tile-Schreibbefehl braucht 4 Bytes, ein Fülleintrag 5 und eine Zeigerkopie 6 einschließlich Metadaten. NMI kann eine bereite Warteschlange verarbeiten; prüfen und befüllen Sie sie vor der Freigabe und koordinieren Sie Erzeuger und Verbraucher.
Dieser Aufruf benötigt 6 * ceil(len / 127) Befehlspuffer-Bytes für die vollständige Operation. Die Formel zählt codierte Einträge einschließlich Metadaten, nicht die übertragenen Nutzdaten. Prüfen Sie vor mehrteiligen Operationen den freien Platz.
Teilt len in Abschnitte von höchstens 127 Bytes; ceil bedeutet Aufrunden. len=0 fügt keinen Eintrag hinzu. Diese Teilung gehört zur Bibliotheksfunktion; das darunterliegende Intrinsic akzeptiert einen vorzeichenlosen 8-Bit-Zähler. Nach Überlauf folgen weitere Einfügeversuche, ohne frühere Einträge zurückzunehmen.
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
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.
Auf FC kennzeichnet Rot die beiden oberen Quadrate, die Kopie aus drei Mustern und das letzte VBlank-Quadrat. Blau kennzeichnet das Rechteck von 32 × 24 und die Kopie aus zwei Mustern. Grün kennzeichnet den Block aus 3 × 2 Kacheln und den Balken von 40 × 8. Der Hintergrund ist schwarz; Position und Farbe jedes gezeichneten Pixels werden geprüft.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\vram.c .\kitaq-docs\samples\api-examples\fc\vram_queue_shapes.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/vram.h:31
Split a byte transfer into copy records of at most 127 bytes. The runtime retains source pointers rather than copying payloads into the queue. Return the overflow latch state after all records have been attempted.
kitaqfc/lib/vram.c:70
u8 vram_queue_memcpy(u16 dst, const void* src, u16 len)
{
const u8* p;
u8 chunk;
p = (const u8*)src;
while (len != 0) {
if (len > 127) chunk = 127;
else chunk = (u8)len;
__vramq_copy(dst, p, chunk);
dst = (u16)(dst + chunk);
p = p + chunk;
len = (u16)(len - chunk);
}
return (u8)(__vramq_overflow() == 0);
}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
u8 vram_queue_memset(u16 dst, u8 value, u16 len);Parameter
dstPPU-Byteadresse (
0x0000–0x3FFF), kein CPU-Zeiger. Das Ziel muss beschreibbar sein: Musteränderungen benötigen CHR-RAM statt CHR-ROM. PPU-Adressabbildung und Spiegelung gelten weiterhin. Wählen Sie für fortlaufendes Kopieren und Füllen die Schrittweite 1 in PPUCTRL. Führen Sie Befehle zu einem sicheren PPU-Zeitpunkt aus und stellen Sie danach den Scrollzustand her; der Ausführer schreibt PPUADDR und PPUDATA, ohne Scrolleinstellungen wiederherzustellen.valueEin 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.
lenAnzahl 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 nach dem Versuch keine Überlaufmeldung gesetzt ist, andernfalls 0. Auch bei passendem aktuellem Eintrag kann ein früherer Überlauf 0 verursachen. Mehrteilige Operationen können teilweise eingereiht bleiben; ein Rückgängigmachen erfolgt nicht. Selbst eine Länge von null kann wegen einer vorhandenen Meldung 0 liefern.
Bedingungen und Grenzen
FC zählt codierte Befehlsbytes in einem festen intrinsischen 128-Byte-Puffer. Ein Tile-Schreibbefehl braucht 4 Bytes, ein Fülleintrag 5 und eine Zeigerkopie 6 einschließlich Metadaten. NMI kann eine bereite Warteschlange verarbeiten; prüfen und befüllen Sie sie vor der Freigabe und koordinieren Sie Erzeuger und Verbraucher.
Dieser Aufruf benötigt 5 * ceil(len / 127) Befehlspuffer-Bytes für die vollständige Operation. Die Formel zählt codierte Einträge einschließlich Metadaten, nicht die übertragenen Nutzdaten. Prüfen Sie vor mehrteiligen Operationen den freien Platz.
Teilt len in Abschnitte von höchstens 127 Bytes; ceil bedeutet Aufrunden. len=0 fügt keinen Eintrag hinzu. Diese Teilung gehört zur Bibliotheksfunktion; das darunterliegende Intrinsic akzeptiert einen vorzeichenlosen 8-Bit-Zähler. Nach Überlauf folgen weitere Einfügeversuche, ohne frühere Einträge zurückzunehmen.
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
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.
Auf FC kennzeichnet Rot die beiden oberen Quadrate, die Kopie aus drei Mustern und das letzte VBlank-Quadrat. Blau kennzeichnet das Rechteck von 32 × 24 und die Kopie aus zwei Mustern. Grün kennzeichnet den Block aus 3 × 2 Kacheln und den Balken von 40 × 8. Der Hintergrund ist schwarz; Position und Farbe jedes gezeichneten Pixels werden geprüft.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\vram.c .\kitaq-docs\samples\api-examples\fc\vram_queue_shapes.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/vram.h:36
Queue fills of at most 127 bytes each. Overflow can leave a partially queued transfer; no rollback is performed.
kitaqfc/lib/vram.c:94
u8 vram_queue_memset(u16 dst, u8 value, u16 len)
{
u8 chunk;
while (len != 0) {
if (len > 127) chunk = 127;
else chunk = (u8)len;
__vramq_fill(dst, value, chunk);
dst = (u16)(dst + chunk);
len = (u16)(len - chunk);
}
return (u8)(__vramq_overflow() == 0);
}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
u8 vram_queue_tile(u8 x, u8 y, u8 tile);Parameter
x, yLinke obere Position in 8×8-Tiles, nicht Pixeln. Es erfolgt kein Abschneiden. Halten Sie
x + w <= 32und auf GBy + h <= 32, im Tile-Bereich einer FC-Nametable<= 30ein. Ein einzelnes Tile hat Breite und Höhe 1.tileTile-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 nach dem Versuch keine Überlaufmeldung gesetzt ist, andernfalls 0. Auch bei passendem aktuellem Eintrag kann ein früherer Überlauf 0 verursachen. Mehrteilige Operationen können teilweise eingereiht bleiben; ein Rückgängigmachen erfolgt nicht. Selbst eine Länge von null kann wegen einer vorhandenen Meldung 0 liefern.
Bedingungen und Grenzen
FC zählt codierte Befehlsbytes in einem festen intrinsischen 128-Byte-Puffer. Ein Tile-Schreibbefehl braucht 4 Bytes, ein Fülleintrag 5 und eine Zeigerkopie 6 einschließlich Metadaten. NMI kann eine bereite Warteschlange verarbeiten; prüfen und befüllen Sie sie vor der Freigabe und koordinieren Sie Erzeuger und Verbraucher.
Dieser Aufruf benötigt 4 Befehlspuffer-Bytes für die vollständige Operation. Die Formel zählt codierte Einträge einschließlich Metadaten, nicht die übertragenen Nutzdaten. Prüfen Sie vor mehrteiligen Operationen den freien Platz.
Kachel- und Rechteckbefehle verwenden das zur Übersetzung festgelegte VRAM_NT_BASE, standardmäßig 0x2000. Blockübertragungen verwenden die angegebene Nametable-Basis (0x2000, 0x2400, 0x2800 oder 0x2C00); Nametable-Spiegelung gilt weiterhin. Adressen werden beim Einreihen mit 32 Bytes je Zeile berechnet. Bleiben Sie innerhalb von 32 × 30 Kacheln, um Attributbytes nicht zu überschreiben.
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
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.
Auf FC kennzeichnet Rot die beiden oberen Quadrate, die Kopie aus drei Mustern und das letzte VBlank-Quadrat. Blau kennzeichnet das Rechteck von 32 × 24 und die Kopie aus zwei Mustern. Grün kennzeichnet den Block aus 3 × 2 Kacheln und den Balken von 40 × 8. Der Hintergrund ist schwarz; Position und Farbe jedes gezeichneten Pixels werden geprüft.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\vram.c .\kitaq-docs\samples\api-examples\fc\vram_queue_shapes.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/vram.h:20
Alias the queued background-tile operation.
kitaqfc/lib/vram.c:32
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
u8 vram_queue_tiles(u16 dst, const void* src, u16 len);Parameter
dstPPU-Byteadresse (
0x0000–0x3FFF), kein CPU-Zeiger. Das Ziel muss beschreibbar sein: Musteränderungen benötigen CHR-RAM statt CHR-ROM. PPU-Adressabbildung und Spiegelung gelten weiterhin. Wählen Sie für fortlaufendes Kopieren und Füllen die Schrittweite 1 in PPUCTRL. Führen Sie Befehle zu einem sicheren PPU-Zeitpunkt aus und stellen Sie danach den Scrollzustand her; der Ausführer schreibt PPUADDR und PPUDATA, ohne Scrolleinstellungen wiederherzustellen.srcNahzeiger 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.
lenAnzahl 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 nach dem Versuch keine Überlaufmeldung gesetzt ist, andernfalls 0. Auch bei passendem aktuellem Eintrag kann ein früherer Überlauf 0 verursachen. Mehrteilige Operationen können teilweise eingereiht bleiben; ein Rückgängigmachen erfolgt nicht. Selbst eine Länge von null kann wegen einer vorhandenen Meldung 0 liefern.
Bedingungen und Grenzen
FC zählt codierte Befehlsbytes in einem festen intrinsischen 128-Byte-Puffer. Ein Tile-Schreibbefehl braucht 4 Bytes, ein Fülleintrag 5 und eine Zeigerkopie 6 einschließlich Metadaten. NMI kann eine bereite Warteschlange verarbeiten; prüfen und befüllen Sie sie vor der Freigabe und koordinieren Sie Erzeuger und Verbraucher.
Dieser Aufruf benötigt 6 * ceil(len / 127) Befehlspuffer-Bytes für die vollständige Operation. Die Formel zählt codierte Einträge einschließlich Metadaten, nicht die übertragenen Nutzdaten. Prüfen Sie vor mehrteiligen Operationen den freien Platz.
Teilt len in Abschnitte von höchstens 127 Bytes; ceil bedeutet Aufrunden. len=0 fügt keinen Eintrag hinzu. Diese Teilung gehört zur Bibliotheksfunktion; das darunterliegende Intrinsic akzeptiert einen vorzeichenlosen 8-Bit-Zähler. Nach Überlauf folgen weitere Einfügeversuche, ohne frühere Einträge zurückzunehmen.
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
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.
Auf FC kennzeichnet Rot die beiden oberen Quadrate, die Kopie aus drei Mustern und das letzte VBlank-Quadrat. Blau kennzeichnet das Rechteck von 32 × 24 und die Kopie aus zwei Mustern. Grün kennzeichnet den Block aus 3 × 2 Kacheln und den Balken von 40 × 8. Der Hintergrund ist schwarz; Position und Farbe jedes gezeichneten Pixels werden geprüft.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaqfc\lib\vram.c .\kitaq-docs\samples\api-examples\fc\vram_queue_shapes.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.nes --mapper=nrom --nes-chr=.\kitaq-docs\samples\api-examples\fc\vram_shapes.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/vram.h:33
Alias the byte-copy queue helper; len remains a byte count, not a tile count.
kitaqfc/lib/vram.c:87
u8 vram_queue_tiles(u16 dst, const void* src, u16 len)
{
return vram_queue_memcpy(dst, src, len);
}vrc6_sound.h — VRC6-Audioerweiterung
Verwenden Sie --mapper=vrc6 (Mapper 24) für diese Registerverdrahtung. Eine Cartridge ohne VRC6 kann diese Stimmen nicht erzeugen. Nur die unteren zwölf Periodenbits werden genutzt; die Hilfen konfigurieren das Frequenzsteuerregister $9003 nicht.
VRC6_PULSE_DUTY_12/25/50/75 bezeichnen 0x00/0x10/0x20/0x30. Die Suffixe sind keine gemessenen Tastgradprozentsätze. KUROSAKI modelliert Code d als (d+1)/16.
nes_vrc6_pulse1_off
Stoppt VRC6-Puls 1 durch Löschen des oberen Timer-/Aktivierungsregisters.
Syntax
void nes_vrc6_pulse1_off(void);Rückgabewert
Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.
Bedingungen und Grenzen
Verwenden Sie --mapper=vrc6 (Mapper 24) für diese Registerverdrahtung. Eine Cartridge ohne VRC6 kann diese Stimmen nicht erzeugen. Nur die unteren zwölf Periodenbits werden genutzt; die Hilfen konfigurieren das Frequenzsteuerregister $9003 nicht.
Anwendungsbeispiel
// Mapper 24: two pulse voices followed by the saw accumulator.
#include "fc_sound_example.h"
#include "vrc6_sound.c"
void main(void) {
// The background font occupies the first four 1 KiB CHR windows.
*((u8*)0xD000)=0; *((u8*)0xD001)=1;
*((u8*)0xD002)=2; *((u8*)0xD003)=3;
sound_begin("VRC6 PULSE PULSE SAW");
nes_vrc6_silence_all();
nes_vrc6_pulse1_set(0x7C,253);
sound_wait(45); nes_vrc6_pulse1_off(); sound_wait(15);
nes_vrc6_pulse2_set(0x3C,253);
sound_wait(45); nes_vrc6_pulse2_off(); sound_wait(15);
nes_vrc6_saw_set(32,289);
sound_wait(45); nes_vrc6_saw_off(); sound_wait(15);
nes_vrc6_silence_all();
sound_end();
}Erwartetes Ergebnis
Es folgen VRC6-Puls 1, Puls 2 mit anderem Tastgrad und Sägezahn, jeweils 45 Frames mit 15 Frames Pause. Alle drei liegen bei etwa 440 Hz und stoppen am Ende.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\sound_vrc6.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\fc-vrc6.nes --mapper=vrc6 --nes-chr=.\kitaq-docs\samples\font.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/vrc6_sound.h:22
Disable pulse 1 by clearing its high timer/enable register.
kitaqfc/lib/vrc6_sound.c:43
void nes_vrc6_pulse1_off(void)
{
VRC6_P1_HI = 0x00;
}nes_vrc6_pulse1_set
Schreibt VRC6-Puls-1-Steuerwert und 12-Bit-Timer und aktiviert die Stimme.
Syntax
void nes_vrc6_pulse1_set(u8 control, u16 period);Parameter
controlVRC6-Pulssteuerung: Bit 7 Gate, Bits 6..4 Tastgradcode, unteres Halbbyte Lautstärke 0..15.
period12-Bit-Timer 0..4095; obere Bits werden verworfen. Das Beispiel nutzt Puls 253 und Sägezahn 289.
Rückgabewert
Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.
Bedingungen und Grenzen
Verwenden Sie --mapper=vrc6 (Mapper 24) für diese Registerverdrahtung. Eine Cartridge ohne VRC6 kann diese Stimmen nicht erzeugen. Nur die unteren zwölf Periodenbits werden genutzt; die Hilfen konfigurieren das Frequenzsteuerregister $9003 nicht.
Anwendungsbeispiel
// Mapper 24: two pulse voices followed by the saw accumulator.
#include "fc_sound_example.h"
#include "vrc6_sound.c"
void main(void) {
// The background font occupies the first four 1 KiB CHR windows.
*((u8*)0xD000)=0; *((u8*)0xD001)=1;
*((u8*)0xD002)=2; *((u8*)0xD003)=3;
sound_begin("VRC6 PULSE PULSE SAW");
nes_vrc6_silence_all();
nes_vrc6_pulse1_set(0x7C,253);
sound_wait(45); nes_vrc6_pulse1_off(); sound_wait(15);
nes_vrc6_pulse2_set(0x3C,253);
sound_wait(45); nes_vrc6_pulse2_off(); sound_wait(15);
nes_vrc6_saw_set(32,289);
sound_wait(45); nes_vrc6_saw_off(); sound_wait(15);
nes_vrc6_silence_all();
sound_end();
}Erwartetes Ergebnis
Es folgen VRC6-Puls 1, Puls 2 mit anderem Tastgrad und Sägezahn, jeweils 45 Frames mit 15 Frames Pause. Alle drei liegen bei etwa 440 Hz und stoppen am Ende.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\sound_vrc6.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\fc-vrc6.nes --mapper=vrc6 --nes-chr=.\kitaq-docs\samples\font.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/vrc6_sound.h:18
Write pulse-1 control and the low 12 timer bits, then enable the channel.
kitaqfc/lib/vrc6_sound.c:27
void nes_vrc6_pulse1_set(u8 control, u16 period)
{
VRC6_P1_CTRL = control;
VRC6_P1_LO = (u8)period;
VRC6_P1_HI = (u8)(0x80 | ((period >> 8) & 0x0F));
}nes_vrc6_pulse2_off
Stoppt VRC6-Puls 2 durch Löschen des oberen Timer-/Aktivierungsregisters.
Syntax
void nes_vrc6_pulse2_off(void);Rückgabewert
Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.
Bedingungen und Grenzen
Verwenden Sie --mapper=vrc6 (Mapper 24) für diese Registerverdrahtung. Eine Cartridge ohne VRC6 kann diese Stimmen nicht erzeugen. Nur die unteren zwölf Periodenbits werden genutzt; die Hilfen konfigurieren das Frequenzsteuerregister $9003 nicht.
Anwendungsbeispiel
// Mapper 24: two pulse voices followed by the saw accumulator.
#include "fc_sound_example.h"
#include "vrc6_sound.c"
void main(void) {
// The background font occupies the first four 1 KiB CHR windows.
*((u8*)0xD000)=0; *((u8*)0xD001)=1;
*((u8*)0xD002)=2; *((u8*)0xD003)=3;
sound_begin("VRC6 PULSE PULSE SAW");
nes_vrc6_silence_all();
nes_vrc6_pulse1_set(0x7C,253);
sound_wait(45); nes_vrc6_pulse1_off(); sound_wait(15);
nes_vrc6_pulse2_set(0x3C,253);
sound_wait(45); nes_vrc6_pulse2_off(); sound_wait(15);
nes_vrc6_saw_set(32,289);
sound_wait(45); nes_vrc6_saw_off(); sound_wait(15);
nes_vrc6_silence_all();
sound_end();
}Erwartetes Ergebnis
Es folgen VRC6-Puls 1, Puls 2 mit anderem Tastgrad und Sägezahn, jeweils 45 Frames mit 15 Frames Pause. Alle drei liegen bei etwa 440 Hz und stoppen am Ende.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\sound_vrc6.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\fc-vrc6.nes --mapper=vrc6 --nes-chr=.\kitaq-docs\samples\font.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/vrc6_sound.h:24
Disable pulse 2 by clearing its high timer/enable register.
kitaqfc/lib/vrc6_sound.c:49
void nes_vrc6_pulse2_off(void)
{
VRC6_P2_HI = 0x00;
}nes_vrc6_pulse2_set
Schreibt VRC6-Puls-2-Steuerwert und 12-Bit-Timer und aktiviert die Stimme.
Syntax
void nes_vrc6_pulse2_set(u8 control, u16 period);Parameter
controlVRC6-Pulssteuerung: Bit 7 Gate, Bits 6..4 Tastgradcode, unteres Halbbyte Lautstärke 0..15.
period12-Bit-Timer 0..4095; obere Bits werden verworfen. Das Beispiel nutzt Puls 253 und Sägezahn 289.
Rückgabewert
Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.
Bedingungen und Grenzen
Verwenden Sie --mapper=vrc6 (Mapper 24) für diese Registerverdrahtung. Eine Cartridge ohne VRC6 kann diese Stimmen nicht erzeugen. Nur die unteren zwölf Periodenbits werden genutzt; die Hilfen konfigurieren das Frequenzsteuerregister $9003 nicht.
Anwendungsbeispiel
// Mapper 24: two pulse voices followed by the saw accumulator.
#include "fc_sound_example.h"
#include "vrc6_sound.c"
void main(void) {
// The background font occupies the first four 1 KiB CHR windows.
*((u8*)0xD000)=0; *((u8*)0xD001)=1;
*((u8*)0xD002)=2; *((u8*)0xD003)=3;
sound_begin("VRC6 PULSE PULSE SAW");
nes_vrc6_silence_all();
nes_vrc6_pulse1_set(0x7C,253);
sound_wait(45); nes_vrc6_pulse1_off(); sound_wait(15);
nes_vrc6_pulse2_set(0x3C,253);
sound_wait(45); nes_vrc6_pulse2_off(); sound_wait(15);
nes_vrc6_saw_set(32,289);
sound_wait(45); nes_vrc6_saw_off(); sound_wait(15);
nes_vrc6_silence_all();
sound_end();
}Erwartetes Ergebnis
Es folgen VRC6-Puls 1, Puls 2 mit anderem Tastgrad und Sägezahn, jeweils 45 Frames mit 15 Frames Pause. Alle drei liegen bei etwa 440 Hz und stoppen am Ende.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\sound_vrc6.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\fc-vrc6.nes --mapper=vrc6 --nes-chr=.\kitaq-docs\samples\font.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/vrc6_sound.h:20
Write pulse-2 control and the low 12 timer bits, then enable the channel.
kitaqfc/lib/vrc6_sound.c:35
void nes_vrc6_pulse2_set(u8 control, u16 period)
{
VRC6_P2_CTRL = control;
VRC6_P2_LO = (u8)period;
VRC6_P2_HI = (u8)(0x80 | ((period >> 8) & 0x0F));
}nes_vrc6_saw_off
Stoppt den VRC6-Sägezahn durch Löschen des oberen Timer-/Aktivierungsregisters.
Syntax
void nes_vrc6_saw_off(void);Rückgabewert
Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.
Bedingungen und Grenzen
Verwenden Sie --mapper=vrc6 (Mapper 24) für diese Registerverdrahtung. Eine Cartridge ohne VRC6 kann diese Stimmen nicht erzeugen. Nur die unteren zwölf Periodenbits werden genutzt; die Hilfen konfigurieren das Frequenzsteuerregister $9003 nicht.
Anwendungsbeispiel
// Mapper 24: two pulse voices followed by the saw accumulator.
#include "fc_sound_example.h"
#include "vrc6_sound.c"
void main(void) {
// The background font occupies the first four 1 KiB CHR windows.
*((u8*)0xD000)=0; *((u8*)0xD001)=1;
*((u8*)0xD002)=2; *((u8*)0xD003)=3;
sound_begin("VRC6 PULSE PULSE SAW");
nes_vrc6_silence_all();
nes_vrc6_pulse1_set(0x7C,253);
sound_wait(45); nes_vrc6_pulse1_off(); sound_wait(15);
nes_vrc6_pulse2_set(0x3C,253);
sound_wait(45); nes_vrc6_pulse2_off(); sound_wait(15);
nes_vrc6_saw_set(32,289);
sound_wait(45); nes_vrc6_saw_off(); sound_wait(15);
nes_vrc6_silence_all();
sound_end();
}Erwartetes Ergebnis
Es folgen VRC6-Puls 1, Puls 2 mit anderem Tastgrad und Sägezahn, jeweils 45 Frames mit 15 Frames Pause. Alle drei liegen bei etwa 440 Hz und stoppen am Ende.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\sound_vrc6.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\fc-vrc6.nes --mapper=vrc6 --nes-chr=.\kitaq-docs\samples\font.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/vrc6_sound.h:28
Disable the saw channel by clearing its high timer/enable register.
kitaqfc/lib/vrc6_sound.c:63
void nes_vrc6_saw_off(void)
{
VRC6_SAW_HI = 0x00;
}nes_vrc6_saw_set
Schreibt die 6-Bit-Akkumulatorrate und den 12-Bit-Timer des VRC6-Sägezahns und aktiviert ihn.
Syntax
void nes_vrc6_saw_set(u8 rate, u16 period);Parameter
rateSägezahn-Akkumulatorzuwachs 0..63; nur die unteren sechs Bits werden verwendet.
period12-Bit-Timer 0..4095; obere Bits werden verworfen. Das Beispiel nutzt Puls 253 und Sägezahn 289.
Rückgabewert
Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.
Bedingungen und Grenzen
Verwenden Sie --mapper=vrc6 (Mapper 24) für diese Registerverdrahtung. Eine Cartridge ohne VRC6 kann diese Stimmen nicht erzeugen. Nur die unteren zwölf Periodenbits werden genutzt; die Hilfen konfigurieren das Frequenzsteuerregister $9003 nicht.
Anwendungsbeispiel
// Mapper 24: two pulse voices followed by the saw accumulator.
#include "fc_sound_example.h"
#include "vrc6_sound.c"
void main(void) {
// The background font occupies the first four 1 KiB CHR windows.
*((u8*)0xD000)=0; *((u8*)0xD001)=1;
*((u8*)0xD002)=2; *((u8*)0xD003)=3;
sound_begin("VRC6 PULSE PULSE SAW");
nes_vrc6_silence_all();
nes_vrc6_pulse1_set(0x7C,253);
sound_wait(45); nes_vrc6_pulse1_off(); sound_wait(15);
nes_vrc6_pulse2_set(0x3C,253);
sound_wait(45); nes_vrc6_pulse2_off(); sound_wait(15);
nes_vrc6_saw_set(32,289);
sound_wait(45); nes_vrc6_saw_off(); sound_wait(15);
nes_vrc6_silence_all();
sound_end();
}Erwartetes Ergebnis
Es folgen VRC6-Puls 1, Puls 2 mit anderem Tastgrad und Sägezahn, jeweils 45 Frames mit 15 Frames Pause. Alle drei liegen bei etwa 440 Hz und stoppen am Ende.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\sound_vrc6.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\fc-vrc6.nes --mapper=vrc6 --nes-chr=.\kitaq-docs\samples\font.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/vrc6_sound.h:26
Mask the saw accumulation rate to six bits, load a 12-bit timer and enable output.
kitaqfc/lib/vrc6_sound.c:55
void nes_vrc6_saw_set(u8 rate, u16 period)
{
VRC6_SAW_RATE = (u8)(rate & 0x3F);
VRC6_SAW_LO = (u8)period;
VRC6_SAW_HI = (u8)(0x80 | ((period >> 8) & 0x0F));
}nes_vrc6_silence_all
Deaktiviert alle drei VRC6-Stimmen und löscht Pulssteuerwerte sowie Sägezahnrate.
Syntax
void nes_vrc6_silence_all(void);Rückgabewert
Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.
Bedingungen und Grenzen
Verwenden Sie --mapper=vrc6 (Mapper 24) für diese Registerverdrahtung. Eine Cartridge ohne VRC6 kann diese Stimmen nicht erzeugen. Nur die unteren zwölf Periodenbits werden genutzt; die Hilfen konfigurieren das Frequenzsteuerregister $9003 nicht.
Anwendungsbeispiel
// Mapper 24: two pulse voices followed by the saw accumulator.
#include "fc_sound_example.h"
#include "vrc6_sound.c"
void main(void) {
// The background font occupies the first four 1 KiB CHR windows.
*((u8*)0xD000)=0; *((u8*)0xD001)=1;
*((u8*)0xD002)=2; *((u8*)0xD003)=3;
sound_begin("VRC6 PULSE PULSE SAW");
nes_vrc6_silence_all();
nes_vrc6_pulse1_set(0x7C,253);
sound_wait(45); nes_vrc6_pulse1_off(); sound_wait(15);
nes_vrc6_pulse2_set(0x3C,253);
sound_wait(45); nes_vrc6_pulse2_off(); sound_wait(15);
nes_vrc6_saw_set(32,289);
sound_wait(45); nes_vrc6_saw_off(); sound_wait(15);
nes_vrc6_silence_all();
sound_end();
}Erwartetes Ergebnis
Es folgen VRC6-Puls 1, Puls 2 mit anderem Tastgrad und Sägezahn, jeweils 45 Frames mit 15 Frames Pause. Alle drei liegen bei etwa 440 Hz und stoppen am Ende.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\sound_vrc6.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\fc-vrc6.nes --mapper=vrc6 --nes-chr=.\kitaq-docs\samples\font.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/vrc6_sound.h:16
Clear channel-enable/high-timer registers and output controls for all VRC6 voices. Requires the VRC6 register layout used by this module. No mapper setup or global frequency-control write is included.
kitaqfc/lib/vrc6_sound.c:16
void nes_vrc6_silence_all(void)
{
VRC6_P1_HI = 0x00;
VRC6_P2_HI = 0x00;
VRC6_SAW_HI = 0x00;
VRC6_P1_CTRL = 0x00;
VRC6_P2_CTRL = 0x00;
VRC6_SAW_RATE = 0x00;
}vrc7_sound.h — VRC7-FM-Audio
Für --mapper=vrc7 (Mapper 85). Schützen Sie Registerauswahl-/Datenpaare gegen dazwischenliegende Interruptschreibzugriffe. Die Hilfen fügen keine Einschwingverzögerung ein. Aufnahmen erfassen KUROSAKIs FM-Modell und bestätigen weder Hardwareklangfarbe noch reales Schreibtiming.
nes_vrc7_channel_set
Konfiguriert Frequenz, Block, Key-Flags, Instrument und Dämpfung einer FM-Stimme.
Syntax
void nes_vrc7_channel_set(u8 channel, u8 instrument, u8 volume, u16 fnum, u8 block, u8 key_flags);Parameter
channelVRC7-Kanal 0..5; größere Werte bewirken nichts.
instrumentInstrument 0..15: 0=Benutzerklang, 1..15=Vorgaben. Nur das untere Halbbyte wird genutzt.
volumeVRC7-Dämpfung 0..15: 0 ist am lautesten, 15 die stärkste Dämpfung. Nur das untere Halbbyte wird genutzt.
fnumFrequenzzahl 0..511, die zusammen mit block die Tonhöhe bestimmt. Nur neun Bits werden genutzt.
blockOktavblock 0..7; nur die unteren drei Bits werden genutzt.
key_flags0x10 Key-on, 0x20 Sustain-Flag; andere Bits werden verworfen.
Rückgabewert
Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.
Bedingungen und Grenzen
Für --mapper=vrc7 (Mapper 85). Schützen Sie Registerauswahl-/Datenpaare gegen dazwischenliegende Interruptschreibzugriffe. Die Hilfen fügen keine Einschwingverzögerung ein. Aufnahmen erfassen KUROSAKIs FM-Modell und bestätigen weder Hardwareklangfarbe noch reales Schreibtiming.
Instrument 0 wird von allen Stimmen geteilt. channel_set schreibt Key/obere Frequenz vor Instrument/Dämpfung. Nach key_off muss die nächste Note auch obere Frequenz und Block wiederherstellen.
Anwendungsbeispiel
// Mapper 85: an FM preset followed by a simple original user instrument.
#include "fc_sound_example.h"
#include "vrc7_sound.c"
__prg_rom u8 patch[8]={0x21,0x21,0x3F,0x00,0xF0,0xF0,0x0F,0x0F};
void main(void) {
// Map the supplied 8 KiB font as eight consecutive 1 KiB CHR windows.
*((u8*)0xA000)=0; *((u8*)0xA010)=1;
*((u8*)0xB000)=2; *((u8*)0xB010)=3;
*((u8*)0xC000)=4; *((u8*)0xC010)=5;
*((u8*)0xD000)=6; *((u8*)0xD010)=7;
sound_begin("VRC7 PRESET AND PATCH");
nes_vrc7_silence_all();
nes_vrc7_channel_set(0,1,3,290,4,VRC7_KEY_ON);
sound_wait(60); nes_vrc7_key_off(0); sound_wait(30);
nes_vrc7_set_user_patch(patch);
nes_vrc7_channel_set(0,0,3,290,4,VRC7_KEY_ON);
sound_wait(60);
// Raw register 30 selects instrument zero and maximum attenuation.
nes_vrc7_write(0x30,0x0F);
nes_vrc7_key_off(0);
nes_vrc7_silence_all(); sound_wait(30);
sound_end();
}Erwartetes Ergebnis
Vergleichen Sie Vorgabeinstrument 1 mit einem eigenen anhaltenden Benutzerinstrument 0, jeweils 60 Frames auf gleicher Tonhöhe. Die Folge endet mit Key-off und maximaler Dämpfung.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\sound_vrc7.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\fc-vrc7.nes --mapper=vrc7 --nes-chr=.\kitaq-docs\samples\font.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/vrc7_sound.h:18
Validate channel 0..5, then pack a 9-bit frequency, 3-bit block, key flags, instrument and volume nibbles into its registers. Volume is the raw hardware attenuation field, not a linear loudness value.
kitaqfc/lib/vrc7_sound.c:32
void nes_vrc7_channel_set(u8 channel, u8 instrument, u8 volume, u16 fnum, u8 block, u8 key_flags)
{
u8 reg;
u8 hi;
if (channel >= 6) return;
reg = channel;
hi = (u8)(((fnum >> 8) & 0x01) | ((block & 0x07) << 1) | (key_flags & 0x30));
nes_vrc7_write((u8)(0x10 + reg), (u8)fnum);
// Key/frequency-high is written before instrument/attenuation; this sequence is not an atomic note update.
nes_vrc7_write((u8)(0x20 + reg), hi);
nes_vrc7_write((u8)(0x30 + reg), (u8)(((instrument & 0x0F) << 4) | (volume & 0x0F)));
}nes_vrc7_key_off
Löscht das gesamte obere Frequenz-/Block-/Key-Register der gewählten Stimme.
Syntax
void nes_vrc7_key_off(u8 channel);Parameter
channelVRC7-Kanal 0..5; größere Werte bewirken nichts.
Rückgabewert
Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.
Bedingungen und Grenzen
Für --mapper=vrc7 (Mapper 85). Schützen Sie Registerauswahl-/Datenpaare gegen dazwischenliegende Interruptschreibzugriffe. Die Hilfen fügen keine Einschwingverzögerung ein. Aufnahmen erfassen KUROSAKIs FM-Modell und bestätigen weder Hardwareklangfarbe noch reales Schreibtiming.
Instrument 0 wird von allen Stimmen geteilt. channel_set schreibt Key/obere Frequenz vor Instrument/Dämpfung. Nach key_off muss die nächste Note auch obere Frequenz und Block wiederherstellen.
Anwendungsbeispiel
// Mapper 85: an FM preset followed by a simple original user instrument.
#include "fc_sound_example.h"
#include "vrc7_sound.c"
__prg_rom u8 patch[8]={0x21,0x21,0x3F,0x00,0xF0,0xF0,0x0F,0x0F};
void main(void) {
// Map the supplied 8 KiB font as eight consecutive 1 KiB CHR windows.
*((u8*)0xA000)=0; *((u8*)0xA010)=1;
*((u8*)0xB000)=2; *((u8*)0xB010)=3;
*((u8*)0xC000)=4; *((u8*)0xC010)=5;
*((u8*)0xD000)=6; *((u8*)0xD010)=7;
sound_begin("VRC7 PRESET AND PATCH");
nes_vrc7_silence_all();
nes_vrc7_channel_set(0,1,3,290,4,VRC7_KEY_ON);
sound_wait(60); nes_vrc7_key_off(0); sound_wait(30);
nes_vrc7_set_user_patch(patch);
nes_vrc7_channel_set(0,0,3,290,4,VRC7_KEY_ON);
sound_wait(60);
// Raw register 30 selects instrument zero and maximum attenuation.
nes_vrc7_write(0x30,0x0F);
nes_vrc7_key_off(0);
nes_vrc7_silence_all(); sound_wait(30);
sound_end();
}Erwartetes Ergebnis
Vergleichen Sie Vorgabeinstrument 1 mit einem eigenen anhaltenden Benutzerinstrument 0, jeweils 60 Frames auf gleicher Tonhöhe. Die Folge endet mit Key-off und maximaler Dämpfung.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\sound_vrc7.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\fc-vrc7.nes --mapper=vrc7 --nes-chr=.\kitaq-docs\samples\font.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/vrc7_sound.h:21
Clear the channel's entire frequency-high/block/key register, not just the key-on bit. A later note must restore frequency and block settings.
kitaqfc/lib/vrc7_sound.c:47
void nes_vrc7_key_off(u8 channel)
{
if (channel >= 6) return;
nes_vrc7_write((u8)(0x20 + channel), 0x00);
}nes_vrc7_set_user_patch
Schreibt acht Bytes der Reihe nach in die VRC7-Benutzerinstrumentregister.
Syntax
void nes_vrc7_set_user_patch(const u8* patch8);Parameter
patch8Acht Bytes zur Definition von Instrument 0. NULL wird nicht geprüft. Halten Sie die Quellbank während des Aufrufs eingeblendet.
Rückgabewert
Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.
Bedingungen und Grenzen
Für --mapper=vrc7 (Mapper 85). Schützen Sie Registerauswahl-/Datenpaare gegen dazwischenliegende Interruptschreibzugriffe. Die Hilfen fügen keine Einschwingverzögerung ein. Aufnahmen erfassen KUROSAKIs FM-Modell und bestätigen weder Hardwareklangfarbe noch reales Schreibtiming.
Instrument 0 wird von allen Stimmen geteilt. channel_set schreibt Key/obere Frequenz vor Instrument/Dämpfung. Nach key_off muss die nächste Note auch obere Frequenz und Block wiederherstellen.
Anwendungsbeispiel
// Mapper 85: an FM preset followed by a simple original user instrument.
#include "fc_sound_example.h"
#include "vrc7_sound.c"
__prg_rom u8 patch[8]={0x21,0x21,0x3F,0x00,0xF0,0xF0,0x0F,0x0F};
void main(void) {
// Map the supplied 8 KiB font as eight consecutive 1 KiB CHR windows.
*((u8*)0xA000)=0; *((u8*)0xA010)=1;
*((u8*)0xB000)=2; *((u8*)0xB010)=3;
*((u8*)0xC000)=4; *((u8*)0xC010)=5;
*((u8*)0xD000)=6; *((u8*)0xD010)=7;
sound_begin("VRC7 PRESET AND PATCH");
nes_vrc7_silence_all();
nes_vrc7_channel_set(0,1,3,290,4,VRC7_KEY_ON);
sound_wait(60); nes_vrc7_key_off(0); sound_wait(30);
nes_vrc7_set_user_patch(patch);
nes_vrc7_channel_set(0,0,3,290,4,VRC7_KEY_ON);
sound_wait(60);
// Raw register 30 selects instrument zero and maximum attenuation.
nes_vrc7_write(0x30,0x0F);
nes_vrc7_key_off(0);
nes_vrc7_silence_all(); sound_wait(30);
sound_end();
}Erwartetes Ergebnis
Vergleichen Sie Vorgabeinstrument 1 mit einem eigenen anhaltenden Benutzerinstrument 0, jeweils 60 Frames auf gleicher Tonhöhe. Die Folge endet mit Key-off und maximaler Dämpfung.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\sound_vrc7.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\fc-vrc7.nes --mapper=vrc7 --nes-chr=.\kitaq-docs\samples\font.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/vrc7_sound.h:14
Copy eight caller-supplied patch bytes into user-instrument registers 0..7.
kitaqfc/lib/vrc7_sound.c:16
void nes_vrc7_set_user_patch(const u8* patch8)
{
const u8* p;
u8 i;
p = patch8;
i = 0;
while (i < 8) {
nes_vrc7_write(i, *p);
p = p + 1;
i = (u8)(i + 1);
}
}nes_vrc7_silence_all
Schaltet alle sechs Stimmen per Key-off aus und wählt Instrument 0 mit maximaler Dämpfung.
Syntax
void nes_vrc7_silence_all(void);Rückgabewert
Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.
Bedingungen und Grenzen
Für --mapper=vrc7 (Mapper 85). Schützen Sie Registerauswahl-/Datenpaare gegen dazwischenliegende Interruptschreibzugriffe. Die Hilfen fügen keine Einschwingverzögerung ein. Aufnahmen erfassen KUROSAKIs FM-Modell und bestätigen weder Hardwareklangfarbe noch reales Schreibtiming.
Instrument 0 wird von allen Stimmen geteilt. channel_set schreibt Key/obere Frequenz vor Instrument/Dämpfung. Nach key_off muss die nächste Note auch obere Frequenz und Block wiederherstellen.
Anwendungsbeispiel
// Mapper 85: an FM preset followed by a simple original user instrument.
#include "fc_sound_example.h"
#include "vrc7_sound.c"
__prg_rom u8 patch[8]={0x21,0x21,0x3F,0x00,0xF0,0xF0,0x0F,0x0F};
void main(void) {
// Map the supplied 8 KiB font as eight consecutive 1 KiB CHR windows.
*((u8*)0xA000)=0; *((u8*)0xA010)=1;
*((u8*)0xB000)=2; *((u8*)0xB010)=3;
*((u8*)0xC000)=4; *((u8*)0xC010)=5;
*((u8*)0xD000)=6; *((u8*)0xD010)=7;
sound_begin("VRC7 PRESET AND PATCH");
nes_vrc7_silence_all();
nes_vrc7_channel_set(0,1,3,290,4,VRC7_KEY_ON);
sound_wait(60); nes_vrc7_key_off(0); sound_wait(30);
nes_vrc7_set_user_patch(patch);
nes_vrc7_channel_set(0,0,3,290,4,VRC7_KEY_ON);
sound_wait(60);
// Raw register 30 selects instrument zero and maximum attenuation.
nes_vrc7_write(0x30,0x0F);
nes_vrc7_key_off(0);
nes_vrc7_silence_all(); sound_wait(30);
sound_end();
}Erwartetes Ergebnis
Vergleichen Sie Vorgabeinstrument 1 mit einem eigenen anhaltenden Benutzerinstrument 0, jeweils 60 Frames auf gleicher Tonhöhe. Die Folge endet mit Key-off und maximaler Dämpfung.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\sound_vrc7.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\fc-vrc7.nes --mapper=vrc7 --nes-chr=.\kitaq-docs\samples\font.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/vrc7_sound.h:23
Key off all six voices and set instrument zero with maximum attenuation.
kitaqfc/lib/vrc7_sound.c:54
void nes_vrc7_silence_all(void)
{
u8 i;
i = 0;
while (i < 6) {
nes_vrc7_key_off(i);
nes_vrc7_write((u8)(0x30 + i), 0x0F);
i = (u8)(i + 1);
}
}nes_vrc7_write
Schreibt die Registernummer in den VRC7-Auswahlport, dann den Wert in den Datenport.
Syntax
void nes_vrc7_write(u8 reg, u8 value);Parameter
regVRC7-Registernummer. Für Kanal 0: 0x10 untere Frequenzbits, 0x20 obere Bits/Block/Key, 0x30 Instrument/Dämpfung.
valueIn das gewählte VRC7-Register zu schreibendes Byte.
Rückgabewert
Kein Rückgabewert. Ändert Audioregister oder Treiberzustand.
Bedingungen und Grenzen
Für --mapper=vrc7 (Mapper 85). Schützen Sie Registerauswahl-/Datenpaare gegen dazwischenliegende Interruptschreibzugriffe. Die Hilfen fügen keine Einschwingverzögerung ein. Aufnahmen erfassen KUROSAKIs FM-Modell und bestätigen weder Hardwareklangfarbe noch reales Schreibtiming.
Instrument 0 wird von allen Stimmen geteilt. channel_set schreibt Key/obere Frequenz vor Instrument/Dämpfung. Nach key_off muss die nächste Note auch obere Frequenz und Block wiederherstellen.
Anwendungsbeispiel
// Mapper 85: an FM preset followed by a simple original user instrument.
#include "fc_sound_example.h"
#include "vrc7_sound.c"
__prg_rom u8 patch[8]={0x21,0x21,0x3F,0x00,0xF0,0xF0,0x0F,0x0F};
void main(void) {
// Map the supplied 8 KiB font as eight consecutive 1 KiB CHR windows.
*((u8*)0xA000)=0; *((u8*)0xA010)=1;
*((u8*)0xB000)=2; *((u8*)0xB010)=3;
*((u8*)0xC000)=4; *((u8*)0xC010)=5;
*((u8*)0xD000)=6; *((u8*)0xD010)=7;
sound_begin("VRC7 PRESET AND PATCH");
nes_vrc7_silence_all();
nes_vrc7_channel_set(0,1,3,290,4,VRC7_KEY_ON);
sound_wait(60); nes_vrc7_key_off(0); sound_wait(30);
nes_vrc7_set_user_patch(patch);
nes_vrc7_channel_set(0,0,3,290,4,VRC7_KEY_ON);
sound_wait(60);
// Raw register 30 selects instrument zero and maximum attenuation.
nes_vrc7_write(0x30,0x0F);
nes_vrc7_key_off(0);
nes_vrc7_silence_all(); sound_wait(30);
sound_end();
}Erwartetes Ergebnis
Vergleichen Sie Vorgabeinstrument 1 mit einem eigenen anhaltenden Benutzerinstrument 0, jeweils 60 Frames auf gleicher Tonhöhe. Die Folge endet mit Key-off und maximaler Dämpfung.

Vollständiges Beispielprogramm
Build-Befehl
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqfc\kitaqfc.exe .\kitaq-docs\samples\api-examples\fc\sound_vrc7.c -I .\kitaqfc\lib -I .\kitaq-docs\samples -o .\out\fc-vrc7.nes --mapper=vrc7 --nes-chr=.\kitaq-docs\samples\font.chr --no-cache --no-disasmImplementierung und Quelltext
kitaqfc/lib/vrc7_sound.h:12
Write register selection followed immediately by data. No explicit device settling delay or cartridge detection is inserted by this wrapper. The caller must arrange device timing and serialize register/data pairs against interrupt writers.
kitaqfc/lib/vrc7_sound.c:8
void nes_vrc7_write(u8 reg, u8 value)
{
VRC7_ADDR = reg;
VRC7_DATA = value;
}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.
actor.h — Arrays für Spielakteure
/*
* Optional declarations for the phase 11 actor helper.
*/
// Callers initialize size and metadata and pass non-null actors.
// attr/flags are retained fields; this helper does not interpret or apply them.
struct NesActor {
unsigned short world_x;
unsigned short world_y;
unsigned char width;
unsigned char height;
unsigned char screen_x;
unsigned char screen_y;
unsigned char attr;
unsigned char flags;
};
// Set the actor's 16-bit world position without updating cached screen coordinates.
void nes_actor_set_world(struct NesActor* actor, unsigned short x, unsigned short y);
// Subtract the camera and retain only the low coordinate bytes. This performs
// wrapping projection, not clipping; callers must hide actors outside the viewport.
void nes_actor_update_screen(struct NesActor* actor, unsigned short camera_x, unsigned short camera_y);
// Draw the byte-stream metasprite at cached screen coordinates and return its
// next OAM index. Actor attr/flags are not applied by this wrapper.
unsigned char nes_actor_draw_metasprite(struct NesActor* actor, unsigned char oam_index, unsigned char* metasprite);
// Test overlap in world coordinates with exclusive right/bottom edges. Keep
// position-plus-size sums within u16; touching edges are not collisions.
// Require positive widths and heights; zero extents are not rejected before the edge tests.
unsigned char nes_actor_collide(struct NesActor* a, struct NesActor* b);kitaqfc/lib/actor.h
asset.h — Ressourcen-IDs und Datenbeschreibungen
#ifndef ASSET_H
#define ASSET_H
#include "core.h"
#include "bank.h"
#define ASSET_TYPE_RAW ((u8)0)
#define ASSET_TYPE_TILES ((u8)1)
#define ASSET_TYPE_MAP ((u8)2)
#define ASSET_TYPE_SONG ((u8)3)
// The descriptor table bank and each payload bank are independent.
// ptr is a CPU-visible address and len counts bytes; type is a tag, not a decoder selection.
typedef __packed struct AssetDesc {
u8 type;
u8 bank;
const u8* ptr;
u16 len;
} AssetDesc;
// Retain a bank-qualified descriptor table; the caller keeps its storage valid.
void asset_set_table(u8 bank, const AssetDesc* table, u8 count);
// Copy a descriptor from its ROM bank into caller storage. Null output or an
// out-of-range ID returns zero without reading the table.
u8 asset_get(u8 asset_id, AssetDesc* out_desc);
// Copy the smaller of the asset length and max_len using a bank-aware transfer.
// Return one for a valid ID even when the payload is truncated.
u8 asset_load_raw(u8 asset_id, void* dst, u16 max_len);
// Switch to the asset bank, upload tile/raw data in chunks of at most 128 bytes,
// then restore the bank recorded by this library. The caller supplies safe PPU timing.
u8 asset_load_tiles(u8 asset_id, u16 vram_dst);
// Return the asset bank or zero on lookup failure; bank zero may also be valid.
u8 asset_get_bank(u8 asset_id);
// Return the stored address without switching banks. Pair it with the descriptor
// bank before reading banked ROM; a failed lookup returns null.
const u8* asset_get_ptr(u8 asset_id);
// Return the descriptor byte length, or zero for an invalid ID.
u16 asset_get_len(u8 asset_id);
#endifkitaqfc/lib/asset.h
attribute.h — Nametable-Attribute
/*
* KITAQFC phase15 attribute patch helpers.
*/
// Copy 64 already-packed attribute bytes into shadow storage. This does not
// convert one palette ID per tile into NES attribute bitfields.
// The source must expose all 64 packed bytes and stay readable for the duration of this copy.
void nes_attr_shadow_build_from_palette_map(unsigned char* src64);
// Apply a palette to every two-by-two tile quadrant touched by the rectangle.
// Empty or out-of-range rectangles leave the shadow unchanged.
void nes_attr_shadow_fill_rect(unsigned char tile_x, unsigned char tile_y, unsigned char width, unsigned char height, unsigned char pal_index);
// Queue the attribute bytes covering a tile rectangle within 32x30 tiles.
// Empty rectangles succeed; invalid bounds fail without queuing.
// Capacity failure may leave earlier rows queued.
unsigned char nes_attr_queue_rect(unsigned short nt_base, unsigned char tile_x, unsigned char tile_y, unsigned char width, unsigned char height);kitaqfc/lib/attribute.h
audio.h — Musik, Soundeffekte und Audiosteuerung
#ifndef AUDIO_H
#define AUDIO_H
#include "core.h"
// Channel bits form a complete replacement mask for nes_apu_channel_enable.
#define NES_APU_ENABLE_PULSE1 0x01
#define NES_APU_ENABLE_PULSE2 0x02
#define NES_APU_ENABLE_TRIANGLE 0x04
#define NES_APU_ENABLE_NOISE 0x08
#define NES_APU_ENABLE_DMC 0x10
// Disable frame IRQs, enable the four tonal/noise channels and install quiet
// control defaults. DMC remains disabled.
void nes_apu_init(void);
// Replace all five channel-enable bits in APU_STATUS; this is not an additive enable.
void nes_apu_channel_enable(u8 mask);
// Disable every channel and clear volume/DMC output settings used by this helper.
void nes_apu_silence_all(void);
// Enable only pulse 1, disable its sweep and load control, 11-bit timer and
// length-table index. Starting this effect disables the other APU channels.
void nes_sfx_square1(u8 duty_volume, u16 period, u8 length_index);
// Enable only pulse 2 and load its control/timer/length fields, disabling other channels.
void nes_sfx_square2(u8 duty_volume, u16 period, u8 length_index);
// Enable only triangle and load linear-counter, timer and length fields.
void nes_sfx_triangle(u8 linear, u16 period, u8 length_index);
// Enable only noise and load envelope/control, period/mode and length fields.
void nes_sfx_noise(u8 volume, u8 period_mode, u8 length_index);
// Trigger the predefined pulse-1 tick effect; it inherits the exclusive-channel behavior.
void nes_sfx_tick_blip(void);
// Trigger the predefined pulse-1 movement effect.
void nes_sfx_move_blip(void);
// Convert a CPU sample address and byte length to DMC register units. Supply
// an address in 0xC000-0xFFC0 aligned to 64 bytes and a representable length
// 16*n+1 in 1..4081; inputs are narrowed without validation or bank management.
void nes_dmc_config(u8 flags_rate, u8 output_level, u16 sample_addr, u16 sample_len);
// Enable DMC together with all four other channels by replacing the status mask.
void nes_dmc_start(void);
// Disable DMC while leaving all four other channel-enable bits set.
void nes_dmc_stop(void);
// Install sample parameters, then start DMC using the full-channel enable mask.
void nes_dmc_play(u8 flags_rate, u8 output_level, u16 sample_addr, u16 sample_len);
#endifkitaqfc/lib/audio.h
audio_vblank.h — Musikwiedergabe im VBlank-Interrupt
#ifndef NES_AUDIO_VBLANK_H
#define NES_AUDIO_VBLANK_H
#include "core.h"
// Original MIT-licensed NMI sequencer. Channel order follows the physical APU:
// CH1 pulse 1, CH2 pulse 2, CH3 triangle, CH4 noise (indices 0, 1, 2, 3).
// Every record is five bytes: delay, CH1, CH2, CH3, CH4.
// Delay 1..255 holds the new state for that many NMI ticks. Delay 0 ends playback.
// Tonal notes 0..71 are C2..B7, tuned for NTSC. Noise 0..15 selects a long-mode
// period; 16..31 selects short mode. HOLD preserves a channel; STOP silences it.
#define NES_AUDIO_NOISE_ENVELOPE 128
#define NES_AUDIO_HOLD 255
#define NES_AUDIO_STOP 254
#define NES_AUDIO_RECORD_BYTES 5
#define NES_AUDIO_QUEUE_CAPACITY 7
// Reset the queue, feeder and diagnostic counters; silence and initialize the
// APU. Owns the four basic channels and disables DMC and APU frame IRQs.
void nes_audio_vblank_init(void);
// Copy one complete validated record to RAM and publish it atomically last.
// Return 1 on success, 0 for null/invalid/full. Call from one foreground producer.
u8 nes_audio_vblank_enqueue(const u8* record);
// Return queued records (0..7), excluding the record whose delay is in progress.
u8 nes_audio_vblank_queued(void);
// Return available record slots (0..7), not bytes.
u8 nes_audio_vblank_free(void);
// Enable consumption at the next NMI. Does not enable PPU NMI itself.
void nes_audio_vblank_start(void);
// Disable consumption, silence, discard queued records and clear the feeder.
void nes_audio_vblank_stop(void);
// Stop and attach a readable five-byte-record stream; return 0 for null, zero
// count or a count above 13107. Nonzero loop repeats the stream. Does not start.
u8 nes_audio_vblank_set_music(const u8* records,u16 count,u8 loop);
// Copy at most seven records from the attached stream. Return copies accepted.
// A one-shot feeder appends a delay-zero terminator after the last timed record.
// Keep the stream's ROM bank mapped during this foreground call only.
u8 nes_audio_vblank_refill(void);
// Set the stream, prefill the queue and start. Return 0 for invalid setup/data.
u8 nes_audio_vblank_play_music(const u8* records,u16 count,u8 loop);
// Return 1 while the BGM consumer is enabled, including a recoverable queue underrun.
u8 nes_audio_vblank_is_playing(void);
// Saturating count of starvation episodes, cleared by init; END is not starvation.
u8 nes_audio_vblank_underruns(void);
// Configure the next note: pulse bits 7..6 select duty and 3..0 select volume;
// noise uses volume 3..0, or NES_AUDIO_NOISE_ENVELOPE | decay_period (0..15)
// for a one-shot hardware envelope (larger periods decay more slowly). The
// next noise note starts at volume 15; its length permits a full decay.
// Triangle uses zero for silent, nonzero for full level.
// Return 0 for channel >=4. Hardware has no triangle volume control.
u8 nes_audio_vblank_set_timbre(u8 channel,u8 control);
// Any nonzero argument freezes both timelines and mutes immediately. Zero
// resumes from the stored delays and restores held notes on the next NMI.
// BGM is_playing remains enabled during pause. Refill may still fill the queue.
void nes_audio_vblank_pause(u8 on);
// Copy 1..7 timed records. Bits 0..3 select channels temporarily owned by SFX.
// BGM continues underneath and its current notes return when the effect ends.
// Return 1 after copying; 0 for null, invalid count/data or an empty low mask.
// Ignore mask bits 4..7. All fields are validated, even unselected channels.
// Delay zero is not accepted for SFX. Invalid input preserves the current SFX.
// Replacement restarts the effect; the first HOLD starts from a stopped note.
// The source need only stay mapped/readable until this foreground call returns.
u8 nes_audio_vblank_play_sfx(const u8* records,u8 count,u8 mask);
// Release effect ownership at the next NMI, restoring current BGM notes.
// This does not stop or restart the BGM and does not write the APU immediately.
void nes_audio_vblank_stop_sfx(void);
// NMI hook: invoke exactly once per NMI. With a custom handler or a compiler
// without automatic audio-hook linking, call it there. Never call from main
// or call it again if the compiler already inserts the hook.
// Saves A/X/Y, uses no compiler scratch bytes and reads only RAM/fixed ROM.
void __nes_audio_vblank_tick(void);
#endifkitaqfc/lib/audio_vblank.h
bank.h — Bankabhängiger Zugriff auf Code und Daten
#ifndef BANK_H
#define BANK_H
#include "core.h"
#include "intrinsics.h"
// Pair a bank selector with its CPU-window address; a near pointer alone cannot select the bank.
typedef __packed struct BankPtr {
u8 bank;
const u8* ptr;
} BankPtr;
extern u8 kq_bank_current;
// Record the bank in the library shadow and invoke the mapper-aware compiler intrinsic.
void bank_switch(u8 bank);
// Read this wrapper's bank shadow; arbitrary mapper writes do not update it.
u8 bank_get_current(void);
// Read one byte from an explicit ROM bank and 16-bit CPU address.
u8 far_data_read8(u8 bank, const void* addr);
// Read a 16-bit value through the bank-aware compiler intrinsic.
u16 far_data_read16(u8 bank, const void* addr);
// Copy len bytes from banked ROM to caller-owned writable storage.
void far_data_read(u8 bank, const void* addr, void* dst, u16 len);
// Store a bank/address pair without reading memory; null output is ignored.
void farptr_make(BankPtr* out, u8 bank, const u8* ptr);
// Read one byte using both the bank and address of the supplied far pointer.
u8 farptr_read8(BankPtr ptr);
// Read a 16-bit value using both components of the far pointer.
u16 farptr_read16(BankPtr ptr);
// Copy len bytes from a far pointer; the caller provides a sufficiently large destination.
void farptr_read(BankPtr ptr, void* dst, u16 len);
// Route a declared zero-argument function through the far-call intrinsic; this is not a general
// callback-pointer dispatcher. Mapper support and fixed-bank call-site rules still apply.
#define far_call(bank, func) __farcall((bank), func)
#endifkitaqfc/lib/bank.h
chain.h — Ringpuffer für Positionsverläufe
#ifndef CHAIN_H
#define CHAIN_H
#include "core.h"
typedef __packed struct ChainPoint {
s16 x;
s16 y;
} ChainPoint;
// head identifies the newest point; count grows to capacity, then old points are overwritten.
// Capacity at most 128 keeps every head + age sum within a byte for this implementation.
typedef __packed struct Chain {
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.
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);
#endifkitaqfc/lib/chain.h
collision.h — Kollisionstests für Rechtecke und andere Formen
/*
* Optional declarations for the phase 11 collision helper.
*/
struct NesBox16 {
unsigned short x;
unsigned short y;
unsigned char w;
unsigned char h;
};
// Test two axis-aligned world boxes using exclusive right/bottom edges.
// Coordinate-plus-size sums must fit u16; touching edges return false.
// Both boxes must have positive dimensions; the overlap test has no separate empty-box guard.
unsigned char nes_box16_intersects(struct NesBox16* a, struct NesBox16* b);
// Test a half-open box: left/top edges are included and right/bottom edges
// excluded. Callers provide valid pointers and non-overflowing edge coordinates.
unsigned char nes_box16_contains_point(struct NesBox16* box, unsigned short px, unsigned short py);kitaqfc/lib/collision.h
core.h — Grundlegende Ganzzahltypen
#ifndef CORE_H
#define CORE_H
// Public scalar aliases for the compiler's byte and 16-bit integer types.
typedef unsigned char u8;
typedef unsigned short u16;
typedef signed char s8;
typedef signed short s16;
// Boolean convenience values; API functions returning bit masks need not normalize to TRUE.
#define TRUE 1
#define FALSE 0
#endifkitaqfc/lib/core.h
danmaku.h — Geschosspools, Fächermuster, Treffer und Streiferkennung
// Copyright (c) 2026 DAISUKE OBA. SPDX-License-Identifier: MIT
#ifndef KITAQFC_DANMAKU_H
#define KITAQFC_DANMAKU_H
#include "core.h"
#include "intrinsics.h"
#define DANMAKU_MAX 64
// Reserve cartridge PRG RAM 0x6000..0x627F (640 bytes), enabled and writable.
// Bullet centers remain in [8,248) x [24,232). These margins prevent byte
// wraparound even at the largest signed Q4.4 velocity accepted by spawn.
extern u8 dm_x[64];
extern u8 dm_y[64];
extern u8 dm_active[64];
extern u8 dm_grazed[64];
extern u8 dm_count;
extern u8 dm_peak;
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 the pool, counters and rotating OAM priority. Player settings survive.
void danmaku_reset(void);
// Remove all bullets and step events; preserve lifetime/peak counters.
void danmaku_clear(void);
// Allocate a bullet at pixel-center x/y with signed 1/16-pixel velocities.
// Return one on success, zero outside the playfield or when all 64 slots are full.
u8 danmaku_spawn(u8 x, u8 y, s8 vx, s8 vy);
// Emit up to 64 bullets. Angles wrap in 32 steps: 0 right, 8 down, 16 left,
// 24 up. Speed is in 1/16 pixel, clamped to 64. Each failed allocation counts.
void danmaku_fan(u8 x, u8 y, u8 direction, u8 step, u8 count, u8 speed);
// Move all live bullets once. Remove offscreen/hitting bullets. Hit uses a
// +/-3-pixel box; graze uses +/-11, once per bullet. Events describe this step.
// This updates logic only; it neither writes OAM nor calls a game damage handler.
void danmaku_step(void);
// Write up to slots consecutive shadow-OAM entries starting at first_oam.
// Rotate bullet priority by 13 modulo 64 and hide unused entries in that range.
// tile is an 8x8 sprite centered at (4,4). Return the number emitted. DMA is
// caller-owned and belongs in VBlank. Hardware's eight-per-scanline limit remains.
u8 danmaku_draw(u8 first_oam, u8 slots, u8 tile, u8 attributes);
#endifkitaqfc/lib/danmaku.h
debug.h — RAM-Protokolle und Zusicherungen
#ifndef DEBUG_H
#define DEBUG_H
#include "core.h"
// Choose 1..255 consistently across units; the valid-entry count is a byte.
#ifndef DEBUG_TRACE_MAX
#define DEBUG_TRACE_MAX 32
#endif
// Names are retained pointers, not copied strings; keep their storage and ROM mapping readable.
typedef __packed struct DebugTraceEntry {
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;
// Build the RAM-resident ASSERT label and reset log length, frame tag and last
// assertion code. Old log storage bytes are not erased.
void debug_init(void);
// Choose the frame tag stored in subsequent debug entries.
void debug_set_frame(u16 frame);
// Append a named marker with the reserved marker value 0xFFFF.
void debug_mark_frame(const u8* label);
// Widen a byte value into the trace entry'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);
// Store the assertion code even if the log is full, then attempt an ASSERT
// entry. The helper records failure but does not stop execution.
void debug_assert_fail(u16 code);
// Read the number of valid entries in the fixed trace buffer.
u8 debug_get_trace_count(void);
// Borrow the internal trace array; bound inspection by debug_get_trace_count.
const DebugTraceEntry* debug_get_trace_log(void);
// Read the latest assertion code, initially zero after debug_init.
u16 debug_get_last_assert(void);
#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)
#endifkitaqfc/lib/debug.h
entity.h — Objektpools mit festen Arrays
#ifndef ENTITY_H
#define ENTITY_H
#include "core.h"
// Choose capacity 1..255 consistently across units; counters are bytes and FF is the failure sentinel.
#ifndef ENTITY_MAX
#define ENTITY_MAX ((u8)16)
#endif
// Coordinates, velocities, state and timer have game-defined units.
// The sprite byte is bookkeeping only; releasing a slot does not hide or free its sprite.
typedef __packed struct Entity {
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.
// Use a callback in common PRG bank 0, or keep its bank mapped throughout dispatch.
typedef void (*EntityFn)(u8 id);
// Reset every slot before the game starts using the pool.
void entity_init(void);
// 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(id) for each active slot in ascending order. A null callback does nothing.
// Changes to later slots take effect during the same traversal. Do not reenter this traversal.
void entity_update_all(EntityFn fn);
// Call the drawing callback for each active slot, using the same traversal rules as update.
// The callback submits drawing data; the pool does not allocate sprites.
void entity_draw_all(EntityFn fn);
// Count occupied slots without changing entity state.
u8 entity_count_active(void);
// Release every entity and restore deterministic defaults, including the no-sprite sentinel.
void entity_clear_all(void);
#endifkitaqfc/lib/entity.h
fc.h — Sammelheader der Bibliothek
#ifndef FC_H
#define FC_H
// Convenience header collecting FC interfaces. Inclusion provides declarations
// and aliases, not every implementation; link only the source modules required
// by the selected runtime, avoiding alternative helpers with conflicting symbols.
#include "core.h"
#include "intrinsics.h"
#include "system.h"
#include "input.h"
#include "runtime.h"
#include "ppu.h"
#include "ppu_direct.h"
#include "vram_queue.h"
#include "vram.h"
#include "oam.h"
#include "sprite.h"
#include "pad.h"
#include "input_repeat.h"
#include "palette.h"
#include "scroll.h"
#include "tilemap.h"
#include "nametable_asset.h"
#include "attribute.h"
#include "scene.h"
#include "metasprite.h"
#include "actor.h"
#include "entity.h"
#include "collision.h"
#include "fixed.h"
#include "physics2d.h"
#include "physics3d.h"
#include "bank.h"
#include "asset.h"
#include "debug.h"
#include "chain.h"
#include "audio.h"
#include "audio_vblank.h"
#include "fds_sound.h"
#include "vrc6_sound.h"
#include "vrc7_sound.h"
#include "mapper.h"
// This final include adds function-like macros, including zero-argument nes_oam_dma.
// Use selective headers when calling the page-argument runtime API with the same name.
#include "nes_game.h"
#endifkitaqfc/lib/fc.h
fds.h — FDS-Diskettenoperationen
#ifndef FDS_H
#define FDS_H
#include "intrinsics.h"
// Return the compile-time FDS mapper selection as 0 or 1; this is not a hardware probe.
u8 __fds_available(void);
// Return the inverted disk-absent bit from 4032 as 0 or 1; this checks presence, not transfer completion.
u8 __fds_disk_ready(void);
// Return raw status mask 4032 & 04, either 0 or 4. This is not a numbered disk-side identifier.
u8 __fds_side(void);
// Read the entire 4030 status register; this is not a stored BIOS error code.
u8 __fds_error(void);
// Poll disk presence until the absent bit clears. There is no timeout or cancellation path.
void __fds_wait_ready(void);
// Alias the same disk-presence wait as __fds_wait_ready; the call can block indefinitely.
void __fds_wait_insert(void);
#endifkitaqfc/lib/fds.h
fds_file.h — Laden von FDS-Dateien
#ifndef FDS_FILE_H
#define FDS_FILE_H
#include "intrinsics.h"
// Native FDS32: load a non-boot file at its disk-header address, then memmove
// PRG bytes to dst. Null dst keeps the native destination (also for PPU files).
// Both CPU spans must fit $0200-$07FF or $6000-$DFFF and be owned by the caller.
// Return 0, a BIOS error, $40 for a missing transfer, or $FF for invalid input.
// Call from common code with disk-I/O interrupt/display prerequisites satisfied.
u8 __fds_load_file(u8 id, u8* dst);
// Overwrite the final non-boot PRG slot on its side, preserving its ID/name/load
// address. len must equal its packaged size; src must be a valid CPU RAM span.
// The resolved physical ordinal selects the slot, independently of file ID.
// Return 0, a BIOS error, or $FF before any write for an invalid slot/span/size.
u8 __fds_save_file(u8 id, const u8* src, u16 len);
// Query the compiled --fds-meta/--fds-manifest table, not the inserted disk; return 0 or 1.
u8 __fds_file_exists(u8 id);
// Return the compiled metadata size, or zero if id is absent. No disk directory is read.
u16 __fds_file_size(u8 id);
#endifkitaqfc/lib/fds_file.h
fds_overlay.h — FDS-Overlaycode
#ifndef FDS_OVERLAY_H
#define FDS_OVERLAY_H
#include "intrinsics.h"
// Load disk file id through BIOS, return its error byte and mark bank residency FF (unknown).
u8 __fds_load_overlay(u8 id);
// Load logical bank 1 from its separate boot file, or bank 2+ from overlay-start-id+(bank-2).
// Return zero on success, FF for invalid/unavailable mappings, or the BIOS error.
// A failed BIOS transfer marks residency FF (unknown); a matching valid guard can skip loading.
u8 __fds_load_bank(u8 bank);
// Return zero when the software residency record matches, otherwise call __fds_load_bank.
u8 __fds_require_bank(u8 bank);
// Return the software resident-bank byte, or FF after a failed bank transfer.
// This is not a checksum of overlay memory.
u8 __fds_current_bank(void);
// Compare a valid bank with the software resident-bank byte; FF (unknown) never matches.
u8 __fds_is_bank_resident(u8 bank);
// Return the linker-generated overlay-function count; zero if the table is disabled.
u8 __fds_overlay_function_count(void);
// Evaluate bank once and call the named zero-argument function using its linked bank.
// Restore the caller window before returning; restoration failure stops in common code.
u8 __fds_overlay_farcall(u8 bank, u16 func);
// Same named, zero-argument dispatch as __fds_overlay_farcall; evaluate bank once.
u8 __fds_farcall(u8 bank, u16 func);
#endifkitaqfc/lib/fds_overlay.h
fds_save.h — Deklarationen zum Speichern auf FDS
#ifndef FDS_SAVE_H
#define FDS_SAVE_H
// Compatibility include for FDS file/save declarations; this header adds no storage or implementation.
#include "fds_file.h"
#endifkitaqfc/lib/fds_save.h
fds_sound.h — FDS-Wavetable-Audio
#ifndef FDS_SOUND_H
#define FDS_SOUND_H
#include "intrinsics.h"
// Write 83 to 4023 and zero to 4089/408A to initialize disk/sound register gates.
void __fds_sound_enable(void);
// Copy exactly 64 readable bytes to wave RAM with wave writes enabled, then set 4089 to zero.
void __fds_wave_load(const u8* wave64);
// Stream 32 readable bytes to 4088; the caller prepares modulation state and write conditions.
void __fds_mod_load(const u8* mod32);
// Write a 12-bit frequency to 4082/4083; upper control bits in 4083 are cleared.
void __fds_freq_set(u16 freq);
// Write (volume & 3F) | 80 to 4080 for direct volume control; masking wraps, rather than clamps.
void __fds_volume_set(u8 vol);
// Write the three raw arguments to 4080, 4084 and 408A in that order.
// The legacy parameter names do not describe three independently packed envelope fields.
void __fds_env_set(u8 speed, u8 gain, u8 mode);
#endifkitaqfc/lib/fds_sound.h
fixed.h — Q8.8-Festkommaarithmetik und Rechtecke
#ifndef FIXED_H
#define FIXED_H
#include "core.h"
// Signed Q8.8 spans -128 to 127 + 255/256; one integer unit is represented by 256.
typedef s16 fix8;
#define FIX_ONE ((fix8)256)
#define FIX_HALF ((fix8)128)
typedef __packed struct Vec2 {
fix8 x;
fix8 y;
} Vec2;
typedef __packed struct KQRect {
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);
#endifkitaqfc/lib/fixed.h
input.h — Tastenzustand, Drücken, Loslassen und Wiederholung
#ifndef INPUT_H
#define INPUT_H
#include "core.h"
#include "intrinsics.h"
// These are shared logical masks, not raw controller-register bit positions.
// input_update translates controller 1 before these masks are applied.
#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 new press pulses immediately; the next pulse occurs DELAY + 1 input updates later.
#ifndef INPUT_REPEAT_DELAY
#define INPUT_REPEAT_DELAY ((u8)18)
#endif
// Later pulses occur RATE + 1 updates apart; zero repeats on each 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;
// Clear held/edge/repeat masks and reset each independent repeat countdown.
void input_init(void);
// Read controller 1 through the safe intrinsic, translate its bit order and
// derive press/release edges. Repeat delays count calls to this function, so
// call it once per intended input tick.
void input_update(void);
// Return true when any masked logical button is held.
u8 input_down(u8 mask);
// Return true when any masked button became pressed in the latest input update.
u8 input_pressed(u8 mask);
// Return true when any masked button became released in the latest update.
u8 input_released(u8 mask);
// Return true for a masked initial press or scheduled repeat pulse.
u8 input_repeat(u8 mask);
// Read the complete translated held-button mask.
u8 input_current(void);
// Read the translated held-button mask from before the latest update.
u8 input_previous(void);
#define btn_down input_down
#define btn_pressed input_pressed
#define btn_released input_released
#define btn_repeat input_repeat
#endifkitaqfc/lib/input.h
input_repeat.h — Wiederholung bei gehaltener Taste
/*
* Optional declarations for the phase 9 NES pad repeat helper.
*
* Button bit layout:
* bit0=A bit1=B bit2=Select bit3=Start bit4=Up bit5=Down bit6=Left bit7=Right
*/
extern unsigned char nes_pad_repeat_delay;
extern unsigned char nes_pad_repeat_interval;
extern unsigned char nes_pad1_repeat;
// Set initial/repeat countdowns and clear repeat output. Zero countdowns are
// allowed and cause a repeat on the next held-button step.
// A fresh press emits immediately. Held repeats follow after delay+1 and then interval+1 steps.
// These are call counts, not milliseconds; use one fresh pad poll before each step.
void nes_pad_repeat_config(unsigned char delay, unsigned char interval);
// Generate per-button repeat bits from the most recently polled pad state.
// Poll first, then call once per tick; a countdown reaching zero emits on the
// following step, so an interval N leaves N decrement steps between pulses.
void nes_pad_repeat_step(void);
// Return the requested newly-pressed bits, not a normalized Boolean.
unsigned char nes_pad_trigger(unsigned char mask);
// Return the requested repeat-pulse bits from the latest repeat step.
unsigned char nes_pad_repeat(unsigned char mask);
// Return the requested newly-released bits from the latest pad poll.
unsigned char nes_pad_release(unsigned char mask);
// Return the requested currently-held bits in the NES pad layout.
unsigned char nes_pad_held(unsigned char mask);kitaqfc/lib/input_repeat.h
intrinsics.h — Compiler-Intrinsics
#ifndef INTRINSICS_H
#define INTRINSICS_H
/*
* FC/NES native intrinsic API.
* This header intentionally does not expose KITAQGB/CGB compatibility stubs.
* The compiler recognizes these names and emits 6502-oriented code or
* calls an internal 6502 helper generated by the backend.
*/
// Direct PPU operations require caller-controlled access timing. Generated helpers share runtime
// argument/scratch storage: do not assume calls are reentrant across NMI or IRQ handlers.
typedef unsigned char u8;
typedef unsigned short u16;
/* memory / bit / math */
// Copy len bytes forward between readable/writable CPU ranges; overlapping copies are not memmove.
// Zero length performs no memory transfer; argument side effects are evaluated before expansion.
void __memcpy(u8* dst, const u8* src, u16 len);
// Fill len CPU bytes with value. Zero length still evaluates argument side effects.
void __memset(u8* dst, u8 value, u16 len);
// Forward copy with an 8-bit length, zero through 255; the dynamic helper promotes it to a word count.
void __memcpy_small(u8* dst, const u8* src, u8 len);
// Fill zero through 255 CPU bytes; this is ordinary RAM access, not a PPU transfer.
void __memset_small(u8* dst, u8 value, u8 len);
// Copy exactly 16 bytes forward; both ranges must be valid and suitably non-overlapping.
void __copy16(u8* dst, const u8* src);
// Copy exactly 32 bytes forward; bank selection and source lifetime belong to the caller.
void __copy32(u8* dst, const u8* src);
// Return 0 or 1 for half-open bounds. Zero extents are empty; coordinates do not wrap across 255.
u8 __xy_in_rect(u8 x, u8 y, u8 rx, u8 ry, u8 rw, u8 rh);
// Return abs(x1-x2)+abs(y1-y2) modulo 256; large distances are not saturated.
u8 __manhattan(u8 x1, u8 y1, u8 x2, u8 y2);
// Return y*width+x as a word without checking coordinates against map dimensions.
u16 __map_index(u8 x, u8 y, u8 width);
// Replace both persistent state bytes. Reusing a seed reproduces the sequence; this is not cryptographic randomness.
void __rng_seed(u16 seed);
// Advance the shared 16-bit LFSR and return the XOR of its two bytes; zero state is reseeded to A55A.
u8 __rng8(void);
// Return base[bit>>3] & (1<<(bit&7)): zero or the bit mask, not a normalized Boolean.
u8 __bit_test(u8* base, u16 bit);
// Set the indexed bit in caller storage without changing the other seven bits in that byte.
void __bit_set(u8* base, u16 bit);
// Clear the indexed bit in caller storage; no bounds check or interrupt exclusion is inserted.
void __bit_clear(u8* base, u16 bit);
// XOR the indexed bit in caller storage; coordinate concurrent writers to avoid lost updates.
void __bit_toggle(u8* base, u16 bit);
// Return the high byte of the unsigned 8-by-8 product, equivalent to floor(a*b/256).
u8 __mul8x8_hi(u8 a, u8 b);
// Return the low word of the unsigned product; overflow wraps without saturation.
u16 __mul16x8(u16 a, u8 b);
// Interpret a and b as signed two's-complement bit patterns and return the low word of their product.
u16 __smul16x8(u16 a, u8 b);
// Return acc+a*b modulo 65536 using unsigned multiplication.
u16 __mac16(u16 acc, u16 a, u8 b);
// Add the signed-pattern product to acc modulo 65536; the API carries the result as u16 bits.
u16 __smac16(u16 acc, u16 a, u8 b);
// FC alias of __smul16x8: signed-pattern raw product, with no Q1.7 scaling shift.
u16 __smul16x8_q1_7(u16 a, u8 b);
// FC alias of __smac16: accumulate a raw signed-pattern product modulo 65536.
u16 __smac16_q1_7(u16 acc, u16 a, u8 b);
// Return a0*b0+a1*b1 modulo 65536. The FC backend inserts no Q8.8 rescaling or rounding.
u16 __dot2_q8_8(u16 a0, u16 a1, u8 b0, u8 b1);
// Sum three unsigned word-by-byte products modulo 65536 without a final scaling shift.
u16 __dot3_q8_8(u16 a0, u16 a1, u16 a2, u8 b0, u8 b1, u8 b2);
// Sum two signed-pattern products modulo 65536; no Q8.8 scaling shift is generated.
u16 __sdot2_q8_8(u16 a0, u16 a1, u8 b0, u8 b1);
// Sum three signed-pattern products modulo 65536; choose operand units explicitly in the caller.
u16 __sdot3_q8_8(u16 a0, u16 a1, u16 a2, u8 b0, u8 b1, u8 b2);
// FC alias of __sdot2_q8_8: two raw signed-pattern products, summed without rescaling.
u16 __sdot2_q1_7(u16 a0, u16 a1, u8 b0, u8 b1);
// FC alias of __sdot3_q8_8: three raw signed-pattern products, summed without rescaling.
u16 __sdot3_q1_7(u16 a0, u16 a1, u16 a2, u8 b0, u8 b1, u8 b2);
/* PRG bank */
// Resolve a symbol or function placement to its byte bank number at compilation time.
u8 __bankof(u16 symbol_or_function);
// Select the mapper-specific PRG bank; the common bank and legal bank range depend on the target board.
void __bankswitch(u8 bank);
// Use the same mapper PRG-switch helper as __bankswitch; retain executable code in a valid mapping.
void __prg_bank_set(u8 bank);
// Call a declared zero-argument function; placement selects its bank and its declared type determines the result.
u8 __farcall(u8 bank, u16 func);
// Switch to the source bank, copy len bytes forward and restore the previous bank.
// Keep destination RAM and helper code accessible throughout; overlapping copies are not memmove.
void __far_memcpy(u8* dst, u8 bank, u16 src, u16 len);
// Temporarily select bank, read one byte at addr and restore the prior bank mapping.
u8 __farpeek8(u8 bank, u16 addr);
// Temporarily select bank and read a little-endian word, then restore the previous mapping.
u16 __farpeek16(u8 bank, u16 addr);
/* PPU / VRAM */
// Invoke the compiler rendering-enable helper; this header contains declarations, not C fallback implementations.
void __ppu_on(void);
// Invoke the compiler rendering-disable helper before bulk direct PPU updates.
void __ppu_off(void);
// Replace PPUMASK with the supplied byte; the caller chooses rendering, clipping and emphasis bits.
void __ppu_mask_set(u8 value);
// Replace PPUCTRL, including NMI enable, pattern-table choices and address increment mode.
void __ppu_ctrl_set(u8 value);
// Read the software PPUCTRL/PPUMASK shadows; use the setters for coherent state.
// Raw writes to $2000/$2001 bypass these shadows. No PPU hardware read occurs.
u8 __ppu_ctrl_get(void);
u8 __ppu_mask_get(void);
// Set the PPU address through the compiler helper; address writes affect the shared scroll/address latch.
void __ppu_addr(u16 ppu_addr);
// Write one PPUDATA byte using the current PPU address and increment mode.
void __ppu_data(u8 value);
// Read PPUSTATUS; the hardware clears VBlank status and resets the shared write latch.
u8 __ppu_read_status(void);
// Read PPUSTATUS to reset the scroll/address write latch; the read also clears VBlank status.
void __scroll_latch_reset(void);
// Save X/Y in runtime shadows, reset the PPU latch and write both scroll bytes immediately.
void __scroll_set(u8 x, u8 y);
// Replace saved X and write an X/Y pair using the retained Y shadow.
void __scroll_x_set(u8 x);
// Replace saved Y and write an X/Y pair using the retained X shadow.
void __scroll_y_set(u8 y);
// Write a byte-counted source range directly; arrange PPU access timing and source-bank visibility.
void __vram_write(u16 ppu_addr, const u8* src, u8 len);
// Write repeated bytes directly; this is not an enqueue operation.
void __vram_fill(u16 ppu_addr, u8 value, u8 len);
// Write one tile directly at 2000+y*32+x; use x<32, y<30 for visible nametable cells.
void __nametable_put(u8 x, u8 y, u8 tile);
// Write one tile in nametable nt&3. Mirroring can alias logical nametables; coordinates are unchecked.
void __nametable_put_nt(u8 nt, u8 x, u8 y, u8 tile);
// Fill rows of nametable zero directly, advancing each row start by 32 bytes.
// Keep the rectangle in bounds and use PPU increment one; this does not enqueue or clip.
void __nametable_rect(u8 x, u8 y, u8 w, u8 h, u8 tile);
// Fill a rectangle in nametable nt&3 with the same unchecked, direct-write row loop.
void __nametable_rect_nt(u8 nt, u8 x, u8 y, u8 w, u8 h, u8 tile);
// Write the entire packed attribute byte at 23C0+(y>>2)*8+(x>>2).
// Use tile coordinates below 32; this does not merge a single palette quadrant.
void __attr_set(u8 x, u8 y, u8 attr);
// Write a whole packed attribute byte in nametable nt&3; other quadrant fields are overwritten.
void __attr_set_nt(u8 nt, u8 x, u8 y, u8 attr);
// Stream exactly 16 source bytes to 3F00. Arrange PPU access timing and increment one.
void __palette_bg_load(const u8* pal16);
// Stream exactly 16 source bytes to 3F10; hardware palette aliases also affect background entries.
void __palette_sp_load(const u8* pal16);
/* NMI VRAM transfer queue. Queue entries are consumed by __vramq_exec(),
* and the default NMI handler calls __vramq_exec() automatically.
*/
// Reset pending intrinsic-queue records; this is separate from runtime.c nes_vram_queue_clear.
void __vramq_clear(void);
// Append one address/value update; use the overflow latch to detect capacity failure.
void __vramq_put(u16 ppu_addr, u8 value);
// Retain the source address for later consumption; keep its storage and bank mapping valid.
void __vramq_copy(u16 ppu_addr, const u8* src, u8 len);
// Append a repeated-byte update; the source value is stored in the record.
void __vramq_fill(u16 ppu_addr, u8 value, u8 len);
// Publish the pending records to the configured consumer. Do not mutate them while consumption can run.
void __vramq_commit(void);
// Execute a ready queue directly; committing and safe PPU timing are caller responsibilities.
void __vramq_exec(void);
// Return encoded bytes currently occupied, not transfer payload bytes or command count.
u8 __vramq_len(void);
// Read the latched capacity failure; reading does not reset it.
u8 __vramq_overflow(void);
// Clear the overflow latch explicitly after handling the failed submission.
void __vramq_clear_overflow(void);
// Return total encoded command-buffer capacity; this is independent of PPU VRAM capacity.
u8 __vramq_capacity(void);
/* NMI / IRQ */
// Spin until the runtime NMI counter changes; the configured handler must advance it. No timeout is emitted.
void __nmi_wait(void);
// Return the current wrapping NMI counter byte, not a Boolean ready flag.
u8 __nmi_ready(void);
// Set bit 7 in the PPUCTRL shadow and write it to hardware, preserving the other shadow bits.
void __nmi_enable(void);
// Clear bit 7 in the PPUCTRL shadow and write it to hardware; CPU IRQ masking is separate.
void __nmi_disable(void);
// Emit SEI to mask CPU IRQs; NMI is unaffected.
void __irq_disable(void);
// Emit CLI to unmask CPU IRQs; the caller must have a valid interrupt handler.
void __irq_enable(void);
// Return the processor-status byte captured before SEI. Pass that byte to __irq_restore.
u8 __irq_save(void);
// Restore processor status with PLP, including arithmetic flags and the saved IRQ mask.
void __irq_restore(u8 state);
/* OAM / input */
// Set OAMADDR to zero and start DMA from CPU page 02; arrange safe PPU timing in the caller.
void __oam_dma(void);
// Set OAMADDR to zero and DMA 256 bytes from page<<8. The source page must remain readable.
void __oam_dma_page(u8 page);
// Hide all 64 page-02 shadow sprites by writing Y=F0; hardware OAM changes only after DMA.
void __oam_clear(void);
// Write Y, tile, attributes and X to one shadow entry. Use indices 0..63; coordinates are raw OAM bytes.
void __sprite_set(u8 index, u8 x, u8 y, u8 tile, u8 attr);
// Replace only shadow X/Y for index 0..63; tile and attribute bytes remain unchanged.
void __sprite_move(u8 index, u8 x, u8 y);
// Replace the selected shadow tile byte; this does not upload tile patterns.
void __sprite_tile(u8 index, u8 tile);
// Replace the selected shadow attribute byte, including palette, priority and flip bits.
void __sprite_attr(u8 index, u8 attr);
// Write F0 to the selected shadow Y byte; issue DMA to make the change visible.
void __sprite_hide(u8 index);
// Expand dx,dy,tile,attr records into page-02 shadow OAM until dx=FF; return the next index.
// Coordinates and the byte OAM cursor wrap; keep the terminated stream within the available slots.
u8 __metasprite_draw(u8 oam_index, u8 base_x, u8 base_y, const u8* metasprite);
// Latch and sample eight D0 bits from port 1; bit order is A,B,Select,Start,Up,Down,Left,Right.
u8 __pad_read1(void);
// Latch and sample eight D0 bits from port 2 in the same NES button order.
u8 __pad_read2(void);
// Repeat pairs of port-1 polls until both bytes match; the retry loop has no fixed limit.
u8 __pad_read1_safe(void);
// Repeat pairs of port-2 polls until both bytes match; this does not populate pad.c globals.
u8 __pad_read2_safe(void);
// Return pad & 0F for A/B/Select/Start; this masks a supplied snapshot and performs no polling.
u8 __pad_buttons(u8 pad);
// Return pad & F0 in the original bit positions; this does not normalize directions to bits 0..3.
u8 __pad_dirs(u8 pad);
/* Famicom/NES expansion input devices.
* D1 readers are for expansion-port controllers/joysticks that expose a
* standard 8-bit joypad stream on data line D1 instead of D0.
* __joypad2p_voice() / __mic_read2p() return the Famicom 2P microphone bit.
*/
// Latch and read an eight-button stream from port-1 data line D1 rather than D0.
u8 __pad_read1_d1(void);
// Latch and read an eight-button stream from port-2 data line D1 rather than D0.
u8 __pad_read2_d1(void);
// Alias the port-1 D1 controller reader; the attached device must use the expected serial protocol.
u8 __exp_pad_read1(void);
// Alias the port-2 D1 controller reader; this is not an expansion-device discovery operation.
u8 __exp_pad_read2(void);
// Return controller-port 4016 bit 2 normalized to 0 or 1; this is a microphone level bit, not PCM audio.
u8 __joypad2p_voice(void);
// Alias the same normalized microphone input bit as __joypad2p_voice.
u8 __mic_read2p(void);
/* Zapper / light gun. The no-suffix names default to the usual port-2/Famicom
* expansion-port mapping. __zapper_light*() returns 1 when light is detected.
*/
// Return raw 4016 & 18, retaining trigger and active-low light bits.
u8 __zapper_raw1(void);
// Return raw 4017 & 18 for the second port.
u8 __zapper_raw2(void);
// Return port-1 trigger bit 4 normalized to 0 or 1.
u8 __zapper_trigger1(void);
// Return port-2 trigger bit 4 normalized to 0 or 1.
u8 __zapper_trigger2(void);
// Invert port-1 bit 3 and normalize: one means light detected.
u8 __zapper_light1(void);
// Invert port-2 bit 3 and normalize: one means light detected.
u8 __zapper_light2(void);
// Default to the port-2 normalized trigger reader.
u8 __zapper_trigger(void);
// Default to the port-2 normalized light reader.
u8 __zapper_light(void);
/* Family BASIC Keyboard. __fkb_scan() writes 18 bytes: 9 rows x 2 columns,
* each byte containing raw $4017 & 0x1E for that row/column.
*/
// Probe selected-row and disabled-matrix bit patterns and return 0 or 1; this is a heuristic detection.
u8 __fkb_detect(void);
// Write 18 raw masked samples (4017 & 1E), two per row, to caller storage; reset 4016 afterward.
void __fkb_scan(u8* dst18);
// Select a matrix row and the low bit of col, then return raw 4017 & 1E.
// Use rows 0..8 for keys; row 9 is used by detection. No row-range validation is emitted.
u8 __fkb_read_row_col(u8 row, u8 col);
/* R.O.B. / Famicom Robot optical flash primitives. These are timing primitives;
* game-specific command sequences should be built on top of __rob_pulse() or
* __rob_send_byte().
*/
// Set PPUMASK and its shadow to 1E or 00, then wait for an NMI-counter change.
// The caller supplies image/palette brightness; rendering enable alone does not create a white screen.
void __rob_flash(u8 bright);
// Run on_frames enabled-mask waits followed by off_frames disabled-mask waits; NMI must advance.
void __rob_pulse(u8 on_frames, u8 off_frames);
// Send eight bits MSB first: one uses 4 on/2 off waits; zero uses 2 on/4 off.
// Requires an advancing runtime NMI counter; 48 waits in total, final PPUMASK=0.
// This raw pattern does not add a robot command preamble or validate reception.
void __rob_send_byte(u8 pattern);
/* Expansion-port TTL serial / MIDI adapter support.
* The low-level serial layer assumes an external adapter that maps OUT0 to TX
* and D4 on $4017 to RX. MIDI helpers bit-bang 8N1 bytes at an approximate
* 31250 bps timing suitable for adapter bring-up and simple music sync.
*/
// Write bit & 1 to 4016, replacing the port output value; coordinate with other port users.
void __serial_tx_bit(u8 bit);
// Read 4017 bit 4 and normalize it to 0 or 1; an external serial adapter supplies the signal.
u8 __serial_rx_bit(void);
// Send start-low, eight least-significant-first bits and stop-high in 57-cycle
// NTSC bit cells (about 31400 bps). Stop DMC DMA and mask IRQ/NMI during transfers;
// PAL timing and electrical adapter compatibility are not established here.
void __midi_out_byte(u8 byte);
// Block for a low start signal and sample eight bits. No timeout, framing check or receive buffer is provided.
u8 __midi_in_byte(void);
// Send 90|(ch&0F), note and velocity. Supply 7-bit data bytes; they are not masked by this helper.
void __midi_note_on(u8 ch, u8 note, u8 velocity);
// Send 80|(ch&0F), note and velocity through the same synchronous serial path.
void __midi_note_off(u8 ch, u8 note, u8 velocity);
// Send B0|(ch&0F), controller and value; both data arguments must be valid 7-bit values.
void __midi_control_change(u8 ch, u8 cc, u8 value);
// Send C0|(ch&0F) followed by the caller-supplied 7-bit program value.
void __midi_program_change(u8 ch, u8 program);
// Transmit the single realtime byte F8 synchronously; this does not schedule future ticks.
void __midi_clock(void);
// Transmit realtime Start (FA) through the serial adapter path.
void __midi_start(void);
// Transmit realtime Continue (FB) through the serial adapter path.
void __midi_continue(void);
// Transmit realtime Stop (FC) through the serial adapter path.
void __midi_stop(void);
/* Mapper */
// Return the low byte of the mapper number selected for this build; no cartridge probe is performed.
u8 __mapper_id(void);
// Select a CNROM bank or MMC3 register 0 bank; unsupported mapper profiles produce a compile error.
void __chr_bank_set(u8 bank);
// Use the same CNROM/MMC3 register 0 selection as __chr_bank_set.
void __chr_bank_set0(u8 bank);
// Select MMC3 register 1, or the same full CNROM bank register; this is mapper-specific banking.
void __chr_bank_set1(u8 bank);
// Emit the selected mapper mirroring operation; available modes and writable control depend on the board.
void __mirroring_set(u8 mode);
// Write the MMC3 IRQ latch and reload registers. This does not enable IRQ delivery.
void __irq_scanline_set(u8 line);
// Alias the MMC3 IRQ latch/reload operation; other mapper profiles are rejected.
void __mapper_irq_set(u8 scanline);
// Write MMC3 E001. The CPU IRQ mask and a valid handler are separate caller responsibilities.
void __mapper_irq_enable(void);
// Write MMC3 E000 to disable and acknowledge mapper IRQs.
void __mapper_irq_disable(void);
// Use the same E000 write as disable; explicitly re-enable when another interrupt is needed.
void __mapper_irq_ack(void);
// Wait for the current hit flag to clear, then for a new hit. No timeout is provided.
void __sprite0_wait_hit(void);
// Wait for a new sprite-zero hit, reset the PPU latch and write X/Y scroll; requires a visible hit setup.
void __split_scroll_sprite0(u8 x, u8 y);
/* FDS. Status and sound primitives are emitted on --mapper=fds.
* File/overlay APIs use the FDS BIOS direct-pointer routines. __fds_load_file()
* and __fds_load_overlay() load to the destination encoded in the disk file
* header. __fds_file_exists() and __fds_file_size() are side-effect-free when
* a disk-builder manifest is supplied with --fds-meta / --fds-manifest.
*/
// Return the compile-time FDS mapper selection as 0 or 1; this is not a hardware probe.
u8 __fds_available(void);
// Return the inverted disk-absent bit from 4032 as 0 or 1; this checks presence, not transfer completion.
u8 __fds_disk_ready(void);
// Return raw status mask 4032 & 04, either 0 or 4. This is not a numbered disk-side identifier.
u8 __fds_side(void);
// Read the entire 4030 status register; this is not a stored BIOS error code.
u8 __fds_error(void);
// Poll disk presence until the absent bit clears. There is no timeout or cancellation path.
void __fds_wait_ready(void);
// Alias the same disk-presence wait as __fds_wait_ready; the call can block indefinitely.
void __fds_wait_insert(void);
// Native FDS32: load a non-boot file at its disk-header address, then memmove
// PRG bytes to dst. Null dst keeps the native destination (also for PPU files).
// Both CPU spans must fit $0200-$07FF or $6000-$DFFF and be owned by the caller.
// Return 0, a BIOS error, $40 for a missing transfer, or $FF for invalid input.
// Call from common code with disk-I/O interrupt/display prerequisites satisfied.
u8 __fds_load_file(u8 id, u8* dst);
// Overwrite the final non-boot PRG slot on its side, preserving its ID/name/load
// address. len must equal its packaged size; src must be a valid CPU RAM span.
// The resolved physical ordinal selects the slot, independently of file ID.
// Return 0, a BIOS error, or $FF before any write for an invalid slot/span/size.
u8 __fds_save_file(u8 id, const u8* src, u16 len);
// Load disk file id through BIOS, return its error byte and mark bank residency FF (unknown).
u8 __fds_load_overlay(u8 id);
// Load logical bank 1 from its separate boot file, or bank 2+ from overlay-start-id+(bank-2).
// Return zero on success, FF for invalid/unavailable mappings, or the BIOS error.
// A failed BIOS transfer marks residency FF (unknown); a matching valid guard can skip loading.
u8 __fds_load_bank(u8 bank);
// Return zero when the software residency record matches, otherwise call __fds_load_bank.
u8 __fds_require_bank(u8 bank);
// Return the software resident-bank byte, or FF after a failed bank transfer.
// This is not a checksum of overlay memory.
u8 __fds_current_bank(void);
// Compare a valid bank with the software resident-bank byte; FF (unknown) never matches.
u8 __fds_is_bank_resident(u8 bank);
// Return the linker-generated overlay-function count; zero if the table is disabled.
u8 __fds_overlay_function_count(void);
// Evaluate bank once and call the named zero-argument function using its linked bank.
// Restore the caller window before returning; restoration failure stops in common code.
u8 __fds_overlay_farcall(u8 bank, u16 func);
// Same named, zero-argument dispatch as __fds_overlay_farcall; evaluate bank once.
u8 __fds_farcall(u8 bank, u16 func);
// Query the compiled --fds-meta/--fds-manifest table, not the inserted disk; return 0 or 1.
u8 __fds_file_exists(u8 id);
// Return the compiled metadata size, or zero if id is absent. No disk directory is read.
u16 __fds_file_size(u8 id);
// Write 83 to 4023 and zero to 4089/408A to initialize disk/sound register gates.
void __fds_sound_enable(void);
// Copy exactly 64 readable bytes to wave RAM with wave writes enabled, then set 4089 to zero.
void __fds_wave_load(const u8* wave);
// Stream 32 readable bytes to 4088; the caller prepares modulation state and write conditions.
void __fds_mod_load(const u8* mod);
// Write a 12-bit frequency to 4082/4083; upper control bits in 4083 are cleared.
void __fds_freq_set(u16 freq);
// Write (volume & 3F) | 80 to 4080 for direct volume control; masking wraps, rather than clamps.
void __fds_volume_set(u8 volume);
// Write the three raw arguments to 4080, 4084 and 408A in that order.
// The legacy parameter names do not describe three independently packed envelope fields.
void __fds_env_set(u8 a, u8 b, u8 c);
#endifkitaqfc/lib/intrinsics.h
keyboard.h — Tastaturabfrage
#ifndef KEYBOARD_H
#define KEYBOARD_H
#include "intrinsics.h"
// Probe selected-row and disabled-matrix bit patterns and return 0 or 1; this is a heuristic detection.
u8 __fkb_detect(void);
// Write 18 raw masked samples (4017 & 1E), two per row, to caller storage; reset 4016 afterward.
void __fkb_scan(u8* dst18);
// Select a matrix row and the low bit of col, then return raw 4017 & 1E.
// Use rows 0..8 for keys; row 9 is used by detection. No row-range validation is emitted.
u8 __fkb_read_row_col(u8 row, u8 col);
#endifkitaqfc/lib/keyboard.h
mapper.h — Mapper-Banken und Interrupts
#ifndef MAPPER_H
#define MAPPER_H
#include "intrinsics.h"
// Resolve a symbol or function placement to its byte bank number at compilation time.
u8 __bankof(u16 symbol_or_function);
// Select the mapper-specific PRG bank; the common bank and legal bank range depend on the target board.
void __bankswitch(u8 bank);
// Use the same mapper PRG-switch helper as __bankswitch; retain executable code in a valid mapping.
void __prg_bank_set(u8 bank);
// Invoke the compiler banked-call path; target placement and calling convention must match the selected mapper.
u8 __farcall(u8 bank, u16 func);
// Switch to the source bank, copy len bytes forward and restore the previous bank.
// Keep destination RAM and helper code accessible throughout; overlapping copies are not memmove.
void __far_memcpy(u8* dst, u8 bank, u16 src, u16 len);
// Temporarily select bank, read one byte at addr and restore the prior bank mapping.
u8 __farpeek8(u8 bank, u16 addr);
// Temporarily select bank and read a little-endian word, then restore the previous mapping.
u16 __farpeek16(u8 bank, u16 addr);
// Return the low byte of the mapper number selected for this build; no cartridge probe is performed.
u8 __mapper_id(void);
// Select a CNROM bank or MMC3 register 0 bank; unsupported mapper profiles produce a compile error.
void __chr_bank_set(u8 bank);
// Use the same CNROM/MMC3 register 0 selection as __chr_bank_set.
void __chr_bank_set0(u8 bank);
// Select MMC3 register 1, or the same full CNROM bank register; this is mapper-specific banking.
void __chr_bank_set1(u8 bank);
// Emit the selected mapper mirroring operation; available modes and writable control depend on the board.
void __mirroring_set(u8 mode);
// Write the MMC3 IRQ latch and reload registers. This does not enable IRQ delivery.
void __irq_scanline_set(u8 line);
// Alias the MMC3 IRQ latch/reload operation; other mapper profiles are rejected.
void __mapper_irq_set(u8 scanline);
// Write MMC3 E001. The CPU IRQ mask and a valid handler are separate caller responsibilities.
void __mapper_irq_enable(void);
// Write MMC3 E000 to disable and acknowledge mapper IRQs.
void __mapper_irq_disable(void);
// Use the same E000 write as disable; explicitly re-enable when another interrupt is needed.
void __mapper_irq_ack(void);
// Wait for the current hit flag to clear, then for a new hit. No timeout is provided.
void __sprite0_wait_hit(void);
// Wait for a new sprite-zero hit, reset the PPU latch and write X/Y scroll; requires a visible hit setup.
void __split_scroll_sprite0(u8 x, u8 y);
#endifkitaqfc/lib/mapper.h
math_fast.h — Schnelle Ganzzahlarithmetik
#ifndef MATH_FAST_H
#define MATH_FAST_H
#include "intrinsics.h"
/*
* Fast math primitives are compiler intrinsics. These declarations are kept
* here so game code can include a game-facing math header instead of the full
* intrinsic surface.
*/
// Return abs(x1-x2)+abs(y1-y2) modulo 256; large distances are not saturated.
u8 __manhattan(u8 x1, u8 y1, u8 x2, u8 y2);
// Return 0 or 1 for half-open bounds. Zero extents are empty; coordinates do not wrap across 255.
u8 __xy_in_rect(u8 x, u8 y, u8 rx, u8 ry, u8 rw, u8 rh);
// Return y*width+x as a word without checking coordinates against map dimensions.
u16 __map_index(u8 x, u8 y, u8 width);
// Advance the shared 16-bit LFSR and return the XOR of its two bytes; zero state is reseeded to A55A.
u8 __rng8(void);
// Replace both persistent state bytes. Reusing a seed reproduces the sequence; this is not cryptographic randomness.
void __rng_seed(u16 seed);
#endifkitaqfc/lib/math_fast.h
math_fixed.h — Intrinsics für Festkommaarithmetik
#ifndef MATH_FIXED_H
#define MATH_FIXED_H
#include "intrinsics.h"
/* Fixed-point helpers are compiler-recognized intrinsic entry points. */
// Return the high byte of the unsigned 8-by-8 product, equivalent to floor(a*b/256).
u8 __mul8x8_hi(u8 a, u8 b);
// Return the low word of the unsigned product; overflow wraps without saturation.
u16 __mul16x8(u16 a, u8 b);
// Interpret a and b as signed two's-complement bit patterns and return the low word of their product.
u16 __smul16x8(u16 a, u8 b);
// Return acc+a*b modulo 65536 using unsigned multiplication.
u16 __mac16(u16 acc, u16 a, u8 b);
// Add the signed-pattern product to acc modulo 65536; the API carries the result as u16 bits.
u16 __smac16(u16 acc, u16 a, u8 b);
// Return a0*b0+a1*b1 modulo 65536. The FC backend inserts no Q8.8 rescaling or rounding.
u16 __dot2_q8_8(u16 a0, u16 a1, u8 b0, u8 b1);
// Sum three unsigned word-by-byte products modulo 65536 without a final scaling shift.
u16 __dot3_q8_8(u16 a0, u16 a1, u16 a2, u8 b0, u8 b1, u8 b2);
// Sum two signed-pattern products modulo 65536; no Q8.8 scaling shift is generated.
u16 __sdot2_q8_8(u16 a0, u16 a1, u8 b0, u8 b1);
// Sum three signed-pattern products modulo 65536; choose operand units explicitly in the caller.
u16 __sdot3_q8_8(u16 a0, u16 a1, u16 a2, u8 b0, u8 b1, u8 b2);
#endifkitaqfc/lib/math_fixed.h
math_lut.h — Nachschlagetabellen
#ifndef MATH_LUT_H
#define MATH_LUT_H
// Uniform 256-phase unsigned sine table in ROM. Range 1..255, centered at 128.
// Link math_lut.c once; indices 0..255 are valid and byte phase wrap is supported.
extern unsigned char MATH_SIN[256];
#endifkitaqfc/lib/math_lut.h
metasprite.h — Bilder aus mehreren Sprites
/*
* Optional declarations for the phase 10 NES metasprite helper.
*
* Metasprite data layout:
* [dx, dy, tile, attr] repeated, terminated by dx=0xFF
*/
// Read four-byte records [dx,dy,tile,attr] until dx=0xFF, writing them to
// shadow OAM. Coordinates and destination offsets wrap as bytes. The caller
// must supply a terminator and enough unused slots; there is no capacity guard.
// Return the next slot index derived from the final wrapped byte offset.
unsigned char nes_metasprite_draw(unsigned char oam_index, unsigned char base_x, unsigned char base_y, unsigned char* metasprite);
// Compiler intrinsic counterpart; this declaration does not route through the C function above.
unsigned char __metasprite_draw(unsigned char oam_index, unsigned char base_x, unsigned char base_y, const unsigned char* metasprite);
// Hide consecutive shadow slots by setting Y to 0xF8. Keep the requested
// range within 64 slots to avoid wrapping and hiding earlier entries.
void nes_metasprite_hide_from(unsigned char oam_index, unsigned char sprite_count);kitaqfc/lib/metasprite.h
mic.h — Mikrofoneingabe
#ifndef MIC_H
#define MIC_H
#define VOICE_H
#include "intrinsics.h"
// Return controller-port 4016 bit 2 normalized to 0 or 1; this is a microphone level bit, not PCM audio.
u8 __joypad2p_voice(void);
// Alias the same normalized microphone input bit as __joypad2p_voice.
u8 __mic_read2p(void);
#endifkitaqfc/lib/mic.h
midi.h — MIDI-Ein- und -Ausgabe
#ifndef MIDI_H
#define MIDI_H
#include "intrinsics.h"
// Write bit & 1 to 4016, replacing the port output value; coordinate with other port users.
void __serial_tx_bit(u8 bit);
// Read 4017 bit 4 and normalize it to 0 or 1; an external serial adapter supplies the signal.
u8 __serial_rx_bit(void);
// Send start-low, eight least-significant-first bits and stop-high using fixed NOP delays.
// Instruction and interrupt overhead is additional; the emitted loop does not establish a verified MIDI baud rate.
void __midi_out_byte(u8 byte);
// Block for a low start signal and sample eight bits. No timeout, framing check or receive buffer is provided.
u8 __midi_in_byte(void);
// Send 90|(ch&0F), note and velocity. Supply 7-bit data bytes; they are not masked by this helper.
void __midi_note_on(u8 ch, u8 note, u8 velocity);
// Send 80|(ch&0F), note and velocity through the same synchronous serial path.
void __midi_note_off(u8 ch, u8 note, u8 velocity);
// Send B0|(ch&0F), controller and value; both data arguments must be valid 7-bit values.
void __midi_control_change(u8 ch, u8 cc, u8 value);
// Send C0|(ch&0F) followed by the caller-supplied 7-bit program value.
void __midi_program_change(u8 ch, u8 program);
// Transmit the single realtime byte F8 synchronously; this does not schedule future ticks.
void __midi_clock(void);
// Transmit realtime Start (FA) through the serial adapter path.
void __midi_start(void);
// Transmit realtime Continue (FB) through the serial adapter path.
void __midi_continue(void);
// Transmit realtime Stop (FC) through the serial adapter path.
void __midi_stop(void);
#endifkitaqfc/lib/midi.h
nametable_asset.h — Nametable-Ressourcen und ihre Platzierung
/*
* Optional declarations for phase12 nametable / attribute asset helpers.
*/
extern unsigned char nes_attr_shadow[64];
// Mask the index to the four logical nametables and return its PPU base.
// Physical storage still depends on the cartridge's mirroring configuration.
unsigned short nes_nt_base_from_index(unsigned char index);
// Locate the 64-byte attribute table at offset 0x03C0 from a nametable base.
unsigned short nes_attr_base_from_nt(unsigned short nt_base);
// Fill all 64 shadow bytes with an already-packed attribute value.
void nes_attr_shadow_clear(unsigned char value);
// Copy an entire packed attribute table into shadow RAM without writing the PPU.
void nes_attr_shadow_copy(unsigned char* src64);
// Replace only the chosen quadrant's palette bits, preserving its neighbors.
// Palette IDs are masked to two bits; tile coordinates must fit the shadow table.
void nes_attr_shadow_set_quad(unsigned char tile_x, unsigned char tile_y, unsigned char pal_index);
// Upload all attribute shadow bytes immediately; the caller provides safe PPU timing.
void nes_attr_apply_now(unsigned short nt_base);
// Copy all shadow attribute bytes into the runtime queue and return its admission result.
unsigned char nes_attr_queue_all(unsigned short nt_base);
// Write one complete 32-tile row directly. The caller validates the row and PPU timing.
void nes_nt_stream_row(unsigned short nt_base, unsigned char row, unsigned char* src32);
// Copy one complete nametable row into the runtime queue.
unsigned char nes_nt_queue_row(unsigned short nt_base, unsigned char row, unsigned char* src32);
// Write each rectangle row immediately, advancing source by pitch rather than
// width. Caller-provided coordinates, storage and timing are not clipped or checked.
void nes_nt_stream_rect(unsigned short nt_base, unsigned char tile_x, unsigned char tile_y, unsigned char width, unsigned char height, unsigned char pitch, unsigned char* src);
// Copy rows into the runtime queue until complete or full. Failure leaves
// earlier rows queued; it does not roll back a partially admitted rectangle.
// Widths must respect the queue literal-record limit.
// Pitch is source bytes per row. Each copied literal record costs width+3 queue bytes;
// check total admission needs when partial updates are unacceptable.
unsigned char nes_nt_queue_rect(unsigned short nt_base, unsigned char tile_x, unsigned char tile_y, unsigned char width, unsigned char height, unsigned char pitch, unsigned char* src);
// Queue one fill record per row, stopping on failure while retaining previously
// queued rows. The runtime fill-length and rectangle bounds requirements apply.
unsigned char nes_nt_queue_fill_rect(unsigned short nt_base, unsigned char tile_x, unsigned char tile_y, unsigned char width, unsigned char height, unsigned char value);
// Upload 960 tile bytes followed by 64 attribute bytes. This bulk operation
// does not disable rendering or wait for VBlank on its own.
void nes_nametable_apply_now(unsigned short nt_base, unsigned char* nam960, unsigned char* attr64);kitaqfc/lib/nametable_asset.h
nes_game.h — Operationsmakros für Spiele
#ifndef NES_GAME_H
#define NES_GAME_H
#include "core.h"
#include "intrinsics.h"
/*
* AI-friendly NES operation aliases.
*
* These names intentionally describe gameplay-side operations. They are thin
* aliases over KITAQFC intrinsics so the compiler can still record the exact
* NES action for diagnostics and KUROSAKI metadata.
*/
// These aliases use the compiler intrinsic queue. They do not select the separate C runtime queue.
#define nes_vram_put(addr, value) __vramq_put((addr), (value))
#define nes_vram_copy(addr, src, len) __vramq_copy((addr), (src), (len))
#define nes_vram_fill(addr, value, len) __vramq_fill((addr), (value), (len))
#define nes_vram_commit() __vramq_commit()
#define nes_vram_clear_queue() __vramq_clear()
#define nes_oam_clear() __oam_clear()
// This zero-argument macro hides the same-named page-argument C runtime function in included code.
#define nes_oam_dma() __oam_dma()
#define nes_sprite_set(i,x,y,t,a) __sprite_set((i),(x),(y),(t),(a))
#define nes_sprite_move(i,x,y) __sprite_move((i),(x),(y))
#define nes_sprite_hide(i) __sprite_hide((i))
// Select the compiler intrinsic implementation even when the C metasprite header is also included.
#define nes_metasprite_draw(i,x,y,data) __metasprite_draw((i),(x),(y),(data))
#define nes_pad1() __pad_read1_safe()
#define nes_pad2() __pad_read2_safe()
#define nes_mapper_irq_set(scanline) __mapper_irq_set((scanline))
#define nes_mapper_irq_enable() __mapper_irq_enable()
#define nes_mapper_irq_disable() __mapper_irq_disable()
#define nes_mapper_irq_ack() __mapper_irq_ack()
#define nes_split_scroll_sprite0(x,y) __split_scroll_sprite0((x),(y))
#define nes_fds_wave_load(wave64) __fds_wave_load((wave64))
#define nes_fds_load_bank(bank) __fds_load_bank((bank))
#define nes_fds_farcall(bank, func) __fds_overlay_farcall((bank), (func))
#endifkitaqfc/lib/nes_game.h
oam.h — Operationen auf der OAM-Arbeitskopie
#ifndef OAM_H
#define OAM_H
#include "intrinsics.h"
// Set OAMADDR to zero and start DMA from CPU page 02; arrange safe PPU timing in the caller.
void __oam_dma(void);
// Set OAMADDR to zero and DMA 256 bytes from page<<8. The source page must remain readable.
void __oam_dma_page(u8 page);
// Hide all 64 page-02 shadow sprites by writing Y=F0; hardware OAM changes only after DMA.
void __oam_clear(void);
// Write Y, tile, attributes and X to one shadow entry. Use indices 0..63; coordinates are raw OAM bytes.
void __sprite_set(u8 index, u8 x, u8 y, u8 tile, u8 attr);
// Replace only shadow X/Y for index 0..63; tile and attribute bytes remain unchanged.
void __sprite_move(u8 index, u8 x, u8 y);
// Replace the selected shadow tile byte; this does not upload tile patterns.
void __sprite_tile(u8 index, u8 tile);
// Replace the selected shadow attribute byte, including palette, priority and flip bits.
void __sprite_attr(u8 index, u8 attr);
// Write F0 to the selected shadow Y byte; issue DMA to make the change visible.
void __sprite_hide(u8 index);
#endifkitaqfc/lib/oam.h
oam_fair.h — Wechselnder Spritevorrang mit Prioritäten
#ifndef KQ_OAM_FAIR_H
#define KQ_OAM_FAIR_H
#include "core.h"
/* 64-entry software sprite pool. Define the five arrays/cursor declared below
* and include oam_fair_impl.h in ONE translation unit, in a fixed PRG bank.
* X/Y are center coordinates, ACTIVE is a byte array. OAM is a 256-byte
* DMA shadow; USED is its byte cursor. Entries already in OAM stay first.
* The odd stride selects every starting entry over 64 calls. Hardware still
* has a 64-sprite / 8-sprite-per-scanline limit: this distributes flicker.
* Call only from the main loop; commit the completed OAM in VBlank.
*/
extern u8 oam_fair_phase;
extern u8 oam_fair_x[64];
extern u8 oam_fair_y[64];
extern u8 oam_fair_active[64];
extern u8 oam_fair_shadow[256];
extern u8 oam_fair_used;
extern u8 oam_fair_limit;
extern u8 oam_fair_tile;
extern u8 oam_fair_attr;
extern u8 oam_fair_drawn;
// Append active pool entries using the configured common tile/attributes. The emitter stops at byte cursor 252,
// leaving slot 63 unused to avoid cursor wrap. Hide unused trailing OAM entries separately before DMA.
void OAM_FairDraw(void);
#endifkitaqfc/lib/oam_fair.h
oam_fair_impl.h — Implementierung des wechselnden Spritevorrangs
#include "oam_fair.h"
u8 oam_fair_phase;
u8 oam_fair_limit;
u8 oam_fair_tile;
u8 oam_fair_attr;
u8 oam_fair_drawn;
u8 oam_fair_scanned;
// Rotate the starting pool entry by 13 modulo 64, then append active sprites
// until the caller's draw limit or OAM byte cursor limit is reached. Coordinates
// describe 8x8 centers: subtract four for X and five for raw OAM Y. Include once
// and invoke it from the main loop with a four-byte-aligned used cursor.
void OAM_FairDraw(void) {
__asm {
LDA oam_fair_phase
CLC
ADC #13
AND #63
STA oam_fair_phase
TAX
LDY oam_fair_used
LDA #0
STA oam_fair_drawn
STA oam_fair_scanned
// Visit each pool entry at most once, preserving already-written OAM entries
// and sharing the configured tile/attribute values across emitted sprites.
kq_fair_loop:
LDA oam_fair_active,X
BEQ kq_fair_next
LDA oam_fair_drawn
CMP oam_fair_limit
BCS kq_fair_done
// Reserve the final four-byte slot so advancing this byte cursor cannot wrap to zero.
CPY #252
BCS kq_fair_done
// Convert the 8x8 center to raw OAM coordinates; Y also needs the hardware minus-one bias.
LDA oam_fair_y,X
SEC
SBC #5
STA oam_fair_shadow,Y
LDA oam_fair_tile
STA oam_fair_shadow+1,Y
LDA oam_fair_attr
STA oam_fair_shadow+2,Y
LDA oam_fair_x,X
SEC
SBC #4
STA oam_fair_shadow+3,Y
INY
INY
INY
INY
INC oam_fair_drawn
// Advance cyclically and stop after returning to this frame's starting entry.
kq_fair_next:
TXA
CLC
ADC #1
AND #63
TAX
CPX oam_fair_phase
BNE kq_fair_loop
// Publish the updated byte cursor for later OAM writers and the VBlank DMA path.
kq_fair_done:
STY oam_fair_used
}
}kitaqfc/lib/oam_fair_impl.h
pad.h — NES-Controllereingaben
/*
* Optional declarations for the phase 8 NES pad runtime.
*
* Button bit layout in nes_pad1_cur / pressed / released:
* bit0=A bit1=B bit2=Select bit3=Start bit4=Up bit5=Down bit6=Left bit7=Right
*/
extern unsigned char nes_pad1_cur;
extern unsigned char nes_pad1_prev;
extern unsigned char nes_pad1_pressed;
extern unsigned char nes_pad1_released;
// Latch controller input with a 1-to-0 strobe and shift eight controller-1 bits
// into held/pressed/released masks. This direct path does not perform repeated
// reads for DMC interference; the final JOY2 read does not populate player-2 state.
void nes_pad_poll(void);kitaqfc/lib/pad.h
palette.h — NES-Paletten
/*
* Optional declarations for the phase 11 NES palette helper.
*/
extern unsigned char nes_palette_shadow[32];
// Copy exactly 32 palette bytes to the fixed shadow buffer without writing the PPU.
void nes_palette_copy(unsigned char* src32);
// Replace shadow palette data and upload all 32 bytes immediately. The caller
// provides a safe PPU access period; this helper does not wait for VBlank.
void nes_palette_apply_now(unsigned char* src32);
// Upload the current palette shadow directly, with timing controlled by the caller.
void nes_palette_apply_shadow_now(void);
// Update the shadow and copy all colors into the runtime queue. A queue
// failure leaves the new shadow contents in place.
// Return one if the runtime queue accepted the copied payload, zero if it was full.
// Admission does not mean the NMI consumer has already updated the PPU.
unsigned char nes_palette_queue_all(unsigned char* src32);
// Update and queue four background palette bytes. pal_index must be 0..3;
// there is no range check before writing the shadow.
unsigned char nes_palette_queue_bg4(unsigned char pal_index, unsigned char* src4);
// Update and queue four sprite palette bytes at the 0x3F10 region. The
// caller supplies pal_index 0..3; NES palette mirroring still applies.
unsigned char nes_palette_queue_sprite4(unsigned char pal_index, unsigned char* src4);kitaqfc/lib/palette.h
physics2d.h — 2D-Bewegung und Kollisionen
#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"
// Lightweight deterministic 2D physics for KITAQFC.
// 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 uses non-reentrant helper 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 by a signed eight-bit coefficient divided by 256.
// 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);
// Optional byte-sized eighth-pixel channels for small custom update loops.
#define KQ2D_SUBPIXEL_BITS ((u8)3)
#define KQ2D_SUBPIXEL_ONE ((u8)8)
#define KQ2D_SUBPIXEL_MASK ((u8)7)
// Optional byte-channel identifiers for application-specific movement.
#define KQ2D_DRAG_BRAKE ((u8)1)
#define KQ2D_DRAG_STUN ((u8)2)
#define KQ2D_DRAG_COAST ((u8)3)
#define KQ2D_DRAG_THRUST ((u8)4)
#define KQ2D_DIR_NONE ((u8)0)
#define KQ2D_DIR_NEGATIVE ((u8)1)
#define KQ2D_DIR_POSITIVE ((u8)2)
/*
* Byte-sized Q5.3 channels for KITAQFC.
*
* Keep the channels as flat game-state fields in a hot loop. That avoids
* aggregate/pointer call traffic while retaining eighth-pixel integration.
*/
// Store integer pixel position separately from the 0..7 fractional remainder.
// Speed is an unsigned eighth-pixel magnitude; direction is a separate channel.
typedef u8 KQ2DPosition;
typedef u8 KQ2DFraction;
typedef u8 KQ2DSpeed;
typedef u8 KQ2DDirection;kitaqfc/lib/physics2d.h
physics3d.h — Physik für achsenparallele 3D-Quader
#pragma once
#include "core.h"
// Lightweight deterministic 3D physics for KITAQFC.
// 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 uses non-reentrant helper 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, dividing each by 256 (toward zero) 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);kitaqfc/lib/physics3d.h
ppu.h — Deklarationen zur PPU-Anzeige
#ifndef PPU_H
#define PPU_H
// Link ppu.c. Bulk palette/nametable transfers require rendering to be disabled.
// Disable background and sprite rendering, preserving other PPUMASK bits.
void nes_ppu_screen_off(void);
// Set scroll to (0,0), then apply the requested PPUCTRL and PPUMASK values.
void nes_ppu_screen_on(unsigned char ctrl, unsigned char mask);
// Copy 32 bytes into $3F00..$3F1F with increment one; preserve PPUCTRL.
// Null is ignored. Hardware palette mirrors apply; source bank must stay mapped.
void nes_ppu_load_palette(unsigned char* pal32);
// Fill 960 tiles and 64 packed attributes; preserve PPUCTRL.
// Accept exactly $2000/$2400/$2800/$2C00; invalid bases are ignored.
void nes_ppu_clear_nt(unsigned short nt_base, unsigned char tile, unsigned char attr);
// Address-byte variants reset the latch and coexist with runtime.c's word seek.
void nes_ppu_seek_bytes(unsigned char hi, unsigned char lo);
// Direct transfers follow the current PPUCTRL increment; count is 0..255.
void nes_ppu_write_bytes(unsigned char hi, unsigned char lo, const unsigned char* src, unsigned char count);
void nes_ppu_fill(unsigned char hi, unsigned char lo, unsigned char value, unsigned char count);
#endifkitaqfc/lib/ppu.h
ppu_direct.h — Direkte PPU-Operationen
#ifndef PPU_DIRECT_H
#define PPU_DIRECT_H
#include "intrinsics.h"
/* Direct PPU access. Use only during vblank or when rendering is disabled. */
// Invoke the compiler rendering-enable helper; this header contains declarations, not C fallback implementations.
void __ppu_on(void);
// Invoke the compiler rendering-disable helper before bulk direct PPU updates.
void __ppu_off(void);
// Replace PPUMASK with the supplied byte; the caller chooses rendering, clipping and emphasis bits.
void __ppu_mask_set(u8 value);
// Replace PPUCTRL, including NMI enable, pattern-table choices and address increment mode.
void __ppu_ctrl_set(u8 value);
// Set the PPU address through the compiler helper; address writes affect the shared scroll/address latch.
void __ppu_addr(u16 ppu_addr);
// Write one PPUDATA byte using the current PPU address and increment mode.
void __ppu_data(u8 value);
// Read PPUSTATUS; the hardware clears VBlank status and resets the shared write latch.
u8 __ppu_read_status(void);
// Write a byte-counted source range directly; arrange PPU access timing and source-bank visibility.
void __vram_write(u16 ppu_addr, const u8* src, u8 len);
// Write repeated bytes directly; this is not an enqueue operation.
void __vram_fill(u16 ppu_addr, u8 value, u8 len);
#endifkitaqfc/lib/ppu_direct.h
rob.h — ROB-Steuerung
#ifndef ROB_H
#define ROB_H
#include "intrinsics.h"
// Set PPUMASK and its shadow to 1E or 00, then wait for an NMI-counter change.
// The caller supplies image/palette brightness; rendering enable alone does not create a white screen.
void __rob_flash(u8 bright);
// Run on_frames enabled-mask waits followed by off_frames disabled-mask waits; NMI must advance.
void __rob_pulse(u8 on_frames, u8 off_frames);
// Send eight bits MSB first, using 4/2-frame pulses for one and 2/4 for zero.
// Preserve the outer bit counter and shifted pattern around each pulse helper.
void __rob_send_byte(u8 pattern);
#endifkitaqfc/lib/rob.h
runtime.h — C-Hilfsfunktionen für NMI, OAM und PPU-Übertragungen
/*
* Core NES runtime declarations.
*
* Declare frame waits, direct PPU transfers, OAM DMA and the copied-payload VRAM queue.
*/
// The four-byte record follows hardware OAM byte order: Y, tile, attributes, X.
struct NesSprite4 {
unsigned char y;
unsigned char tile;
unsigned char attr;
unsigned char x;
};
extern unsigned char nes_nmi_counter;
extern unsigned char nes_oam_shadow[256];
// This counter measures the separate 192-byte copied-payload runtime queue, not the compiler intrinsic queue.
extern unsigned char nes_vram_queue_used;
extern unsigned char nes_vram_queue_overflow;
// Wait until the NMI handler advances its counter. NMI must already be enabled
// and able to execute; this polling loop has no timeout.
void nes_wait_nmi(void);
// Wait for the current VBlank to end, then for the next one to begin. Each
// PPUSTATUS read has hardware side effects, including clearing the VBlank flag.
void nes_vblank_wait(void);
// Reset the PPU address latch with a status read, then write the high/low address bytes.
void nes_ppu_seek(unsigned short ppu_addr);
// Write len source bytes directly through PPUDATA. Call only during an appropriate
// PPU access period; the address increment mode comes from the current PPUCTRL.
void nes_ppu_stream_write(unsigned short ppu_addr, unsigned char* src, unsigned short len);
// Write value repeatedly through PPUDATA, using the current PPU address increment
// mode. This routine does not wait for VBlank or disable rendering.
void nes_ppu_stream_fill(unsigned short ppu_addr, unsigned char value, unsigned short len);
// Reset the OAM destination and DMA one 256-byte CPU page. The hardware stalls
// the CPU during transfer; page is the source address high byte.
void nes_oam_dma(unsigned char page);
// Discard pending VRAM commands and clear the overflow latch; no PPU writes occur.
void nes_vram_queue_clear(void);
// Copy a literal payload into the queue and publish its new used length last.
// Accept lengths 0..127; reject larger lengths and latch overflow without changing the queue.
// The caller must ensure queue production cannot race its NMI consumer.
unsigned char nes_vram_queue_try_write(unsigned short ppu_addr, unsigned char* src, unsigned char len);
// Queue a four-byte fill record: address high/low, length with bit 7 set, value.
// Reject lengths above 127 and latch overflow on any capacity/format failure.
unsigned char nes_vram_queue_try_fill(unsigned short ppu_addr, unsigned char value, unsigned char len);
// Consume complete records in order during a safe PPU access period. Reading
// PPUSTATUS resets the shared address latch before each address pair. The caller
// is responsible for ensuring the transfer fits its NMI/VBlank time budget.
void nes_vram_queue_nmi_flush(void);kitaqfc/lib/runtime.h
scene.h — Szenenregistrierung, -wechsel und -aktualisierung
#ifndef SCENE_H
#define SCENE_H
#include "core.h"
typedef void (*SceneFunc)(void);
typedef __packed struct SceneDef {
SceneFunc enter;
SceneFunc update;
SceneFunc draw;
SceneFunc exit;
} SceneDef;
// One shared in-flight transfer. remaining counts source bytes not yet copied into the queue.
// An inactive stream may still have commands awaiting the NMI consumer.
struct NesSceneStreamState {
unsigned char* src;
unsigned short ppu_addr;
unsigned short remaining;
unsigned char chunk;
unsigned char active;
};
extern struct NesSceneStreamState nes_scene_stream_state;
// 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();
// Replace the single active transfer and retain its source pointer. Keep the
// source storage and any required ROM bank readable until all bytes are queued.
void nes_scene_stream_begin(unsigned short ppu_addr, unsigned char* src, unsigned short len, unsigned char chunk);
// Prepare the 960-byte tile portion of a nametable using 32-byte queue records.
void nes_scene_stream_begin_nametable(unsigned short nt_base, unsigned char* src960);
// Prepare the 64-byte attribute table at nametable base + 0x03C0.
void nes_scene_stream_begin_attr(unsigned short nt_base, unsigned char* src64);
// Prepare a 32-byte palette transfer to PPU address 0x3F00.
void nes_scene_stream_begin_palette(unsigned char* src32);
// Queue as many chunks as available capacity allows, capped at 127 bytes each.
// Return one when queue exhaustion requires a later retry, zero when all data has
// been queued. Zero does not mean the NMI consumer has already written the PPU.
unsigned char nes_scene_stream_step(void);
#endifkitaqfc/lib/scene.h
scroll.h — Hintergrund, Fenster und geteiltes Scrollen
/*
* Optional declarations for the phase 9 NES scroll helper.
*/
extern unsigned char nes_scroll_ctrl_base;
extern unsigned short nes_scroll_camera_x;
extern unsigned short nes_scroll_camera_y;
// Store PPUCTRL bits other than the two nametable-selection bits for later application.
void nes_scroll_set_base_ctrl(unsigned char ctrl);
// Store camera coordinates without touching hardware registers.
void nes_scroll_set(unsigned short camera_x, unsigned short camera_y);
// Combine bit 8 of each camera coordinate with base PPUCTRL, reset the latch
// by reading PPUSTATUS, and write low-byte X/Y scroll. This uses 256-unit
// wrapping on both axes rather than normalizing Y to a 240-pixel nametable height.
// Initialize base control to the intended PPUCTRL value, including NMI enable, before applying.
// Only coordinate bits 0..8 are used; arrange safe PPU timing in the caller.
void nes_scroll_apply(void);
// Subtract the screen anchor from the world point into unsigned camera
// coordinates. Underflow wraps; world-edge clamping belongs to the game.
void nes_camera_follow_center(unsigned short target_x, unsigned short target_y, unsigned char center_x, unsigned char center_y);kitaqfc/lib/scroll.h
sprite.h — OBJ-Reservierung, Positionierung, Metasprites und Animation
#ifndef SPRITE_H
#define SPRITE_H
#include "core.h"
#include "intrinsics.h"
// Keep this value within 1..64; tracking arrays and hardware OAM contain exactly 64 slots.
#ifndef SPRITE_MAX
#define SPRITE_MAX ((u8)64)
#endif
#define SPRITE_FLAG_PAL1 ((u8)0x01)
#define SPRITE_FLAG_PAL2 ((u8)0x02)
#define SPRITE_FLAG_PAL3 ((u8)0x03)
#define SPRITE_FLAG_PRIORITY ((u8)0x20)
#define SPRITE_FLAG_XFLIP ((u8)0x40)
#define SPRITE_FLAG_YFLIP ((u8)0x80)
// Signed per-part offsets are added modulo 256. This struct API has an explicit count,
// unlike the FF-terminated byte-stream API in metasprite.h.
typedef struct MetaSpritePart {
s8 dx;
s8 dy;
u8 tile;
u8 flags;
} MetaSpritePart;
// Initialize frame/ticks to valid values. Returned tile IDs advance by one regardless of hardware sprite size.
typedef struct SpriteAnim {
u8 first_tile;
u8 frame_count;
u8 frame;
u8 ticks;
u8 ticks_per_frame;
} SpriteAnim;
extern u8 kq_sprite_active[64];
extern u8 kq_sprite_used;
extern u8 kq_sprite_height;
// Reset allocation/position state and hide each OAM slot through the intrinsic.
// The software height defaults to eight; hardware sprite size is configured elsewhere.
void sprite_init(void);
// Claim and hide the first free slot, or return 0xFF if all slots are active.
u8 sprite_alloc(void);
// Release an active valid slot and hide it; invalid/repeated frees are ignored.
void sprite_free(u8 id);
// Update software coordinates and the intrinsic OAM position for a valid slot.
void sprite_set_pos(u8 id, u8 x, u8 y);
// Replace the tile byte of a valid OAM slot without changing allocation state.
void sprite_set_tile(u8 id, u8 tile);
// Replace the hardware attribute byte of a valid OAM slot.
void sprite_set_flags(u8 id, u8 flags);
// Mark the software position off screen and hide its OAM entry without freeing it.
void sprite_hide(u8 id);
// Transfer intrinsic shadow OAM immediately; this wrapper does not wait for VBlank.
void sprite_flush_oam_now(void);
// Wait for NMI before requesting OAM DMA.
void sprite_flush_oam(void);
// 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(void);
// Flag software overlap estimates above eight sprites on one scanline.
u8 sprite_warn_scanline_overflow(void);
// Estimate peak overlap across 240 lines from software Y/height values.
// This does not model pixel transparency, OAM priority or every hardware overflow quirk.
u8 sprite_max_scanline_count(void);
// 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 and wrap the frame index, returning the selected tile.
// Zero ticks-per-frame freezes advancement; null state returns zero.
u8 anim_update(SpriteAnim* anim);
#endifkitaqfc/lib/sprite.h
system.h — Start, Bildzähler, Wartefunktionen und Interrupts
#ifndef SYSTEM_H
#define SYSTEM_H
#include "core.h"
#include "intrinsics.h"
// A synchronous callback invoked after the software frame count is incremented.
typedef void (*SystemCallback)(void);
extern u16 kq_system_frame;
// Reset the software frame counter and callback storage, then enable NMI.
void system_init(void);
// Wait for NMI, count the completed wait, then invoke the registered callback.
void system_wait_vblank(void);
// Replace the per-wait callback; null disables callback dispatch.
void system_set_vblank_callback(SystemCallback callback);
// Return the wrapping 16-bit count of completed waits through this wrapper.
u16 system_get_frame(void);
// Return the low byte of the software frame counter.
u8 system_get_frame8(void);
// Enable maskable CPU IRQs through the intrinsic; NMI is controlled separately.
void system_enable_interrupts(void);
// Disable maskable CPU IRQs; this does not disable the PPU's NMI source.
void system_disable_interrupts(void);
#define fc_init system_init
#define fc_wait_vblank system_wait_vblank
#define fc_set_vblank_callback system_set_vblank_callback
#define fc_frame_count system_get_frame
#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
#endifkitaqfc/lib/system.h
tilemap.h — Rechteckige Operationen auf Kachelkarten
/*
* Optional declarations for the phase 11 tilemap helper.
*/
// The map borrows row-major tile bytes; keep width*height bytes readable in the active CPU mapping.
// solid_from is a tile-ID threshold, not an independent collision bitmap.
struct NesTilemap {
unsigned char* tiles;
unsigned char width;
unsigned char height;
unsigned char solid_from;
};
// Compute a row-major byte offset by adding the row stride ty times. This
// internal arithmetic helper does not validate coordinates.
unsigned short nes_tilemap_index(struct NesTilemap* map, unsigned char tx, unsigned char ty);
// Return a tile byte, or 0xFF when coordinates exceed map dimensions. The
// map/storage pointers must be valid; 0xFF may also be an actual stored tile.
unsigned char nes_tilemap_get(struct NesTilemap* map, unsigned char tx, unsigned char ty);
// Treat out-of-bounds/0xFF tiles as solid, then compare other tile IDs with
// the map's solid_from threshold.
unsigned char nes_tilemap_point_solid(struct NesTilemap* map, unsigned char tx, unsigned char ty);
// Convert pixels to eight-pixel tile X and narrow to a byte. Keep world X
// below 2048 when wraparound is not intended.
unsigned char nes_world_to_tile8_x(unsigned short world_x);
// Convert pixels to eight-pixel tile Y with the same byte-coordinate limit.
unsigned char nes_world_to_tile8_y(unsigned short world_y);
// Convert a world point to tile coordinates and apply the tile solidity rule.
unsigned char nes_tilemap_world_point_solid(struct NesTilemap* map, unsigned short world_x, unsigned short world_y);
// Test only the four corners of a nonempty world box. Interior/edge tiles
// between the corners are not scanned, so large boxes can miss obstacles.
// Width/height must be nonzero and endpoint arithmetic must not overflow.
unsigned char nes_tilemap_world_box_solid(struct NesTilemap* map, unsigned short world_x, unsigned short world_y, unsigned char width, unsigned char height);kitaqfc/lib/tilemap.h
vram.h — VRAM-Aktualisierungen und Übertragung per Warteschlange
#ifndef VRAM_H
#define VRAM_H
#include "core.h"
#include "intrinsics.h"
// Coordinates use 32-byte nametable rows. These wrappers do not clip to the 32x30 visible tile area.
#ifndef VRAM_NT_BASE
#define VRAM_NT_BASE ((u16)0x2000)
#endif
// Clear the intrinsic queue and its overflow latch.
void vram_init(void);
// Discard queued commands and explicitly reset the overflow latch.
void vram_clear_queue(void);
// Queue one tile at the default nametable base. Return the current overflow
// status, which may include a failure from an earlier operation.
u8 vram_queue_bg_tile(u8 x, u8 y, u8 tile);
// Alias the queued background-tile operation.
u8 vram_queue_tile(u8 x, u8 y, u8 tile);
// Queue one fill per row. This is not transactional: capacity exhaustion can
// leave earlier rows queued, and the loop continues attempting later rows.
u8 vram_queue_bg_rect(u8 x, u8 y, u8 w, u8 h, u8 tile);
// Queue each tightly packed source row as a pointer-based copy record. Keep
// source storage and its ROM bank accessible until queue execution finishes;
// partial queuing remains possible on overflow.
u8 vram_queue_bg_block(u16 base, u8 x, u8 y, u8 w, u8 h, const u8* src);
// Split a byte transfer into copy records of at most 127 bytes. The runtime
// retains source pointers rather than copying payloads into the queue. Return
// the overflow latch state after all records have been attempted.
u8 vram_queue_memcpy(u16 dst, const void* src, u16 len);
// Alias the byte-copy queue helper; len remains a byte count, not a tile count.
u8 vram_queue_tiles(u16 dst, const void* src, u16 len);
// Queue fills of at most 127 bytes each. Overflow can leave a partially queued
// transfer; no rollback is performed.
u8 vram_queue_memset(u16 dst, u8 value, u16 len);
// Invoke the queue executor directly. Its ready flag must already be set by
// commit, and the caller supplies appropriate PPU timing.
void vram_flush_now(void);
// Commit queued records for consumption and wait for the NMI path.
void vram_flush(void);
// Return the encoded queue length in bytes, not the number of commands.
u8 vram_get_queue_used(void);
// Return the remaining command-buffer capacity in bytes. A command requires
// space for its complete encoded record, including its address and metadata.
// Read before committing: NMI may consume a committed queue asynchronously.
u8 vram_get_queue_free(void);
// Return the queue's total capacity in bytes, independent of its current usage.
// This describes the command buffer, not free space in PPU VRAM.
u8 vram_get_queue_capacity(void);
// Read the overflow latch without clearing it.
u8 vram_get_overflowed(void);
#endifkitaqfc/lib/vram.h
vram_queue.h — Durch NMI verarbeitete VRAM-Warteschlangen
#ifndef VRAM_QUEUE_H
#define VRAM_QUEUE_H
#include "intrinsics.h"
/* Safe frame-time VRAM queue. These names are compiler intrinsic entry points. */
// Reset pending intrinsic-queue records; this is separate from runtime.c nes_vram_queue_clear.
void __vramq_clear(void);
// Append one address/value update; use the overflow latch to detect capacity failure.
void __vramq_put(u16 ppu_addr, u8 value);
// Retain the source address for later consumption; keep its storage and bank mapping valid.
void __vramq_copy(u16 ppu_addr, const u8* src, u8 len);
// Append a repeated-byte update; the source value is stored in the record.
void __vramq_fill(u16 ppu_addr, u8 value, u8 len);
// Publish the pending records to the configured consumer. Do not mutate them while consumption can run.
void __vramq_commit(void);
// Execute a ready queue directly; committing and safe PPU timing are caller responsibilities.
void __vramq_exec(void);
// Return encoded bytes currently occupied, not transfer payload bytes or command count.
u8 __vramq_len(void);
// Read the latched capacity failure; reading does not reset it.
u8 __vramq_overflow(void);
// Clear the overflow latch explicitly after handling the failed submission.
void __vramq_clear_overflow(void);
// Return total encoded command-buffer capacity; this is independent of PPU VRAM capacity.
u8 __vramq_capacity(void);
#endifkitaqfc/lib/vram_queue.h
vrc6_sound.h — VRC6-Audioerweiterung
#ifndef VRC6_SOUND_H
#define VRC6_SOUND_H
#include "core.h"
// Retained names for raw control codes 0..3; their numeric suffixes are not measured duty percentages.
// The KUROSAKI pulse model uses (code+1)/16 for these codes. Combine with a low volume nibble.
#define VRC6_PULSE_DUTY_12 0x00
#define VRC6_PULSE_DUTY_25 0x10
#define VRC6_PULSE_DUTY_50 0x20
#define VRC6_PULSE_DUTY_75 0x30
#define VRC6_PULSE_GATE 0x80
// Clear channel-enable/high-timer registers and output controls for all VRC6 voices.
// Requires the VRC6 register layout used by this module. No mapper setup or global frequency-control write is included.
void nes_vrc6_silence_all(void);
// Write pulse-1 control and the low 12 timer bits, then enable the channel.
void nes_vrc6_pulse1_set(u8 control, u16 period);
// Write pulse-2 control and the low 12 timer bits, then enable the channel.
void nes_vrc6_pulse2_set(u8 control, u16 period);
// Disable pulse 1 by clearing its high timer/enable register.
void nes_vrc6_pulse1_off(void);
// Disable pulse 2 by clearing its high timer/enable register.
void nes_vrc6_pulse2_off(void);
// Mask the saw accumulation rate to six bits, load a 12-bit timer and enable output.
void nes_vrc6_saw_set(u8 rate, u16 period);
// Disable the saw channel by clearing its high timer/enable register.
void nes_vrc6_saw_off(void);
#endifkitaqfc/lib/vrc6_sound.h
vrc7_sound.h — VRC7-FM-Audio
#ifndef VRC7_SOUND_H
#define VRC7_SOUND_H
#include "core.h"
#define VRC7_KEY_ON 0x10
#define VRC7_SUSTAIN 0x20
// Write register selection followed immediately by data. No explicit device
// settling delay or cartridge detection is inserted by this wrapper.
// The caller must arrange device timing and serialize register/data pairs against interrupt writers.
void nes_vrc7_write(u8 reg, u8 value);
// Copy eight caller-supplied patch bytes into user-instrument registers 0..7.
void nes_vrc7_set_user_patch(const u8* patch8);
// Validate channel 0..5, then pack a 9-bit frequency, 3-bit block, key flags,
// instrument and volume nibbles into its registers. Volume is the raw hardware
// attenuation field, not a linear loudness value.
void nes_vrc7_channel_set(u8 channel, u8 instrument, u8 volume, u16 fnum, u8 block, u8 key_flags);
// Clear the channel's entire frequency-high/block/key register, not just the
// key-on bit. A later note must restore frequency and block settings.
void nes_vrc7_key_off(u8 channel);
// Key off all six voices and set instrument zero with maximum attenuation.
void nes_vrc7_silence_all(void);
#endifkitaqfc/lib/vrc7_sound.h
wire3d.h — Drahtgitterdarstellung für DMG
// Copyright (c) 2026 DAISUKE OBA. SPDX-License-Identifier: MIT
#ifndef KITAQFC_WIRE3D_H
#define KITAQFC_WIRE3D_H
#include "core.h"
#include "intrinsics.h"
// Choose a supported viewport before including wire3d.c. Smaller views reduce
// line work and dirty CHR transfers; all use original one-bit line graphics.
#ifndef WIRE3D_FC_WIDTH
#define WIRE3D_FC_WIDTH 64
#endif
#ifndef WIRE3D_FC_HEIGHT
#define WIRE3D_FC_HEIGHT 48
#endif
#if WIRE3D_FC_WIDTH == 64 && WIRE3D_FC_HEIGHT == 48
#define WIRE3D_FC_TILES 48
#elif WIRE3D_FC_WIDTH == 96 && WIRE3D_FC_HEIGHT == 64
#define WIRE3D_FC_TILES 96
#elif WIRE3D_FC_WIDTH == 128 && WIRE3D_FC_HEIGHT == 96
#define WIRE3D_FC_TILES 192
#else
#error Select 64x48, 96x64 or 128x96 for the wireframe viewport
#endif
#define WIRE3D_FC_VERTEX_LIMIT 24
typedef struct Wire3DFC_Vec3 { s8 x; s8 y; s8 z; } Wire3DFC_Vec3;
typedef struct Wire3DFC_Edge { u8 a; u8 b; } Wire3DFC_Edge;
extern u8 wire3d_transfer_frames;
extern u8 wire3d_uploaded_tiles;
// Own both CHR-RAM pattern tables and nametable zero. Requires writable 8 KiB
// CHR RAM and PRG RAM 0x6800..0x70BF; reserves ZP 0x00..0x0A for drawing/transfer.
// Build with --nes-chr-ram and provide cartridge PRG RAM for the stage.
// Center the viewport, clear video memory, select cyan-on-dark colors and turn
// on background rendering with NMI disabled. Do not run another PPU writer.
void Wire3DFC_Init(void);
// Clear the previous staged drawing. The displayed front image remains intact.
void Wire3DFC_BeginFrame(void);
// Draw a connected, inclusive segment. Endpoints must be -512..511. Pixels
// outside the viewport are clipped; completely outside bounding boxes return.
void Wire3DFC_DrawLine2D(s16 ax,s16 ay,s16 bx,s16 by);
// Rotate a small model-space point in Y/X/Z order. Angles wrap in 32 steps.
// Start with components in -63..63; supply three distinct writable pointers.
void Wire3DFC_RotatePoint(s16* x,s16* y,s16* z,u8 rx,u8 ry,u8 rz);
// Project camera-space coordinates using an integer reciprocal table. Require
// x/y within -127..127 and z within 32..255. Return zero without touching outputs
// on invalid input; success returns one and writes unclipped screen coordinates.
u8 Wire3DFC_ProjectPoint(s16 x,s16 y,s16 z,s16* sx,s16* sy);
// Draw when both endpoints pass the projection range. Near-plane crossings
// are rejected, not intersected with the near plane; screen pixels are clipped.
void Wire3DFC_DrawLine3D(s16 ax,s16 ay,s16 az,s16 bx,s16 by,s16 bz);
// Rotate, translate and project up to 24 vertices, then draw indexed edges.
// Invalid edge indices/depth endpoints are skipped. Model data must remain
// readable in the current PRG mapping. This draws all edges, without face culling.
void Wire3DFC_DrawModel(const Wire3DFC_Vec3* vertices,u8 vertex_count,const Wire3DFC_Edge* edges,u8 edge_count,s16 x,s16 y,s16 z,u8 rx,u8 ry,u8 rz);
// Upload changed tiles to the hidden CHR table in bounded VBlank batches and
// swap only after completion. Blocks across as many frames as needed. The two
// counters report this call's upload batches plus swap, and tile count.
void Wire3DFC_EndFrame(void);
#endifkitaqfc/lib/wire3d.h
wire3d_tables.h —
// Copyright (c) 2026 DAISUKE OBA. SPDX-License-Identifier: MIT
// Generated from round(64*sin(2*pi*i/32)) and round(64*width/z).
// Depths below 32 are rejected. Saturating 256 to 255 at the largest
// viewport/nearest depth bounds the projection error without a ninth bit.
__prg_rom const s8 w3dfc_sin[32]={
0,12,24,36,45,53,59,63,64,63,59,53,45,36,24,12,
0,-12,-24,-36,-45,-53,-59,-63,-64,-63,-59,-53,-45,-36,-24,-12,
};
#if WIRE3D_FC_WIDTH == 64
__prg_rom const u8 w3dfc_recip[256]={
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
128,124,120,117,114,111,108,105,102,100,98,95,93,91,89,87,
85,84,82,80,79,77,76,74,73,72,71,69,68,67,66,65,
64,63,62,61,60,59,59,58,57,56,55,55,54,53,53,52,
51,51,50,49,49,48,48,47,47,46,46,45,45,44,44,43,
43,42,42,41,41,41,40,40,39,39,39,38,38,38,37,37,
37,36,36,36,35,35,35,34,34,34,34,33,33,33,33,32,
32,32,32,31,31,31,31,30,30,30,30,29,29,29,29,29,
28,28,28,28,28,27,27,27,27,27,27,26,26,26,26,26,
26,25,25,25,25,25,25,25,24,24,24,24,24,24,24,23,
23,23,23,23,23,23,23,22,22,22,22,22,22,22,22,21,
21,21,21,21,21,21,21,21,20,20,20,20,20,20,20,20,
20,20,20,19,19,19,19,19,19,19,19,19,19,19,18,18,
18,18,18,18,18,18,18,18,18,18,18,17,17,17,17,17,
17,17,17,17,17,17,17,17,17,16,16,16,16,16,16,16,
};
__prg_rom const u8 w3dfc_row_lo[48]={
0,1,2,3,4,5,6,7,64,65,66,67,68,69,70,71,
128,129,130,131,132,133,134,135,192,193,194,195,196,197,198,199,
0,1,2,3,4,5,6,7,64,65,66,67,68,69,70,71,
};
__prg_rom const u8 w3dfc_row_hi[48]={
104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,
};
__prg_rom const u8 w3dfc_tile_row[48]={
0,0,0,0,0,0,0,0,8,8,8,8,8,8,8,8,
16,16,16,16,16,16,16,16,24,24,24,24,24,24,24,24,
32,32,32,32,32,32,32,32,40,40,40,40,40,40,40,40,
};
#elif WIRE3D_FC_WIDTH == 96
__prg_rom const u8 w3dfc_recip[256]={
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
192,186,181,176,171,166,162,158,154,150,146,143,140,137,134,131,
128,125,123,120,118,116,114,112,110,108,106,104,102,101,99,98,
96,95,93,92,90,89,88,87,85,84,83,82,81,80,79,78,
77,76,75,74,73,72,71,71,70,69,68,68,67,66,65,65,
64,63,63,62,61,61,60,60,59,59,58,57,57,56,56,55,
55,54,54,53,53,53,52,52,51,51,50,50,50,49,49,48,
48,48,47,47,47,46,46,46,45,45,45,44,44,44,43,43,
43,42,42,42,42,41,41,41,40,40,40,40,39,39,39,39,
38,38,38,38,37,37,37,37,37,36,36,36,36,36,35,35,
35,35,35,34,34,34,34,34,33,33,33,33,33,33,32,32,
32,32,32,32,31,31,31,31,31,31,30,30,30,30,30,30,
30,29,29,29,29,29,29,29,28,28,28,28,28,28,28,28,
27,27,27,27,27,27,27,27,26,26,26,26,26,26,26,26,
26,25,25,25,25,25,25,25,25,25,25,24,24,24,24,24,
};
__prg_rom const u8 w3dfc_row_lo[64]={
0,1,2,3,4,5,6,7,96,97,98,99,100,101,102,103,
192,193,194,195,196,197,198,199,32,33,34,35,36,37,38,39,
128,129,130,131,132,133,134,135,224,225,226,227,228,229,230,231,
64,65,66,67,68,69,70,71,160,161,162,163,164,165,166,167,
};
__prg_rom const u8 w3dfc_row_hi[64]={
104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
104,104,104,104,104,104,104,104,105,105,105,105,105,105,105,105,
105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,
106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,
};
__prg_rom const u8 w3dfc_tile_row[64]={
0,0,0,0,0,0,0,0,12,12,12,12,12,12,12,12,
24,24,24,24,24,24,24,24,36,36,36,36,36,36,36,36,
48,48,48,48,48,48,48,48,60,60,60,60,60,60,60,60,
72,72,72,72,72,72,72,72,84,84,84,84,84,84,84,84,
};
#elif WIRE3D_FC_WIDTH == 128
__prg_rom const u8 w3dfc_recip[256]={
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
255,248,241,234,228,221,216,210,205,200,195,191,186,182,178,174,
171,167,164,161,158,155,152,149,146,144,141,139,137,134,132,130,
128,126,124,122,120,119,117,115,114,112,111,109,108,106,105,104,
102,101,100,99,98,96,95,94,93,92,91,90,89,88,87,86,
85,84,84,83,82,81,80,80,79,78,77,77,76,75,74,74,
73,72,72,71,71,70,69,69,68,68,67,67,66,66,65,65,
64,64,63,63,62,62,61,61,60,60,59,59,59,58,58,57,
57,56,56,56,55,55,55,54,54,54,53,53,53,52,52,52,
51,51,51,50,50,50,49,49,49,48,48,48,48,47,47,47,
47,46,46,46,46,45,45,45,45,44,44,44,44,43,43,43,
43,42,42,42,42,42,41,41,41,41,41,40,40,40,40,40,
39,39,39,39,39,38,38,38,38,38,38,37,37,37,37,37,
37,36,36,36,36,36,36,35,35,35,35,35,35,35,34,34,
34,34,34,34,34,33,33,33,33,33,33,33,33,32,32,32,
};
__prg_rom const u8 w3dfc_row_lo[96]={
0,1,2,3,4,5,6,7,128,129,130,131,132,133,134,135,
0,1,2,3,4,5,6,7,128,129,130,131,132,133,134,135,
0,1,2,3,4,5,6,7,128,129,130,131,132,133,134,135,
0,1,2,3,4,5,6,7,128,129,130,131,132,133,134,135,
0,1,2,3,4,5,6,7,128,129,130,131,132,133,134,135,
0,1,2,3,4,5,6,7,128,129,130,131,132,133,134,135,
};
__prg_rom const u8 w3dfc_row_hi[96]={
104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,
105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,
106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,
107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,
108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,
109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
};
__prg_rom const u8 w3dfc_tile_row[96]={
0,0,0,0,0,0,0,0,16,16,16,16,16,16,16,16,
32,32,32,32,32,32,32,32,48,48,48,48,48,48,48,48,
64,64,64,64,64,64,64,64,80,80,80,80,80,80,80,80,
96,96,96,96,96,96,96,96,112,112,112,112,112,112,112,112,
128,128,128,128,128,128,128,128,144,144,144,144,144,144,144,144,
160,160,160,160,160,160,160,160,176,176,176,176,176,176,176,176,
};
#endifkitaqfc/lib/wire3d_tables.h
zapper.h — Eingabeschnittstelle für die Lichtpistole
#ifndef ZAPPER_H
#define ZAPPER_H
#include "intrinsics.h"
// Return raw 4016 & 18, retaining trigger and active-low light bits.
u8 __zapper_raw1(void);
// Return raw 4017 & 18 for the second port.
u8 __zapper_raw2(void);
// Return port-1 trigger bit 4 normalized to 0 or 1.
u8 __zapper_trigger1(void);
// Return port-2 trigger bit 4 normalized to 0 or 1.
u8 __zapper_trigger2(void);
// Invert port-1 bit 3 and normalize: one means light detected.
u8 __zapper_light1(void);
// Invert port-2 bit 3 and normalize: one means light detected.
u8 __zapper_light2(void);
// Default to the port-2 normalized trigger reader.
u8 __zapper_trigger(void);
// Default to the port-2 normalized light reader.
u8 __zapper_light(void);
#endifkitaqfc/lib/zapper.h
zx0.h —
#pragma once
#include "core.h"
// 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 into caller-owned RAM, then transfer to CHR RAM or nametable memory.
// Rendering must be off. Preserve PPUCTRL; set scroll before enabling rendering.
// The workspace must hold the whole output. No palette upload or CHR ROM writes.
u16 zx0_decompress_vram(u16 ppu_addr,void* workspace,u16 capacity,const void* src,u16 packed_size);kitaqfc/lib/zx0.h






