SERIE KITAQ • EDICIÓN DE REFERENCIA
BIBLIOTECA KITAQGB
Herramientas para crear un juego
Código fuente recopilado: 14 de septiembre de 2026 · Edición inglesa: 14 de septiembre de 2026
Uso de la biblioteca con el compilador nativo
lib/ contiene cabeceras y fuentes C que se compilan en la ROM de la consola. El compilador de PC y las herramientas están escritos en Rust; el código de los juegos, las bibliotecas de destino y sus API siguen en C. SOURCE_MANIFEST.json y LIBRARY_MERGE.json registran las fuentes elegidas cuando se incluyen.
kitaqgb · Compilador nativo Rust y herramientas auxiliares · GitHub Actions
Las compilaciones nativas y comprobaciones de ejecución finalizaron correctamente en Windows, Linux, macOS ARM y macOS Intel. KITAQGB superó 48 pruebas y 395 comprobaciones de herramientas por entorno; KITAQFC, 55 y 401. También se probó Rust 1.85. PUBLIC_DISTRIBUTION.json registra los hashes de los binarios instalados y el origen de la validación. Los flujos públicos de GitHub Actions compilan y prueban estas fuentes de forma independiente.
Las salidas de referencia guardadas comprueban bytes de ROM, diagnósticos y formatos de las herramientas. Las anteriores pruebas de emulación C# son registros históricos vinculados a sus fuentes originales. No demuestran automáticamente todas las API Rust, el hardware real ni el arranque completo de juegos mediante el BIOS FDS. El script PNG original no está disponible y se reconstruyó a partir de su especificación; no puede afirmarse igualdad de bytes con él.
Programas de ejemplo completos
Se incluyen todos los programas, las cabeceras compartidas, el archivo ascii.c suministrado y sus recursos convertidos. Los nombres que empiezan por m_ son funciones auxiliares de estos manuales. Lee cada comando de compilación junto a su resultado esperado y su registro de verificación. Ejecuta los comandos desde la carpeta que contiene los repositorios hermanos.
Script de compilación por lotes / Resultados y capturas de pantalla
Mostrar el juego de caracteres incluido gb_font.c
Objetivo: Muestra qué letras, dígitos y signos de puntuación contiene la fuente original incluida y cómo dibujarlos.
Funcionamiento: m_init prepara la pantalla y la fuente. m_text dibuja cada línea; m_put dibuja las comillas dobles mediante el código de carácter 34.
Controles y resultado esperado: Busque 26 letras mayúsculas, 26 minúsculas, 10 dígitos y 30 signos de puntuación. Compruebe que todos los glifos sean legibles. No se requiere ninguna entrada.

Descargar código fuente / Estado de la verificación
.\kitaqgb\kitaqgb.exe kitaq-docs/samples/gb_font.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_font.gb --profile=dev --rst-disable --stack-bank=fixed// Display the letters, digits and punctuation from the supplied ascii.c font.
// Expected: Uppercase, lowercase, numbers and all 30 supplied punctuation glyphs
#include "gb_common.h"
// Lay out every supplied character category, yielding between rows. The final
// m_put uses character code 34 to display the double quote separately.
void main() {
m_init();
m_text(2,3,"FONT");
m_text(2,5,"ABCDEFGHIJKLMNOP"); m_wait();
m_text(2,6,"QRSTUVWXYZ"); m_wait();
m_text(2,8,"0123456789"); m_wait();
m_text(2,10,"abcdefghijklmnop"); m_wait();
m_text(2,11,"qrstuvwxyz"); m_wait();
m_text(2,13,"!#$%&'()*+,-./"); m_wait();
m_text(2,14,":;<=>?@[]^_`{}~"); m_wait();
m_put(16,13,34); m_wait();
while (1) { m_wait(); }
}Su primer texto en pantalla gb_hello.c
Objetivo: Muestra la secuencia básica para iniciar una ROM y dibujar texto y un número en el fondo.
Funcionamiento: Después de m_init, m_text dibuja el saludo y m_number da formato a 42. El bucle final espera fotogramas y mantiene la pantalla visible.
Controles y resultado esperado: La pantalla muestra HELLO WORLD y 042. El cero inicial corresponde al formato decimal de tres dígitos.

Descargar código fuente / Estado de la verificación
.\kitaqgb\kitaqgb.exe kitaq-docs/samples/gb_hello.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_hello.gb --profile=dev --rst-disable --stack-bank=fixed// Display a first message on screen.
// Expected: HELLO WORLD and 042
#include "gb_common.h"
// Initialize the display/font, write HELLO WORLD and a three-digit 042,
// then wait for frames so the result remains visible.
void main() {
m_init();
m_text(2,3,"HELLO");
m_text(2,5,"HELLO WORLD");
m_number(42);
while (1) { m_wait(); }
}Calcular con un valor intermedio más amplio gb_arithmetic.c
Objetivo: Muestra cómo conservar un resultado intermedio que no cabe en ocho bits.
Funcionamiento: (u16)200 + 100 produce 300. El programa divide el resultado entre 10 y luego lo convierte a u8 para mostrarlo. Observa que la conversión al tipo más amplio ocurre antes de la suma.
Controles y resultado esperado: 030 representa el resultado calculado, 30.

Descargar código fuente / Estado de la verificación
.\kitaqgb\kitaqgb.exe kitaq-docs/samples/gb_arithmetic.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_arithmetic.gb --profile=dev --rst-disable --stack-bank=fixed// Variables, arithmetic and type conversion.
// Expected: 030
#include "gb_common.h"
// Widen before adding 200 + 100, divide the 16-bit sum, and display 30.
// The cast demonstrates avoiding an 8-bit intermediate result.
void main() {
m_init();
m_text(2,3,"ARITHMETIC");
u16 sum;
sum = (u16)200 + 100;
m_number((u8)(sum / 10));
while (1) { m_wait(); }
}Bifurcaciones y bucles gb_control.c
Objetivo: Prueba for, continue, while, do/while y switch en un cálculo sencillo.
Funcionamiento: Sumar de 0 a 7 omitiendo 3 da 25. El bucle while avanza hasta 30, do/while hasta 32 y switch selecciona case 32 para asignar 42.
Controles y resultado esperado: 042 es el resultado final de estos bucles y bifurcaciones.

Descargar código fuente / Estado de la verificación
.\kitaqgb\kitaqgb.exe kitaq-docs/samples/gb_control.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_control.gb --profile=dev --rst-disable --stack-bank=fixed// Conditional branches and loops.
// Expected: 042
#include "gb_common.h"
// Exercise loop control and a final branch, then display the selected value 42.
void main() {
m_init();
m_text(2,3,"CONTROL");
u8 i; u8 sum; sum=0;
for (i=0;i<8;i++) { if (i==3) continue; sum=(u8)(sum+i); }
while (sum<30) { sum++; }
do { sum++; } while (sum<32);
switch (sum) { case 32: sum=42; break; default: sum=0; break; }
m_number(sum);
while (1) { m_wait(); }
}Funciones, arrays, estructuras y punteros gb_aggregate.c
Objetivo: Muestra cómo agrupar valores y acceder a ellos mediante funciones y punteros.
Funcionamiento: El programa copia un Point que contiene (10,20) y después escribe de 1 a 4 en un array mediante un puntero. Suma el resultado de la función, 30, a los valores del array 1, 2 y 4 y a la constante 5.
Controles y resultado esperado: La suma se muestra como 042. Siga la copia de la estructura, las escrituras en ptr[i] y el valor devuelto por la función.
![Funciones, arrays, estructuras y punteros: La suma se muestra como 042. Siga la copia de la estructura, las escrituras en ptr[i] y el valor devuelto por la función.](../verification/gb_aggregate.png)
Descargar código fuente / Estado de la verificación
.\kitaqgb\kitaqgb.exe kitaq-docs/samples/gb_aggregate.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_aggregate.gb --profile=dev --rst-disable --stack-bank=fixed// Functions, arrays, structures and pointers.
// Expected: 042
#include "gb_common.h"
typedef struct { u8 x; u8 y; } Point;
// Add two byte values and explicitly narrow the returned result to u8.
u8 add(u8 a,u8 b) { return (u8)(a+b); }
// Copy a structure, fill an array through a pointer, and combine selected values
// through add() to produce 42. Keep the final screen visible in the idle loop.
void main() {
m_init();
m_text(2,3,"AGGREGATE");
Point a; Point b; u8 i; u8 data[4]; u8* ptr;
a.x=10; a.y=20; b=a; ptr=data;
for(i=0;i<4;i++) ptr[i]=(u8)(i+1);
m_number((u8)(add(b.x,b.y)+ptr[0]+ptr[1]+ptr[3]+5));
while (1) { m_wait(); }
}Banderas de bits y copia de búfer gb_bits_memory.c
Objetivo: Agrupa banderas en un byte y copia un búfer en un área de almacenamiento independiente.
Funcionamiento: __memset borra cuatro bytes. El programa activa el bit 3, invierte el bit 1 y después copia los cuatro bytes con __memcpy.
Controles y resultado esperado: el primer byte de destino se muestra como 010; el bit 3 aporta 8 y el bit 1 aporta 2.

Descargar código fuente / Estado de la verificación
.\kitaqgb\kitaqgb.exe kitaq-docs/samples/gb_bits_memory.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_bits_memory.gb --profile=dev --rst-disable --stack-bank=fixed// Bit operations and memory copying.
// Expected: 010
#include "gb_common.h"
void __memset(void* dst,u8 value,u16 len);
void __memcpy(void* dst,const void* src,u16 len);
void __bit_set(u8* base,u16 bit);
void __bit_toggle(u8* base,u16 bit);
// Clear the source bytes, set bits 3 and 1, copy the buffer, and display 8 + 2 = 10.
void main() {
m_init();
m_text(2,3,"BITS MEMORY");
u8 data[4]; u8 copy[4];
__memset(data,0,4); __bit_set(data,3); __bit_toggle(data,1);
__memcpy(copy,data,4); m_number(copy[0]);
while (1) { m_wait(); }
}Contar nuevas pulsaciones de un botón gb_input.c
Objetivo: Distingue una nueva pulsación de un botón que sigue pulsado.
Funcionamiento: Cada fotograma llama a input_update. El contador solo avanza cuando input_pressed(BTN_A) es verdadero.
Controles y resultado esperado: el contador comienza en 000. Pulse A para obtener 001; mantenerlo pulsado no añade más. Suéltelo y vuelva a pulsarlo para obtener 002. El contador de un byte vuelve a 000 después de 255.

Descargar código fuente / Estado de la verificación
.\kitaqgb\kitaqgb.exe kitaqgb/lib/input.c kitaq-docs/samples/gb_input.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_input.gb --profile=dev --rst-disable --stack-bank=fixed// Distinguish a new button press from a held button.
// Expected: 000 initially; A increments once per press
#include "gb_common.h"
#include "input.h"
u8 manual_count;
// Sample buttons once per frame and increment only on a new A press.
// Holding A does not repeatedly increment; the byte-sized counter wraps after 255.
void main() {
m_init();
m_text(2,3,"INPUT");
input_init();
m_number(0);
while (1) { m_wait(); input_update(); if(input_pressed(BTN_A)) { manual_count++; m_number(manual_count); } }
}Multiplicar valores de punto fijo Q8.8 gb_fixed.c
Objetivo: Muestra la conversión de entero a Q8.8, la multiplicación y la conversión de vuelta a entero.
Funcionamiento: fix_from_int convierte 3 y 4 a Q8.8. fix_mul los multiplica y fix_to_int convierte el producto de vuelta a entero.
Controles y resultado esperado: 012 significa 3 × 4 = 12. Es el entero convertido, no el valor interno escalado por 256.

Descargar código fuente / Estado de la verificación
.\kitaqgb\kitaqgb.exe kitaqgb/lib/fixed.c kitaq-docs/samples/gb_fixed.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_fixed.gb --profile=dev --rst-disable --stack-bank=fixed// Calculate with signed Q8.8 fixed-point values.
// Expected: 012
#include "gb_common.h"
#include "fixed.h"
// Convert 3 and 4 to Q8.8, multiply them, convert the result back to an
// integer, and display 12.
void main() {
m_init();
m_text(2,3,"FIXED");
fix8 a; fix8 b; a=fix_from_int(3); b=fix_from_int(4);
m_number((u8)fix_to_int(fix_mul(a,b)));
while (1) { m_wait(); }
}Asignar desde un pool fijo de objetos gb_entity.c
Objetivo: Crea un objeto a partir de un conjunto fijo de posiciones, sin asignación dinámica de memoria.
Funcionamiento: entity_init reinicia el pool. entity_create crea el tipo 1 en (20,30); el programa comprueba el ID de fallo 0xFF antes de establecer vx en 2.
Controles y resultado esperado: 001 es la cantidad de objetos activos, no un ID ni una coordenada. Este ejemplo no actualiza ni dibuja el objeto, por lo que no aparece ningún personaje en movimiento.

Descargar código fuente / Estado de la verificación
.\kitaqgb\kitaqgb.exe kitaqgb/lib/entity.c kitaq-docs/samples/gb_entity.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_entity.gb --profile=dev --rst-disable --stack-bank=fixed// Allocate an entity from a fixed-capacity object pool.
// Expected: 001
#include "gb_common.h"
#include "entity.h"
// Create one entity and check the 0xFF allocation-failure sentinel before
// accessing its velocity. Display the pool occupancy, not the entity ID.
void main() {
m_init();
m_text(2,3,"ENTITY");
u8 id; entity_init(); id=entity_create(1,20,30);
if(id!=0xFF) entity_get(id)->vx=2; m_number(entity_count_active());
while (1) { m_wait(); }
}Registrar un valor de diagnóstico en RAM gb_debug.c
Objetivo: Conserva un valor del juego con nombre en un búfer de diagnóstico, separado de la visualización en pantalla.
Funcionamiento: El programa inicializa la depuración, establece la etiqueta de fotograma en 1 y registra el valor 42 con el nombre HP.
Controles y resultado esperado: 001 es la cantidad de entradas de traza. HP=42 se guarda en el búfer de diagnóstico; la pantalla por sí sola no muestra ni verifica ese contenido.

Descargar código fuente / Estado de la verificación
.\kitaqgb\kitaqgb.exe kitaqgb/lib/debug.c kitaq-docs/samples/gb_debug.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_debug.gb --profile=dev --rst-disable --stack-bank=fixed// Record diagnostic values in the debug trace.
// Expected: 001; trace log contains HP=42
#include "gb_common.h"
#include "debug.h"
// Record HP = 42 with frame tag 1 and display the number of trace entries.
// The trace buffer contains the value; the screen displays the count, not HP.
void main() {
m_init();
m_text(2,3,"DEBUG");
debug_init(); debug_set_frame(1); debug_trace_u8("HP",42);
m_number(debug_get_trace_count());
while (1) { m_wait(); }
}Guardar un historial de posiciones gb_chain.c
Objetivo: Muestra cómo guardar un historial de posiciones en un búfer circular.
Funcionamiento: chain_init asocia un array con espacio para cuatro puntos. Después, chain_push_head registra (20,30).
Controles y resultado esperado: 042 es un marcador fijo de finalización, no una coordenada ni una cantidad. Inspecciona trail y points para comprobar el historial guardado. Este programa no dibuja un cuerpo que siga al protagonista.

Descargar código fuente / Estado de la verificación
.\kitaqgb\kitaqgb.exe kitaqgb/lib/chain.c kitaq-docs/samples/gb_chain.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_chain.gb --profile=dev --rst-disable --stack-bank=fixed// Store a position history in a ring buffer.
// Expected: 042; history contains (20,30)
#include "gb_common.h"
#include "chain.h"
Chain trail; ChainPoint points[4];
// Attach four history slots and record one point. The displayed 42 is a fixed
// completion marker; inspect the chain to verify the stored (20,30) point.
void main() {
m_init();
m_text(2,3,"CHAIN");
chain_init(&trail,points,4); chain_push_head(&trail,20,30);
m_number(42);
while (1) { m_wait(); }
}Leer el contador de fotogramas de la biblioteca gb_system.c
Objetivo: Muestra cómo las esperas contadas en fotogramas afectan al contador de fotogramas de la biblioteca.
Funcionamiento: Después de system_init, el programa llama dos veces a system_wait_vblank y muestra system_get_frame8.
Controles y resultado esperado: El resultado es 002. El bucle de espera utiliza la función auxiliar m_wait del manual, por lo que el valor mostrado no sigue aumentando.

Descargar código fuente / Estado de la verificación
.\kitaqgb\kitaqgb.exe kitaqgb/lib/system.c kitaq-docs/samples/gb_system.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_system.gb --profile=dev --rst-disable --stack-bank=fixed// Count completed frame waits.
// Expected: 002
#include "gb_common.h"
#include "system.h"
// Reset the library frame count, perform two counted waits, and display 2.
// Subsequent m_wait calls leave that library counter unchanged.
void main() {
m_init();
m_text(2,3,"SYSTEM");
system_init(); system_wait_vblank(); system_wait_vblank();
m_number(system_get_frame8());
while (1) { m_wait(); }
}Seleccionar el ID de la escena actual gb_scene.c
Objetivo: Muestra cómo seleccionar un ID para distinguir escenas, como la pantalla de título y la partida.
Funcionamiento: El programa registra dos entradas SceneDef inicializadas a cero y selecciona el ID 1 mediante scene_change.
Controles y resultado esperado: 001 es el ID actual devuelto por scene_get_current. El ejemplo no registra callbacks de escena ni dibujo de transiciones.

Descargar código fuente / Estado de la verificación
.\kitaqgb\kitaqgb.exe kitaqgb/lib/scene.c kitaq-docs/samples/gb_scene.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_scene.gb --profile=dev --rst-disable --stack-bank=fixed// Switch the current scene ID.
// Expected: 001; no callbacks registered
#include "gb_common.h"
#include "scene.h"
SceneDef manual_scenes[2];
// Register two zero-initialized scene entries, select ID 1 and display it.
// No callbacks are registered in this example.
void main() {
m_init();
m_text(2,3,"SCENE");
scene_init(manual_scenes,2); scene_change(1);
m_number(scene_get_current());
while (1) { m_wait(); }
}Convertir coordenadas del mundo en coordenadas de pantalla gb_camera.c
Objetivo: Resta la posición de la cámara para obtener la posición en pantalla de un punto del mundo.
Funcionamiento: Camera_Set recibe el valor Q8.8 2560, equivalente a X=10 píxeles. Después, Camera_WorldToScreenX convierte la coordenada del mundo X=52.
Controles y resultado esperado: 052 menos 010 da el 042 mostrado. Es un cálculo de coordenadas; no desplaza el fondo.

Descargar código fuente / Estado de la verificación
.\kitaqgb\kitaqgb.exe kitaqgb/lib/scroll.c kitaqgb/lib/camera.c kitaq-docs/samples/gb_camera.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_camera.gb --profile=dev --rst-disable --stack-bank=fixed// Convert world coordinates to screen coordinates.
// Expected: 042: world x=52 minus camera x=10
#include "gb_common.h"
#include "camera.h"
Camera8_8 cam;
// Set the camera X coordinate to 10 pixels in Q8.8 (10 * 256), then subtract
// it from world X = 52 to display screen X = 42.
void main() {
m_init();
m_text(2,3,"CAMERA");
Camera_Init(&cam); Camera_Set(&cam,2560,0);
m_number((u8)Camera_WorldToScreenX(&cam,52));
while (1) { m_wait(); }
}Descomprimir datos RLE en RAM gb_rle.c
Objetivo: Prueba una representación compacta de bytes repetidos mediante pares de cantidad y valor.
Funcionamiento: Los bytes comprimidos {3,42,0} representan tres copias de 42 seguidas de un terminador con cantidad cero. rle_decode escribe en un destino de tres bytes.
Controles y resultado esperado: el último byte, out[2], se muestra como 042. Los tres bytes descomprimidos deben contener 42.
![Descomprimir datos RLE en RAM: el último byte, out[2], se muestra como 042. Los tres bytes descomprimidos deben contener 42.](../verification/gb_rle.png)
Descargar código fuente / Estado de la verificación
.\kitaqgb\kitaqgb.exe kitaqgb/lib/rle.c kitaq-docs/samples/gb_rle.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_rle.gb --profile=dev --rst-disable --stack-bank=fixed// Decode run-length encoded data.
// Expected: 042; three bytes each equal to 42
#include "gb_common.h"
#include "rpg.h"
__prg_rom u8 packed[] = {3,42,0};
// Decode count/value pair (3,42), terminated by a zero count, into a
// three-byte buffer and display the final decoded byte.
void main() {
m_init();
m_text(2,3,"RLE");
u8 out[3]; rle_decode(out,packed); m_number(out[2]);
while (1) { m_wait(); }
}Leer y escribir una casilla del tablero gb_board.c
Objetivo: Muestra cómo se corresponden las coordenadas de una cuadrícula con el almacenamiento de un juego de tablero.
Funcionamiento: Un array de 16 bytes almacena un tablero de 4×4. El programa lo borra, escribe 42 en la celda (2,1) y vuelve a leer esa misma celda.
Controles y resultado esperado: 042 es el valor leído de nuevo. El programa no dibuja el tablero de 4×4.

Descargar código fuente / Estado de la verificación
.\kitaqgb\kitaqgb.exe kitaqgb/lib/slg_board.c kitaq-docs/samples/gb_board.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_board.gb --profile=dev --rst-disable --stack-bank=fixed// Read and write cells in a game board.
// Expected: 042
#include "gb_common.h"
#include "slg.h"
SLGBoard board; u8 cells[16];
// Create a cleared 4-by-4 board in caller-owned storage, write 42 at (2,1),
// and display the value read back from the same cell.
void main() {
m_init();
m_text(2,3,"BOARD");
slg_board_init(&board,4,4,cells); slg_board_clear(&board,0);
slg_board_set(&board,2,1,42); m_number(slg_board_get(&board,2,1));
while (1) { m_wait(); }
}Avanzar una caja un paso de física gb_physics.c
Objetivo: Inicializa un mundo y un cuerpo rectangular, y después actualiza la posición a partir de la velocidad.
Funcionamiento: El cuerpo empieza en (40,40), con velocidad (2,0) y gravedad cero. El programa llama a kq2d_step una vez.
Controles y resultado esperado: 042 es la coordenada X resultante, medida en píxeles enteros en este ejemplo. No se dibuja una caja ni una animación continua.

Descargar código fuente / Estado de la verificación
.\kitaqgb\kitaqgb.exe kitaqgb/lib/fixed.c kitaqgb/lib/physics2d.c kitaq-docs/samples/gb_physics.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_physics.gb --profile=dev --rst-disable --stack-bank=fixed// Advance a rectangular body through one physics step.
// Expected: 042: integer pixel coordinates
#include "gb_common.h"
#include "physics2d.h"
KQWorld2D world; KQBody2D boxes[1];
// Create one box at X = 40, set horizontal velocity 2 and zero gravity,
// then display its X coordinate after a single physics step.
void main() {
m_init();
m_text(2,3,"PHYSICS");
kq2d_world_init(&world,boxes,1);
kq2d_body_init(&boxes[0],40,40,4,4);
kq2d_body_set_velocity(&boxes[0],2,0);
world.gravity_x=0; world.gravity_y=0;
kq2d_step(&world); m_number((u8)boxes[0].x);
while (1) { m_wait(); }
}Gestionar la finalización y el tiempo de espera de una transferencia serie gb_link.c
Objetivo: Distingue una transferencia completada de otra que no termina dentro del límite de espera.
Funcionamiento: El maestro envía 42 y espera con Link_WaitByte. Al finalizar, muestra el byte recibido; si vence el tiempo de espera, cancela la transferencia y muestra cero.
Controles y resultado esperado: Una transferencia completada sin conexión puede devolver 255. Si vence el tiempo de espera, muestra 000; con un par conectado, muestra el byte recibido. El resultado no siempre es 042.

Descargar código fuente / Estado de la verificación
.\kitaqgb\kitaqgb.exe kitaqgb/lib/link_hwregs_gb.c kitaqgb/lib/link.c kitaq-docs/samples/gb_link.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_link.gb --profile=dev --rst-disable --stack-bank=fixed// Handle serial transfers that do not deliver a byte in time.
// Expected: 255 for disconnected link; 000 if timeout; peer value when connected
#include "gb_common.h"
#include "link.h"
// Start a master transfer of byte 42 and wait with a bounded timeout.
// Display the received byte on completion; cancel and display zero on timeout.
void main() {
m_init();
m_text(2,3,"LINK");
u8 value; Link_InitMaster(); Link_BeginTransfer(42);
if(Link_WaitByte(4,&value)) m_number(value);
else { Link_Cancel(); m_number(0); }
while (1) { m_wait(); }
}Leer datos de ROM con un argumento de banco gb_bank.c
Objetivo: Muestra los argumentos necesarios para copiar datos de ROM a RAM.
Funcionamiento: far_data_read copia los dos bytes 7 y 42 en copied, con el argumento de banco 0 y longitud 2.
Controles y resultado esperado: El segundo byte de destino se muestra como 042. Este ejemplo lee ROM fija; no demuestra una transferencia entre distintos bancos conmutables.

Descargar código fuente / Estado de la verificación
.\kitaqgb\kitaqgb.exe kitaqgb/lib/bank.c kitaq-docs/samples/gb_bank.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_bank.gb --profile=dev --rst-disable --stack-bank=fixed// Read data using an explicit ROM bank.
// Expected: 042; explicit bank argument 0
#include "gb_common.h"
#include "bank.h"
__prg_rom u8 values[] = {7,42}; u8 copied[2];
// Copy two ROM bytes using bank argument zero and display the second byte.
// This introduces the API; it does not test switching between distinct payload banks.
void main() {
m_init();
m_text(2,3,"BANK");
far_data_read(0,values,copied,2); m_number(copied[1]);
while (1) { m_wait(); }
}Cargar datos por ID de recurso gb_asset.c
Objetivo: Registra la ubicación y la longitud de un recurso y después recupera sus bytes por ID.
Funcionamiento: El recurso 0 tiene tipo RAW, banco 0, un puntero a {7,42} y longitud 2. asset_load_raw lo copia a un búfer RAM de dos bytes.
Controles y resultado esperado: El segundo byte se muestra como 042. Esto demuestra la búsqueda y copia de recursos, no el renderizado de imágenes.

Descargar código fuente / Estado de la verificación
.\kitaqgb\kitaqgb.exe kitaqgb/lib/asset.c kitaq-docs/samples/gb_asset.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_asset.gb --profile=dev --rst-disable --stack-bank=fixed// Load asset bytes into RAM by asset ID.
// Expected: 042
#include "gb_common.h"
#include "asset.h"
AssetDesc table[1]; __prg_rom u8 values[] = {7,42}; u8 copied[2];
// Register a two-byte raw asset, copy it into RAM and display its second byte.
// This example uses bank zero and a destination sized for the complete payload.
void main() {
m_init();
m_text(2,3,"ASSET");
table[0].type=ASSET_TYPE_RAW; table[0].bank=0;
table[0].ptr=values; table[0].len=2;
asset_set_table(0,table,1); asset_load_raw(0,copied,2);
m_number(copied[1]);
while (1) { m_wait(); }
}Asignar un proyectil gb_danmaku.c
Objetivo: Inicializa el pool de proyectiles y comprueba su ocupación tras crear uno.
Funcionamiento: Después de danmaku_reset, el programa llama a danmaku_spawn(40,40,16,0) y muestra dm_count.
Controles y resultado esperado: 001 es la cantidad de proyectiles asignados. Aquí no hay un bucle de actualización de proyectiles ni un compositor de fondo, así que no se dibuja ningún proyectil en movimiento.

Descargar código fuente / Estado de la verificación
.\kitaqgb\kitaqgb.exe kitaqgb/lib/danmaku.c kitaq-docs/samples/gb_danmaku.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_danmaku.gb --profile=dev --rst-disable --stack-bank=fixed// Allocate a bullet and inspect the pool count.
// Expected: 001; numeric pool example, no bullet BG compositor
#include "gb_common.h"
#include "danmaku.h"
// Reset the bullet pool, spawn one bullet and display the active count.
// This numeric example does not install the background bullet compositor.
void main() {
m_init();
m_text(2,3,"DANMAKU");
danmaku_reset(); danmaku_spawn(40,40,16,0);
m_number(dm_count);
while (1) { m_wait(); }
}Configurar una paleta de fondo de CGB gb_cgb_palette.c
Objetivo: Elige los colores del fondo y del texto mediante los componentes RGB de Game Boy Color.
Funcionamiento: El programa desactiva el LCD durante VBlank, configura el color 0 de la paleta 0 como blanco (31,31,31) y el color 3 como violeta (12,0,22), y después activa la pantalla.
Controles y resultado esperado: Ejecútelo en modo CGB para ver texto violeta y 042 sobre blanco. La salida monocroma de DMG no permite comprobar estos colores.

Descargar código fuente / Estado de la verificación
.\kitaqgb\kitaqgb.exe kitaqgb/lib/cgb_palette.c kitaq-docs/samples/gb_cgb_palette.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_cgb_palette.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb// Set Game Boy Color palette entries.
// Expected: 042 in purple on white; CGB mode
#include "gb_common.h"
#include "cgb_palette.h"
// Set palette-zero background colors to white and purple, then display 42.
// Run the ROM in CGB mode to observe the color result.
void main() {
m_init();
m_text(2,3,"CGB PALETTE");
// Disable the LCD during VBlank so both palette bytes remain accessible.
m_wait(); M_LCDC = 0;
cgb_bg_rgb(0,0,31,31,31); cgb_bg_rgb(0,3,12,0,22);
M_LCDC = 0x91;
m_number(42);
while (1) { m_wait(); }
}Desplazar el fondo horizontalmente gb_scroll.c
Objetivo: Mueve el punto de vista sin volver a dibujar el contenido del fondo.
Funcionamiento: Cada fotograma incrementa phase y lo pasa a Scroll_SetBg. La posición de ocho bits vuelve a cero después de 255.
Controles y resultado esperado: La palabra SCROLL se mueve hacia la izquierda. Observe su posición a lo largo del tiempo; una sola captura no puede mostrar el movimiento.

Descargar código fuente / Estado de la verificación
.\kitaqgb\kitaqgb.exe kitaqgb/lib/scroll.c kitaq-docs/samples/gb_scroll.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_scroll.gb --profile=dev --rst-disable --stack-bank=fixed// Scroll the background horizontally.
// Expected: title moves left as SCX increases
#include "gb_common.h"
#include "scroll.h"
u8 phase;
// Advance an 8-bit horizontal scroll position once per frame, wrapping naturally
// after 255. Background motion demonstrates the changing scroll register.
void main() {
m_init();
m_text(2,3,"SCROLL");
Scroll_SetBg(0,0);
while (1) { m_wait(); phase++; Scroll_SetBg(phase,0); }
}Encolar una actualización de tile gb_vram_queue.c
Objetivo: Separa una solicitud de dibujo de la transferencia a VRAM que la aplica.
Funcionamiento: vram_queue_bg_tile encola el tile 52 en la coordenada (3,8) y vram_flush lo transfiere. En la fuente incluida, el tile 52 es el dígito 4.
Controles y resultado esperado: Busque un único 4 en la coordenada de tile del fondo (3,8). Es una actualización de tile, no un contador numérico.

Descargar código fuente / Estado de la verificación
.\kitaqgb\kitaqgb.exe kitaqgb/lib/vram.c kitaq-docs/samples/gb_vram_queue.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_vram_queue.gb --profile=dev --rst-disable --stack-bank=fixed// Queue a VRAM update and flush it at VBlank.
// Expected: 4 at (3,8)
#include "gb_common.h"
#include "vram.h"
// Queue font tile 52 (the digit 4) at tile coordinate (3,8), then wait for
// VBlank and execute the queued transfer.
void main() {
m_init();
m_text(2,3,"VRAM QUEUE");
vram_init();
vram_queue_bg_tile(3,8,52); vram_flush();
while (1) { m_wait(); }
}Mostrar un sprite mediante DMA de OAM gb_sprite.c
Objetivo: Asigna y muestra un sprite de forma independiente del fondo.
Funcionamiento: El pool recién inicializado proporciona la posición 0. El programa selecciona el tile 65, establece la posición (70,80), activa la visualización OBJ y transfiere la OAM espejo en cada fotograma.
Controles y resultado esperado: Aparece una letra A inmóvil en la posición de sprite indicada. En un juego, comprueba si falló la asignación antes de usar el ID devuelto.

Descargar código fuente / Estado de la verificación
.\kitaqgb\kitaqgb.exe kitaqgb/lib/sprite.c kitaq-docs/samples/gb_sprite.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_sprite.gb --profile=dev --rst-disable --stack-bank=fixed// Display a sprite through the OAM DMA path.
// Expected: letter A at sprite position
#include "gb_common.h"
#include "sprite.h"
// Allocate the first sprite, choose font tile 65 (A), set its position and
// enable sprite display. Flush shadow OAM after each frame wait.
void main() {
m_init();
m_text(2,3,"SPRITE");
// The freshly reset pool guarantees slot zero for this first allocation.
// In a running game, check the allocation-failure sentinel before using the returned ID.
sprite_init(); sprite_set_tile(sprite_alloc(),65);
sprite_set_pos(0,70,80); M_LCDC=(u8)(M_LCDC|2);
while (1) { m_wait(); sprite_flush_oam_now(); }
}Generar un valor aleatorio reproducible gb_rng.c
Objetivo: Utiliza una semilla para reproducir una secuencia pseudoaleatoria.
Funcionamiento: rng_seed(1234) inicializa el generador y después se llama una vez a rng_range(10). El límite superior, 10, queda excluido.
Controles y resultado esperado: La pantalla muestra un valor entre 000 y 009. Reiniciar el mismo programa con la misma semilla reproduce ese valor; no cambia en cada fotograma.

Descargar código fuente / Estado de la verificación
.\kitaqgb\kitaqgb.exe kitaqgb/lib/rng.c kitaq-docs/samples/gb_rng.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_rng.gb --profile=dev --rst-disable --stack-bank=fixed// Generate a repeatable pseudorandom value from a seed.
// Expected: value 000 through 009; same seed repeats
#include "gb_common.h"
#include "rpg.h"
// Seed the generator with 1234 and display one value in [0,10).
// Restarting with the same seed reproduces the sequence.
void main() {
m_init();
m_text(2,3,"RNG");
rng_seed(1234); m_number(rng_range(10));
while (1) { m_wait(); }
}Guardar una bandera de estado del juego gb_flags.c
Objetivo: Representa un estado booleano, como si un evento ha terminado, mediante un número de bandera.
Funcionamiento: El programa borra la bandera 12, la activa y la vuelve a leer con flag_get.
Controles y resultado esperado: 001 significa que el indicador 12 es verdadero. El ejemplo opera sobre indicadores en RAM y no los conserva al apagar y encender.

Descargar código fuente / Estado de la verificación
.\kitaqgb\kitaqgb.exe kitaqgb/lib/flags.c kitaq-docs/samples/gb_flags.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_flags.gb --profile=dev --rst-disable --stack-bank=fixed// Read and write RAM-backed game-state flags.
// Expected: 001
#include "gb_common.h"
#include "rpg.h"
// Clear and set flag 12, then display its Boolean value. This does not write
// a save file or demonstrate persistence across power cycles.
void main() {
m_init();
m_text(2,3,"FLAGS");
flag_clear(12); flag_set(12); m_number(flag_get(12));
while (1) { m_wait(); }
}Avanzar un círculo un paso de física gb_circle.c
Objetivo: Configura un cuerpo circular y actualiza su posición a partir de la velocidad.
Funcionamiento: El círculo activo tiene radio 4, posición (40,40) y velocidad (2,0). La gravedad es cero y linear_damping_q8 vale 255; kq2dc_step se ejecuta una vez.
Controles y resultado esperado: 042 es la coordenada X entera resultante. El ejemplo no dibuja un contorno circular ni una animación de colisión.

Descargar código fuente / Estado de la verificación
.\kitaqgb\kitaqgb.exe kitaqgb/lib/physics2d_circle.c kitaq-docs/samples/gb_circle.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_circle.gb --profile=dev --rst-disable --stack-bank=fixed// Advance a circular body through one physics step.
// Expected: 042 after one step; this example uses integer pixels
#include "gb_common.h"
#include "physics2d_circle.h"
KQCircleBody2D balls[1]; KQCircleWorld2D world;
// Activate one circle at X = 40 with horizontal velocity 2 and zero gravity.
// Advance one step and display its resulting integer-pixel X coordinate.
void main() {
m_init();
m_text(2,3,"CIRCLE");
kq2dc_world_init(&world,balls,1);
balls[0].active=1; balls[0].x=40; balls[0].y=40;
balls[0].radius=4; balls[0].inv_mass_q8=256;
balls[0].vx=2; balls[0].vy=0;
world.gravity_x=0; world.gravity_y=0; world.linear_damping_q8=255;
kq2dc_step(&world); m_number((u8)balls[0].x);
while (1) { m_wait(); }
}Procesar un efecto de sonido en cada fotograma gb_sound.c
Objetivo: Inicia un flujo de efectos de sonido y lo hace avanzar mediante actualizaciones regulares por fotograma.
Funcionamiento: Después de Audio_Init, Audio_PlaySFX inicia tone en el canal de ID 1. El bucle principal llama a Audio_Update una vez por fotograma.
Controles y resultado esperado: Suena un efecto de pulso corto mientras se mantiene visible 042. El número es un marcador fijo, no el volumen ni la posición de reproducción. Evalúa el sonido mediante la salida de audio o una grabación.

Descargar código fuente / Estado de la verificación
.\kitaqgb\kitaqgb.exe kitaqgb/lib/audio_hwregs_gb.c kitaqgb/lib/audio.c kitaq-docs/samples/gb_sound.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_sound.gb --profile=dev --rst-disable --stack-bank=fixed// Play a Game Boy pulse-channel sound effect.
// Expected: 042 and a short pulse tone
#include "gb_common.h"
#include "audio.h"
__prg_rom u8 tone[] = { 24,0xF0,24,0xE0,24,0xC0,24,0xA0,24,0x80,24,0x60,0 };
// Start a pulse-channel effect and service Audio_Update once per frame
// so the effect stream advances while 42 remains on screen.
void main() {
m_init();
m_text(2,3,"SOUND");
Audio_Init(); Audio_PlaySFX(tone,1); m_number(42);
while (1) { m_wait(); Audio_Update(); }
}Diccionario de la API de biblioteca
554 entradas. Abre una entrada para consultar su sintaxis, argumentos, notas del código fuente y ejemplo de uso. Los fragmentos de llamada requieren inicialización previa; no son ROM independientes. Los ejemplos de paso de argumentos muestran cómo llegar a la API con los valores preparados, pero no demuestran su funcionamiento en el dispositivo.
zx0
Decodifica recursos compatibles con ZX0 en RAM o VRAM. Prepáralos en el PC con kitaqgb-zx0.exe y decodifica durante la ejecución solo los datos necesarios. --format=auto compara las cargas raw, RLE y ZX0 y elige la menor; en empate prefiere raw, RLE y después ZX0. Mantén el contenedor completo dentro de 65535 bytes, incluida su cabecera de nueve bytes, y divide los recursos para ajustarlos a los bancos CPU y la RAM reales.
Einar Saukas diseñó el formato ZX0 y el algoritmo de compresión original. El compresor y el descompresor incluidos aquí son implementaciones independientes de KITAQ, con copyright de DAISUKE OBA y publicados bajo la licencia MIT.
Ejecute estos comandos del equipo anfitrión desde la raíz del repositorio. Compile la herramienta con tools/zx0/build.ps1.
.\kitaqgb-zx0.exe tiles.bin tiles.zx0
.\kitaqgb-zx0.exe tiles.bin tiles.h --header=tiles
.\kitaqgb-zx0.exe map.bin map.kqa --format=auto
.\kitaqgb-zx0.exe tiles.zx0 restored.bin --decompresszx0_decompress
Decodifica un flujo ZX0 v2 en una región RAM acotada. Las coincidencias referencian bytes ya decodificados, por lo que el destino debe permitir lectura y escritura. Úsalo para mapas de tiles o tablas de niveles que la CPU procese antes de utilizarlos.
Sintaxis
u16 zx0_decompress(void* dst, u16 capacity, const void* src, u16 packed_size);Parámetros
dstInicio de la RAM de destino escribible; no debe ser null. Expresa la capacidad en bytes, no en elementos del array.
capacityCantidad de bytes escribibles en el destino. Un flujo ZX0 normal necesita al menos un byte. Un recurso KQA1 raw vacío puede tener éxito con capacidad cero.
srcInicio de los datos comprimidos legibles mediante el mapeo de banco actual. No debe ser null.
packed_sizeCantidad de bytes de la entrada completa. Un flujo ZX0 incluye su marcador final y no tiene bytes adicionales después. Un contenedor KQA1 incluye su cabecera de nueve bytes. Máximo: 65535 bytes.
Valor devuelto
Devuelve la cantidad de bytes decodificados si tiene éxito o cero si hay error. Comprueba siempre también zx0_error.
Condiciones y límites
Incluye zx0.h y compila lib/zx0.c. Estas rutinas comparten memoria temporal y no admiten reentrada desde interrupciones. La entrada y la salida no deben solaparse, dar la vuelta al espacio de direcciones de CPU ni cruzar ventanas de bancos actualmente mapeados. La biblioteca no cambia los bancos de recursos.
Cada llamada actualiza zx0_error: 0 éxito, 1 argumento inválido, 2 entrada truncada, 3 flujo malformado, 4 espacio de salida insuficiente, 5 pantalla activa. Un fallo puede dejar una salida parcial; no la uses. Si varias condiciones son inválidas, la primera detectada determina el código.
Acepta flujos ZX0 v2 hacia delante. ZX0 v1, flujos hacia atrás y diccionarios externos quedan fuera de esta interfaz. Conoce el tamaño decodificado del recurso generado en el equipo anfitrión y proporciona suficiente espacio.
Ejemplo de uso
count=zx0_decompress(decoded_map,16,packed_map,packed_map_SIZE);
if(count!=16||zx0_error!=ZX0_OK)failures++;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La fila RAM MAP repite tiles de cuadrado, rombo y damero. AUTO RLE MAP forma una barra horizontal con dieciséis cuadrados. VRAM TILES repite los mismos tres tiles tras decodificar sus píxeles en VRAM. En CGB y FC, el cuadrado es blanco, el rombo rojo y el damero azul; DMG usa tonos grises. CHECKS OK confirma que las tres llamadas devolvieron los tamaños decodificados esperados sin error.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\zx0_decode.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\zx0_decode.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/zx0.h:15
Return decoded bytes, or zero on error (possibly after partial writes). Source and output must not overlap or cross their current CPU bank windows. Capacity and packed_size are byte counts. No prefix/backward/v1 streams.
kitaqgb/lib/zx0.c:52
u16 zx0_decompress(void* dst,u16 capacity,const void* src,u16 packed_size) {
u8 phase; u8 low; u8* out; u8* match;
u16 count; u16 distance; u16 used; u16 upper;
zx0_error=ZX0_OK;
if(!kq_zx_arguments(dst,capacity,src,packed_size)) { zx0_error=ZX0_BAD_ARGUMENT; return 0; }
kq_zx_input=(const u8*)src; kq_zx_left=packed_size;
kq_zx_mask=0; kq_zx_borrowed=0;
out=(u8*)dst; used=0; distance=1; phase=0;
// Phase 0 is literal, 1 reuses the last distance, 2 carries a new distance.
while(1) {
if(phase==2) {
upper=kq_zx_number(1);
if(zx0_error) return 0;
if(upper==256) {
if(kq_zx_left!=0) { zx0_error=ZX0_BAD_STREAM; return 0; }
return used;
}
if(upper>255) { zx0_error=ZX0_BAD_STREAM; return 0; }
low=kq_zx_byte();
distance=(u16)((upper<<7)-(low>>1));
kq_zx_borrowed=1; kq_zx_borrow_value=(u8)(low&1);
count=kq_zx_number(0);
if(count==65535) { zx0_error=ZX0_BAD_STREAM; return 0; }
count++;
} else count=kq_zx_number(0);
if(zx0_error) return 0;
if(count>capacity-used) { zx0_error=ZX0_OUTPUT_FULL; return 0; }
if(phase==0) {
if(count>kq_zx_left) { zx0_error=ZX0_TRUNCATED; return 0; }
kq_zx_left-=count; used+=count;
while(count!=0) { *out++=*kq_zx_input++; count--; }
phase=kq_zx_bit()?2:1;
} else {
if(distance>used) { zx0_error=ZX0_BAD_STREAM; return 0; }
match=out-distance; used+=count;
// Forward byte copying deliberately supports overlapping matches.
while(count!=0) { *out++=*match++; count--; }
phase=kq_zx_bit()?2:0;
}
if(zx0_error) return 0;
}
}asset_decompress
Lee el códec y los tamaños de la cabecera KQA1 generada por --format=auto y después copia bytes raw o decodifica RLE/ZX0 en RAM. El código que llama no necesita una rama distinta por códec.
Sintaxis
u16 asset_decompress(void* dst, u16 capacity, const void* src, u16 packed_size);Parámetros
dstInicio de la RAM de destino escribible; no debe ser null. Expresa la capacidad en bytes, no en elementos del array.
capacityCantidad de bytes escribibles en el destino. Un flujo ZX0 normal necesita al menos un byte. Un recurso KQA1 raw vacío puede tener éxito con capacidad cero.
srcInicio de los datos comprimidos legibles mediante el mapeo de banco actual. No debe ser null.
packed_sizeCantidad de bytes de la entrada completa. Un flujo ZX0 incluye su marcador final y no tiene bytes adicionales después. Un contenedor KQA1 incluye su cabecera de nueve bytes. Máximo: 65535 bytes.
Valor devuelto
Devuelve la cantidad de bytes decodificados si tiene éxito o cero si hay error. Comprueba siempre también zx0_error.
Condiciones y límites
Incluye zx0.h y compila lib/zx0.c. Estas rutinas comparten memoria temporal y no admiten reentrada desde interrupciones. La entrada y la salida no deben solaparse, dar la vuelta al espacio de direcciones de CPU ni cruzar ventanas de bancos actualmente mapeados. La biblioteca no cambia los bancos de recursos.
Cada llamada actualiza zx0_error: 0 éxito, 1 argumento inválido, 2 entrada truncada, 3 flujo malformado, 4 espacio de salida insuficiente, 5 pantalla activa. Un fallo puede dejar una salida parcial; no la uses. Si varias condiciones son inválidas, la primera detectada determina el código.
KQA1 es el contenedor de recursos KITAQ: identificador de cuatro bytes, códec de un byte (0 raw, 1 RLE, 2 ZX0), tamaño decodificado u16, tamaño de carga útil u16 y la carga útil. Los campos u16 usan orden little-endian. RLE repite pares count/value con count entre 1 y 255 y un terminador count cero. Un recurso raw vacío tiene éxito con retorno cero y error cero.
Ejemplo de uso
count=asset_decompress(decoded_auto,16,packed_auto,packed_auto_SIZE);
if(count!=16||zx0_error!=ZX0_OK)failures++;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La fila RAM MAP repite tiles de cuadrado, rombo y damero. AUTO RLE MAP forma una barra horizontal con dieciséis cuadrados. VRAM TILES repite los mismos tres tiles tras decodificar sus píxeles en VRAM. En CGB y FC, el cuadrado es blanco, el rombo rojo y el damero azul; DMG usa tonos grises. CHECKS OK confirma que las tres llamadas devolvieron los tamaños decodificados esperados sin error.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\zx0_decode.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\zx0_decode.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/zx0.h:18
Decode a KQA1 raw/RLE/ZX0 asset produced with --format=auto. Empty raw assets return zero with zx0_error==ZX0_OK.
kitaqgb/lib/zx0.c:95
u16 asset_decompress(void* dst,u16 capacity,const void* src,u16 packed_size) {
const u8* in; u8* out; u16 raw; u16 packed; u16 used;
u8 codec; u8 count; u8 value;
zx0_error=ZX0_OK;
if(packed_size<9||!kq_zx_arguments(dst,capacity,src,packed_size)) { zx0_error=ZX0_BAD_ARGUMENT; return 0; }
in=(const u8*)src; out=(u8*)dst;
if(in[0]!=75||in[1]!=81||in[2]!=65||in[3]!=49) { zx0_error=ZX0_BAD_STREAM; return 0; }
codec=in[4]; raw=(u16)((u16)in[5]|((u16)in[6]<<8));
packed=(u16)((u16)in[7]|((u16)in[8]<<8));
if(packed!=packed_size-9||codec>2) { zx0_error=ZX0_BAD_STREAM; return 0; }
if(raw>capacity) { zx0_error=ZX0_OUTPUT_FULL; return 0; }
in+=9;
if(codec==2) {
used=zx0_decompress(dst,raw,in,packed);
if(zx0_error==0&&used!=raw) zx0_error=ZX0_BAD_STREAM;
return zx0_error?0:used;
}
if(codec==0) {
if(raw!=packed) { zx0_error=ZX0_BAD_STREAM; return 0; }
used=raw; while(raw!=0) { *out++=*in++; raw--; } return used;
}
used=0;
while(packed!=0) {
count=*in++; packed--;
if(count==0) {
if(packed!=0||used!=raw) { zx0_error=ZX0_BAD_STREAM; return 0; }
return used;
}
if(packed==0) { zx0_error=ZX0_TRUNCATED; return 0; }
value=*in++; packed--;
if((u16)count>raw-used) { zx0_error=ZX0_OUTPUT_FULL; return 0; }
used+=count; while(count!=0) { *out++=value; count--; }
}
zx0_error=ZX0_TRUNCATED; return 0;
}zx0_decompress_vram
Con el LCD detenido, decodifica píxeles de tiles o datos de mapa ZX0 directamente en el banco VRAM seleccionado. La propia VRAM aporta el historial de coincidencias, sin necesidad de un búfer RAM intermedio.
Sintaxis
u16 zx0_decompress_vram(u16 vram_addr, const void* src, u16 packed_size);Parámetros
vram_addrDirección inicial de VRAM, 0x8000..0x9FFF. La salida queda limitada por el final de VRAM en 0xA000. En CGB, selecciona VBK antes de llamar.
srcInicio de los datos comprimidos legibles mediante el mapeo de banco actual. No debe ser null.
packed_sizeCantidad de bytes de la entrada completa. Un flujo ZX0 incluye su marcador final y no tiene bytes adicionales después. Un contenedor KQA1 incluye su cabecera de nueve bytes. Máximo: 65535 bytes.
Valor devuelto
Devuelve la cantidad de bytes decodificados si tiene éxito o cero si hay error. Comprueba siempre también zx0_error.
Condiciones y límites
Incluye zx0.h y compila lib/zx0.c. Estas rutinas comparten memoria temporal y no admiten reentrada desde interrupciones. La entrada y la salida no deben solaparse, dar la vuelta al espacio de direcciones de CPU ni cruzar ventanas de bancos actualmente mapeados. La biblioteca no cambia los bancos de recursos.
Cada llamada actualiza zx0_error: 0 éxito, 1 argumento inválido, 2 entrada truncada, 3 flujo malformado, 4 espacio de salida insuficiente, 5 pantalla activa. Un fallo puede dejar una salida parcial; no la uses. Si varias condiciones son inválidas, la primera detectada determina el código.
Acepta flujos ZX0 v2 hacia delante. ZX0 v1, flujos hacia atrás y diccionarios externos quedan fuera de esta interfaz. Conoce el tamaño decodificado del recurso generado en el equipo anfitrión y proporciona suficiente espacio.
Devuelve el error 5 si el LCD está encendido; estar en VBlank no basta. No cambia la pantalla, VBK ni la configuración de interrupciones. El código que llama detiene y reinicia el LCD.
Ejemplo de uso
count=zx0_decompress_vram(0x8800,packed_tiles,packed_tiles_SIZE);
if(count!=48||zx0_error!=ZX0_OK)failures++;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La fila RAM MAP repite tiles de cuadrado, rombo y damero. AUTO RLE MAP forma una barra horizontal con dieciséis cuadrados. VRAM TILES repite los mismos tres tiles tras decodificar sus píxeles en VRAM. En CGB y FC, el cuadrado es blanco, el rombo rojo y el damero azul; DMG usa tonos grises. CHECKS OK confirma que las tres llamadas devolvieron los tamaños decodificados esperados sin error.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\zx0_decode.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\zx0_decode.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/zx0.h:21
Decode directly into the selected GB VRAM bank ($8000..$9FFF), with LCD off. Preserve LCDC, VBK and interrupt state. Output must fit before $A000.
kitaqgb/lib/zx0.c:132
u16 zx0_decompress_vram(u16 vram_addr,const void* src,u16 packed_size) {
zx0_error=ZX0_OK;
if(vram_addr<0x8000||vram_addr>=0xA000) { zx0_error=ZX0_BAD_ARGUMENT; return 0; }
if(kq_zx_lcdc&0x80) { zx0_error=ZX0_DISPLAY_ACTIVE; return 0; }
return zx0_decompress((void*)vram_addr,(u16)(0xA000-vram_addr),src,packed_size);
}asset.h — Identificadores de recursos y descriptores de datos
La biblioteca de recursos localiza datos en bancos de ROM mediante un ID de 8 bits. Incluya asset.c y, en FC, también bank.c. Cada AssetDesc empaquetado ocupa 6 bytes: tipo, banco del recurso, dirección de 16 bits y longitud en bytes. La tabla y los datos pueden estar en bancos distintos.
Registre la tabla antes de buscar recursos. El registro es un estado global compartido: no lo cambie durante una búsqueda. La biblioteca comprueba los ID y el puntero de salida de asset_get, pero no valida la tabla, las direcciones de los datos ni el contenido del cartucho.
Busca un recurso RAW o TILES y transfiere sus desc.len bytes mediante __vram_copy. Seleccione antes el banco de ROM de los datos: esta función de GB usa desc.ptr directamente y no selecciona desc.bank para la transferencia.
asset_get
Copia un AssetDesc desde el banco de ROM de la tabla registrada al espacio proporcionado por el programa. Obtiene los metadatos del recurso, no sus datos.
Sintaxis
u8 asset_get(u8 asset_id, AssetDesc* out_desc);Parámetros
asset_idÍndice del recurso, empezando por cero. Debe cumplir
asset_id < counten la tabla registrada.out_descEspacio escribible para un descriptor de 6 bytes. Un puntero nulo se rechaza antes de acceder a la tabla.
Valor devuelto
1 si se copia el descriptor; 0 si el destino es nulo o el ID queda fuera del rango. Esos fallos no modifican el destino.
Condiciones y límites
Registre la tabla antes de buscar recursos. El registro es un estado global compartido: no lo cambie durante una búsqueda. La biblioteca comprueba los ID y el puntero de salida de asset_get, pero no valida la tabla, las direcciones de los datos ni el contenido del cartucho.
Los ejemplos sitúan el código llamante en el banco fijo 0 para que cambiar el banco de origen no retire el código en ejecución. Las transferencias son síncronas. No las interrumpa con otra copia que cambie bancos ni suponga que la función garantiza por sí sola la seguridad de todas las interrupciones.
Ejemplo de uso
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);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Lee el descriptor 0 y comprueba tipo TILES, banco 2, puntero y longitud de 144 bytes. Los ID inválidos y el destino nulo deben fallar; una búsqueda fallida conserva el valor previo de salida.
Imagen esperada: una fila roja empieza en (16,32) y ocupa 72×8 píxeles. Repite tres veces un triángulo de 8×8, un cuadrado de 8×8 con borde de un píxel y un tile con sus cuatro columnas izquierdas rellenas. El triángulo crece desde un píxel arriba a la izquierda hasta ocho en la fila inferior.
En GB, el triángulo y contorno azules de (16,64) muestran __farmemcpy; la pareja verde de (16,96), __far_memcpy. Cada pareja ocupa 16×8 píxeles. CGB usa esos colores; DMG muestra las mismas formas en negro sobre blanco.
El estado esperado es FAILED CHECKS 000 y FIRST FAILURE 00. La verificación ejecuta 300 fotogramas y compara texto, formas y colores con lo esperado. Es una prueba en emulador, no en hardware físico.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\asset_banks.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\asset_banks.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/asset.h:24
Copy one descriptor from its ROM bank into caller storage. Return zero for a null destination or an out-of-range ID; table validity is the caller's responsibility.
kitaqgb/lib/asset.c:18
u8 asset_get(u8 asset_id, AssetDesc* out_desc)
{
if (out_desc == 0) return 0;
if (asset_id >= asset_table_count) return 0;
__farmemcpy(out_desc, asset_table_bank, asset_table + asset_id, sizeof(AssetDesc));
return 1;
}asset_get_bank
Lee del descriptor el banco de los datos del recurso. No es el banco de la tabla, y la función no deja seleccionado el banco del recurso.
Sintaxis
u8 asset_get_bank(u8 asset_id);Parámetros
asset_idÍndice del recurso, empezando por cero. Debe cumplir
asset_id < counten la tabla registrada.
Valor devuelto
El campo bank de 8 bits, o 0 si falla la búsqueda. El banco cero también puede ser válido; use asset_get() para distinguir éxito y valor cero.
Condiciones y límites
Registre la tabla antes de buscar recursos. El registro es un estado global compartido: no lo cambie durante una búsqueda. La biblioteca comprueba los ID y el puntero de salida de asset_get, pero no valida la tabla, las direcciones de los datos ni el contenido del cartucho.
Cada consulta llama de nuevo a asset_get y copia un descriptor. Si necesita banco, puntero y longitud, llame una sola vez a asset_get y lea sus campos.
Los ejemplos sitúan el código llamante en el banco fijo 0 para que cambiar el banco de origen no retire el código en ejecución. Las transferencias son síncronas. No las interrumpa con otra copia que cambie bancos ni suponga que la función garantiza por sí sola la seguridad de todas las interrupciones.
Ejemplo de uso
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.Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Se espera el banco 2 de los datos aunque la tabla esté en el banco 3. También se comprueba que un ID inválido devuelve cero.
Imagen esperada: una fila roja empieza en (16,32) y ocupa 72×8 píxeles. Repite tres veces un triángulo de 8×8, un cuadrado de 8×8 con borde de un píxel y un tile con sus cuatro columnas izquierdas rellenas. El triángulo crece desde un píxel arriba a la izquierda hasta ocho en la fila inferior.
En GB, el triángulo y contorno azules de (16,64) muestran __farmemcpy; la pareja verde de (16,96), __far_memcpy. Cada pareja ocupa 16×8 píxeles. CGB usa esos colores; DMG muestra las mismas formas en negro sobre blanco.
El estado esperado es FAILED CHECKS 000 y FIRST FAILURE 00. La verificación ejecuta 300 fotogramas y compara texto, formas y colores con lo esperado. Es una prueba en emulador, no en hardware físico.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\asset_banks.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\asset_banks.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/asset.h:32
Return the descriptor bank, or zero on lookup failure; zero can also be a valid bank.
kitaqgb/lib/asset.c:51
u8 asset_get_bank(u8 asset_id)
{
AssetDesc desc;
if (asset_get(asset_id, &desc) == 0) return 0;
return desc.bank;
}asset_get_len
Lee la longitud del recurso en bytes desde su descriptor. Devuelve metadatos; no examina los datos ni convierte la longitud en cantidad de tiles, elementos o fotogramas.
Sintaxis
u16 asset_get_len(u8 asset_id);Parámetros
asset_idÍndice del recurso, empezando por cero. Debe cumplir
asset_id < counten la tabla registrada.
Valor devuelto
El campo len de 16 bits, en bytes, o 0 si falla la búsqueda. Un recurso vacío también mide cero; use asset_get() para distinguirlos.
Condiciones y límites
Registre la tabla antes de buscar recursos. El registro es un estado global compartido: no lo cambie durante una búsqueda. La biblioteca comprueba los ID y el puntero de salida de asset_get, pero no valida la tabla, las direcciones de los datos ni el contenido del cartucho.
Cada consulta llama de nuevo a asset_get y copia un descriptor. Si necesita banco, puntero y longitud, llame una sola vez a asset_get y lea sus campos.
Los ejemplos sitúan el código llamante en el banco fijo 0 para que cambiar el banco de origen no retire el código en ejecución. Las transferencias son síncronas. No las interrumpa con otra copia que cambie bancos ni suponga que la función garantiza por sí sola la seguridad de todas las interrupciones.
Ejemplo de uso
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.Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El recurso de nueve tiles debe indicar 144 bytes, no nueve tiles. Un recurso vacío y un ID inválido deben devolver cero.
Imagen esperada: una fila roja empieza en (16,32) y ocupa 72×8 píxeles. Repite tres veces un triángulo de 8×8, un cuadrado de 8×8 con borde de un píxel y un tile con sus cuatro columnas izquierdas rellenas. El triángulo crece desde un píxel arriba a la izquierda hasta ocho en la fila inferior.
En GB, el triángulo y contorno azules de (16,64) muestran __farmemcpy; la pareja verde de (16,96), __far_memcpy. Cada pareja ocupa 16×8 píxeles. CGB usa esos colores; DMG muestra las mismas formas en negro sobre blanco.
El estado esperado es FAILED CHECKS 000 y FIRST FAILURE 00. La verificación ejecuta 300 fotogramas y compara texto, formas y colores con lo esperado. Es una prueba en emulador, no en hardware físico.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\asset_banks.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\asset_banks.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/asset.h:37
Return the descriptor byte length, or zero if its ID cannot be resolved.
kitaqgb/lib/asset.c:68
u16 asset_get_len(u8 asset_id)
{
AssetDesc desc;
if (asset_get(asset_id, &desc) == 0) return 0;
return desc.len;
}asset_get_ptr
Lee la dirección de 16 bits guardada en el descriptor. El puntero cercano devuelto no incluye el banco. Para leer otro banco de ROM, combínelo con asset_get_bank() y una función de copia entre bancos.
Sintaxis
const u8* asset_get_ptr(u8 asset_id);Parámetros
asset_idÍndice del recurso, empezando por cero. Debe cumplir
asset_id < counten la tabla registrada.
Valor devuelto
El const u8* guardado, o un puntero nulo si falla la búsqueda. El puntero del descriptor no se valida; use asset_get() para identificar un fallo de búsqueda.
Condiciones y límites
Registre la tabla antes de buscar recursos. El registro es un estado global compartido: no lo cambie durante una búsqueda. La biblioteca comprueba los ID y el puntero de salida de asset_get, pero no valida la tabla, las direcciones de los datos ni el contenido del cartucho.
Cada consulta llama de nuevo a asset_get y copia un descriptor. Si necesita banco, puntero y longitud, llame una sola vez a asset_get y lea sus campos.
Los ejemplos sitúan el código llamante en el banco fijo 0 para que cambiar el banco de origen no retire el código en ejecución. Las transferencias son síncronas. No las interrumpa con otra copia que cambie bancos ni suponga que la función garantiza por sí sola la seguridad de todas las interrupciones.
Ejemplo de uso
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.Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El puntero debe coincidir con la dirección enlazada del recurso, mientras sigue siendo legible un marcador del banco 1. Después se pasa ese puntero junto con el banco 2 a una copia entre bancos.
Imagen esperada: una fila roja empieza en (16,32) y ocupa 72×8 píxeles. Repite tres veces un triángulo de 8×8, un cuadrado de 8×8 con borde de un píxel y un tile con sus cuatro columnas izquierdas rellenas. El triángulo crece desde un píxel arriba a la izquierda hasta ocho en la fila inferior.
En GB, el triángulo y contorno azules de (16,64) muestran __farmemcpy; la pareja verde de (16,96), __far_memcpy. Cada pareja ocupa 16×8 píxeles. CGB usa esos colores; DMG muestra las mismas formas en negro sobre blanco.
El estado esperado es FAILED CHECKS 000 y FIRST FAILURE 00. La verificación ejecuta 300 fotogramas y compara texto, formas y colores con lo esperado. Es una prueba en emulador, no en hardware físico.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\asset_banks.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\asset_banks.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/asset.h:35
Return the stored address without switching banks. Use the descriptor bank with far-data helpers before dereferencing banked assets; failure returns null.
kitaqgb/lib/asset.c:60
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
Busca el recurso y copia min(desc.len, max_len) bytes desde su banco de ROM a memoria escribible. Ignora el tipo: los gráficos, mapas y canciones se copian como bytes, sin interpretar el formato ni descomprimirlos.
Sintaxis
u8 asset_load_raw(u8 asset_id, void* dst, u16 max_len);Parámetros
asset_idÍndice del recurso, empezando por cero. Debe cumplir
asset_id < counten la tabla registrada.dstDestino en memoria escribible, con espacio para todos los bytes copiados. Salvo en una transferencia de cero bytes, no se comprueba si el destino es nulo o inválido.
max_lenMáximo de bytes que se copiarán, de 0 a 65535. Un límite menor trunca la copia; cero no copia ningún byte de los datos.
Valor devuelto
0 si falla la búsqueda; en caso contrario, 1, incluso si la copia se trunca, el límite es cero o el recurso está vacío. No devuelve una cantidad de bytes ni garantiza que haya cabido todo el recurso.
Condiciones y límites
Registre la tabla antes de buscar recursos. El registro es un estado global compartido: no lo cambie durante una búsqueda. La biblioteca comprueba los ID y el puntero de salida de asset_get, pero no valida la tabla, las direcciones de los datos ni el contenido del cartucho.
Mantenga todo el origen en el mapeo de ROM previsto y todo el destino en memoria escribible. La copia no cambia automáticamente de banco al cruzar una ventana, no trata solapamientos como memmove ni sincroniza escrituras en VRAM. Para VRAM, use las API de transferencia gráfica.
Los ejemplos sitúan el código llamante en el banco fijo 0 para que cambiar el banco de origen no retire el código en ejecución. Las transferencias son síncronas. No las interrumpa con otra copia que cambie bancos ni suponga que la función garantiza por sí sola la seguridad de todas las interrupciones.
Ejemplo de uso
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);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Un límite de siete copia solo siete bytes de un recurso de 144, deja el siguiente en 0x55 y aun así devuelve éxito. También se prueban la copia completa, el límite cero, un recurso vacío y la copia de datos MAP.
Imagen esperada: una fila roja empieza en (16,32) y ocupa 72×8 píxeles. Repite tres veces un triángulo de 8×8, un cuadrado de 8×8 con borde de un píxel y un tile con sus cuatro columnas izquierdas rellenas. El triángulo crece desde un píxel arriba a la izquierda hasta ocho en la fila inferior.
En GB, el triángulo y contorno azules de (16,64) muestran __farmemcpy; la pareja verde de (16,96), __far_memcpy. Cada pareja ocupa 16×8 píxeles. CGB usa esos colores; DMG muestra las mismas formas en negro sobre blanco.
El estado esperado es FAILED CHECKS 000 y FIRST FAILURE 00. La verificación ejecuta 300 fotogramas y compara texto, formas y colores con lo esperado. Es una prueba en emulador, no en hardware físico.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\asset_banks.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\asset_banks.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/asset.h:27
Copy at most max_len bytes using the asset's bank. Success means the ID was valid, even when the payload was truncated to fit the supplied limit.
kitaqgb/lib/asset.c:28
u8 asset_load_raw(u8 asset_id, void* dst, u16 max_len)
{
AssetDesc desc;
u16 len;
if (asset_get(asset_id, &desc) == 0) return 0;
len = desc.len;
if (len > max_len) len = max_len;
__farmemcpy(dst, desc.bank, desc.ptr, len);
return 1;
}asset_load_tiles
Busca un recurso RAW o TILES y transfiere sus desc.len bytes mediante __vram_copy. Seleccione antes el banco de ROM de los datos: esta función de GB usa desc.ptr directamente y no selecciona desc.bank para la transferencia.
Sintaxis
u8 asset_load_tiles(u8 asset_id, u16 vram_dst);Parámetros
asset_idÍndice del recurso, empezando por cero. Debe cumplir
asset_id < counten la tabla registrada.vram_dstDirección de byte en VRAM, entre
$8000y$9FFF, no un número de tile. Para patrones, use una dirección alineada a 16 bytes y una longitud múltiplo de 16; la biblioteca no comprueba estas condiciones.
Valor devuelto
0 si el ID es inválido o el tipo no es RAW/TILES; 1 tras una transferencia aceptada, incluso con longitud cero. El éxito no valida el formato gráfico ni su visualización en VRAM.
Condiciones y límites
Registre la tabla antes de buscar recursos. El registro es un estado global compartido: no lo cambie durante una búsqueda. La biblioteca comprueba los ID y el puntero de salida de asset_get, pero no valida la tabla, las direcciones de los datos ni el contenido del cartucho.
Los ejemplos sitúan el código llamante en el banco fijo 0 para que cambiar el banco de origen no retire el código en ejecución. Las transferencias son síncronas. No las interrumpa con otra copia que cambie bancos ni suponga que la función garantiza por sí sola la seguridad de todas las interrupciones.
La transferencia solo escribe bytes: no coloca tiles en el mapa, asigna colores ni reserva VRAM. Configure el mapa y las paletas por separado. Los ejemplos transfieren con el renderizado desactivado y activan la imagen cuando está lista.
La rutina de GB restaura el banco registrado por el compilador. Manténgalo actualizado con __bankswitch; escribir directamente en el mapper no lo actualiza. La posición de HRAM que guarda el banco de retorno es compartida, por lo que no admite transferencias anidadas que la sobrescriban.
Ejemplo de uso
__bankswitch(payload_bank); // GB tile upload expects the payload bank already visible.
loaded=asset_load_tiles(0,0x8010); // Nine tiles = 144 bytes, LCD off.
expect(loaded==1,24);
__bankswitch(1);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La carga usa nueve patrones originales de 8×8 píxeles, 144 bytes en total, y comprueba el rechazo de MAP e ID inválidos. En FC, la longitud prueba tanto el bloque de 128 bytes como los 16 restantes.
Imagen esperada: una fila roja empieza en (16,32) y ocupa 72×8 píxeles. Repite tres veces un triángulo de 8×8, un cuadrado de 8×8 con borde de un píxel y un tile con sus cuatro columnas izquierdas rellenas. El triángulo crece desde un píxel arriba a la izquierda hasta ocho en la fila inferior.
En GB, el triángulo y contorno azules de (16,64) muestran __farmemcpy; la pareja verde de (16,96), __far_memcpy. Cada pareja ocupa 16×8 píxeles. CGB usa esos colores; DMG muestra las mismas formas en negro sobre blanco.
El estado esperado es FAILED CHECKS 000 y FIRST FAILURE 00. La verificación ejecuta 300 fotogramas y compara texto, formas y colores con lo esperado. Es una prueba en emulador, no en hardware físico.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\asset_banks.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\asset_banks.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/asset.h:30
Accept tile/raw descriptors and transfer their bytes to VRAM. This path passes the descriptor pointer directly; callers must arrange the correct visible ROM bank.
kitaqgb/lib/asset.c:41
u8 asset_load_tiles(u8 asset_id, u16 vram_dst)
{
AssetDesc desc;
if (asset_get(asset_id, &desc) == 0) return 0;
if (desc.type != ASSET_TYPE_TILES && desc.type != ASSET_TYPE_RAW) return 0;
__vram_copy(vram_dst, desc.ptr, desc.len);
return 1;
}asset_set_table
Registra el banco, la dirección y el número de entradas de la única tabla activa. Guarda esos tres valores; no copia la tabla, carga recursos ni reserva memoria.
Sintaxis
void asset_set_table(u8 bank, const AssetDesc* table, u8 count);Parámetros
bankBanco de ROM de la tabla de descriptores, expresado en 8 bits; no es el banco de los datos.
tablePuntero cercano a
countentradasAssetDescconsecutivas. Loscount * 6bytes deben seguir siendo legibles en el banco de la tabla mientras esté registrada.countNúmero de entradas, de 0 a 255. Con cero no hay ningún ID válido;
asset_set_table(0, 0, 0)registra una tabla vacía de forma segura.
Valor devuelto
Ninguno (void).
Condiciones y límites
Registre la tabla antes de buscar recursos. El registro es un estado global compartido: no lo cambie durante una búsqueda. La biblioteca comprueba los ID y el puntero de salida de asset_get, pero no valida la tabla, las direcciones de los datos ni el contenido del cartucho.
Ejemplo de uso
asset_set_table(3,asset_descriptors,4); // Four descriptors in bank 3, payloads in bank 2.Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo registra cuatro descriptores en el banco 3, con los datos no vacíos en el banco 2. También registra una tabla vacía y comprueba que la búsqueda falla sin leer la dirección cero.
Imagen esperada: una fila roja empieza en (16,32) y ocupa 72×8 píxeles. Repite tres veces un triángulo de 8×8, un cuadrado de 8×8 con borde de un píxel y un tile con sus cuatro columnas izquierdas rellenas. El triángulo crece desde un píxel arriba a la izquierda hasta ocho en la fila inferior.
En GB, el triángulo y contorno azules de (16,64) muestran __farmemcpy; la pareja verde de (16,96), __far_memcpy. Cada pareja ocupa 16×8 píxeles. CGB usa esos colores; DMG muestra las mismas formas en negro sobre blanco.
El estado esperado es FAILED CHECKS 000 y FIRST FAILURE 00. La verificación ejecuta 300 fotogramas y compara texto, formas y colores con lo esperado. Es una prueba en emulador, no en hardware físico.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\asset_banks.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\asset_banks.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/asset.h:21
Retain the descriptor table address, bank and count; the table is not copied.
kitaqgb/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;
}audio.h — Música, efectos de sonido y control de audio
Ofrece acceso directo a cuatro voces, música/efectos en bancos, enrutamiento estéreo, fundidos de volumen y ondas propias. Los ID de canal del flujo musical y las API directas son CH1=0, CH2=1, CH3=2, CH4=3. CH3 reproduce formas de onda; CH4 genera ruido.
Incluye audio_hwregs_gb.c antes de audio.c y llama a Audio_Init al arrancar. Llama a Audio_Update exactamente una vez por fotograma, unos 59,7 Hz. Las lecturas del flujo cambian temporalmente el mapeo ROM; no vuelvas a entrar en este controlador desde una interrupción.
Un efecto consume un par (note,value) por actualización y termina en note=0. value es NR12 para efectos de pulsos y NR32 para CH3. Antepon 0xFF a los datos CH3 y conserva la memoria hasta que termine. Las prioridades compiten dentro de una ranura; una prioridad igual también puede sustituir al efecto actual.
Audio_CancelMasterVolumeFade
Detiene los pasos siguientes del fundido conservando niveles y registros actuales.
Sintaxis
void Audio_CancelMasterVolumeFade();Valor devuelto
Sin valor de retorno. Modifica registros de sonido o el estado del controlador.
Ejemplo de uso
// A sustained pulse moves left, right and center, then fades to a quieter level.
#include "gb_sound_example.h"
void main() {
sound_begin("PAN AND VOLUME");
Audio_SetMasterVolume(7,7);
Audio_Ch1NoteOn(33,0xC0,2);
Audio_SetPan(AUDIO_CHANNEL_CH1,AUDIO_PAN_LEFT);
sound_result[0]=NR51;
sound_wait(30);
// Packed low two bits are CH1: 2 means right. Other channels remain centered.
Audio_SetPanPacked(2);
sound_result[1]=NR51;
sound_wait(30);
Audio_SetPanPacked(0);
sound_result[2]=NR51;
Audio_FadeToMasterVolume(1,1,5);
sound_wait(30);
sound_result[3]=NR50;
sound_result[4]=Audio_FadeActive;
sound_wait(30);
// Cancel halfway through a rise: retain volume 4 instead of reaching 7.
Audio_FadeToMasterVolume(7,7,5);
sound_wait(15);
Audio_CancelMasterVolumeFade();
sound_result[5]=NR50;
sound_wait(30);
sound_result[6]=NR50;
// A zero fade interval sets the target immediately. Level zero is not mute.
Audio_FadeToMasterVolume(0,0,0);
sound_result[7]=NR50;
sound_wait(30);
Audio_StopChannel(AUDIO_CHANNEL_CH1);
sound_wait(15);
sound_end();
}Resultado esperado
A4 pasa a izquierda, derecha y centro. En el centro baja del nivel 7 al 1, sube al 4 y permanece ahí. El nivel 0 aún se oye débilmente; detener el canal produce silencio. Cambiar el enrutamiento puede dejar un transitorio de filtro que se desvanece.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_mix.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-mix.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/audio.h:125
Cancel further volume steps, retaining the current cached levels and hardware output.
kitaqgb/lib/audio.c:548
void Audio_CancelMasterVolumeFade() {
Audio_FadeTargetLeft = Audio_MasterLeft;
Audio_FadeTargetRight = Audio_MasterRight;
Audio_FadeStepFrames = 0;
Audio_FadeCounter = 0;
Audio_FadeActive = 0;
}Audio_Ch1NoteOn
Configura barrido, ciclo de trabajo, envolvente y altura de CH1, y dispara el pulso.
Sintaxis
void __stackcall Audio_Ch1NoteOn(u8 note, u8 vol_env, u8 duty2);Parámetros
noteÍndice de tabla de alturas de 0 a 67. Consulta las notas sobre la reutilización de frecuencias y la diferencia de octava de CH3.
vol_envCodificación NR12/NR22/NR42: nibble alto para volumen inicial, bit 3 para envolvente creciente y tres bits bajos para su período. 0xC0 mantiene el volumen en 12.
duty2Ciclo de trabajo: 0=12,5 %, 1=25 %, 3=75 %; los demás valores seleccionan 50 %.
Valor devuelto
Sin valor de retorno. Modifica registros de sonido o el estado del controlador.
Condiciones y límites
note indexa una tabla de alturas de 0 a 67: 0 es C2 y 33 es A4. Los valores superiores a 67 se limitan a 67; 60..67 usan las frecuencias de 48..55. Con el mismo índice, CH3 suena una octava por debajo de un canal de pulsos. Las funciones de inicio de nota disparan el hardware directamente sin comprobar activación ni pausa.
Ejemplo de uso
// Four isolated voices, each lasting 30 frames, separated by 15 silent frames.
#include "gb_sound_example.h"
void main() {
sound_begin("FOUR SOUND CHANNELS");
Audio_SetMasterVolume(3,3);
// CH1: A4, 50% duty, fixed envelope volume 12.
Audio_SetCh1Duty(2);
sound_result[0]=Audio_Ch1Duty;
Audio_Ch1NoteOn(33,0xC0,Audio_Ch1Duty);
sound_result[1]=NR12;
sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH1); sound_wait(15);
// CH2: A4, 25% duty. Changing the cached duty takes effect on this trigger.
Audio_SetCh2Duty(1);
sound_result[2]=Audio_Ch2Duty;
Audio_Ch2NoteOn(33,0xC0,Audio_Ch2Duty);
sound_result[3]=NR22;
sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH2); sound_wait(15);
// CH3: the initialized triangle wave, at 50% digital output level.
Audio_SetCh3Level(AUDIO_CH3_LEVEL_50);
sound_result[4]=Audio_Ch3Level;
Audio_Ch3NoteOn(33,Audio_Ch3Level);
sound_result[5]=NR32;
sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH3); sound_wait(15);
// CH4: a sustained noise burst; param is NR43, not a pitched note number.
Audio_SetCh4Param(0x35);
sound_result[6]=Audio_Ch4Param;
Audio_Ch4NoteOn(Audio_Ch4Param,0xC0);
sound_result[7]=NR43;
sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH4); sound_wait(15);
sound_end();
}Resultado esperado
Tras aproximadamente medio segundo de silencio, se oyen CH1 A4, CH2 A4, CH3 A3 y ruido. Cada voz dura 30 fotogramas, con pausas de 15. SEQUENCE COMPLETE indica el final del programa; usa la grabación para valorar el sonido.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_channels.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-channels.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/audio.h:151
Trigger CH1 with the cached sweep and the supplied raw envelope. Clamp the note index; duty values 0, 1 and 3 select their encodings, and all others use 2.
kitaqgb/lib/audio.c:132
void __stackcall Audio_Ch1NoteOn(u8 note, u8 vol_env, u8 duty2) {
u16 freq;
u8 duty_reg;
u8 hi;
if (note > AUDIO_NOTE_MAX) note = AUDIO_NOTE_MAX;
freq = GB_FREQ_TABLE[note];
duty_reg = 128;
if (duty2 == 0) duty_reg = 0;
else if (duty2 == 1) duty_reg = 64;
else if (duty2 == 3) duty_reg = 192;
NR10 = Audio_Ch1Sweep;
NR11 = duty_reg;
NR12 = vol_env;
NR13 = (u8)(freq & 0xFF);
hi = (u8)((u16)freq >> 8);
NR14 = (u8)(hi | 0x80);
}Audio_Ch2NoteOn
Configura ciclo de trabajo, envolvente y altura de CH2, y dispara el pulso.
Sintaxis
void __stackcall Audio_Ch2NoteOn(u8 note, u8 vol_env, u8 duty2);Parámetros
noteÍndice de tabla de alturas de 0 a 67. Consulta las notas sobre la reutilización de frecuencias y la diferencia de octava de CH3.
vol_envCodificación NR12/NR22/NR42: nibble alto para volumen inicial, bit 3 para envolvente creciente y tres bits bajos para su período. 0xC0 mantiene el volumen en 12.
duty2Ciclo de trabajo: 0=12,5 %, 1=25 %, 3=75 %; los demás valores seleccionan 50 %.
Valor devuelto
Sin valor de retorno. Modifica registros de sonido o el estado del controlador.
Condiciones y límites
note indexa una tabla de alturas de 0 a 67: 0 es C2 y 33 es A4. Los valores superiores a 67 se limitan a 67; 60..67 usan las frecuencias de 48..55. Con el mismo índice, CH3 suena una octava por debajo de un canal de pulsos. Las funciones de inicio de nota disparan el hardware directamente sin comprobar activación ni pausa.
Ejemplo de uso
// Four isolated voices, each lasting 30 frames, separated by 15 silent frames.
#include "gb_sound_example.h"
void main() {
sound_begin("FOUR SOUND CHANNELS");
Audio_SetMasterVolume(3,3);
// CH1: A4, 50% duty, fixed envelope volume 12.
Audio_SetCh1Duty(2);
sound_result[0]=Audio_Ch1Duty;
Audio_Ch1NoteOn(33,0xC0,Audio_Ch1Duty);
sound_result[1]=NR12;
sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH1); sound_wait(15);
// CH2: A4, 25% duty. Changing the cached duty takes effect on this trigger.
Audio_SetCh2Duty(1);
sound_result[2]=Audio_Ch2Duty;
Audio_Ch2NoteOn(33,0xC0,Audio_Ch2Duty);
sound_result[3]=NR22;
sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH2); sound_wait(15);
// CH3: the initialized triangle wave, at 50% digital output level.
Audio_SetCh3Level(AUDIO_CH3_LEVEL_50);
sound_result[4]=Audio_Ch3Level;
Audio_Ch3NoteOn(33,Audio_Ch3Level);
sound_result[5]=NR32;
sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH3); sound_wait(15);
// CH4: a sustained noise burst; param is NR43, not a pitched note number.
Audio_SetCh4Param(0x35);
sound_result[6]=Audio_Ch4Param;
Audio_Ch4NoteOn(Audio_Ch4Param,0xC0);
sound_result[7]=NR43;
sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH4); sound_wait(15);
sound_end();
}Resultado esperado
Tras aproximadamente medio segundo de silencio, se oyen CH1 A4, CH2 A4, CH3 A3 y ruido. Cada voz dura 30 fotogramas, con pausas de 15. SEQUENCE COMPLETE indica el final del programa; usa la grabación para valorar el sonido.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_channels.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-channels.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/audio.h:154
Trigger CH2 with the supplied raw envelope and a clamped note index. Duty values 0, 1 and 3 select their encodings; all other values use duty 2.
kitaqgb/lib/audio.c:666
void __stackcall Audio_Ch2NoteOn(u8 note, u8 vol_env, u8 duty2) {
u16 freq;
u8 duty_reg;
u8 hi;
if (note > AUDIO_NOTE_MAX) note = AUDIO_NOTE_MAX;
freq = GB_FREQ_TABLE[note];
duty_reg = 128;
if (duty2 == 0) duty_reg = 0;
else if (duty2 == 1) duty_reg = 64;
else if (duty2 == 3) duty_reg = 192;
NR21 = duty_reg;
NR22 = vol_env;
NR23 = (u8)(freq & 0xFF);
hi = (u8)((u16)freq >> 8);
NR24 = (u8)(hi | 0x80);
}Audio_Ch3NoteOn
Dispara la onda CH3 cargada con la altura y el nivel NR32 solicitados.
Sintaxis
void __stackcall Audio_Ch3NoteOn(u8 note, u8 level);Parámetros
noteÍndice de tabla de alturas de 0 a 67. Consulta las notas sobre la reutilización de frecuencias y la diferencia de octava de CH3.
levelCodificación NR32: 0x00=silencio, 0x20=100 %, 0x40=50 %, 0x60=25 %.
Valor devuelto
Sin valor de retorno. Modifica registros de sonido o el estado del controlador.
Condiciones y límites
note indexa una tabla de alturas de 0 a 67: 0 es C2 y 33 es A4. Los valores superiores a 67 se limitan a 67; 60..67 usan las frecuencias de 48..55. Con el mismo índice, CH3 suena una octava por debajo de un canal de pulsos. Las funciones de inicio de nota disparan el hardware directamente sin comprobar activación ni pausa.
Ejemplo de uso
// Four isolated voices, each lasting 30 frames, separated by 15 silent frames.
#include "gb_sound_example.h"
void main() {
sound_begin("FOUR SOUND CHANNELS");
Audio_SetMasterVolume(3,3);
// CH1: A4, 50% duty, fixed envelope volume 12.
Audio_SetCh1Duty(2);
sound_result[0]=Audio_Ch1Duty;
Audio_Ch1NoteOn(33,0xC0,Audio_Ch1Duty);
sound_result[1]=NR12;
sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH1); sound_wait(15);
// CH2: A4, 25% duty. Changing the cached duty takes effect on this trigger.
Audio_SetCh2Duty(1);
sound_result[2]=Audio_Ch2Duty;
Audio_Ch2NoteOn(33,0xC0,Audio_Ch2Duty);
sound_result[3]=NR22;
sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH2); sound_wait(15);
// CH3: the initialized triangle wave, at 50% digital output level.
Audio_SetCh3Level(AUDIO_CH3_LEVEL_50);
sound_result[4]=Audio_Ch3Level;
Audio_Ch3NoteOn(33,Audio_Ch3Level);
sound_result[5]=NR32;
sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH3); sound_wait(15);
// CH4: a sustained noise burst; param is NR43, not a pitched note number.
Audio_SetCh4Param(0x35);
sound_result[6]=Audio_Ch4Param;
Audio_Ch4NoteOn(Audio_Ch4Param,0xC0);
sound_result[7]=NR43;
sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH4); sound_wait(15);
sound_end();
}Resultado esperado
Tras aproximadamente medio segundo de silencio, se oyen CH1 A4, CH2 A4, CH3 A3 y ruido. Cada voz dura 30 fotogramas, con pausas de 15. SEQUENCE COMPLETE indica el final del programa; usa la grabación para valorar el sonido.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_channels.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-channels.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/audio.h:157
Clamp the note index, program the raw NR32 output level, and trigger CH3. Wave RAM must already contain the desired waveform; this does not load one.
kitaqgb/lib/audio.c:115
void __stackcall Audio_Ch3NoteOn(u8 note, u8 level) {
u16 freq;
u8 hi;
if (note > AUDIO_NOTE_MAX) note = AUDIO_NOTE_MAX;
freq = GB_FREQ_TABLE[note];
NR30 = 128;
NR31 = 0;
NR32 = level;
NR33 = (u8)(freq & 255);
hi = (u8)((u16)freq >> 8);
NR34 = (u8)(hi | 128);
}Audio_Ch4NoteOn
Guarda los parámetros de ruido, configura los registros de envolvente y contador polinómico, y dispara CH4.
Sintaxis
void __stackcall Audio_Ch4NoteOn(u8 param, u8 vol_env);Parámetros
paramNR43 bruto: bits 7..4 para desplazamiento del reloj, bit 3 para LFSR corto y bits 2..0 para código divisor.
vol_envCodificación NR12/NR22/NR42: nibble alto para volumen inicial, bit 3 para envolvente creciente y tres bits bajos para su período. 0xC0 mantiene el volumen en 12.
Valor devuelto
Sin valor de retorno. Modifica registros de sonido o el estado del controlador.
Condiciones y límites
No se habilita la parada automática por longitud. Termina el sonido mediante la envolvente o una parada explícita.
Ejemplo de uso
// Four isolated voices, each lasting 30 frames, separated by 15 silent frames.
#include "gb_sound_example.h"
void main() {
sound_begin("FOUR SOUND CHANNELS");
Audio_SetMasterVolume(3,3);
// CH1: A4, 50% duty, fixed envelope volume 12.
Audio_SetCh1Duty(2);
sound_result[0]=Audio_Ch1Duty;
Audio_Ch1NoteOn(33,0xC0,Audio_Ch1Duty);
sound_result[1]=NR12;
sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH1); sound_wait(15);
// CH2: A4, 25% duty. Changing the cached duty takes effect on this trigger.
Audio_SetCh2Duty(1);
sound_result[2]=Audio_Ch2Duty;
Audio_Ch2NoteOn(33,0xC0,Audio_Ch2Duty);
sound_result[3]=NR22;
sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH2); sound_wait(15);
// CH3: the initialized triangle wave, at 50% digital output level.
Audio_SetCh3Level(AUDIO_CH3_LEVEL_50);
sound_result[4]=Audio_Ch3Level;
Audio_Ch3NoteOn(33,Audio_Ch3Level);
sound_result[5]=NR32;
sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH3); sound_wait(15);
// CH4: a sustained noise burst; param is NR43, not a pitched note number.
Audio_SetCh4Param(0x35);
sound_result[6]=Audio_Ch4Param;
Audio_Ch4NoteOn(Audio_Ch4Param,0xC0);
sound_result[7]=NR43;
sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH4); sound_wait(15);
sound_end();
}Resultado esperado
Tras aproximadamente medio segundo de silencio, se oyen CH1 A4, CH2 A4, CH3 A3 y ruido. Cada voz dura 30 fotogramas, con pausas de 15. SEQUENCE COMPLETE indica el final del programa; usa la grabación para valorar el sonido.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_channels.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-channels.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/audio.h:160
Cache the supplied noise parameter, program the raw envelope and polynomial registers, then trigger CH4 with the length-enable bit clear.
kitaqgb/lib/audio.c:688
void __stackcall Audio_Ch4NoteOn(u8 param, u8 vol_env) {
Audio_SetCh4Param(param);
NR41 = 0x20;
NR42 = vol_env;
NR43 = Audio_Ch4Param;
NR44 = 0x80;
}Audio_FadeToMasterVolume
Mueve cada nivel de salida un paso hacia el objetivo al intervalo solicitado.
Sintaxis
void __stackcall Audio_FadeToMasterVolume(u8 left, u8 right, u8 step_frames);Parámetros
leftNivel maestro izquierdo, de 0 a 7; los valores mayores se limitan a 7. Cero no es silencio total.
rightNivel maestro derecho, de 0 a 7; los valores mayores se limitan a 7.
step_framesNúmero de llamadas Audio_Update por cambio de un nivel. Cero aplica el objetivo inmediatamente.
Valor devuelto
Sin valor de retorno. Modifica registros de sonido o el estado del controlador.
Condiciones y límites
Incluye audio_hwregs_gb.c antes de audio.c y llama a Audio_Init al arrancar. Llama a Audio_Update exactamente una vez por fotograma, unos 59,7 Hz. Las lecturas del flujo cambian temporalmente el mapeo ROM; no vuelvas a entrar en este controlador desde una interrupción.
Ejemplo de uso
// A sustained pulse moves left, right and center, then fades to a quieter level.
#include "gb_sound_example.h"
void main() {
sound_begin("PAN AND VOLUME");
Audio_SetMasterVolume(7,7);
Audio_Ch1NoteOn(33,0xC0,2);
Audio_SetPan(AUDIO_CHANNEL_CH1,AUDIO_PAN_LEFT);
sound_result[0]=NR51;
sound_wait(30);
// Packed low two bits are CH1: 2 means right. Other channels remain centered.
Audio_SetPanPacked(2);
sound_result[1]=NR51;
sound_wait(30);
Audio_SetPanPacked(0);
sound_result[2]=NR51;
Audio_FadeToMasterVolume(1,1,5);
sound_wait(30);
sound_result[3]=NR50;
sound_result[4]=Audio_FadeActive;
sound_wait(30);
// Cancel halfway through a rise: retain volume 4 instead of reaching 7.
Audio_FadeToMasterVolume(7,7,5);
sound_wait(15);
Audio_CancelMasterVolumeFade();
sound_result[5]=NR50;
sound_wait(30);
sound_result[6]=NR50;
// A zero fade interval sets the target immediately. Level zero is not mute.
Audio_FadeToMasterVolume(0,0,0);
sound_result[7]=NR50;
sound_wait(30);
Audio_StopChannel(AUDIO_CHANNEL_CH1);
sound_wait(15);
sound_end();
}Resultado esperado
A4 pasa a izquierda, derecha y centro. En el centro baja del nivel 7 al 1, sube al 4 y permanece ahí. El nivel 0 aún se oye débilmente; detener el canal produce silencio. Cambiar el enrutamiento puede dejar un transitorio de filtro que se desvanece.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_mix.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-mix.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/audio.h:123
Move left/right volume toward clamped targets at the requested Audio_Update call interval. An interval of zero applies the levels immediately.
kitaqgb/lib/audio.c:528
void __stackcall Audio_FadeToMasterVolume(u8 left, u8 right, u8 step_frames) {
Audio_FadeTargetLeft = Audio_ClampVolume(left);
Audio_FadeTargetRight = Audio_ClampVolume(right);
if (step_frames == 0) {
Audio_SetMasterVolume(Audio_FadeTargetLeft, Audio_FadeTargetRight);
return;
}
Audio_FadeStepFrames = step_frames;
Audio_FadeCounter = step_frames;
if (Audio_MasterLeft == Audio_FadeTargetLeft && Audio_MasterRight == Audio_FadeTargetRight) {
Audio_FadeActive = 0;
Audio_FadeCounter = 0;
} else {
Audio_FadeActive = 1;
}
}Audio_Init
Activa la APU, inicializa música, efectos, pausa, mezcla y onda, y deja todos los canales en silencio.
Sintaxis
void Audio_Init();Valor devuelto
Sin valor de retorno. Modifica registros de sonido o el estado del controlador.
Condiciones y límites
Incluye audio_hwregs_gb.c antes de audio.c y llama a Audio_Init al arrancar. Llama a Audio_Update exactamente una vez por fotograma, unos 59,7 Hz. Las lecturas del flujo cambian temporalmente el mapeo ROM; no vuelvas a entrar en este controlador desde una interrupción.
Ejemplo de uso
// Four isolated voices, each lasting 30 frames, separated by 15 silent frames.
#include "gb_sound_example.h"
void main() {
sound_begin("FOUR SOUND CHANNELS");
Audio_SetMasterVolume(3,3);
// CH1: A4, 50% duty, fixed envelope volume 12.
Audio_SetCh1Duty(2);
sound_result[0]=Audio_Ch1Duty;
Audio_Ch1NoteOn(33,0xC0,Audio_Ch1Duty);
sound_result[1]=NR12;
sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH1); sound_wait(15);
// CH2: A4, 25% duty. Changing the cached duty takes effect on this trigger.
Audio_SetCh2Duty(1);
sound_result[2]=Audio_Ch2Duty;
Audio_Ch2NoteOn(33,0xC0,Audio_Ch2Duty);
sound_result[3]=NR22;
sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH2); sound_wait(15);
// CH3: the initialized triangle wave, at 50% digital output level.
Audio_SetCh3Level(AUDIO_CH3_LEVEL_50);
sound_result[4]=Audio_Ch3Level;
Audio_Ch3NoteOn(33,Audio_Ch3Level);
sound_result[5]=NR32;
sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH3); sound_wait(15);
// CH4: a sustained noise burst; param is NR43, not a pitched note number.
Audio_SetCh4Param(0x35);
sound_result[6]=Audio_Ch4Param;
Audio_Ch4NoteOn(Audio_Ch4Param,0xC0);
sound_result[7]=NR43;
sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH4); sound_wait(15);
sound_end();
}Resultado esperado
Tras aproximadamente medio segundo de silencio, se oyen CH1 A4, CH2 A4, CH3 A3 y ruido. Cada voz dura 30 fotogramas, con pausas de 15. SEQUENCE COMPLETE indica el final del programa; usa la grabación para valorar el sonido.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_channels.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-channels.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/audio.h:76
Enable the APU and reset software streams, instruments, mix and fade state. Load the initial triangle wave, then leave every channel silent. Call at startup before concurrent interrupt-driven audio service can access these shared fields.
kitaqgb/lib/audio.c:864
void Audio_Init() {
NR52 = 0x80;
NR51 = 0xFF;
Audio_Pan = 0xFF;
Audio_EffectPan = AUDIO_PAN_INHERIT;
Audio_EffectPan3 = AUDIO_PAN_INHERIT;
Audio_UpdateNR51();
Audio_SetMasterVolume(AUDIO_VOLUME_MAX, AUDIO_VOLUME_MAX);
Audio_SilenceAll();
Audio_PlayingMusic = 0;
Audio_Paused = 0;
Audio_MusicEnabled = 1;
Audio_SfxEnabled = 1;
Audio_Delay = 0;
Audio_MusicBank = 0;
Audio_MusicPointer = 0;
Audio_MusicLoopPoint = 0;
Audio_EffectPointer = 0;
Audio_EffectPriority = 0;
Audio_EffectBank = 0;
Audio_EffectPointer3 = 0;
Audio_EffectPriority3 = 0;
Audio_EffectBank3 = 0;
Audio_EffectUsesCh2 = 0;
Audio_EffectPan = AUDIO_PAN_INHERIT;
Audio_EffectPan3 = AUDIO_PAN_INHERIT;
Audio_LastChMask = 0;
Audio_LastCh1Note = 0;
Audio_LastCh2Note = 0;
Audio_LastCh3Note = 0;
Audio_LastCh4Param = 0;
Audio_Ch1Duty = 2;
Audio_Ch2Duty = 2;
Audio_Ch1Env = 0xF1;
Audio_Ch2Env = 0xF2;
Audio_Ch4Env = 0xF1;
Audio_Ch4Param = 0x00;
Audio_Ch3Level = AUDIO_CH3_LEVEL_100;
Audio_Ch3Wave = AUDIO_WAVE_TRIANGLE;
Audio_Ch1Sweep = 0x00;
Audio_SetCustomWaveTriangle();
#ifdef AUDIO_EXCLUDE_WAVE_LOAD_API
Audio_ApplyWaveBytes(Audio_CustomWave);
#else
Audio_LoadWave(Audio_Ch3Wave);
#endif
Audio_Ch3Off();
}Audio_LoadCustomWave
Copia dieciséis bytes a la caché de onda personalizada y a la RAM de onda CH3.
Sintaxis
void __stackcall Audio_LoadCustomWave(const u8 *wave16);Parámetros
wave16Dieciséis bytes legibles; los nibbles alto y bajo codifican muestras sucesivas. Ignora NULL.
Valor devuelto
Sin valor de retorno. Modifica registros de sonido o el estado del controlador.
Condiciones y límites
El código que llama puede reutilizar el origen tras copiarlo. La función deshabilita el DAC para escribir; quien llama debe volver a disparar la nota.
Ejemplo de uso
// Compare a triangle preset with an original packed 32-sample pulse waveform.
#include "gb_sound_example.h"
__prg_rom u8 custom_wave[16]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0,0,0,0,0,0,0,0};
void main() {
sound_begin("WAVE PRESET CUSTOM");
Audio_SetMasterVolume(3,3);
Audio_LoadWave(AUDIO_WAVE_TRIANGLE);
Audio_Ch3NoteOn(33,AUDIO_CH3_LEVEL_100);
sound_wait(45); Audio_StopChannel(AUDIO_CHANNEL_CH3); sound_wait(15);
// Loading copies all sixteen bytes and enables the DAC without triggering a note.
Audio_LoadCustomWave(custom_wave);
sound_result[0]=Audio_CustomWave[0]; sound_result[1]=Audio_CustomWave[8];
Audio_Ch3NoteOn(33,AUDIO_CH3_LEVEL_100);
sound_wait(45); Audio_StopChannel(AUDIO_CHANNEL_CH3); sound_wait(15);
// The cache survives another preset load; select CUSTOM to reuse it.
Audio_LoadWave(AUDIO_WAVE_SAW);
Audio_LoadWave(AUDIO_WAVE_CUSTOM);
sound_result[2]=WAVE0; sound_result[3]=WAVE8;
Audio_Ch3NoteOn(33,AUDIO_CH3_LEVEL_100);
sound_wait(45); Audio_StopChannel(AUDIO_CHANNEL_CH3); sound_wait(15);
sound_end();
}Resultado esperado
Se oyen el preajuste triangular, una onda de pulsos original y esa misma onda recargada desde la caché. Cada una dura 45 fotogramas con pausas de 15. Las tres están en unos 220 Hz; solo la primera tiene otro timbre.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_wave.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-wave.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/audio.h:138
Copy 16 packed sample bytes into the persistent custom cache and wave RAM. A null pointer is ignored; the source is needed only for this call.
kitaqgb/lib/audio.c:614
void __stackcall Audio_LoadCustomWave(const u8 *wave16) {
if (wave16 == 0) return;
Audio_CustomWave[0] = wave16[0]; Audio_CustomWave[1] = wave16[1];
Audio_CustomWave[2] = wave16[2]; Audio_CustomWave[3] = wave16[3];
Audio_CustomWave[4] = wave16[4]; Audio_CustomWave[5] = wave16[5];
Audio_CustomWave[6] = wave16[6]; Audio_CustomWave[7] = wave16[7];
Audio_CustomWave[8] = wave16[8]; Audio_CustomWave[9] = wave16[9];
Audio_CustomWave[10] = wave16[10]; Audio_CustomWave[11] = wave16[11];
Audio_CustomWave[12] = wave16[12]; Audio_CustomWave[13] = wave16[13];
Audio_CustomWave[14] = wave16[14]; Audio_CustomWave[15] = wave16[15];
Audio_ApplyWaveBytes(Audio_CustomWave);
}Audio_LoadWave
Instala una onda predefinida o personalizada en caché en la RAM de onda CH3.
Sintaxis
void __stackcall Audio_LoadWave(u8 wave_id);Parámetros
wave_idID AUDIO_WAVE_* de 0 a 7; 7 selecciona la onda personalizada en caché. Los valores mayores que 7 no hacen nada.
Valor devuelto
Sin valor de retorno. Modifica registros de sonido o el estado del controlador.
Condiciones y límites
Cargar no inicia una nota ni cambia Audio_Ch3Wave. El preajuste triangular también reinicia la caché personalizada como triángulo. Llama a Audio_Ch3NoteOn para hacer sonar la voz.
Ejemplo de uso
// Compare a triangle preset with an original packed 32-sample pulse waveform.
#include "gb_sound_example.h"
__prg_rom u8 custom_wave[16]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0,0,0,0,0,0,0,0};
void main() {
sound_begin("WAVE PRESET CUSTOM");
Audio_SetMasterVolume(3,3);
Audio_LoadWave(AUDIO_WAVE_TRIANGLE);
Audio_Ch3NoteOn(33,AUDIO_CH3_LEVEL_100);
sound_wait(45); Audio_StopChannel(AUDIO_CHANNEL_CH3); sound_wait(15);
// Loading copies all sixteen bytes and enables the DAC without triggering a note.
Audio_LoadCustomWave(custom_wave);
sound_result[0]=Audio_CustomWave[0]; sound_result[1]=Audio_CustomWave[8];
Audio_Ch3NoteOn(33,AUDIO_CH3_LEVEL_100);
sound_wait(45); Audio_StopChannel(AUDIO_CHANNEL_CH3); sound_wait(15);
// The cache survives another preset load; select CUSTOM to reuse it.
Audio_LoadWave(AUDIO_WAVE_SAW);
Audio_LoadWave(AUDIO_WAVE_CUSTOM);
sound_result[2]=WAVE0; sound_result[3]=WAVE8;
Audio_Ch3NoteOn(33,AUDIO_CH3_LEVEL_100);
sound_wait(45); Audio_StopChannel(AUDIO_CHANNEL_CH3); sound_wait(15);
sound_end();
}Resultado esperado
Se oyen el preajuste triangular, una onda de pulsos original y esa misma onda recargada desde la caché. Cada una dura 45 fotogramas con pausas de 15. Las tres están en unos 220 Hz; solo la primera tiene otro timbre.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_wave.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-wave.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/audio.h:135
Install a named preset or the cached custom wave. Unknown IDs are ignored. This does not update Audio_Ch3Wave or trigger a new note.
kitaqgb/lib/audio.c:631
void __stackcall Audio_LoadWave(u8 wave_id) {
if (wave_id == AUDIO_WAVE_TRIANGLE) Audio_LoadWave0();
else if (wave_id == AUDIO_WAVE_SAW) Audio_LoadWave1();
else if (wave_id == AUDIO_WAVE_VOWEL_A) Audio_LoadWave2();
else if (wave_id == AUDIO_WAVE_VOWEL_I) Audio_LoadWave3();
else if (wave_id == AUDIO_WAVE_VOWEL_U) Audio_LoadWave4();
else if (wave_id == AUDIO_WAVE_VOWEL_E) Audio_LoadWave5();
else if (wave_id == AUDIO_WAVE_VOWEL_O) Audio_LoadWave6();
else if (wave_id == AUDIO_WAVE_CUSTOM) Audio_ApplyWaveBytes(Audio_CustomWave);
}Audio_PlayMusic
Prepara la canción del banco indicado desde el principio y reinicia instrumentos, panorama y delay.
Sintaxis
void __stackcall Audio_PlayMusic(u8 bank, u8 *song);Parámetros
bankBanco ROM que contiene el flujo; debe coincidir con su ubicación.
songDirección inicial de la canción. El controlador usa el array prestado, que debe seguir siendo legible durante toda la reproducción.
Valor devuelto
Sin valor de retorno. Modifica registros de sonido o el estado del controlador.
Condiciones y límites
Incluye audio_hwregs_gb.c antes de audio.c y llama a Audio_Init al arrancar. Llama a Audio_Update exactamente una vez por fotograma, unos 59,7 Hz. Las lecturas del flujo cambian temporalmente el mapeo ROM; no vuelvas a entrar en este controlador desde una interrupción.
El siguiente Audio_Update lee los datos. No se comprueba NULL. Los efectos existentes siguen activos.
Ejemplo de uso
// Original two-note phrase: pause preserves the cursor; the enable gate does not.
#include "gb_sound_example.h"
__prg_rom u8 song[]={
AUDIO_CMD_SET_INST,AUDIO_STREAM_CHANNEL_CH1,2,0xC0,
AUDIO_CMD_NOTE,AUDIO_STREAM_CHANNEL_CH1,33,AUDIO_CMD_WAIT,59,
AUDIO_CMD_NOTE,AUDIO_STREAM_CHANNEL_CH1,40,AUDIO_CMD_WAIT,59,
AUDIO_CMD_LOOP
};
void main() {
u8 delay;
sound_begin("MUSIC PAUSE GATE");
Audio_SetMasterVolume(3,3);
Audio_PlayMusic(0,song);
sound_wait(30);
delay=Audio_Delay;
Audio_SetPaused(1);
sound_wait(30);
sound_result[0]=(u8)(Audio_Delay==delay);
sound_result[1]=Audio_Paused;
Audio_SetPaused(0);
sound_wait(30);
sound_result[2]=Audio_Paused;
// Disabling suppresses note writes; the next 30 updates still consume data.
Audio_SetMusicEnabled(0);
sound_wait(30);
sound_result[3]=Audio_Delay;
sound_result[4]=Audio_MusicEnabled;
// Explicitly stop the sounding channel while leaving the stream running.
Audio_StopChannel(AUDIO_CHANNEL_CH1);
sound_wait(30);
Audio_SetMusicEnabled(1);
sound_wait(30);
Audio_StopMusic();
sound_result[5]=Audio_PlayingMusic;
sound_wait(30);
sound_end();
}Resultado esperado
Se oyen una nota, silencio en pausa, reanudación, una nota retenida al deshabilitar la música, silencio explícito del canal, la siguiente nota tras habilitar y, al final, parada. La RAM también verifica que 30 actualizaciones en pausa conservan delay, mientras que deshabilitar la música deja que avance hasta 30.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_music.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-music.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/audio.h:83
Retain the bank and song pointer, reset legacy instruments/cursors, and arm playback from the beginning. Supply a valid, persistent song; no bytes are copied and null is not checked. Existing effect streams remain active.
kitaqgb/lib/audio.c:924
void __stackcall Audio_PlayMusic(u8 bank, u8 *song) {
Audio_PlayingMusic = 0;
Audio_MusicBank = bank;
Audio_MusicPointer = song;
Audio_MusicLoopPoint = song;
Audio_Delay = 0;
Audio_LastChMask = 0;
Audio_Ch1Duty = 2;
Audio_Ch2Duty = 2;
Audio_Ch1Env = 0xF1;
Audio_Ch2Env = 0xF2;
Audio_Ch4Env = 0xF1;
Audio_Ch4Param = 0x00;
Audio_Ch3Level = AUDIO_CH3_LEVEL_100;
Audio_Ch3Wave = AUDIO_WAVE_TRIANGLE;
Audio_Ch1Sweep = 0x00;
Audio_Pan = 0xFF;
Audio_UpdateNR51();
Audio_LoadWave(Audio_Ch3Wave);
Audio_PlayingMusic = 1;
}Audio_PlaySFX
Captura el banco ROM actual y solicita un efecto que hereda el panorama base.
Sintaxis
void __stackcall Audio_PlaySFX(u8 *sfx, u8 priority);Parámetros
sfxInicio del flujo de bytes del efecto. Consulta las notas para los formatos de pulsos y CH3.
priorityPrioridad de 0 a 255. Gana el valor mayor; uno igual también puede sustituir al efecto actual.
Valor devuelto
Sin valor de retorno. Modifica registros de sonido o el estado del controlador.
Condiciones y límites
Un efecto consume un par (note,value) por actualización y termina en note=0. value es NR12 para efectos de pulsos y NR32 para CH3. Antepon 0xFF a los datos CH3 y conserva la memoria hasta que termine. Las prioridades compiten dentro de una ranura; una prioridad igual también puede sustituir al efecto actual.
En la configuración normal, liberar un efecto apaga CH3. Silencia CH1 si la música está detenida, pero no vuelve a tocar automáticamente una nota anterior mientras la música sigue activa. Con AUDIO_VBLANK_SFX_RESTORE, la liberación solicita la recuperación a la ISR.
Ejemplo de uso
// Each pair lasts one update. Priority controls replacement within each slot.
#include "gb_sound_example.h"
#pragma bank 2
__prg_rom u8 effect[]={33,0xC0,33,0xC0,33,0xC0,33,0xC0,33,0xC0,33,0xC0,
40,0xC0,40,0xC0,40,0xC0,40,0xC0,40,0xC0,40,0xC0,0};
__prg_rom u8 wave_effect[]={AUDIO_SFX_CH3_MARKER,
33,0x20,33,0x20,33,0x20,33,0x20,33,0x20,33,0x20,
40,0x20,40,0x20,40,0x20,40,0x20,40,0x20,40,0x20,0};
#pragma bank 0
void main() {
sound_begin("BANKED SOUND EFFECT");
Audio_SetMasterVolume(3,3);
// Read the marker in bank 2 while restoring the caller's original mapping.
Audio_PlaySFXPannedBanked(2,effect,5,AUDIO_PAN_LEFT);
sound_result[0]=Audio_EffectPriority;
Audio_PlaySFXBanked(2,effect,4);
sound_result[1]=Audio_EffectPriority;
sound_wait(30);
Audio_PlaySFXPannedBanked(2,wave_effect,5,AUDIO_PAN_RIGHT);
sound_result[2]=Audio_EffectPriority3;
sound_wait(30);
// Implicit-bank entry points capture bank 2; the service restores bank 1.
__bankswitch(2);
Audio_PlaySFX(effect,5);
__bankswitch(1);
sound_result[3]=Audio_EffectBank;
sound_wait(30);
__bankswitch(2);
Audio_PlaySFXPanned(effect,5,AUDIO_PAN_RIGHT);
__bankswitch(1);
sound_wait(6);
Audio_StopSfx();
sound_result[4]=(u8)(Audio_EffectPointer==0);
sound_wait(24);
// Disabling effects releases current owners; re-enable before the next request.
Audio_PlaySFXBanked(2,effect,5);
sound_wait(6);
Audio_SetSfxEnabled(0);
sound_result[5]=Audio_SfxEnabled;
sound_result[6]=(u8)(Audio_EffectPointer==0);
sound_wait(24);
Audio_SetSfxEnabled(1);
Audio_PlaySFXBanked(2,effect,5);
sound_wait(30);
sound_result[7]=Audio_SfxEnabled;
sound_end();
}Resultado esperado
Los datos del banco 2 reproducen un pulso ascendente corto a la izquierda, un efecto de onda a la derecha y un pulso centrado. Los ejemplos posteriores detienen antes un pulso derecho, deshabilitan un efecto y vuelven a habilitar la reproducción. Una solicitud de prioridad 4 no sustituye a la prioridad 5.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_sfx.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-sfx.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/audio.h:93
Capture the currently mapped ROM bank and start an effect with inherited pan. Use the explicit-bank API when the pointer belongs to another bank.
kitaqgb/lib/audio.c:1085
void __stackcall Audio_PlaySFX(u8 *sfx, u8 priority) {
Audio_PlaySFXBanked(__rom_bank, sfx, priority);
}Audio_PlaySFXBanked
Identifica el tipo de efecto en el banco de origen explícito y solicita reproducirlo con el panorama base.
Sintaxis
void __stackcall Audio_PlaySFXBanked(u8 bank, u8 *sfx, u8 priority);Parámetros
bankBanco ROM que contiene el flujo; debe coincidir con su ubicación.
sfxInicio del flujo de bytes del efecto. Consulta las notas para los formatos de pulsos y CH3.
priorityPrioridad de 0 a 255. Gana el valor mayor; uno igual también puede sustituir al efecto actual.
Valor devuelto
Sin valor de retorno. Modifica registros de sonido o el estado del controlador.
Condiciones y límites
Un efecto consume un par (note,value) por actualización y termina en note=0. value es NR12 para efectos de pulsos y NR32 para CH3. Antepon 0xFF a los datos CH3 y conserva la memoria hasta que termine. Las prioridades compiten dentro de una ranura; una prioridad igual también puede sustituir al efecto actual.
En la configuración normal, liberar un efecto apaga CH3. Silencia CH1 si la música está detenida, pero no vuelve a tocar automáticamente una nota anterior mientras la música sigue activa. Con AUDIO_VBLANK_SFX_RESTORE, la liberación solicita la recuperación a la ISR.
Ejemplo de uso
// Each pair lasts one update. Priority controls replacement within each slot.
#include "gb_sound_example.h"
#pragma bank 2
__prg_rom u8 effect[]={33,0xC0,33,0xC0,33,0xC0,33,0xC0,33,0xC0,33,0xC0,
40,0xC0,40,0xC0,40,0xC0,40,0xC0,40,0xC0,40,0xC0,0};
__prg_rom u8 wave_effect[]={AUDIO_SFX_CH3_MARKER,
33,0x20,33,0x20,33,0x20,33,0x20,33,0x20,33,0x20,
40,0x20,40,0x20,40,0x20,40,0x20,40,0x20,40,0x20,0};
#pragma bank 0
void main() {
sound_begin("BANKED SOUND EFFECT");
Audio_SetMasterVolume(3,3);
// Read the marker in bank 2 while restoring the caller's original mapping.
Audio_PlaySFXPannedBanked(2,effect,5,AUDIO_PAN_LEFT);
sound_result[0]=Audio_EffectPriority;
Audio_PlaySFXBanked(2,effect,4);
sound_result[1]=Audio_EffectPriority;
sound_wait(30);
Audio_PlaySFXPannedBanked(2,wave_effect,5,AUDIO_PAN_RIGHT);
sound_result[2]=Audio_EffectPriority3;
sound_wait(30);
// Implicit-bank entry points capture bank 2; the service restores bank 1.
__bankswitch(2);
Audio_PlaySFX(effect,5);
__bankswitch(1);
sound_result[3]=Audio_EffectBank;
sound_wait(30);
__bankswitch(2);
Audio_PlaySFXPanned(effect,5,AUDIO_PAN_RIGHT);
__bankswitch(1);
sound_wait(6);
Audio_StopSfx();
sound_result[4]=(u8)(Audio_EffectPointer==0);
sound_wait(24);
// Disabling effects releases current owners; re-enable before the next request.
Audio_PlaySFXBanked(2,effect,5);
sound_wait(6);
Audio_SetSfxEnabled(0);
sound_result[5]=Audio_SfxEnabled;
sound_result[6]=(u8)(Audio_EffectPointer==0);
sound_wait(24);
Audio_SetSfxEnabled(1);
Audio_PlaySFXBanked(2,effect,5);
sound_wait(30);
sound_result[7]=Audio_SfxEnabled;
sound_end();
}Resultado esperado
Los datos del banco 2 reproducen un pulso ascendente corto a la izquierda, un efecto de onda a la derecha y un pulso centrado. Los ejemplos posteriores detienen antes un pulso derecho, deshabilitan un efecto y vuelven a habilitar la reproducción. Una solicitud de prioridad 4 no sustituye a la prioridad 5.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_sfx.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-sfx.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/audio.h:95
Start a banked effect with the channel's base pan, subject to priority arbitration.
kitaqgb/lib/audio.c:1078
void __stackcall Audio_PlaySFXBanked(u8 bank, u8 *sfx, u8 priority) {
Audio_PlaySFXPannedBanked(bank, sfx, priority, AUDIO_PAN_INHERIT);
}Audio_PlaySFXPanned
Captura el banco ROM actual y solicita un efecto con panorama específico.
Sintaxis
void __stackcall Audio_PlaySFXPanned(u8 *sfx, u8 priority, u8 pan);Parámetros
sfxInicio del flujo de bytes del efecto. Consulta las notas para los formatos de pulsos y CH3.
priorityPrioridad de 0 a 255. Gana el valor mayor; uno igual también puede sustituir al efecto actual.
pan0=centro, 1=izquierda, 2=derecha, 3=silencio. Las API de efectos tratan valores mayores que 3, incluido 0xFF, como herencia del panorama base.
Valor devuelto
Sin valor de retorno. Modifica registros de sonido o el estado del controlador.
Condiciones y límites
Un efecto consume un par (note,value) por actualización y termina en note=0. value es NR12 para efectos de pulsos y NR32 para CH3. Antepon 0xFF a los datos CH3 y conserva la memoria hasta que termine. Las prioridades compiten dentro de una ranura; una prioridad igual también puede sustituir al efecto actual.
En la configuración normal, liberar un efecto apaga CH3. Silencia CH1 si la música está detenida, pero no vuelve a tocar automáticamente una nota anterior mientras la música sigue activa. Con AUDIO_VBLANK_SFX_RESTORE, la liberación solicita la recuperación a la ISR.
Ejemplo de uso
// Each pair lasts one update. Priority controls replacement within each slot.
#include "gb_sound_example.h"
#pragma bank 2
__prg_rom u8 effect[]={33,0xC0,33,0xC0,33,0xC0,33,0xC0,33,0xC0,33,0xC0,
40,0xC0,40,0xC0,40,0xC0,40,0xC0,40,0xC0,40,0xC0,0};
__prg_rom u8 wave_effect[]={AUDIO_SFX_CH3_MARKER,
33,0x20,33,0x20,33,0x20,33,0x20,33,0x20,33,0x20,
40,0x20,40,0x20,40,0x20,40,0x20,40,0x20,40,0x20,0};
#pragma bank 0
void main() {
sound_begin("BANKED SOUND EFFECT");
Audio_SetMasterVolume(3,3);
// Read the marker in bank 2 while restoring the caller's original mapping.
Audio_PlaySFXPannedBanked(2,effect,5,AUDIO_PAN_LEFT);
sound_result[0]=Audio_EffectPriority;
Audio_PlaySFXBanked(2,effect,4);
sound_result[1]=Audio_EffectPriority;
sound_wait(30);
Audio_PlaySFXPannedBanked(2,wave_effect,5,AUDIO_PAN_RIGHT);
sound_result[2]=Audio_EffectPriority3;
sound_wait(30);
// Implicit-bank entry points capture bank 2; the service restores bank 1.
__bankswitch(2);
Audio_PlaySFX(effect,5);
__bankswitch(1);
sound_result[3]=Audio_EffectBank;
sound_wait(30);
__bankswitch(2);
Audio_PlaySFXPanned(effect,5,AUDIO_PAN_RIGHT);
__bankswitch(1);
sound_wait(6);
Audio_StopSfx();
sound_result[4]=(u8)(Audio_EffectPointer==0);
sound_wait(24);
// Disabling effects releases current owners; re-enable before the next request.
Audio_PlaySFXBanked(2,effect,5);
sound_wait(6);
Audio_SetSfxEnabled(0);
sound_result[5]=Audio_SfxEnabled;
sound_result[6]=(u8)(Audio_EffectPointer==0);
sound_wait(24);
Audio_SetSfxEnabled(1);
Audio_PlaySFXBanked(2,effect,5);
sound_wait(30);
sound_result[7]=Audio_SfxEnabled;
sound_end();
}Resultado esperado
Los datos del banco 2 reproducen un pulso ascendente corto a la izquierda, un efecto de onda a la derecha y un pulso centrado. Los ejemplos posteriores detienen antes un pulso derecho, deshabilitan un efecto y vuelven a habilitar la reproducción. Una solicitud de prioridad 4 no sustituye a la prioridad 5.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_sfx.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-sfx.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/audio.h:98
Capture the currently mapped ROM bank and request an effect with a pan override. Use the explicit-bank API when the pointer belongs to another bank.
kitaqgb/lib/audio.c:1091
void __stackcall Audio_PlaySFXPanned(u8 *sfx, u8 priority, u8 pan) {
Audio_PlaySFXPannedBanked(__rom_bank, sfx, priority, pan);
}Audio_PlaySFXPannedBanked
Adquiere una ranura de efecto de pulsos o CH3 con banco, prioridad y panorama explícitos.
Sintaxis
void __stackcall Audio_PlaySFXPannedBanked(u8 bank, u8 *sfx, u8 priority, u8 pan);Parámetros
bankBanco ROM que contiene el flujo; debe coincidir con su ubicación.
sfxInicio del flujo de bytes del efecto. Consulta las notas para los formatos de pulsos y CH3.
priorityPrioridad de 0 a 255. Gana el valor mayor; uno igual también puede sustituir al efecto actual.
pan0=centro, 1=izquierda, 2=derecha, 3=silencio. Las API de efectos tratan valores mayores que 3, incluido 0xFF, como herencia del panorama base.
Valor devuelto
Sin valor de retorno. Modifica registros de sonido o el estado del controlador.
Condiciones y límites
Un efecto consume un par (note,value) por actualización y termina en note=0. value es NR12 para efectos de pulsos y NR32 para CH3. Antepon 0xFF a los datos CH3 y conserva la memoria hasta que termine. Las prioridades compiten dentro de una ranura; una prioridad igual también puede sustituir al efecto actual.
En la configuración normal, liberar un efecto apaga CH3. Silencia CH1 si la música está detenida, pero no vuelve a tocar automáticamente una nota anterior mientras la música sigue activa. Con AUDIO_VBLANK_SFX_RESTORE, la liberación solicita la recuperación a la ISR.
Ejemplo de uso
// Each pair lasts one update. Priority controls replacement within each slot.
#include "gb_sound_example.h"
#pragma bank 2
__prg_rom u8 effect[]={33,0xC0,33,0xC0,33,0xC0,33,0xC0,33,0xC0,33,0xC0,
40,0xC0,40,0xC0,40,0xC0,40,0xC0,40,0xC0,40,0xC0,0};
__prg_rom u8 wave_effect[]={AUDIO_SFX_CH3_MARKER,
33,0x20,33,0x20,33,0x20,33,0x20,33,0x20,33,0x20,
40,0x20,40,0x20,40,0x20,40,0x20,40,0x20,40,0x20,0};
#pragma bank 0
void main() {
sound_begin("BANKED SOUND EFFECT");
Audio_SetMasterVolume(3,3);
// Read the marker in bank 2 while restoring the caller's original mapping.
Audio_PlaySFXPannedBanked(2,effect,5,AUDIO_PAN_LEFT);
sound_result[0]=Audio_EffectPriority;
Audio_PlaySFXBanked(2,effect,4);
sound_result[1]=Audio_EffectPriority;
sound_wait(30);
Audio_PlaySFXPannedBanked(2,wave_effect,5,AUDIO_PAN_RIGHT);
sound_result[2]=Audio_EffectPriority3;
sound_wait(30);
// Implicit-bank entry points capture bank 2; the service restores bank 1.
__bankswitch(2);
Audio_PlaySFX(effect,5);
__bankswitch(1);
sound_result[3]=Audio_EffectBank;
sound_wait(30);
__bankswitch(2);
Audio_PlaySFXPanned(effect,5,AUDIO_PAN_RIGHT);
__bankswitch(1);
sound_wait(6);
Audio_StopSfx();
sound_result[4]=(u8)(Audio_EffectPointer==0);
sound_wait(24);
// Disabling effects releases current owners; re-enable before the next request.
Audio_PlaySFXBanked(2,effect,5);
sound_wait(6);
Audio_SetSfxEnabled(0);
sound_result[5]=Audio_SfxEnabled;
sound_result[6]=(u8)(Audio_EffectPointer==0);
sound_wait(24);
Audio_SetSfxEnabled(1);
Audio_PlaySFXBanked(2,effect,5);
sound_wait(30);
sound_result[7]=Audio_SfxEnabled;
sound_end();
}Resultado esperado
Los datos del banco 2 reproducen un pulso ascendente corto a la izquierda, un efecto de onda a la derecha y un pulso centrado. Los ejemplos posteriores detienen antes un pulso derecho, deshabilitan un efecto y vuelven a habilitar la reproducción. Una solicitud de prioridad 4 no sustituye a la prioridad 5.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_sfx.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-sfx.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/audio.h:103
Retain a banked effect stream if its priority equals or exceeds the current owner's priority, or that slot is empty. A leading CH3 marker selects the wave slot and is skipped; other streams use the pulse slot. Paused requests are ignored. Keep stream storage valid until completion; acceptance does not trigger a note.
kitaqgb/lib/audio.c:1041
void __stackcall Audio_PlaySFXPannedBanked(u8 bank, u8 *sfx, u8 priority, u8 pan) {
u8 sfx_pan = pan;
u8 use_ch3 = 0;
if (sfx_pan > AUDIO_PAN_MUTE) sfx_pan = AUDIO_PAN_INHERIT;
if (Audio_Paused != 0) return;
if (sfx != 0) {
use_ch3 = Audio_SfxStartsOnCh3Banked(bank, sfx);
if (use_ch3 != 0) {
if (Audio_EffectPointer3 == 0 || priority >= Audio_EffectPriority3) {
Audio_EffectPointer3 = sfx + 1;
Audio_EffectPriority3 = priority;
Audio_EffectBank3 = bank;
Audio_EffectPan3 = sfx_pan;
Audio_UpdateNR51();
}
return;
}
}
if (Audio_EffectPointer == 0 || priority >= Audio_EffectPriority) {
#ifdef AUDIO_VBLANK_SFX_AUTO_CH2
// Choose pulse-channel ownership when accepting the effect, so its later
// updates and deferred recovery agree on which physical channel was borrowed.
Audio_EffectUsesCh2 = (u8)(AudioVBlank_MusicPlaying != 0 &&
AudioVBlank_MusicEnabled != 0);
#else
Audio_EffectUsesCh2 = 0;
#endif
Audio_EffectPointer = sfx;
Audio_EffectPriority = priority;
Audio_EffectBank = bank;
Audio_EffectPan = sfx_pan;
Audio_UpdateNR51();
}
}Audio_SetCh1Duty
Guarda el índice de ciclo de trabajo de la próxima nota CH1.
Sintaxis
void __stackcall Audio_SetCh1Duty(u8 duty);Parámetros
dutyÍndice de ciclo de trabajo; se guardan los dos bits bajos. 0=12,5 %, 1=25 %, 2=50 %, 3=75 %.
Valor devuelto
Sin valor de retorno. Modifica registros de sonido o el estado del controlador.
Condiciones y límites
Esta llamada por sí sola no cambia los registros de sonido activos. Pasa el valor guardado al inicio de nota o usa el flujo correspondiente para aplicarlo.
Ejemplo de uso
// Four isolated voices, each lasting 30 frames, separated by 15 silent frames.
#include "gb_sound_example.h"
void main() {
sound_begin("FOUR SOUND CHANNELS");
Audio_SetMasterVolume(3,3);
// CH1: A4, 50% duty, fixed envelope volume 12.
Audio_SetCh1Duty(2);
sound_result[0]=Audio_Ch1Duty;
Audio_Ch1NoteOn(33,0xC0,Audio_Ch1Duty);
sound_result[1]=NR12;
sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH1); sound_wait(15);
// CH2: A4, 25% duty. Changing the cached duty takes effect on this trigger.
Audio_SetCh2Duty(1);
sound_result[2]=Audio_Ch2Duty;
Audio_Ch2NoteOn(33,0xC0,Audio_Ch2Duty);
sound_result[3]=NR22;
sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH2); sound_wait(15);
// CH3: the initialized triangle wave, at 50% digital output level.
Audio_SetCh3Level(AUDIO_CH3_LEVEL_50);
sound_result[4]=Audio_Ch3Level;
Audio_Ch3NoteOn(33,Audio_Ch3Level);
sound_result[5]=NR32;
sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH3); sound_wait(15);
// CH4: a sustained noise burst; param is NR43, not a pitched note number.
Audio_SetCh4Param(0x35);
sound_result[6]=Audio_Ch4Param;
Audio_Ch4NoteOn(Audio_Ch4Param,0xC0);
sound_result[7]=NR43;
sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH4); sound_wait(15);
sound_end();
}Resultado esperado
Tras aproximadamente medio segundo de silencio, se oyen CH1 A4, CH2 A4, CH3 A3 y ruido. Cada voz dura 30 fotogramas, con pausas de 15. SEQUENCE COMPLETE indica el final del programa; usa la grabación para valorar el sonido.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_channels.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-channels.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/audio.h:141
Cache the low two duty bits for the next CH1 note; do not change the active register.
kitaqgb/lib/audio.c:644
void __stackcall Audio_SetCh1Duty(u8 duty) {
Audio_Ch1Duty = (u8)(duty & 3);
}Audio_SetCh2Duty
Guarda el índice de ciclo de trabajo de la próxima nota CH2.
Sintaxis
void __stackcall Audio_SetCh2Duty(u8 duty);Parámetros
dutyÍndice de ciclo de trabajo; se guardan los dos bits bajos. 0=12,5 %, 1=25 %, 2=50 %, 3=75 %.
Valor devuelto
Sin valor de retorno. Modifica registros de sonido o el estado del controlador.
Condiciones y límites
Esta llamada por sí sola no cambia los registros de sonido activos. Pasa el valor guardado al inicio de nota o usa el flujo correspondiente para aplicarlo.
Ejemplo de uso
// Four isolated voices, each lasting 30 frames, separated by 15 silent frames.
#include "gb_sound_example.h"
void main() {
sound_begin("FOUR SOUND CHANNELS");
Audio_SetMasterVolume(3,3);
// CH1: A4, 50% duty, fixed envelope volume 12.
Audio_SetCh1Duty(2);
sound_result[0]=Audio_Ch1Duty;
Audio_Ch1NoteOn(33,0xC0,Audio_Ch1Duty);
sound_result[1]=NR12;
sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH1); sound_wait(15);
// CH2: A4, 25% duty. Changing the cached duty takes effect on this trigger.
Audio_SetCh2Duty(1);
sound_result[2]=Audio_Ch2Duty;
Audio_Ch2NoteOn(33,0xC0,Audio_Ch2Duty);
sound_result[3]=NR22;
sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH2); sound_wait(15);
// CH3: the initialized triangle wave, at 50% digital output level.
Audio_SetCh3Level(AUDIO_CH3_LEVEL_50);
sound_result[4]=Audio_Ch3Level;
Audio_Ch3NoteOn(33,Audio_Ch3Level);
sound_result[5]=NR32;
sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH3); sound_wait(15);
// CH4: a sustained noise burst; param is NR43, not a pitched note number.
Audio_SetCh4Param(0x35);
sound_result[6]=Audio_Ch4Param;
Audio_Ch4NoteOn(Audio_Ch4Param,0xC0);
sound_result[7]=NR43;
sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH4); sound_wait(15);
sound_end();
}Resultado esperado
Tras aproximadamente medio segundo de silencio, se oyen CH1 A4, CH2 A4, CH3 A3 y ruido. Cada voz dura 30 fotogramas, con pausas de 15. SEQUENCE COMPLETE indica el final del programa; usa la grabación para valorar el sonido.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_channels.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-channels.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/audio.h:143
Cache the low two duty bits for the next CH2 note; do not change the active register.
kitaqgb/lib/audio.c:649
void __stackcall Audio_SetCh2Duty(u8 duty) {
Audio_Ch2Duty = (u8)(duty & 3);
}Audio_SetCh3Level
Guarda el nivel de salida NR32 de la próxima nota CH3.
Sintaxis
void __stackcall Audio_SetCh3Level(u8 level);Parámetros
levelCodificación NR32: 0x00=silencio, 0x20=100 %, 0x40=50 %, 0x60=25 %.
Valor devuelto
Sin valor de retorno. Modifica registros de sonido o el estado del controlador.
Condiciones y límites
Esta llamada por sí sola no cambia los registros de sonido activos. Pasa el valor guardado al inicio de nota o usa el flujo correspondiente para aplicarlo.
Ejemplo de uso
// Four isolated voices, each lasting 30 frames, separated by 15 silent frames.
#include "gb_sound_example.h"
void main() {
sound_begin("FOUR SOUND CHANNELS");
Audio_SetMasterVolume(3,3);
// CH1: A4, 50% duty, fixed envelope volume 12.
Audio_SetCh1Duty(2);
sound_result[0]=Audio_Ch1Duty;
Audio_Ch1NoteOn(33,0xC0,Audio_Ch1Duty);
sound_result[1]=NR12;
sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH1); sound_wait(15);
// CH2: A4, 25% duty. Changing the cached duty takes effect on this trigger.
Audio_SetCh2Duty(1);
sound_result[2]=Audio_Ch2Duty;
Audio_Ch2NoteOn(33,0xC0,Audio_Ch2Duty);
sound_result[3]=NR22;
sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH2); sound_wait(15);
// CH3: the initialized triangle wave, at 50% digital output level.
Audio_SetCh3Level(AUDIO_CH3_LEVEL_50);
sound_result[4]=Audio_Ch3Level;
Audio_Ch3NoteOn(33,Audio_Ch3Level);
sound_result[5]=NR32;
sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH3); sound_wait(15);
// CH4: a sustained noise burst; param is NR43, not a pitched note number.
Audio_SetCh4Param(0x35);
sound_result[6]=Audio_Ch4Param;
Audio_Ch4NoteOn(Audio_Ch4Param,0xC0);
sound_result[7]=NR43;
sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH4); sound_wait(15);
sound_end();
}Resultado esperado
Tras aproximadamente medio segundo de silencio, se oyen CH1 A4, CH2 A4, CH3 A3 y ruido. Cada voz dura 30 fotogramas, con pausas de 15. SEQUENCE COMPLETE indica el final del programa; usa la grabación para valorar el sonido.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_channels.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-channels.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/audio.h:145
Cache the raw NR32 level encoding for the next CH3 note without writing hardware.
kitaqgb/lib/audio.c:654
void __stackcall Audio_SetCh3Level(u8 level) {
Audio_Ch3Level = level;
}Audio_SetCh4Param
Guarda los parámetros de ruido NR43 de la próxima nota CH4.
Sintaxis
void __stackcall Audio_SetCh4Param(u8 param);Parámetros
paramNR43 bruto: bits 7..4 para desplazamiento del reloj, bit 3 para LFSR corto y bits 2..0 para código divisor.
Valor devuelto
Sin valor de retorno. Modifica registros de sonido o el estado del controlador.
Condiciones y límites
Esta llamada por sí sola no cambia los registros de sonido activos. Pasa el valor guardado al inicio de nota o usa el flujo correspondiente para aplicarlo.
Ejemplo de uso
// Four isolated voices, each lasting 30 frames, separated by 15 silent frames.
#include "gb_sound_example.h"
void main() {
sound_begin("FOUR SOUND CHANNELS");
Audio_SetMasterVolume(3,3);
// CH1: A4, 50% duty, fixed envelope volume 12.
Audio_SetCh1Duty(2);
sound_result[0]=Audio_Ch1Duty;
Audio_Ch1NoteOn(33,0xC0,Audio_Ch1Duty);
sound_result[1]=NR12;
sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH1); sound_wait(15);
// CH2: A4, 25% duty. Changing the cached duty takes effect on this trigger.
Audio_SetCh2Duty(1);
sound_result[2]=Audio_Ch2Duty;
Audio_Ch2NoteOn(33,0xC0,Audio_Ch2Duty);
sound_result[3]=NR22;
sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH2); sound_wait(15);
// CH3: the initialized triangle wave, at 50% digital output level.
Audio_SetCh3Level(AUDIO_CH3_LEVEL_50);
sound_result[4]=Audio_Ch3Level;
Audio_Ch3NoteOn(33,Audio_Ch3Level);
sound_result[5]=NR32;
sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH3); sound_wait(15);
// CH4: a sustained noise burst; param is NR43, not a pitched note number.
Audio_SetCh4Param(0x35);
sound_result[6]=Audio_Ch4Param;
Audio_Ch4NoteOn(Audio_Ch4Param,0xC0);
sound_result[7]=NR43;
sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH4); sound_wait(15);
sound_end();
}Resultado esperado
Tras aproximadamente medio segundo de silencio, se oyen CH1 A4, CH2 A4, CH3 A3 y ruido. Cada voz dura 30 fotogramas, con pausas de 15. SEQUENCE COMPLETE indica el final del programa; usa la grabación para valorar el sonido.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_channels.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-channels.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/audio.h:147
Cache the raw noise polynomial encoding for the next CH4 note without writing hardware.
kitaqgb/lib/audio.c:659
void __stackcall Audio_SetCh4Param(u8 param) {
Audio_Ch4Param = param;
}Audio_SetMasterVolume
Limita los niveles maestros izquierdo/derecho a 0..7, los escribe de inmediato y cancela el fundido activo.
Sintaxis
void __stackcall Audio_SetMasterVolume(u8 left, u8 right);Parámetros
leftNivel maestro izquierdo, de 0 a 7; los valores mayores se limitan a 7. Cero no es silencio total.
rightNivel maestro derecho, de 0 a 7; los valores mayores se limitan a 7.
Valor devuelto
Sin valor de retorno. Modifica registros de sonido o el estado del controlador.
Ejemplo de uso
// A sustained pulse moves left, right and center, then fades to a quieter level.
#include "gb_sound_example.h"
void main() {
sound_begin("PAN AND VOLUME");
Audio_SetMasterVolume(7,7);
Audio_Ch1NoteOn(33,0xC0,2);
Audio_SetPan(AUDIO_CHANNEL_CH1,AUDIO_PAN_LEFT);
sound_result[0]=NR51;
sound_wait(30);
// Packed low two bits are CH1: 2 means right. Other channels remain centered.
Audio_SetPanPacked(2);
sound_result[1]=NR51;
sound_wait(30);
Audio_SetPanPacked(0);
sound_result[2]=NR51;
Audio_FadeToMasterVolume(1,1,5);
sound_wait(30);
sound_result[3]=NR50;
sound_result[4]=Audio_FadeActive;
sound_wait(30);
// Cancel halfway through a rise: retain volume 4 instead of reaching 7.
Audio_FadeToMasterVolume(7,7,5);
sound_wait(15);
Audio_CancelMasterVolumeFade();
sound_result[5]=NR50;
sound_wait(30);
sound_result[6]=NR50;
// A zero fade interval sets the target immediately. Level zero is not mute.
Audio_FadeToMasterVolume(0,0,0);
sound_result[7]=NR50;
sound_wait(30);
Audio_StopChannel(AUDIO_CHANNEL_CH1);
sound_wait(15);
sound_end();
}Resultado esperado
A4 pasa a izquierda, derecha y centro. En el centro baja del nivel 7 al 1, sube al 4 y permanece ahí. El nivel 0 aún se oye débilmente; detener el canal produce silencio. Cambiar el enrutamiento puede dejar un transitorio de filtro que se desvanece.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_mix.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-mix.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/audio.h:120
Clamp both output levels to 0..7, cancel any fade, and write NR50 immediately.
kitaqgb/lib/audio.c:515
void __stackcall Audio_SetMasterVolume(u8 left, u8 right) {
Audio_MasterLeft = Audio_ClampVolume(left);
Audio_MasterRight = Audio_ClampVolume(right);
Audio_FadeTargetLeft = Audio_MasterLeft;
Audio_FadeTargetRight = Audio_MasterRight;
Audio_FadeStepFrames = 0;
Audio_FadeCounter = 0;
Audio_FadeActive = 0;
Audio_UpdateNR50();
}Audio_SetMusicEnabled
Controla si el decodificador musical normal escribe notas nuevas.
Sintaxis
void __stackcall Audio_SetMusicEnabled(u8 on);Parámetros
onCero deshabilita y un valor no nulo habilita. Consulta la descripción para distinguir entre silenciar y bloquear las actualizaciones.
Valor devuelto
Sin valor de retorno. Modifica registros de sonido o el estado del controlador.
Condiciones y límites
Deshabilitar sigue avanzando el flujo y procesando instrumentos y panorama. No silencia la nota actual. Usa Audio_SetPaused para pausar la reproducción.
Ejemplo de uso
// Original two-note phrase: pause preserves the cursor; the enable gate does not.
#include "gb_sound_example.h"
__prg_rom u8 song[]={
AUDIO_CMD_SET_INST,AUDIO_STREAM_CHANNEL_CH1,2,0xC0,
AUDIO_CMD_NOTE,AUDIO_STREAM_CHANNEL_CH1,33,AUDIO_CMD_WAIT,59,
AUDIO_CMD_NOTE,AUDIO_STREAM_CHANNEL_CH1,40,AUDIO_CMD_WAIT,59,
AUDIO_CMD_LOOP
};
void main() {
u8 delay;
sound_begin("MUSIC PAUSE GATE");
Audio_SetMasterVolume(3,3);
Audio_PlayMusic(0,song);
sound_wait(30);
delay=Audio_Delay;
Audio_SetPaused(1);
sound_wait(30);
sound_result[0]=(u8)(Audio_Delay==delay);
sound_result[1]=Audio_Paused;
Audio_SetPaused(0);
sound_wait(30);
sound_result[2]=Audio_Paused;
// Disabling suppresses note writes; the next 30 updates still consume data.
Audio_SetMusicEnabled(0);
sound_wait(30);
sound_result[3]=Audio_Delay;
sound_result[4]=Audio_MusicEnabled;
// Explicitly stop the sounding channel while leaving the stream running.
Audio_StopChannel(AUDIO_CHANNEL_CH1);
sound_wait(30);
Audio_SetMusicEnabled(1);
sound_wait(30);
Audio_StopMusic();
sound_result[5]=Audio_PlayingMusic;
sound_wait(30);
sound_end();
}Resultado esperado
Se oyen una nota, silencio en pausa, reanudación, una nota retenida al deshabilitar la música, silencio explícito del canal, la siguiente nota tras habilitar y, al final, parada. La RAM también verifica que 30 actualizaciones en pausa conservan delay, mientras que deshabilitar la música deja que avance hasta 30.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_music.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-music.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/audio.h:114
Set the music-processing gate. This does not silence notes already playing or stop the legacy stream cursor from consuming commands.
kitaqgb/lib/audio.c:498
void __stackcall Audio_SetMusicEnabled(u8 on) {
if (on != 0) Audio_MusicEnabled = 1;
else Audio_MusicEnabled = 0;
}Audio_SetPan
Cambia el panorama base de una voz física y vuelve a aplicar los panoramas específicos de los efectos activos.
Sintaxis
void __stackcall Audio_SetPan(u8 ch, u8 pan);Parámetros
chID de canal: 0=CH1, 1=CH2, 2=CH3, 3=CH4. Las API directas y los flujos musicales usan los mismos ID.
pan0=centro, 1=izquierda, 2=derecha, 3=silencio. Las API de efectos tratan valores mayores que 3, incluido 0xFF, como herencia del panorama base.
Valor devuelto
Sin valor de retorno. Modifica registros de sonido o el estado del controlador.
Condiciones y límites
Un canal desconocido selecciona CH4. Aquí pan fuera de 0..3 silencia; no es la opción de heredar de las API de efectos.
Ejemplo de uso
// A sustained pulse moves left, right and center, then fades to a quieter level.
#include "gb_sound_example.h"
void main() {
sound_begin("PAN AND VOLUME");
Audio_SetMasterVolume(7,7);
Audio_Ch1NoteOn(33,0xC0,2);
Audio_SetPan(AUDIO_CHANNEL_CH1,AUDIO_PAN_LEFT);
sound_result[0]=NR51;
sound_wait(30);
// Packed low two bits are CH1: 2 means right. Other channels remain centered.
Audio_SetPanPacked(2);
sound_result[1]=NR51;
sound_wait(30);
Audio_SetPanPacked(0);
sound_result[2]=NR51;
Audio_FadeToMasterVolume(1,1,5);
sound_wait(30);
sound_result[3]=NR50;
sound_result[4]=Audio_FadeActive;
sound_wait(30);
// Cancel halfway through a rise: retain volume 4 instead of reaching 7.
Audio_FadeToMasterVolume(7,7,5);
sound_wait(15);
Audio_CancelMasterVolumeFade();
sound_result[5]=NR50;
sound_wait(30);
sound_result[6]=NR50;
// A zero fade interval sets the target immediately. Level zero is not mute.
Audio_FadeToMasterVolume(0,0,0);
sound_result[7]=NR50;
sound_wait(30);
Audio_StopChannel(AUDIO_CHANNEL_CH1);
sound_wait(15);
sound_end();
}Resultado esperado
A4 pasa a izquierda, derecha y centro. En el centro baja del nivel 7 al 1, sube al 4 y permanece ahí. El nivel 0 aún se oye débilmente; detener el canal produce silencio. Cambiar el enrutamiento puede dejar un transitorio de filtro que se desvanece.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_mix.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-mix.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/audio.h:129
Update the base pan for a physical channel and reapply active effect overrides. Unknown channel IDs select CH4; unsupported pan values mute the selected channel.
kitaqgb/lib/audio.c:558
void __stackcall Audio_SetPan(u8 ch, u8 pan) {
u8 r_bit;
u8 l_bit;
u8 mask;
if (ch == AUDIO_CHANNEL_CH1) {
r_bit = 0x01;
l_bit = 0x10;
} else if (ch == AUDIO_CHANNEL_CH2) {
r_bit = 0x02;
l_bit = 0x20;
} else if (ch == AUDIO_CHANNEL_CH3) {
r_bit = 0x04;
l_bit = 0x40;
} else {
r_bit = 0x08;
l_bit = 0x80;
}
mask = (u8)(l_bit | r_bit);
Audio_Pan = (u8)(Audio_Pan & (u8)~mask);
if (pan == AUDIO_PAN_CENTER) Audio_Pan = (u8)(Audio_Pan | mask);
else if (pan == AUDIO_PAN_LEFT) Audio_Pan = (u8)(Audio_Pan | l_bit);
else if (pan == AUDIO_PAN_RIGHT) Audio_Pan = (u8)(Audio_Pan | r_bit);
Audio_UpdateNR51();
}Audio_SetPanPacked
Extrae cuatro panoramas base de un byte y actualiza NR51 una vez.
Sintaxis
void __stackcall Audio_SetPanPacked(u8 packed);Parámetros
packedDos bits por canal físico: CH1 en 0..1, CH2 en 2..3, CH3 en 4..5 y CH4 en 6..7. Cada campo usa los valores de panorama.
Valor devuelto
Sin valor de retorno. Modifica registros de sonido o el estado del controlador.
Ejemplo de uso
// A sustained pulse moves left, right and center, then fades to a quieter level.
#include "gb_sound_example.h"
void main() {
sound_begin("PAN AND VOLUME");
Audio_SetMasterVolume(7,7);
Audio_Ch1NoteOn(33,0xC0,2);
Audio_SetPan(AUDIO_CHANNEL_CH1,AUDIO_PAN_LEFT);
sound_result[0]=NR51;
sound_wait(30);
// Packed low two bits are CH1: 2 means right. Other channels remain centered.
Audio_SetPanPacked(2);
sound_result[1]=NR51;
sound_wait(30);
Audio_SetPanPacked(0);
sound_result[2]=NR51;
Audio_FadeToMasterVolume(1,1,5);
sound_wait(30);
sound_result[3]=NR50;
sound_result[4]=Audio_FadeActive;
sound_wait(30);
// Cancel halfway through a rise: retain volume 4 instead of reaching 7.
Audio_FadeToMasterVolume(7,7,5);
sound_wait(15);
Audio_CancelMasterVolumeFade();
sound_result[5]=NR50;
sound_wait(30);
sound_result[6]=NR50;
// A zero fade interval sets the target immediately. Level zero is not mute.
Audio_FadeToMasterVolume(0,0,0);
sound_result[7]=NR50;
sound_wait(30);
Audio_StopChannel(AUDIO_CHANNEL_CH1);
sound_wait(15);
sound_end();
}Resultado esperado
A4 pasa a izquierda, derecha y centro. En el centro baja del nivel 7 al 1, sube al 4 y permanece ahí. El nivel 0 aún se oye débilmente; detener el canal produce silencio. Cambiar el enrutamiento puede dejar un transitorio de filtro que se desvanece.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_mix.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-mix.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/audio.h:132
Two bits per channel (CH1 in bits 0-1): center, left, right, mute. Applies all four positions with one NR51 update for sequencer automation.
kitaqgb/lib/audio.c:589
void __stackcall Audio_SetPanPacked(u8 packed) {
u8 mix = 0;
u8 pan = (u8)(packed & 3);
if (pan == AUDIO_PAN_CENTER) mix = (u8)(mix | 0x11);
else if (pan == AUDIO_PAN_LEFT) mix = (u8)(mix | 0x10);
else if (pan == AUDIO_PAN_RIGHT) mix = (u8)(mix | 0x01);
pan = (u8)((packed >> 2) & 3);
if (pan == AUDIO_PAN_CENTER) mix = (u8)(mix | 0x22);
else if (pan == AUDIO_PAN_LEFT) mix = (u8)(mix | 0x20);
else if (pan == AUDIO_PAN_RIGHT) mix = (u8)(mix | 0x02);
pan = (u8)((packed >> 4) & 3);
if (pan == AUDIO_PAN_CENTER) mix = (u8)(mix | 0x44);
else if (pan == AUDIO_PAN_LEFT) mix = (u8)(mix | 0x40);
else if (pan == AUDIO_PAN_RIGHT) mix = (u8)(mix | 0x04);
pan = (u8)((packed >> 6) & 3);
if (pan == AUDIO_PAN_CENTER) mix = (u8)(mix | 0x88);
else if (pan == AUDIO_PAN_LEFT) mix = (u8)(mix | 0x80);
else if (pan == AUDIO_PAN_RIGHT) mix = (u8)(mix | 0x08);
Audio_Pan = mix;
Audio_UpdateNR51();
}Audio_SetPaused
Silencia en pausa conservando las posiciones de música y efectos. Al reanudar vuelve a disparar las notas que correspondan de CH1, CH2 y CH4.
Sintaxis
void __stackcall Audio_SetPaused(u8 on);Parámetros
onCero deshabilita y un valor no nulo habilita. Consulta la descripción para distinguir entre silenciar y bloquear las actualizaciones.
Valor devuelto
Sin valor de retorno. Modifica registros de sonido o el estado del controlador.
Condiciones y límites
Incluye audio_hwregs_gb.c antes de audio.c y llama a Audio_Init al arrancar. Llama a Audio_Update exactamente una vez por fotograma, unos 59,7 Hz. Las lecturas del flujo cambian temporalmente el mapeo ROM; no vuelvas a entrar en este controlador desde una interrupción.
Esta rutina no vuelve a disparar CH3. Los efectos continúan en una actualización posterior. Las llamadas directas de inicio de nota pueden sonar incluso en pausa.
Ejemplo de uso
// Original two-note phrase: pause preserves the cursor; the enable gate does not.
#include "gb_sound_example.h"
__prg_rom u8 song[]={
AUDIO_CMD_SET_INST,AUDIO_STREAM_CHANNEL_CH1,2,0xC0,
AUDIO_CMD_NOTE,AUDIO_STREAM_CHANNEL_CH1,33,AUDIO_CMD_WAIT,59,
AUDIO_CMD_NOTE,AUDIO_STREAM_CHANNEL_CH1,40,AUDIO_CMD_WAIT,59,
AUDIO_CMD_LOOP
};
void main() {
u8 delay;
sound_begin("MUSIC PAUSE GATE");
Audio_SetMasterVolume(3,3);
Audio_PlayMusic(0,song);
sound_wait(30);
delay=Audio_Delay;
Audio_SetPaused(1);
sound_wait(30);
sound_result[0]=(u8)(Audio_Delay==delay);
sound_result[1]=Audio_Paused;
Audio_SetPaused(0);
sound_wait(30);
sound_result[2]=Audio_Paused;
// Disabling suppresses note writes; the next 30 updates still consume data.
Audio_SetMusicEnabled(0);
sound_wait(30);
sound_result[3]=Audio_Delay;
sound_result[4]=Audio_MusicEnabled;
// Explicitly stop the sounding channel while leaving the stream running.
Audio_StopChannel(AUDIO_CHANNEL_CH1);
sound_wait(30);
Audio_SetMusicEnabled(1);
sound_wait(30);
Audio_StopMusic();
sound_result[5]=Audio_PlayingMusic;
sound_wait(30);
sound_end();
}Resultado esperado
Se oyen una nota, silencio en pausa, reanudación, una nota retenida al deshabilitar la música, silencio explícito del canal, la siguiente nota tras habilitar y, al final, parada. La RAM también verifica que 30 actualizaciones en pausa conservan delay, mientras que deshabilitar la música deja que avance hasta 30.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_music.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-music.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/audio.h:90
On pause entry, silence hardware while retaining cursors. On resume, retrigger eligible legacy CH1, CH2 and CH4 notes; CH3 is not retriggered here. Updates still advance master fades while paused, and effect playback resumes on a later update.
kitaqgb/lib/audio.c:1010
void __stackcall Audio_SetPaused(u8 on) {
if (on != 0) {
if (Audio_Paused == 0) {
Audio_Paused = 1;
Audio_SilenceAll();
}
} else {
if (Audio_Paused != 0) {
Audio_Paused = 0;
if (Audio_PlayingMusic != 0 && Audio_MusicEnabled != 0) {
if ((Audio_LastChMask & AUDIO_RESUME_CH1) != 0 && Audio_EffectPointer == 0) {
Audio_Ch1NoteOn(Audio_LastCh1Note, Audio_Ch1Env, Audio_Ch1Duty);
}
if ((Audio_LastChMask & AUDIO_RESUME_CH2) != 0) {
Audio_Ch2NoteOn(Audio_LastCh2Note, Audio_Ch2Env, Audio_Ch2Duty);
}
if ((Audio_LastChMask & AUDIO_RESUME_CH4) != 0) {
Audio_Ch4NoteOn(Audio_LastCh4Param, Audio_Ch4Env);
}
}
}
}
}Audio_SetSfxEnabled
Permite o bloquea las escrituras de notas de efectos; deshabilitar también libera sus ranuras.
Sintaxis
void __stackcall Audio_SetSfxEnabled(u8 on);Parámetros
onCero deshabilita y un valor no nulo habilita. Consulta la descripción para distinguir entre silenciar y bloquear las actualizaciones.
Valor devuelto
Sin valor de retorno. Modifica registros de sonido o el estado del controlador.
Condiciones y límites
En la configuración normal, liberar un efecto apaga CH3. Silencia CH1 si la música está detenida, pero no vuelve a tocar automáticamente una nota anterior mientras la música sigue activa. Con AUDIO_VBLANK_SFX_RESTORE, la liberación solicita la recuperación a la ISR.
Iniciar con efectos deshabilitados puede registrar un flujo, pero las actualizaciones suprimen sus escrituras de notas. Habilita los efectos antes de pedir reproducción audible.
Ejemplo de uso
// Each pair lasts one update. Priority controls replacement within each slot.
#include "gb_sound_example.h"
#pragma bank 2
__prg_rom u8 effect[]={33,0xC0,33,0xC0,33,0xC0,33,0xC0,33,0xC0,33,0xC0,
40,0xC0,40,0xC0,40,0xC0,40,0xC0,40,0xC0,40,0xC0,0};
__prg_rom u8 wave_effect[]={AUDIO_SFX_CH3_MARKER,
33,0x20,33,0x20,33,0x20,33,0x20,33,0x20,33,0x20,
40,0x20,40,0x20,40,0x20,40,0x20,40,0x20,40,0x20,0};
#pragma bank 0
void main() {
sound_begin("BANKED SOUND EFFECT");
Audio_SetMasterVolume(3,3);
// Read the marker in bank 2 while restoring the caller's original mapping.
Audio_PlaySFXPannedBanked(2,effect,5,AUDIO_PAN_LEFT);
sound_result[0]=Audio_EffectPriority;
Audio_PlaySFXBanked(2,effect,4);
sound_result[1]=Audio_EffectPriority;
sound_wait(30);
Audio_PlaySFXPannedBanked(2,wave_effect,5,AUDIO_PAN_RIGHT);
sound_result[2]=Audio_EffectPriority3;
sound_wait(30);
// Implicit-bank entry points capture bank 2; the service restores bank 1.
__bankswitch(2);
Audio_PlaySFX(effect,5);
__bankswitch(1);
sound_result[3]=Audio_EffectBank;
sound_wait(30);
__bankswitch(2);
Audio_PlaySFXPanned(effect,5,AUDIO_PAN_RIGHT);
__bankswitch(1);
sound_wait(6);
Audio_StopSfx();
sound_result[4]=(u8)(Audio_EffectPointer==0);
sound_wait(24);
// Disabling effects releases current owners; re-enable before the next request.
Audio_PlaySFXBanked(2,effect,5);
sound_wait(6);
Audio_SetSfxEnabled(0);
sound_result[5]=Audio_SfxEnabled;
sound_result[6]=(u8)(Audio_EffectPointer==0);
sound_wait(24);
Audio_SetSfxEnabled(1);
Audio_PlaySFXBanked(2,effect,5);
sound_wait(30);
sound_result[7]=Audio_SfxEnabled;
sound_end();
}Resultado esperado
Los datos del banco 2 reproducen un pulso ascendente corto a la izquierda, un efecto de onda a la derecha y un pulso centrado. Los ejemplos posteriores detienen antes un pulso derecho, deshabilitan un efecto y vuelven a habilitar la reproducción. Una solicitud de prioridad 4 no sustituye a la prioridad 5.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_sfx.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-sfx.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/audio.h:117
Enable effect note writes, or disable them and release both effect streams. Disabling follows Audio_StopSfx recovery rules rather than silencing all channels.
kitaqgb/lib/audio.c:505
void __stackcall Audio_SetSfxEnabled(u8 on) {
if (on != 0) {
Audio_SfxEnabled = 1;
} else {
Audio_SfxEnabled = 0;
Audio_StopSfx();
}
}Audio_StopChannel
Detiene una voz física y elimina su nota musical de la máscara de reanudación.
Sintaxis
void __stackcall Audio_StopChannel(u8 ch);Parámetros
chID de canal: 0=CH1, 1=CH2, 2=CH3, 3=CH4. Las API directas y los flujos musicales usan los mismos ID.
Valor devuelto
Sin valor de retorno. Modifica registros de sonido o el estado del controlador.
Condiciones y límites
CH1/CH3 también borran su ranura de efecto. Los valores fuera de 0..3 no hacen nada. Las notas retenidas por VBlank se gestionan aparte.
Ejemplo de uso
// Four isolated voices, each lasting 30 frames, separated by 15 silent frames.
#include "gb_sound_example.h"
void main() {
sound_begin("FOUR SOUND CHANNELS");
Audio_SetMasterVolume(3,3);
// CH1: A4, 50% duty, fixed envelope volume 12.
Audio_SetCh1Duty(2);
sound_result[0]=Audio_Ch1Duty;
Audio_Ch1NoteOn(33,0xC0,Audio_Ch1Duty);
sound_result[1]=NR12;
sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH1); sound_wait(15);
// CH2: A4, 25% duty. Changing the cached duty takes effect on this trigger.
Audio_SetCh2Duty(1);
sound_result[2]=Audio_Ch2Duty;
Audio_Ch2NoteOn(33,0xC0,Audio_Ch2Duty);
sound_result[3]=NR22;
sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH2); sound_wait(15);
// CH3: the initialized triangle wave, at 50% digital output level.
Audio_SetCh3Level(AUDIO_CH3_LEVEL_50);
sound_result[4]=Audio_Ch3Level;
Audio_Ch3NoteOn(33,Audio_Ch3Level);
sound_result[5]=NR32;
sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH3); sound_wait(15);
// CH4: a sustained noise burst; param is NR43, not a pitched note number.
Audio_SetCh4Param(0x35);
sound_result[6]=Audio_Ch4Param;
Audio_Ch4NoteOn(Audio_Ch4Param,0xC0);
sound_result[7]=NR43;
sound_wait(30); Audio_StopChannel(AUDIO_CHANNEL_CH4); sound_wait(15);
sound_end();
}Resultado esperado
Tras aproximadamente medio segundo de silencio, se oyen CH1 A4, CH2 A4, CH3 A3 y ruido. Cada voz dura 30 fotogramas, con pausas de 15. SEQUENCE COMPLETE indica el final del programa; usa la grabación para valorar el sonido.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_channels.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-channels.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/audio.h:110
Stop a physical channel and clear its legacy resume bit. CH1 also clears the pulse effect stream; CH3 clears the wave effect stream. This is the legacy channel API and does not clear a VBlank driver's independently latched notes.
kitaqgb/lib/audio.c:981
void __stackcall Audio_StopChannel(u8 ch) {
if (ch == AUDIO_CHANNEL_CH1) {
Audio_EffectPointer = 0;
Audio_EffectPriority = 0;
Audio_EffectBank = 0;
Audio_EffectPan = AUDIO_PAN_INHERIT;
Audio_LastChMask = (u8)(Audio_LastChMask & (u8)~AUDIO_RESUME_CH1);
Audio_UpdateNR51();
Audio_SilenceCh1();
} else if (ch == AUDIO_CHANNEL_CH2) {
Audio_LastChMask = (u8)(Audio_LastChMask & (u8)~AUDIO_RESUME_CH2);
Audio_SilenceCh2();
} else if (ch == AUDIO_CHANNEL_CH3) {
Audio_EffectPointer3 = 0;
Audio_EffectPriority3 = 0;
Audio_EffectBank3 = 0;
Audio_EffectPan3 = AUDIO_PAN_INHERIT;
Audio_LastChMask = (u8)(Audio_LastChMask & (u8)~AUDIO_RESUME_CH3);
Audio_UpdateNR51();
Audio_Ch3Off();
} else if (ch == AUDIO_CHANNEL_CH4) {
Audio_LastChMask = (u8)(Audio_LastChMask & (u8)~AUDIO_RESUME_CH4);
Audio_SilenceCh4();
}
}Audio_StopMusic
Borra la reproducción de canción y su máscara de reanudación, y silencia inmediatamente las cuatro voces.
Sintaxis
void Audio_StopMusic();Valor devuelto
Sin valor de retorno. Modifica registros de sonido o el estado del controlador.
Condiciones y límites
Los punteros de efectos se conservan, así que un Audio_Update posterior puede hacer sonar un efecto. Llama también a Audio_StopSfx para detenerlo todo.
Ejemplo de uso
// Original two-note phrase: pause preserves the cursor; the enable gate does not.
#include "gb_sound_example.h"
__prg_rom u8 song[]={
AUDIO_CMD_SET_INST,AUDIO_STREAM_CHANNEL_CH1,2,0xC0,
AUDIO_CMD_NOTE,AUDIO_STREAM_CHANNEL_CH1,33,AUDIO_CMD_WAIT,59,
AUDIO_CMD_NOTE,AUDIO_STREAM_CHANNEL_CH1,40,AUDIO_CMD_WAIT,59,
AUDIO_CMD_LOOP
};
void main() {
u8 delay;
sound_begin("MUSIC PAUSE GATE");
Audio_SetMasterVolume(3,3);
Audio_PlayMusic(0,song);
sound_wait(30);
delay=Audio_Delay;
Audio_SetPaused(1);
sound_wait(30);
sound_result[0]=(u8)(Audio_Delay==delay);
sound_result[1]=Audio_Paused;
Audio_SetPaused(0);
sound_wait(30);
sound_result[2]=Audio_Paused;
// Disabling suppresses note writes; the next 30 updates still consume data.
Audio_SetMusicEnabled(0);
sound_wait(30);
sound_result[3]=Audio_Delay;
sound_result[4]=Audio_MusicEnabled;
// Explicitly stop the sounding channel while leaving the stream running.
Audio_StopChannel(AUDIO_CHANNEL_CH1);
sound_wait(30);
Audio_SetMusicEnabled(1);
sound_wait(30);
Audio_StopMusic();
sound_result[5]=Audio_PlayingMusic;
sound_wait(30);
sound_end();
}Resultado esperado
Se oyen una nota, silencio en pausa, reanudación, una nota retenida al deshabilitar la música, silencio explícito del canal, la siguiente nota tras habilitar y, al final, parada. La RAM también verifica que 30 actualizaciones en pausa conservan delay, mientras que deshabilitar la música deja que avance hasta 30.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_music.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-music.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/audio.h:86
Stop legacy music and clear its resume mask, then silence all physical channels. Effect pointers remain active and may produce sound on a later update.
kitaqgb/lib/audio.c:952
void Audio_StopMusic() {
Audio_PlayingMusic = 0;
Audio_LastChMask = 0;
Audio_SilenceAll();
}Audio_StopSfx
Borra ambos flujos de efectos y sus panoramas específicos, y libera los canales prestados.
Sintaxis
void Audio_StopSfx();Valor devuelto
Sin valor de retorno. Modifica registros de sonido o el estado del controlador.
Condiciones y límites
Un efecto consume un par (note,value) por actualización y termina en note=0. value es NR12 para efectos de pulsos y NR32 para CH3. Antepon 0xFF a los datos CH3 y conserva la memoria hasta que termine. Las prioridades compiten dentro de una ranura; una prioridad igual también puede sustituir al efecto actual.
En la configuración normal, liberar un efecto apaga CH3. Silencia CH1 si la música está detenida, pero no vuelve a tocar automáticamente una nota anterior mientras la música sigue activa. Con AUDIO_VBLANK_SFX_RESTORE, la liberación solicita la recuperación a la ISR.
Ejemplo de uso
// Each pair lasts one update. Priority controls replacement within each slot.
#include "gb_sound_example.h"
#pragma bank 2
__prg_rom u8 effect[]={33,0xC0,33,0xC0,33,0xC0,33,0xC0,33,0xC0,33,0xC0,
40,0xC0,40,0xC0,40,0xC0,40,0xC0,40,0xC0,40,0xC0,0};
__prg_rom u8 wave_effect[]={AUDIO_SFX_CH3_MARKER,
33,0x20,33,0x20,33,0x20,33,0x20,33,0x20,33,0x20,
40,0x20,40,0x20,40,0x20,40,0x20,40,0x20,40,0x20,0};
#pragma bank 0
void main() {
sound_begin("BANKED SOUND EFFECT");
Audio_SetMasterVolume(3,3);
// Read the marker in bank 2 while restoring the caller's original mapping.
Audio_PlaySFXPannedBanked(2,effect,5,AUDIO_PAN_LEFT);
sound_result[0]=Audio_EffectPriority;
Audio_PlaySFXBanked(2,effect,4);
sound_result[1]=Audio_EffectPriority;
sound_wait(30);
Audio_PlaySFXPannedBanked(2,wave_effect,5,AUDIO_PAN_RIGHT);
sound_result[2]=Audio_EffectPriority3;
sound_wait(30);
// Implicit-bank entry points capture bank 2; the service restores bank 1.
__bankswitch(2);
Audio_PlaySFX(effect,5);
__bankswitch(1);
sound_result[3]=Audio_EffectBank;
sound_wait(30);
__bankswitch(2);
Audio_PlaySFXPanned(effect,5,AUDIO_PAN_RIGHT);
__bankswitch(1);
sound_wait(6);
Audio_StopSfx();
sound_result[4]=(u8)(Audio_EffectPointer==0);
sound_wait(24);
// Disabling effects releases current owners; re-enable before the next request.
Audio_PlaySFXBanked(2,effect,5);
sound_wait(6);
Audio_SetSfxEnabled(0);
sound_result[5]=Audio_SfxEnabled;
sound_result[6]=(u8)(Audio_EffectPointer==0);
sound_wait(24);
Audio_SetSfxEnabled(1);
Audio_PlaySFXBanked(2,effect,5);
sound_wait(30);
sound_result[7]=Audio_SfxEnabled;
sound_end();
}Resultado esperado
Los datos del banco 2 reproducen un pulso ascendente corto a la izquierda, un efecto de onda a la derecha y un pulso centrado. Los ejemplos posteriores detienen antes un pulso derecho, deshabilitan un efecto y vuelven a habilitar la reproducción. Una solicitud de prioridad 4 no sustituye a la prioridad 5.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_sfx.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-sfx.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/audio.h:106
Clear both effect streams and their pan overrides. When not paused, release borrowed channels through the configured legacy or VBlank recovery path.
kitaqgb/lib/audio.c:960
void Audio_StopSfx() {
Audio_EffectPointer = 0;
Audio_EffectPriority = 0;
Audio_EffectBank = 0;
Audio_EffectPointer3 = 0;
Audio_EffectPriority3 = 0;
Audio_EffectBank3 = 0;
Audio_EffectPan = AUDIO_PAN_INHERIT;
Audio_EffectPan3 = AUDIO_PAN_INHERIT;
Audio_UpdateNR51();
if (Audio_Paused != 0) return;
Audio_ReleaseCh1AfterSfx();
Audio_RestoreCh3FromMusic();
}Audio_Update
Avanza una vez el fundido de volumen; salvo en pausa, procesa después efectos y música, en ese orden.
Sintaxis
void Audio_Update();Valor devuelto
Sin valor de retorno. Modifica registros de sonido o el estado del controlador.
Condiciones y límites
Incluye audio_hwregs_gb.c antes de audio.c y llama a Audio_Init al arrancar. Llama a Audio_Update exactamente una vez por fotograma, unos 59,7 Hz. Las lecturas del flujo cambian temporalmente el mapeo ROM; no vuelvas a entrar en este controlador desde una interrupción.
Los fundidos continúan en pausa. Leer WAIT n va seguido de n llamadas de espera, por lo que la orden siguiente llega tras n+1 actualizaciones.
Ejemplo de uso
// Original two-note phrase: pause preserves the cursor; the enable gate does not.
#include "gb_sound_example.h"
__prg_rom u8 song[]={
AUDIO_CMD_SET_INST,AUDIO_STREAM_CHANNEL_CH1,2,0xC0,
AUDIO_CMD_NOTE,AUDIO_STREAM_CHANNEL_CH1,33,AUDIO_CMD_WAIT,59,
AUDIO_CMD_NOTE,AUDIO_STREAM_CHANNEL_CH1,40,AUDIO_CMD_WAIT,59,
AUDIO_CMD_LOOP
};
void main() {
u8 delay;
sound_begin("MUSIC PAUSE GATE");
Audio_SetMasterVolume(3,3);
Audio_PlayMusic(0,song);
sound_wait(30);
delay=Audio_Delay;
Audio_SetPaused(1);
sound_wait(30);
sound_result[0]=(u8)(Audio_Delay==delay);
sound_result[1]=Audio_Paused;
Audio_SetPaused(0);
sound_wait(30);
sound_result[2]=Audio_Paused;
// Disabling suppresses note writes; the next 30 updates still consume data.
Audio_SetMusicEnabled(0);
sound_wait(30);
sound_result[3]=Audio_Delay;
sound_result[4]=Audio_MusicEnabled;
// Explicitly stop the sounding channel while leaving the stream running.
Audio_StopChannel(AUDIO_CHANNEL_CH1);
sound_wait(30);
Audio_SetMusicEnabled(1);
sound_wait(30);
Audio_StopMusic();
sound_result[5]=Audio_PlayingMusic;
sound_wait(30);
sound_end();
}Resultado esperado
Se oyen una nota, silencio en pausa, reanudación, una nota retenida al deshabilitar la música, silencio explícito del canal, la siguiente nota tras habilitar y, al final, parada. La RAM también verifica que 30 actualizaciones en pausa conservan delay, mientras que deshabilitar la música deja que avance hasta 30.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_music.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-music.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/audio.h:79
Advance the master fade first. Unless paused, service both effect streams then the optional legacy music decoder. Call once per frame for frame-based timing.
kitaqgb/lib/audio.c:849
void Audio_Update() {
Audio_UpdateFade();
if (Audio_Paused != 0) return;
Audio_ServiceSfx();
#ifndef AUDIO_EXCLUDE_LEGACY_MUSIC_SERVICE
Audio_ServiceMusic();
#endif
}audio_vblank.h — Reproducción musical mediante la interrupción VBlank
Procesa música en VBlank, coordina el uso de voces por efectos y ofrece un hook por fotograma. No avances además la misma canción con el decodificador musical normal.
audio_vblank.c implementa __kq_vblank_vector; no instales además otro vector VBlank que compita con él. El ejemplo define Audio_NoiseEffectActive, excluye el decodificador musical normal y usa Audio_Update solo para efectos y fundidos. Bloquea las interrupciones al cambiar punteros de canción o estado compartido.
Guarda los datos de canción de lectura directa en ROM fija u otra zona siempre visible para la ISR. Cada registro tiene cinco bytes: delay, CH1, CH2, CH3, CH4. En los campos de nota, 0xFF mantiene la voz y 0xFD la detiene. En delay, 0xFF termina la reproducción y 0xFE repite. Es la disposición del registro, no la numeración de canales. La reproducción por cola WRAM es otro modo; envía registros completos de cinco bytes con AudioVBlank_QueueRefill.
AudioVBlank_DisableIrq
Borra solo el bit VBlank de IE, sin cambiar otras fuentes de interrupción ni el sonido.
Sintaxis
void AudioVBlank_DisableIrq();Valor devuelto
Sin valor de retorno. Modifica registros de sonido o el estado del controlador.
Condiciones y límites
audio_vblank.c implementa __kq_vblank_vector; no instales además otro vector VBlank que compita con él. El ejemplo define Audio_NoiseEffectActive, excluye el decodificador musical normal y usa Audio_Update solo para efectos y fundidos. Bloquea las interrupciones al cambiar punteros de canción o estado compartido.
Guarda los datos de canción de lectura directa en ROM fija u otra zona siempre visible para la ISR. Cada registro tiene cinco bytes: delay, CH1, CH2, CH3, CH4. En los campos de nota, 0xFF mantiene la voz y 0xFD la detiene. En delay, 0xFF termina la reproducción y 0xFE repite. Es la disposición del registro, no la numeración de canales. La reproducción por cola WRAM es otro modo; envía registros completos de cinco bytes con AudioVBlank_QueueRefill.
Ejemplo de uso
// Direct fixed-bank music with an actual VBlank ISR and a counting frame hook.
#define SOUND_VBLANK
#include "gb_sound_example.h"
__wram u8 hook_count;
__prg_rom u8 irq_song[]={30,33,0xFF,0xFF,0xFF,30,40,0xFF,0xFF,0xFF,0xFE};
void frame_hook() { hook_count++; }
void main() {
u8 before;
sound_begin("VBLANK MUSIC GATES");
Audio_NoiseEffectActive=0;
AudioVBlank_Init();
sound_result[0]=AudioVBlank_MusicPlaying;
AudioVBlank_Ch1Envelope=0xC0;
Audio_SetMasterVolume(3,3);
hook_count=0; AudioVBlank_FrameHook=frame_hook;
AudioVBlank_SetMusic(irq_song);
AudioVBlank_Play();
AudioVBlank_EnableIrq();
sound_wait(45);
// Disable music processing while the hook and current note remain active.
__asm { DI }
AudioVBlank_SetEnabled(0); before=hook_count;
__asm { EI }
sound_wait(30);
sound_result[1]=(u8)(hook_count!=before);
__asm { DI }
AudioVBlank_Stop();
__asm { EI }
sound_wait(30);
__asm { DI }
AudioVBlank_SetEnabled(1); AudioVBlank_PlayMusic(irq_song);
__asm { EI }
sound_wait(45);
AudioVBlank_DisableIrq();
before=hook_count;
sound_wait(30);
sound_result[2]=(u8)(hook_count==before);
sound_result[3]=(u8)(AudioVBlank_IE&1);
AudioVBlank_Stop(); sound_wait(30);
sound_end();
}Resultado esperado
La ISR toca una canción de dos notas. Compara bloquear las actualizaciones musicales, que conserva el sonido; Stop, que lo silencia; y bloquear IRQ tras reiniciar, que también conserva el sonido. La RAM verifica que el hook sigue funcionando con la música deshabilitada y se detiene al deshabilitar IRQ.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_vblank.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-vblank.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/audio_vblank.h:118
Clear only the VBlank bit in IE. Other interrupt sources and current sound remain unchanged.
kitaqgb/lib/audio_vblank_control.inc:129
void AudioVBlank_DisableIrq()
{
AudioVBlank_IE = (u8)(AudioVBlank_IE & 0xFE);
}AudioVBlank_EnableIrq
Activa el bit VBlank de IE y ejecuta EI para habilitar globalmente las interrupciones de CPU.
Sintaxis
void AudioVBlank_EnableIrq();Valor devuelto
Sin valor de retorno. Modifica registros de sonido o el estado del controlador.
Condiciones y límites
audio_vblank.c implementa __kq_vblank_vector; no instales además otro vector VBlank que compita con él. El ejemplo define Audio_NoiseEffectActive, excluye el decodificador musical normal y usa Audio_Update solo para efectos y fundidos. Bloquea las interrupciones al cambiar punteros de canción o estado compartido.
Guarda los datos de canción de lectura directa en ROM fija u otra zona siempre visible para la ISR. Cada registro tiene cinco bytes: delay, CH1, CH2, CH3, CH4. En los campos de nota, 0xFF mantiene la voz y 0xFD la detiene. En delay, 0xFF termina la reproducción y 0xFE repite. Es la disposición del registro, no la numeración de canales. La reproducción por cola WRAM es otro modo; envía registros completos de cinco bytes con AudioVBlank_QueueRefill.
Ejemplo de uso
// Direct fixed-bank music with an actual VBlank ISR and a counting frame hook.
#define SOUND_VBLANK
#include "gb_sound_example.h"
__wram u8 hook_count;
__prg_rom u8 irq_song[]={30,33,0xFF,0xFF,0xFF,30,40,0xFF,0xFF,0xFF,0xFE};
void frame_hook() { hook_count++; }
void main() {
u8 before;
sound_begin("VBLANK MUSIC GATES");
Audio_NoiseEffectActive=0;
AudioVBlank_Init();
sound_result[0]=AudioVBlank_MusicPlaying;
AudioVBlank_Ch1Envelope=0xC0;
Audio_SetMasterVolume(3,3);
hook_count=0; AudioVBlank_FrameHook=frame_hook;
AudioVBlank_SetMusic(irq_song);
AudioVBlank_Play();
AudioVBlank_EnableIrq();
sound_wait(45);
// Disable music processing while the hook and current note remain active.
__asm { DI }
AudioVBlank_SetEnabled(0); before=hook_count;
__asm { EI }
sound_wait(30);
sound_result[1]=(u8)(hook_count!=before);
__asm { DI }
AudioVBlank_Stop();
__asm { EI }
sound_wait(30);
__asm { DI }
AudioVBlank_SetEnabled(1); AudioVBlank_PlayMusic(irq_song);
__asm { EI }
sound_wait(45);
AudioVBlank_DisableIrq();
before=hook_count;
sound_wait(30);
sound_result[2]=(u8)(hook_count==before);
sound_result[3]=(u8)(AudioVBlank_IE&1);
AudioVBlank_Stop(); sound_wait(30);
sound_end();
}Resultado esperado
La ISR toca una canción de dos notas. Compara bloquear las actualizaciones musicales, que conserva el sonido; Stop, que lo silencia; y bloquear IRQ tras reiniciar, que también conserva el sonido. La RAM verifica que el hook sigue funcionando con la música deshabilitada y se detiene al deshabilitar IRQ.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_vblank.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-vblank.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/audio_vblank.h:116
Enable the VBlank source in IE and execute EI, enabling CPU interrupts globally. Install the correct interrupt vector and initialize driver state first.
kitaqgb/lib/audio_vblank_control.inc:122
void AudioVBlank_EnableIrq()
{
AudioVBlank_IE = (u8)(AudioVBlank_IE | 0x01);
__asm { EI }
}AudioVBlank_Init
Inicializa el estado musical VBlank, la cola, los instrumentos y el hook. No inicializa la APU ni bloquea interrupciones.
Sintaxis
void AudioVBlank_Init();Valor devuelto
Sin valor de retorno. Modifica registros de sonido o el estado del controlador.
Condiciones y límites
audio_vblank.c implementa __kq_vblank_vector; no instales además otro vector VBlank que compita con él. El ejemplo define Audio_NoiseEffectActive, excluye el decodificador musical normal y usa Audio_Update solo para efectos y fundidos. Bloquea las interrupciones al cambiar punteros de canción o estado compartido.
Guarda los datos de canción de lectura directa en ROM fija u otra zona siempre visible para la ISR. Cada registro tiene cinco bytes: delay, CH1, CH2, CH3, CH4. En los campos de nota, 0xFF mantiene la voz y 0xFD la detiene. En delay, 0xFF termina la reproducción y 0xFE repite. Es la disposición del registro, no la numeración de canales. La reproducción por cola WRAM es otro modo; envía registros completos de cinco bytes con AudioVBlank_QueueRefill.
Ejemplo de uso
// Direct fixed-bank music with an actual VBlank ISR and a counting frame hook.
#define SOUND_VBLANK
#include "gb_sound_example.h"
__wram u8 hook_count;
__prg_rom u8 irq_song[]={30,33,0xFF,0xFF,0xFF,30,40,0xFF,0xFF,0xFF,0xFE};
void frame_hook() { hook_count++; }
void main() {
u8 before;
sound_begin("VBLANK MUSIC GATES");
Audio_NoiseEffectActive=0;
AudioVBlank_Init();
sound_result[0]=AudioVBlank_MusicPlaying;
AudioVBlank_Ch1Envelope=0xC0;
Audio_SetMasterVolume(3,3);
hook_count=0; AudioVBlank_FrameHook=frame_hook;
AudioVBlank_SetMusic(irq_song);
AudioVBlank_Play();
AudioVBlank_EnableIrq();
sound_wait(45);
// Disable music processing while the hook and current note remain active.
__asm { DI }
AudioVBlank_SetEnabled(0); before=hook_count;
__asm { EI }
sound_wait(30);
sound_result[1]=(u8)(hook_count!=before);
__asm { DI }
AudioVBlank_Stop();
__asm { EI }
sound_wait(30);
__asm { DI }
AudioVBlank_SetEnabled(1); AudioVBlank_PlayMusic(irq_song);
__asm { EI }
sound_wait(45);
AudioVBlank_DisableIrq();
before=hook_count;
sound_wait(30);
sound_result[2]=(u8)(hook_count==before);
sound_result[3]=(u8)(AudioVBlank_IE&1);
AudioVBlank_Stop(); sound_wait(30);
sound_end();
}Resultado esperado
La ISR toca una canción de dos notas. Compara bloquear las actualizaciones musicales, que conserva el sonido; Stop, que lo silencia; y bloquear IRQ tras reiniciar, que también conserva el sonido. La RAM verifica que el hook sigue funcionando con la música deshabilitada y se detiene al deshabilitar IRQ.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_vblank.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-vblank.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/audio_vblank.h:85
Reset software playback state, queue counters, instruments and the frame hook. Call before enabling this ISR; the routine does not mask interrupts or initialize the APU registers and cannot synchronize with an active handler.
kitaqgb/lib/audio_vblank_control.inc:6
void AudioVBlank_Init()
{
AudioVBlank_MusicEnabled = 1;
AudioVBlank_MusicPlaying = 0;
AudioVBlank_MusicDelay = 0;
AudioVBlank_MusicStart = 0;
AudioVBlank_MusicPointer = 0;
AudioVBlank_MusicLoopPoint = 0;
AudioVBlank_Step = 0;
AudioVBlank_Ch2Note = AUDIO_VBLANK_REST;
AudioVBlank_Ch1Note = AUDIO_VBLANK_REST;
AudioVBlank_Ch3Note = AUDIO_VBLANK_REST;
AudioVBlank_Ch2LatchedNote = AUDIO_VBLANK_STOP;
AudioVBlank_Ch1LatchedNote = AUDIO_VBLANK_STOP;
AudioVBlank_Ch3LatchedNote = AUDIO_VBLANK_STOP;
AudioVBlank_RestoreCh1Pending = 0;
AudioVBlank_RestoreCh3Pending = 0;
AudioVBlank_Ch4Param = AUDIO_VBLANK_REST;
AudioVBlank_Ch1Envelope = 0xF1;
AudioVBlank_Ch2Envelope = 0xF2;
AudioVBlank_Ch4Envelope = 0xF1;
AudioVBlank_Ch1Duty = 0x80;
AudioVBlank_Ch2Duty = 0x80;
AudioVBlank_Ch1Sweep = 0x00;
AudioVBlank_Ch3Level = 0x20;
AudioVBlank_ControlCommand = 0;
AudioVBlank_ControlArg0 = 0;
AudioVBlank_ControlArg1 = 0;
AudioVBlank_ControlArg2 = 0;
AudioVBlank_QueueMode = 0;
AudioVBlank_QueueReadIndex = 0;
AudioVBlank_QueueWriteIndex = 0;
AudioVBlank_QueueCount = 0;
AudioVBlank_QueueUnderruns = 0;
AudioVBlank_FrameHook = 0;
}AudioVBlank_Play
Reinicia la canción seleccionada desde el principio y sale del modo cola. Una canción NULL detiene la reproducción.
Sintaxis
void AudioVBlank_Play();Valor devuelto
Sin valor de retorno. Modifica registros de sonido o el estado del controlador.
Condiciones y límites
audio_vblank.c implementa __kq_vblank_vector; no instales además otro vector VBlank que compita con él. El ejemplo define Audio_NoiseEffectActive, excluye el decodificador musical normal y usa Audio_Update solo para efectos y fundidos. Bloquea las interrupciones al cambiar punteros de canción o estado compartido.
Guarda los datos de canción de lectura directa en ROM fija u otra zona siempre visible para la ISR. Cada registro tiene cinco bytes: delay, CH1, CH2, CH3, CH4. En los campos de nota, 0xFF mantiene la voz y 0xFD la detiene. En delay, 0xFF termina la reproducción y 0xFE repite. Es la disposición del registro, no la numeración de canales. La reproducción por cola WRAM es otro modo; envía registros completos de cinco bytes con AudioVBlank_QueueRefill.
Ejemplo de uso
// Direct fixed-bank music with an actual VBlank ISR and a counting frame hook.
#define SOUND_VBLANK
#include "gb_sound_example.h"
__wram u8 hook_count;
__prg_rom u8 irq_song[]={30,33,0xFF,0xFF,0xFF,30,40,0xFF,0xFF,0xFF,0xFE};
void frame_hook() { hook_count++; }
void main() {
u8 before;
sound_begin("VBLANK MUSIC GATES");
Audio_NoiseEffectActive=0;
AudioVBlank_Init();
sound_result[0]=AudioVBlank_MusicPlaying;
AudioVBlank_Ch1Envelope=0xC0;
Audio_SetMasterVolume(3,3);
hook_count=0; AudioVBlank_FrameHook=frame_hook;
AudioVBlank_SetMusic(irq_song);
AudioVBlank_Play();
AudioVBlank_EnableIrq();
sound_wait(45);
// Disable music processing while the hook and current note remain active.
__asm { DI }
AudioVBlank_SetEnabled(0); before=hook_count;
__asm { EI }
sound_wait(30);
sound_result[1]=(u8)(hook_count!=before);
__asm { DI }
AudioVBlank_Stop();
__asm { EI }
sound_wait(30);
__asm { DI }
AudioVBlank_SetEnabled(1); AudioVBlank_PlayMusic(irq_song);
__asm { EI }
sound_wait(45);
AudioVBlank_DisableIrq();
before=hook_count;
sound_wait(30);
sound_result[2]=(u8)(hook_count==before);
sound_result[3]=(u8)(AudioVBlank_IE&1);
AudioVBlank_Stop(); sound_wait(30);
sound_end();
}Resultado esperado
La ISR toca una canción de dos notas. Compara bloquear las actualizaciones musicales, que conserva el sonido; Stop, que lo silencia; y bloquear IRQ tras reiniciar, que también conserva el sonido. La RAM verifica que el hook sigue funcionando con la música deshabilitada y se detiene al deshabilitar IRQ.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_vblank.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-vblank.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/audio_vblank.h:103
Restart the selected direct song at its beginning, leaving queue mode. A null song invokes Stop; this does not enable the music or IRQ gates.
kitaqgb/lib/audio_vblank_control.inc:58
void AudioVBlank_Play()
{
if (AudioVBlank_MusicStart == 0) {
AudioVBlank_Stop();
return;
}
AudioVBlank_MusicPointer = AudioVBlank_MusicStart;
AudioVBlank_MusicLoopPoint = AudioVBlank_MusicStart;
AudioVBlank_MusicDelay = 0;
AudioVBlank_Step = 0;
AudioVBlank_QueueMode = 0;
AudioVBlank_MusicPlaying = 1;
}AudioVBlank_PlayMusic
Selecciona una canción de lectura directa y prepara su reproducción desde el principio.
Sintaxis
void __stackcall AudioVBlank_PlayMusic(u8 *song);Parámetros
songDirección inicial de la canción. El controlador usa el array prestado, que debe seguir siendo legible durante toda la reproducción.
Valor devuelto
Sin valor de retorno. Modifica registros de sonido o el estado del controlador.
Condiciones y límites
audio_vblank.c implementa __kq_vblank_vector; no instales además otro vector VBlank que compita con él. El ejemplo define Audio_NoiseEffectActive, excluye el decodificador musical normal y usa Audio_Update solo para efectos y fundidos. Bloquea las interrupciones al cambiar punteros de canción o estado compartido.
Guarda los datos de canción de lectura directa en ROM fija u otra zona siempre visible para la ISR. Cada registro tiene cinco bytes: delay, CH1, CH2, CH3, CH4. En los campos de nota, 0xFF mantiene la voz y 0xFD la detiene. En delay, 0xFF termina la reproducción y 0xFE repite. Es la disposición del registro, no la numeración de canales. La reproducción por cola WRAM es otro modo; envía registros completos de cinco bytes con AudioVBlank_QueueRefill.
Ejemplo de uso
// Direct fixed-bank music with an actual VBlank ISR and a counting frame hook.
#define SOUND_VBLANK
#include "gb_sound_example.h"
__wram u8 hook_count;
__prg_rom u8 irq_song[]={30,33,0xFF,0xFF,0xFF,30,40,0xFF,0xFF,0xFF,0xFE};
void frame_hook() { hook_count++; }
void main() {
u8 before;
sound_begin("VBLANK MUSIC GATES");
Audio_NoiseEffectActive=0;
AudioVBlank_Init();
sound_result[0]=AudioVBlank_MusicPlaying;
AudioVBlank_Ch1Envelope=0xC0;
Audio_SetMasterVolume(3,3);
hook_count=0; AudioVBlank_FrameHook=frame_hook;
AudioVBlank_SetMusic(irq_song);
AudioVBlank_Play();
AudioVBlank_EnableIrq();
sound_wait(45);
// Disable music processing while the hook and current note remain active.
__asm { DI }
AudioVBlank_SetEnabled(0); before=hook_count;
__asm { EI }
sound_wait(30);
sound_result[1]=(u8)(hook_count!=before);
__asm { DI }
AudioVBlank_Stop();
__asm { EI }
sound_wait(30);
__asm { DI }
AudioVBlank_SetEnabled(1); AudioVBlank_PlayMusic(irq_song);
__asm { EI }
sound_wait(45);
AudioVBlank_DisableIrq();
before=hook_count;
sound_wait(30);
sound_result[2]=(u8)(hook_count==before);
sound_result[3]=(u8)(AudioVBlank_IE&1);
AudioVBlank_Stop(); sound_wait(30);
sound_end();
}Resultado esperado
La ISR toca una canción de dos notas. Compara bloquear las actualizaciones musicales, que conserva el sonido; Stop, que lo silencia; y bloquear IRQ tras reiniciar, que también conserva el sonido. La RAM verifica que el hook sigue funcionando con la música deshabilitada y se detiene al deshabilitar IRQ.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_vblank.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-vblank.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/audio_vblank.h:105
Select and restart a directly addressed song. This is not the banked WRAM-queue path.
kitaqgb/lib/audio_vblank_control.inc:73
void __stackcall AudioVBlank_PlayMusic(u8 *song)
{
AudioVBlank_SetMusic(song);
AudioVBlank_Play();
}AudioVBlank_QueuePlay
Consulte los cambios y la verificación del 2026-10-03 para las diferencias locales de esta API.
Activa la reproducción si el modo de cola está activo y hay al menos un registro disponible. Conserva los cursores, el retardo, la activación de la música y el estado de pausa. Reinicia y precarga la cola antes de iniciar un nuevo flujo.
Sintaxis
u8 AudioVBlank_QueuePlay();Valor devuelto
Devuelve uno si se acepta la solicitud, o cero si la cola está vacía o no está activo el modo de cola. Para consumir registros, la ISR debe ejecutarse, la música debe estar activada y el controlador no debe estar en pausa.
Condiciones y límites
Después de AudioVBlank_Init, llama a QueueReset, QueueRefill y QueuePlay, en ese orden. Compila audio_vblank.c en su configuración normal; AUDIO_VBLANK_CORE_ONLY excluye las funciones C que alimentan la cola. El código principal llena una cola de dieciséis registros de cinco bytes y la rutina de interrupción VBlank los consume.
Usa un único productor en el código principal. No lo invoques de forma recursiva ni desde una ISR o FrameHook. Cada paso breve que hace disponible un registro guarda IE y enmascara las fuentes de interrupción; después restaura IE y SVBK. IME no cambia. El código que llama debe seleccionar y mantener el banco ROM/RAM de origen.
Los registros temporizados contienen delay, ch1_note, ch2_note, ch3_note y ch4_noise_param. END también debe ser un registro completo de cinco bytes. El productor debe implementar LOOP volviendo a enviar los registros necesarios. No pases sin convertir un flujo de comandos de reproducción directa de longitud variable.
Ejemplo de uso
if(AudioVBlank_QueuePlay()==0) sound_result[0]++;
AudioVBlank_EnableIrq();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo reproduce seis veces una frase original de ocho notas y se detiene. Envía 49 registros —48 notas y END— a través de la cola de dieciséis posiciones. Comprueba que se acepten los 49, que no haya falta de datos, que la reproducción se detenga y que se gestionen la cola vacía o llena, el puntero nulo y el recuento cero. También verifica la restauración del banco WRAM de CGB, la conservación de IME, la emisión de sonido y el silencio al terminar.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\audio_vblank_queue.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\audio_vblank_queue.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/audio_vblank.h:96
Start/resume queued playback; return 1 on success, 0 for an empty/nonqueue mode. Does not enable the interrupt, music gate or clear pause. Queue before starting.
kitaqgb/lib/audio_vblank_queue.inc:112
u8 AudioVBlank_QueuePlay()
{
u8 saved_ie;
u8 started;
saved_ie = AudioVBlank_IE;
AudioVBlank_IE = 0;
started = 0;
if (AudioVBlank_QueueMode != 0 && AudioVBlank_QueueCount != 0) {
AudioVBlank_MusicPlaying = 1;
started = 1;
}
AudioVBlank_IE = saved_ie;
return started;
}AudioVBlank_QueueRefill
Consulte los cambios y la verificación del 2026-10-03 para las diferencias locales de esta API.
Copia registros completos de cinco bytes en las posiciones libres y hace disponible cada uno solo después de terminar su copia. Una llamada acepta como máximo dieciséis registros.
Sintaxis
u8 __stackcall AudioVBlank_QueueRefill(const u8 *records, u8 count);Parámetros
recordsMatriz de registros situada en el banco actualmente legible. Debe haber cinco bytes legibles por cada registro aceptado. Un puntero nulo hace que se devuelva cero.
countNúmero de registros que se intentará enviar, no de bytes. Los valores superiores a dieciséis se limitan a dieciséis; cero no hace nada.
Valor devuelto
Devuelve el número de registros realmente aceptados, de 0 a 16. Devuelve cero si la cola está llena, la entrada es nula, el recuento es cero o no está activo el modo de cola. Avanza el origen cinco veces el valor devuelto. La ISR puede liberar posiciones durante la llamada, por lo que el resultado no tiene por qué coincidir con el espacio libre al entrar.
Condiciones y límites
Después de AudioVBlank_Init, llama a QueueReset, QueueRefill y QueuePlay, en ese orden. Compila audio_vblank.c en su configuración normal; AUDIO_VBLANK_CORE_ONLY excluye las funciones C que alimentan la cola. El código principal llena una cola de dieciséis registros de cinco bytes y la rutina de interrupción VBlank los consume.
Usa un único productor en el código principal. No lo invoques de forma recursiva ni desde una ISR o FrameHook. Cada paso breve que hace disponible un registro guarda IE y enmascara las fuentes de interrupción; después restaura IE y SVBK. IME no cambia. El código que llama debe seleccionar y mantener el banco ROM/RAM de origen.
Los registros temporizados contienen delay, ch1_note, ch2_note, ch3_note y ch4_noise_param. END también debe ser un registro completo de cinco bytes. El productor debe implementar LOOP volviendo a enviar los registros necesarios. No pases sin convertir un flujo de comandos de reproducción directa de longitud variable.
Ejemplo de uso
next=AudioVBlank_QueueRefill(queue_song,16);
// next counts records; each record occupies five source bytes.Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo reproduce seis veces una frase original de ocho notas y se detiene. Envía 49 registros —48 notas y END— a través de la cola de dieciséis posiciones. Comprueba que se acepten los 49, que no haya falta de datos, que la reproducción se detenga y que se gestionen la cola vacía o llena, el puntero nulo y el recuento cero. También verifica la restauración del banco WRAM de CGB, la conservación de IME, la emisión de sonido y el silencio al terminar.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\audio_vblank_queue.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\audio_vblank_queue.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/audio_vblank.h:93
Copy complete records from the currently mapped source; return records accepted. Each call attempts at most 16 records and stops when full. Null/zero returns 0. Supports ROM and RAM sources, restores SVBK and IE, and never changes IME. Single foreground producer only: do not call from an ISR or frame hook. LOOP must be expanded by the producer. END occupies a full five-byte record.
kitaqgb/lib/audio_vblank_queue.inc:93
u8 __stackcall AudioVBlank_QueueRefill(const u8 *records, u8 count)
{
u8 accepted;
u8 i;
if (records == 0 || count == 0 || AudioVBlank_QueueMode == 0) return 0;
if (count > AUDIO_VBLANK_QUEUE_RECORDS) count = AUDIO_VBLANK_QUEUE_RECORDS;
accepted = 0;
while (accepted < count) {
if (AudioVBlank_QueueCount >= AUDIO_VBLANK_QUEUE_RECORDS) break;
for (i = 0; i < 5; i++) AudioVBlank_QueueStaging[i] = records[i];
if (AudioVBlank_QueuePublish() == 0) break;
records += 5;
accepted++;
}
return accepted;
}AudioVBlank_QueueReset
Consulte los cambios y la verificación del 2026-10-03 para las diferencias locales de esta API.
Detiene y silencia la reproducción, selecciona el modo de cola y pone a cero las posiciones de lectura y escritura, el número de registros y el contador de falta de datos. Descarta los registros pendientes para preparar un nuevo flujo.
Sintaxis
void AudioVBlank_QueueReset();Valor devuelto
No devuelve ningún valor. Conserva los ajustes de activación de la música y de pausa.
Condiciones y límites
Después de AudioVBlank_Init, llama a QueueReset, QueueRefill y QueuePlay, en ese orden. Compila audio_vblank.c en su configuración normal; AUDIO_VBLANK_CORE_ONLY excluye las funciones C que alimentan la cola. El código principal llena una cola de dieciséis registros de cinco bytes y la rutina de interrupción VBlank los consume.
Usa un único productor en el código principal. No lo invoques de forma recursiva ni desde una ISR o FrameHook. Cada paso breve que hace disponible un registro guarda IE y enmascara las fuentes de interrupción; después restaura IE y SVBK. IME no cambia. El código que llama debe seleccionar y mantener el banco ROM/RAM de origen.
Los registros temporizados contienen delay, ch1_note, ch2_note, ch3_note y ch4_noise_param. END también debe ser un registro completo de cinco bytes. El productor debe implementar LOOP volviendo a enviar los registros necesarios. No pases sin convertir un flujo de comandos de reproducción directa de longitud variable.
Ejemplo de uso
AudioVBlank_QueueReset(); // Silence playback and discard any queued records.Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo reproduce seis veces una frase original de ocho notas y se detiene. Envía 49 registros —48 notas y END— a través de la cola de dieciséis posiciones. Comprueba que se acepten los 49, que no haya falta de datos, que la reproducción se detenga y que se gestionen la cola vacía o llena, el puntero nulo y el recuento cero. También verifica la restauración del banco WRAM de CGB, la conservación de IME, la emisión de sonido y el silencio al terminar.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\audio_vblank_queue.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\audio_vblank_queue.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/audio_vblank.h:87
Stop music and select an empty WRAM queue; preserve IE, IME and enable/pause gates.
kitaqgb/lib/audio_vblank_queue.inc:76
void AudioVBlank_QueueReset()
{
u8 saved_ie;
saved_ie = AudioVBlank_IE;
AudioVBlank_IE = 0;
AudioVBlank_Stop();
AudioVBlank_QueueMode = 1;
AudioVBlank_QueueReadIndex = 0;
AudioVBlank_QueueWriteIndex = 0;
AudioVBlank_QueueCount = 0;
AudioVBlank_QueueUnderruns = 0;
AudioVBlank_IE = saved_ie;
}AudioVBlank_RequestRestoreCh1
Establece la solicitud 2 de solo liberación de pulso si no hay nada pendiente, conservando una solicitud de recuperación 1 existente.
Sintaxis
void AudioVBlank_RequestRestoreCh1();Valor devuelto
Sin valor de retorno. Modifica registros de sonido o el estado del controlador.
Condiciones y límites
audio_vblank.c implementa __kq_vblank_vector; no instales además otro vector VBlank que compita con él. El ejemplo define Audio_NoiseEffectActive, excluye el decodificador musical normal y usa Audio_Update solo para efectos y fundidos. Bloquea las interrupciones al cambiar punteros de canción o estado compartido.
Al llamar directamente a la recuperación, el código que llama debe asegurarse de que el efecto haya liberado la voz y borrar después la bandera pendiente. Las funciones de solicitud por sí solas no escriben registros de sonido.
Ejemplo de uso
// Exercise the recovery API with IRQ disabled and explicit effect ownership.
#define SOUND_VBLANK
#include "gb_sound_example.h"
void main() {
sound_begin("EFFECT RECOVERY");
Audio_NoiseEffectActive=0; AudioVBlank_Init();
Audio_SetMasterVolume(3,3);
AudioVBlank_MusicPlaying=1;
AudioVBlank_Ch1Envelope=0xC0; AudioVBlank_Ch1LatchedNote=33;
AudioVBlank_Ch3LatchedNote=33;
// Value 1 represents a suppressed BGM event and survives a release request.
AudioVBlank_RestoreCh1Pending=1;
AudioVBlank_RequestRestoreCh1();
sound_result[0]=AudioVBlank_RestoreCh1Pending;
AudioVBlank_RestoreCh1(); AudioVBlank_RestoreCh1Pending=0;
sound_wait(30);
// Without a pending event, RequestRestore creates release-only value 2.
AudioVBlank_RequestRestoreCh1();
sound_result[1]=AudioVBlank_RestoreCh1Pending;
AudioVBlank_RestoreCh1(); AudioVBlank_RestoreCh1Pending=0;
sound_wait(30);
AudioVBlank_RestoreCh3Pending=1;
AudioVBlank_RequestRestoreCh3();
sound_result[2]=AudioVBlank_RestoreCh3Pending;
AudioVBlank_RestoreCh3(); AudioVBlank_RestoreCh3Pending=0;
sound_wait(30);
AudioVBlank_RequestRestoreCh3();
sound_result[3]=AudioVBlank_RestoreCh3Pending;
AudioVBlank_RestoreCh3(); AudioVBlank_RestoreCh3Pending=0;
sound_wait(30);
AudioVBlank_Stop();
sound_end();
}Resultado esperado
Se oyen recuperación de pulso, silencio, recuperación de onda y silencio, cada uno durante 30 fotogramas. Una solicitud de liberación conserva el valor pendiente 1; sin evento pendiente produce el valor 2, solo liberación. Aquí IRQ está deshabilitado y el código que llama gestiona explícitamente el uso de los canales.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_recovery.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-recovery.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/audio_vblank.h:129
Request deferred pulse-channel release only when no recovery is pending. Preserve value 1, which records a music event suppressed while an effect owned it.
kitaqgb/lib/audio_vblank.c:908
void AudioVBlank_RequestRestoreCh1()
{
if (AudioVBlank_RestoreCh1Pending == 0)
AudioVBlank_RestoreCh1Pending = 2;
}AudioVBlank_RequestRestoreCh3
Establece la solicitud 2 de solo liberación de onda si no hay nada pendiente, conservando una solicitud de recuperación 1 existente.
Sintaxis
void AudioVBlank_RequestRestoreCh3();Valor devuelto
Sin valor de retorno. Modifica registros de sonido o el estado del controlador.
Condiciones y límites
audio_vblank.c implementa __kq_vblank_vector; no instales además otro vector VBlank que compita con él. El ejemplo define Audio_NoiseEffectActive, excluye el decodificador musical normal y usa Audio_Update solo para efectos y fundidos. Bloquea las interrupciones al cambiar punteros de canción o estado compartido.
Al llamar directamente a la recuperación, el código que llama debe asegurarse de que el efecto haya liberado la voz y borrar después la bandera pendiente. Las funciones de solicitud por sí solas no escriben registros de sonido.
Ejemplo de uso
// Exercise the recovery API with IRQ disabled and explicit effect ownership.
#define SOUND_VBLANK
#include "gb_sound_example.h"
void main() {
sound_begin("EFFECT RECOVERY");
Audio_NoiseEffectActive=0; AudioVBlank_Init();
Audio_SetMasterVolume(3,3);
AudioVBlank_MusicPlaying=1;
AudioVBlank_Ch1Envelope=0xC0; AudioVBlank_Ch1LatchedNote=33;
AudioVBlank_Ch3LatchedNote=33;
// Value 1 represents a suppressed BGM event and survives a release request.
AudioVBlank_RestoreCh1Pending=1;
AudioVBlank_RequestRestoreCh1();
sound_result[0]=AudioVBlank_RestoreCh1Pending;
AudioVBlank_RestoreCh1(); AudioVBlank_RestoreCh1Pending=0;
sound_wait(30);
// Without a pending event, RequestRestore creates release-only value 2.
AudioVBlank_RequestRestoreCh1();
sound_result[1]=AudioVBlank_RestoreCh1Pending;
AudioVBlank_RestoreCh1(); AudioVBlank_RestoreCh1Pending=0;
sound_wait(30);
AudioVBlank_RestoreCh3Pending=1;
AudioVBlank_RequestRestoreCh3();
sound_result[2]=AudioVBlank_RestoreCh3Pending;
AudioVBlank_RestoreCh3(); AudioVBlank_RestoreCh3Pending=0;
sound_wait(30);
AudioVBlank_RequestRestoreCh3();
sound_result[3]=AudioVBlank_RestoreCh3Pending;
AudioVBlank_RestoreCh3(); AudioVBlank_RestoreCh3Pending=0;
sound_wait(30);
AudioVBlank_Stop();
sound_end();
}Resultado esperado
Se oyen recuperación de pulso, silencio, recuperación de onda y silencio, cada uno durante 30 fotogramas. Una solicitud de liberación conserva el valor pendiente 1; sin evento pendiente produce el valor 2, solo liberación. Aquí IRQ está deshabilitado y el código que llama gestiona explícitamente el uso de los canales.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_recovery.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-recovery.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/audio_vblank.h:132
Request a deferred wave-channel release only if no recovery is pending. Preserve value 1, which records a new music event suppressed by the effect.
kitaqgb/lib/audio_vblank.c:916
void AudioVBlank_RequestRestoreCh3()
{
if (AudioVBlank_RestoreCh3Pending == 0)
AudioVBlank_RestoreCh3Pending = 2;
}AudioVBlank_RestoreCh1
Restaura una nota musical retenida en la voz de pulsos prestada al efecto (CH1 o CH2), o la libera en silencio.
Sintaxis
void AudioVBlank_RestoreCh1();Valor devuelto
Sin valor de retorno. Modifica registros de sonido o el estado del controlador.
Condiciones y límites
audio_vblank.c implementa __kq_vblank_vector; no instales además otro vector VBlank que compita con él. El ejemplo define Audio_NoiseEffectActive, excluye el decodificador musical normal y usa Audio_Update solo para efectos y fundidos. Bloquea las interrupciones al cambiar punteros de canción o estado compartido.
Al llamar directamente a la recuperación, el código que llama debe asegurarse de que el efecto haya liberado la voz y borrar después la bandera pendiente. Las funciones de solicitud por sí solas no escriben registros de sonido.
Ejemplo de uso
// Exercise the recovery API with IRQ disabled and explicit effect ownership.
#define SOUND_VBLANK
#include "gb_sound_example.h"
void main() {
sound_begin("EFFECT RECOVERY");
Audio_NoiseEffectActive=0; AudioVBlank_Init();
Audio_SetMasterVolume(3,3);
AudioVBlank_MusicPlaying=1;
AudioVBlank_Ch1Envelope=0xC0; AudioVBlank_Ch1LatchedNote=33;
AudioVBlank_Ch3LatchedNote=33;
// Value 1 represents a suppressed BGM event and survives a release request.
AudioVBlank_RestoreCh1Pending=1;
AudioVBlank_RequestRestoreCh1();
sound_result[0]=AudioVBlank_RestoreCh1Pending;
AudioVBlank_RestoreCh1(); AudioVBlank_RestoreCh1Pending=0;
sound_wait(30);
// Without a pending event, RequestRestore creates release-only value 2.
AudioVBlank_RequestRestoreCh1();
sound_result[1]=AudioVBlank_RestoreCh1Pending;
AudioVBlank_RestoreCh1(); AudioVBlank_RestoreCh1Pending=0;
sound_wait(30);
AudioVBlank_RestoreCh3Pending=1;
AudioVBlank_RequestRestoreCh3();
sound_result[2]=AudioVBlank_RestoreCh3Pending;
AudioVBlank_RestoreCh3(); AudioVBlank_RestoreCh3Pending=0;
sound_wait(30);
AudioVBlank_RequestRestoreCh3();
sound_result[3]=AudioVBlank_RestoreCh3Pending;
AudioVBlank_RestoreCh3(); AudioVBlank_RestoreCh3Pending=0;
sound_wait(30);
AudioVBlank_Stop();
sound_end();
}Resultado esperado
Se oyen recuperación de pulso, silencio, recuperación de onda y silencio, cada uno durante 30 fotogramas. Una solicitud de liberación conserva el valor pendiente 1; sin evento pendiente produce el valor 2, solo liberación. Aquí IRQ está deshabilitado y el código que llama gestiona explícitamente el uso de los canales.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_recovery.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-recovery.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/audio_vblank.h:122
Recover the borrowed pulse channel (CH1 or CH2) from its latched music event. Pending value 2, disabled music, or a non-note latch silences it instead. The caller must first establish that the effect has released the channel.
kitaqgb/lib/audio_vblank.c:769
void AudioVBlank_RestoreCh1()
{
__asm {
LD_A_MEM Audio_EffectUsesCh2
OR_A
JR_NZ audiovb_restore_ch2
LD_A_MEM AudioVBlank_RestoreCh1Pending
CP_IMM 2
JR_Z audiovb_restore_ch1_off
LD_A_MEM AudioVBlank_MusicPlaying
OR_A
JR_Z audiovb_restore_ch1_off
LD_A_MEM AudioVBlank_MusicEnabled
OR_A
JR_Z audiovb_restore_ch1_off
LD_A_MEM Audio_MusicEnabled
OR_A
JR_Z audiovb_restore_ch1_off
LD_A_MEM AudioVBlank_Ch1LatchedNote
CP_IMM 0x44
JR_NC audiovb_restore_ch1_off
LD_C_A
LD_A_MEM AudioVBlank_Ch1Sweep
LDH_MEM_A 0x10
LD_A_MEM AudioVBlank_Ch1Duty
LDH_MEM_A 0x11
LD_A_MEM AudioVBlank_Ch1Envelope
LDH_MEM_A 0x12
LD_A_C
LD_E_A
LD_D_IMM 0
LD_HL_IMM AudioVBlank_FreqLo
ADD_HL_DE
LD_A_HL
LDH_MEM_A 0x13
LD_HL_IMM AudioVBlank_FreqHi
ADD_HL_DE
LD_A_HL
OR_IMM 0x80
LDH_MEM_A 0x14
JR audiovb_restore_ch1_done
audiovb_restore_ch1_off:
XOR_A
LDH_MEM_A 0x12
audiovb_restore_ch1_done:
JR audiovb_restore_square_done
audiovb_restore_ch2:
LD_A_MEM AudioVBlank_RestoreCh1Pending
CP_IMM 2
JR_Z audiovb_restore_ch2_off
LD_A_MEM AudioVBlank_MusicPlaying
OR_A
JR_Z audiovb_restore_ch2_off
LD_A_MEM AudioVBlank_MusicEnabled
OR_A
JR_Z audiovb_restore_ch2_off
LD_A_MEM Audio_MusicEnabled
OR_A
JR_Z audiovb_restore_ch2_off
LD_A_MEM AudioVBlank_Ch2LatchedNote
CP_IMM 0x44
JR_NC audiovb_restore_ch2_off
LD_C_A
LD_A_MEM AudioVBlank_Ch2Duty
LDH_MEM_A 0x16
LD_A_MEM AudioVBlank_Ch2Envelope
LDH_MEM_A 0x17
LD_A_C
LD_E_A
LD_D_IMM 0
LD_HL_IMM AudioVBlank_FreqLo
ADD_HL_DE
LD_A_HL
LDH_MEM_A 0x18
LD_HL_IMM AudioVBlank_FreqHi
ADD_HL_DE
LD_A_HL
OR_IMM 0x80
LDH_MEM_A 0x19
JR audiovb_restore_square_done
audiovb_restore_ch2_off:
XOR_A
LDH_MEM_A 0x17
audiovb_restore_square_done:
}
}AudioVBlank_RestoreCh3
Restaura la nota retenida de CH3 tras liberar el efecto, o deshabilita su DAC.
Sintaxis
void AudioVBlank_RestoreCh3();Valor devuelto
Sin valor de retorno. Modifica registros de sonido o el estado del controlador.
Condiciones y límites
audio_vblank.c implementa __kq_vblank_vector; no instales además otro vector VBlank que compita con él. El ejemplo define Audio_NoiseEffectActive, excluye el decodificador musical normal y usa Audio_Update solo para efectos y fundidos. Bloquea las interrupciones al cambiar punteros de canción o estado compartido.
Al llamar directamente a la recuperación, el código que llama debe asegurarse de que el efecto haya liberado la voz y borrar después la bandera pendiente. Las funciones de solicitud por sí solas no escriben registros de sonido.
Ejemplo de uso
// Exercise the recovery API with IRQ disabled and explicit effect ownership.
#define SOUND_VBLANK
#include "gb_sound_example.h"
void main() {
sound_begin("EFFECT RECOVERY");
Audio_NoiseEffectActive=0; AudioVBlank_Init();
Audio_SetMasterVolume(3,3);
AudioVBlank_MusicPlaying=1;
AudioVBlank_Ch1Envelope=0xC0; AudioVBlank_Ch1LatchedNote=33;
AudioVBlank_Ch3LatchedNote=33;
// Value 1 represents a suppressed BGM event and survives a release request.
AudioVBlank_RestoreCh1Pending=1;
AudioVBlank_RequestRestoreCh1();
sound_result[0]=AudioVBlank_RestoreCh1Pending;
AudioVBlank_RestoreCh1(); AudioVBlank_RestoreCh1Pending=0;
sound_wait(30);
// Without a pending event, RequestRestore creates release-only value 2.
AudioVBlank_RequestRestoreCh1();
sound_result[1]=AudioVBlank_RestoreCh1Pending;
AudioVBlank_RestoreCh1(); AudioVBlank_RestoreCh1Pending=0;
sound_wait(30);
AudioVBlank_RestoreCh3Pending=1;
AudioVBlank_RequestRestoreCh3();
sound_result[2]=AudioVBlank_RestoreCh3Pending;
AudioVBlank_RestoreCh3(); AudioVBlank_RestoreCh3Pending=0;
sound_wait(30);
AudioVBlank_RequestRestoreCh3();
sound_result[3]=AudioVBlank_RestoreCh3Pending;
AudioVBlank_RestoreCh3(); AudioVBlank_RestoreCh3Pending=0;
sound_wait(30);
AudioVBlank_Stop();
sound_end();
}Resultado esperado
Se oyen recuperación de pulso, silencio, recuperación de onda y silencio, cada uno durante 30 fotogramas. Una solicitud de liberación conserva el valor pendiente 1; sin evento pendiente produce el valor 2, solo liberación. Aquí IRQ está deshabilitado y el código que llama gestiona explícitamente el uso de los canales.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_recovery.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-recovery.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/audio_vblank.h:126
Recover a latched wave-channel music event after effect release, or disable the DAC for a release-only request, disabled music, or a non-note latch. The caller owns effect arbitration and clearing the pending flag.
kitaqgb/lib/audio_vblank.c:860
void AudioVBlank_RestoreCh3()
{
__asm {
LD_A_MEM AudioVBlank_RestoreCh3Pending
CP_IMM 2
JR_Z audiovb_restore_ch3_off
LD_A_MEM AudioVBlank_MusicPlaying
OR_A
JR_Z audiovb_restore_ch3_off
LD_A_MEM AudioVBlank_MusicEnabled
OR_A
JR_Z audiovb_restore_ch3_off
LD_A_MEM Audio_MusicEnabled
OR_A
JR_Z audiovb_restore_ch3_off
LD_A_MEM AudioVBlank_Ch3LatchedNote
CP_IMM 0x44
JR_NC audiovb_restore_ch3_off
LD_C_A
LD_A_IMM 0x80
LDH_MEM_A 0x1A
XOR_A
LDH_MEM_A 0x1B
LD_A_MEM AudioVBlank_Ch3Level
LDH_MEM_A 0x1C
LD_A_C
LD_E_A
LD_D_IMM 0
LD_HL_IMM AudioVBlank_FreqLo
ADD_HL_DE
LD_A_HL
LDH_MEM_A 0x1D
LD_HL_IMM AudioVBlank_FreqHi
ADD_HL_DE
LD_A_HL
OR_IMM 0x80
LDH_MEM_A 0x1E
JR audiovb_restore_ch3_done
audiovb_restore_ch3_off:
XOR_A
LDH_MEM_A 0x1A
audiovb_restore_ch3_done:
}
}AudioVBlank_SetEnabled
Permite o bloquea la música VBlank y borra las solicitudes de recuperación al deshabilitarla. El sonido actual e IRQ no cambian.
Sintaxis
void __stackcall AudioVBlank_SetEnabled(u8 on);Parámetros
onCero deshabilita y un valor no nulo habilita. Consulta la descripción para distinguir entre silenciar y bloquear las actualizaciones.
Valor devuelto
Sin valor de retorno. Modifica registros de sonido o el estado del controlador.
Condiciones y límites
audio_vblank.c implementa __kq_vblank_vector; no instales además otro vector VBlank que compita con él. El ejemplo define Audio_NoiseEffectActive, excluye el decodificador musical normal y usa Audio_Update solo para efectos y fundidos. Bloquea las interrupciones al cambiar punteros de canción o estado compartido.
Guarda los datos de canción de lectura directa en ROM fija u otra zona siempre visible para la ISR. Cada registro tiene cinco bytes: delay, CH1, CH2, CH3, CH4. En los campos de nota, 0xFF mantiene la voz y 0xFD la detiene. En delay, 0xFF termina la reproducción y 0xFE repite. Es la disposición del registro, no la numeración de canales. La reproducción por cola WRAM es otro modo; envía registros completos de cinco bytes con AudioVBlank_QueueRefill.
Ejemplo de uso
// Direct fixed-bank music with an actual VBlank ISR and a counting frame hook.
#define SOUND_VBLANK
#include "gb_sound_example.h"
__wram u8 hook_count;
__prg_rom u8 irq_song[]={30,33,0xFF,0xFF,0xFF,30,40,0xFF,0xFF,0xFF,0xFE};
void frame_hook() { hook_count++; }
void main() {
u8 before;
sound_begin("VBLANK MUSIC GATES");
Audio_NoiseEffectActive=0;
AudioVBlank_Init();
sound_result[0]=AudioVBlank_MusicPlaying;
AudioVBlank_Ch1Envelope=0xC0;
Audio_SetMasterVolume(3,3);
hook_count=0; AudioVBlank_FrameHook=frame_hook;
AudioVBlank_SetMusic(irq_song);
AudioVBlank_Play();
AudioVBlank_EnableIrq();
sound_wait(45);
// Disable music processing while the hook and current note remain active.
__asm { DI }
AudioVBlank_SetEnabled(0); before=hook_count;
__asm { EI }
sound_wait(30);
sound_result[1]=(u8)(hook_count!=before);
__asm { DI }
AudioVBlank_Stop();
__asm { EI }
sound_wait(30);
__asm { DI }
AudioVBlank_SetEnabled(1); AudioVBlank_PlayMusic(irq_song);
__asm { EI }
sound_wait(45);
AudioVBlank_DisableIrq();
before=hook_count;
sound_wait(30);
sound_result[2]=(u8)(hook_count==before);
sound_result[3]=(u8)(AudioVBlank_IE&1);
AudioVBlank_Stop(); sound_wait(30);
sound_end();
}Resultado esperado
La ISR toca una canción de dos notas. Compara bloquear las actualizaciones musicales, que conserva el sonido; Stop, que lo silencia; y bloquear IRQ tras reiniciar, que también conserva el sonido. La RAM verifica que el hook sigue funcionando con la música deshabilitada y se detiene al deshabilitar IRQ.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_vblank.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-vblank.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/audio_vblank.h:113
Gate music processing and clear pending CH1/CH3 recovery on disable. No audio register is written here: disabling does not itself silence a note already playing or disable the VBlank interrupt.
kitaqgb/lib/audio_vblank_control.inc:109
void __stackcall AudioVBlank_SetEnabled(u8 on)
{
if (on != 0) AudioVBlank_MusicEnabled = 1;
else {
AudioVBlank_MusicEnabled = 0;
// Do not carry a stale SFX-recovery request into a later song.
AudioVBlank_RestoreCh1Pending = 0;
AudioVBlank_RestoreCh3Pending = 0;
}
}AudioVBlank_SetMusic
Selecciona una canción de lectura directa y reinicia sus cursores sin cambiar la bandera de reproducción.
Sintaxis
void __stackcall AudioVBlank_SetMusic(u8 *song);Parámetros
songDirección inicial de la canción. El controlador usa el array prestado, que debe seguir siendo legible durante toda la reproducción.
Valor devuelto
Sin valor de retorno. Modifica registros de sonido o el estado del controlador.
Condiciones y límites
audio_vblank.c implementa __kq_vblank_vector; no instales además otro vector VBlank que compita con él. El ejemplo define Audio_NoiseEffectActive, excluye el decodificador musical normal y usa Audio_Update solo para efectos y fundidos. Bloquea las interrupciones al cambiar punteros de canción o estado compartido.
Guarda los datos de canción de lectura directa en ROM fija u otra zona siempre visible para la ISR. Cada registro tiene cinco bytes: delay, CH1, CH2, CH3, CH4. En los campos de nota, 0xFF mantiene la voz y 0xFD la detiene. En delay, 0xFF termina la reproducción y 0xFE repite. Es la disposición del registro, no la numeración de canales. La reproducción por cola WRAM es otro modo; envía registros completos de cinco bytes con AudioVBlank_QueueRefill.
Ejemplo de uso
// Direct fixed-bank music with an actual VBlank ISR and a counting frame hook.
#define SOUND_VBLANK
#include "gb_sound_example.h"
__wram u8 hook_count;
__prg_rom u8 irq_song[]={30,33,0xFF,0xFF,0xFF,30,40,0xFF,0xFF,0xFF,0xFE};
void frame_hook() { hook_count++; }
void main() {
u8 before;
sound_begin("VBLANK MUSIC GATES");
Audio_NoiseEffectActive=0;
AudioVBlank_Init();
sound_result[0]=AudioVBlank_MusicPlaying;
AudioVBlank_Ch1Envelope=0xC0;
Audio_SetMasterVolume(3,3);
hook_count=0; AudioVBlank_FrameHook=frame_hook;
AudioVBlank_SetMusic(irq_song);
AudioVBlank_Play();
AudioVBlank_EnableIrq();
sound_wait(45);
// Disable music processing while the hook and current note remain active.
__asm { DI }
AudioVBlank_SetEnabled(0); before=hook_count;
__asm { EI }
sound_wait(30);
sound_result[1]=(u8)(hook_count!=before);
__asm { DI }
AudioVBlank_Stop();
__asm { EI }
sound_wait(30);
__asm { DI }
AudioVBlank_SetEnabled(1); AudioVBlank_PlayMusic(irq_song);
__asm { EI }
sound_wait(45);
AudioVBlank_DisableIrq();
before=hook_count;
sound_wait(30);
sound_result[2]=(u8)(hook_count==before);
sound_result[3]=(u8)(AudioVBlank_IE&1);
AudioVBlank_Stop(); sound_wait(30);
sound_end();
}Resultado esperado
La ISR toca una canción de dos notas. Compara bloquear las actualizaciones musicales, que conserva el sonido; Stop, que lo silencia; y bloquear IRQ tras reiniciar, que también conserva el sonido. La RAM verifica que el hook sigue funcionando con la música deshabilitada y se detiene al deshabilitar IRQ.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_vblank.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-vblank.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/audio_vblank.h:100
Select a directly addressed song and reset its cursors, leaving the playing flag unchanged. Song storage must remain accessible to the fixed-bank ISR; coordinate this multi-field update with interrupt execution.
kitaqgb/lib/audio_vblank_control.inc:46
void __stackcall AudioVBlank_SetMusic(u8 *song)
{
AudioVBlank_MusicStart = song;
AudioVBlank_MusicPointer = song;
AudioVBlank_MusicLoopPoint = song;
AudioVBlank_MusicDelay = 0;
AudioVBlank_Step = 0;
AudioVBlank_QueueMode = 0;
}AudioVBlank_Stop
Borra los estados de reproducción, delay y recuperación, y silencia inmediatamente pulsos, ruido y onda. IRQ sigue habilitado.
Sintaxis
void AudioVBlank_Stop();Valor devuelto
Sin valor de retorno. Modifica registros de sonido o el estado del controlador.
Condiciones y límites
audio_vblank.c implementa __kq_vblank_vector; no instales además otro vector VBlank que compita con él. El ejemplo define Audio_NoiseEffectActive, excluye el decodificador musical normal y usa Audio_Update solo para efectos y fundidos. Bloquea las interrupciones al cambiar punteros de canción o estado compartido.
Guarda los datos de canción de lectura directa en ROM fija u otra zona siempre visible para la ISR. Cada registro tiene cinco bytes: delay, CH1, CH2, CH3, CH4. En los campos de nota, 0xFF mantiene la voz y 0xFD la detiene. En delay, 0xFF termina la reproducción y 0xFE repite. Es la disposición del registro, no la numeración de canales. La reproducción por cola WRAM es otro modo; envía registros completos de cinco bytes con AudioVBlank_QueueRefill.
Ejemplo de uso
// Direct fixed-bank music with an actual VBlank ISR and a counting frame hook.
#define SOUND_VBLANK
#include "gb_sound_example.h"
__wram u8 hook_count;
__prg_rom u8 irq_song[]={30,33,0xFF,0xFF,0xFF,30,40,0xFF,0xFF,0xFF,0xFE};
void frame_hook() { hook_count++; }
void main() {
u8 before;
sound_begin("VBLANK MUSIC GATES");
Audio_NoiseEffectActive=0;
AudioVBlank_Init();
sound_result[0]=AudioVBlank_MusicPlaying;
AudioVBlank_Ch1Envelope=0xC0;
Audio_SetMasterVolume(3,3);
hook_count=0; AudioVBlank_FrameHook=frame_hook;
AudioVBlank_SetMusic(irq_song);
AudioVBlank_Play();
AudioVBlank_EnableIrq();
sound_wait(45);
// Disable music processing while the hook and current note remain active.
__asm { DI }
AudioVBlank_SetEnabled(0); before=hook_count;
__asm { EI }
sound_wait(30);
sound_result[1]=(u8)(hook_count!=before);
__asm { DI }
AudioVBlank_Stop();
__asm { EI }
sound_wait(30);
__asm { DI }
AudioVBlank_SetEnabled(1); AudioVBlank_PlayMusic(irq_song);
__asm { EI }
sound_wait(45);
AudioVBlank_DisableIrq();
before=hook_count;
sound_wait(30);
sound_result[2]=(u8)(hook_count==before);
sound_result[3]=(u8)(AudioVBlank_IE&1);
AudioVBlank_Stop(); sound_wait(30);
sound_end();
}Resultado esperado
La ISR toca una canción de dos notas. Compara bloquear las actualizaciones musicales, que conserva el sonido; Stop, que lo silencia; y bloquear IRQ tras reiniciar, que también conserva el sonido. La RAM verifica que el hook sigue funcionando con la música deshabilitada y se detiene al deshabilitar IRQ.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sound_vblank.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\gb-vblank.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/audio_vblank.h:109
Stop software playback and silence pulse/noise envelopes and the wave DAC. Song pointers and the IRQ enable remain unchanged; the routine writes the physical channels directly, so coordinate ownership with sound effects.
kitaqgb/lib/audio_vblank_control.inc:82
void AudioVBlank_Stop()
{
AudioVBlank_MusicPlaying = 0;
AudioVBlank_MusicDelay = 0;
AudioVBlank_Step = 0;
AudioVBlank_Ch2Note = AUDIO_VBLANK_REST;
AudioVBlank_Ch1Note = AUDIO_VBLANK_REST;
AudioVBlank_Ch3Note = AUDIO_VBLANK_REST;
AudioVBlank_Ch2LatchedNote = AUDIO_VBLANK_STOP;
AudioVBlank_Ch1LatchedNote = AUDIO_VBLANK_STOP;
AudioVBlank_Ch3LatchedNote = AUDIO_VBLANK_STOP;
AudioVBlank_RestoreCh1Pending = 0;
AudioVBlank_RestoreCh3Pending = 0;
AudioVBlank_Ch4Param = AUDIO_VBLANK_REST;
__asm {
XOR_A
LDH_MEM_A 0x12
LDH_MEM_A 0x17
LDH_MEM_A 0x1C
LDH_MEM_A 0x1A
LDH_MEM_A 0x21
}
}bank.h — Acceso a código y datos por bancos
Un banco ROM es un bloque de almacenamiento del cartucho que se asigna al espacio de direcciones de la CPU. Distintos bancos pueden ocupar la misma dirección, por lo que un puntero de 16 bits no basta para identificar los datos. BankPtr es un descriptor de tres bytes sin relleno: un byte de banco y dos de puntero. Se crea con farptr_make y se lee con farptr_read8, farptr_read16 o farptr_read.
El ejemplo GB usa un cartucho MBC5: el código del banco fijo 0 permanece accesible en $0000–$3FFF, mientras que los bancos 1, 2 y 3 se seleccionan en $4000–$7FFF. Coloca bank_switch y el código que continúa después en ROM fija. Inicializa el registro de la biblioteca con bank_switch antes de consultarlo. En GB, far_call acepta un puntero de callback; __farcall exige un nombre de función.
bank_get_current
Devuelve el último número de banco guardado por bank_switch. Lee un registro de software, no los registros del cartucho.
Sintaxis
u8 bank_get_current();Valor devuelto
El valor u8 guardado por la última llamada a bank_switch; cero antes de inicializarlo.
Condiciones y límites
El registro de la biblioteca empieza en cero y no detecta el mapa inicial del cartucho. Inicialízalo con bank_switch. Las intrínsecas y las escrituras directas al mapper no actualizan este registro separado; bank_get_current no permite verificar el mapa real del hardware.
Ejemplo de uso
starting_bank=bank_get_current(); // Last value recorded by bank_switch.
bank_expect(starting_bank==2,1);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
bank_switch(2) registra y selecciona inicialmente el banco 2. Después, el cambio directo selecciona el banco 1 y lee A1 de home1 mientras bank_get_current sigue indicando 2; al volver, home2 devuelve B2 otra vez.
El programa completo enseña a identificar datos con un banco y una dirección cercana, a llamar callbacks entre bancos y a distinguir el registro de la biblioteca del mapa real. Todos los números se muestran en hexadecimal. BANK IN y BANK OUT deben ser 02; BYTE HEX, D3; WORD HEX, 5C7A; FAILED CHECKS y FIRST FAILURE, 00. CGB y FC muestran texto azul; DMG, negro.
CALL COUNT muestra 03: far_call, __farcall y __farcall_ptr invocan el callback una vez cada uno.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\banked_data_calls.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\banked_data_calls.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/bank.h:21
Return the last bank recorded by bank_switch; this does not read cartridge hardware.
kitaqgb/lib/bank.c:15
u8 bank_get_current()
{
return kq_bank_current;
}bank_switch
Consulte los cambios y la verificación del 2026-10-03 para las diferencias locales de esta API.
Selecciona el banco ROM y registra su número tanto en la biblioteca bank como en el estado del compilador. Las lecturas y llamadas lejanas usan este último para restaurar el banco anterior.
Sintaxis
void bank_switch(u8 bank);Parámetros
bankNúmero de banco ROM de 8 bits sin signo. En una llamada debe coincidir con la ubicación de la función; en una lectura selecciona el origen. Usa el intervalo válido para el cartucho.
Valor devuelto
Ninguno (void).
Condiciones y límites
Un cambio de banco persistente no debe retirar el código en ejecución ni su dirección de retorno. Coloca esta llamada, la propia bank_switch cuando se use y el código posterior en el banco común o fijo 0, como hace el ejemplo.
El registro de la biblioteca empieza en cero y no detecta el mapa inicial del cartucho. Inicialízalo con bank_switch. Las intrínsecas y las escrituras directas al mapper no actualizan este registro separado; bank_get_current no permite verificar el mapa real del hardware.
Estas interfaces GB manejan ocho bits de banco y no ajustan el noveno bit de MBC5. Siguen vigentes las reglas del cartucho, incluido el tratamiento del banco cero. El ejemplo usa explícitamente los bancos MBC5 1–3; no mezcles este estado con escrituras al mapper sin registrar.
Ejemplo de uso
bank_switch(2); // Select the payload window and update library bookkeeping.Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
bank_switch(2) registra y selecciona inicialmente el banco 2. Después, el cambio directo selecciona el banco 1 y lee A1 de home1 mientras bank_get_current sigue indicando 2; al volver, home2 devuelve B2 otra vez.
El programa completo enseña a identificar datos con un banco y una dirección cercana, a llamar callbacks entre bancos y a distinguir el registro de la biblioteca del mapa real. Todos los números se muestran en hexadecimal. BANK IN y BANK OUT deben ser 02; BYTE HEX, D3; WORD HEX, 5C7A; FAILED CHECKS y FIRST FAILURE, 00. CGB y FC muestran texto azul; DMG, negro.
CALL COUNT muestra 03: far_call, __farcall y __farcall_ptr invocan el callback una vez cada uno.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\banked_data_calls.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\banked_data_calls.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/bank.h:19
Update both the library bank record and the compiler shadow used by far reads and calls. Invoke this permanent bank change from fixed-bank code.
kitaqgb/lib/bank.c:8
void bank_switch(u8 bank)
{
kq_bank_current = bank;
__bankswitch(bank);
}far_call
Pasa un número de banco y un puntero de callback a __farcall_ptr. Esta función de biblioteca ejecuta el callback sin argumentos y vuelve una vez restaurado el banco del llamador.
Sintaxis
void far_call(u8 bank, const void* func);Parámetros
bankNúmero de banco ROM de 8 bits sin signo. En una llamada debe coincidir con la ubicación de la función; en una lectura selecciona el origen. Usa el intervalo válido para el cartucho.
funcDirección ejecutable válida de un callback sin parámetros. Puede darse como nombre de función o puntero de ejecución. No se comprueban en ejecución los punteros nulos ni una combinación incorrecta de banco y dirección.
Valor devuelto
Ninguno (void).
Condiciones y límites
Estas llamadas no pasan argumentos del usuario ni hacen que el callback admita reentrada por interrupciones. Gestiona correctamente sus datos, pila e interrupciones. La restauración de bancos se prueba con llamadas anidadas y repetidas; el ejemplo no cubre hardware físico ni cualquier posible intercalado de interrupciones.
Estas interfaces GB manejan ocho bits de banco y no ajustan el noveno bit de MBC5. Siguen vigentes las reglas del cartucho, incluido el tratamiento del banco cero. El ejemplo usa explícitamente los bancos MBC5 1–3; no mezcles este estado con escrituras al mapper sin registrar.
Ejemplo de uso
far_call(3,callback); // No arguments; callback reads payload[0] in bank 3.
bank_expect(callback_count==1 && callback_byte==0xD3,15);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
En este punto del programa completo, far_call eleva callback_count a 1. El callback lee D3 del banco 3. Una lectura cercana posterior de B2 en home2 verifica el retorno con el banco 2 seleccionado.
El programa completo enseña a identificar datos con un banco y una dirección cercana, a llamar callbacks entre bancos y a distinguir el registro de la biblioteca del mapa real. Todos los números se muestran en hexadecimal. BANK IN y BANK OUT deben ser 02; BYTE HEX, D3; WORD HEX, 5C7A; FAILED CHECKS y FIRST FAILURE, 00. CGB y FC muestran texto azul; DMG, negro.
CALL COUNT muestra 03: far_call, __farcall y __farcall_ptr invocan el callback una vez cada uno.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\banked_data_calls.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\banked_data_calls.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/bank.h:30
Invoke a no-argument callback in its ROM bank, then restore the caller bank. The pointer must identify executable code; no arguments are forwarded.
kitaqgb/lib/bank.c:40
void far_call(u8 bank, const void* func)
{
__farcall_ptr(bank, func);
}far_data_read
Copia len bytes del banco ROM indicado a la RAM del llamador mediante la intrínseca de copia lejana. Restaura el banco anterior antes de volver.
Sintaxis
void far_data_read(u8 bank, const void* addr, void* dst, u16 len);Parámetros
bankNúmero de banco ROM de 8 bits sin signo. En una llamada debe coincidir con la ubicación de la función; en una lectura selecciona el origen. Usa el intervalo válido para el cartucho.
addrPuntero cercano a bytes legibles del banco de ROM seleccionado. No incluye el número de banco.
dstDestino en memoria escribible, con espacio para todos los bytes copiados. Salvo en una transferencia de cero bytes, no se comprueba si el destino es nulo o inválido.
lenCantidad de bytes, de 0 a 65535. Con cero no se copia memoria, pero sí se selecciona y restaura el banco.
Valor devuelto
Ninguno (void).
Condiciones y límites
Mantenga todo el origen en el mapeo de ROM previsto y todo el destino en memoria escribible. La copia no cambia automáticamente de banco al cruzar una ventana, no trata solapamientos como memmove ni sincroniza escrituras en VRAM. Para VRAM, use las API de transferencia gráfica.
Las lecturas y copias lejanas son síncronas y usan memoria de trabajo compartida del compilador. No dejes que una interrupción ejecute otra transferencia sobre esa memoria mientras está en uso. En GB, la copia también guarda el banco anterior en una posición HRAM compartida. El ejemplo ejecuta las operaciones desde código fijo, sin un manejador de transferencia que compita.
Estas interfaces GB manejan ocho bits de banco y no ajustan el noveno bit de MBC5. Siguen vigentes las reglas del cartucho, incluido el tratamiento del banco cero. El ejemplo usa explícitamente los bancos MBC5 1–3; no mezcles este estado con escrituras al mapper sin registrar.
Ejemplo de uso
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);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Este fragmento copia 4 bytes mediante far_data_read y contrasta el búfer con D3 7A 5C 96. El llamador conserva su descriptor o puntero de origen; el programa completo comprueba aparte una copia de longitud cero y la restauración del banco.
El programa completo enseña a identificar datos con un banco y una dirección cercana, a llamar callbacks entre bancos y a distinguir el registro de la biblioteca del mapa real. Todos los números se muestran en hexadecimal. BANK IN y BANK OUT deben ser 02; BYTE HEX, D3; WORD HEX, 5C7A; FAILED CHECKS y FIRST FAILURE, 00. CGB y FC muestran texto azul; DMG, negro.
CALL COUNT muestra 03: far_call, __farcall y __farcall_ptr invocan el callback una vez cada uno.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\banked_data_calls.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\banked_data_calls.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/bank.h:27
Copy len bytes from banked ROM into caller-owned writable storage.
kitaqgb/lib/bank.c:33
void far_data_read(u8 bank, const void* addr, void* dst, u16 len)
{
__farmemcpy(dst, bank, addr, len);
}far_data_read16
Lee dos bytes consecutivos mediante __farpeek16 y forma una palabra little-endian. El primer byte ocupa los ocho bits bajos.
Sintaxis
u16 far_data_read16(u8 bank, const void* addr);Parámetros
bankNúmero de banco ROM de 8 bits sin signo. En una llamada debe coincidir con la ubicación de la función; en una lectura selecciona el origen. Usa el intervalo válido para el cartucho.
addrPuntero cercano a bytes legibles del banco de ROM seleccionado. No incluye el número de banco.
Valor devuelto
La palabra little-endian leída, como u16 (0–65535).
Condiciones y límites
El byte o la palabra completos deben ser legibles en el mapa CPU seleccionado. No se validan punteros, no se recortan direcciones ni se cambia automáticamente de banco al cruzar una ventana. Una palabra necesita dos bytes consecutivos válidos.
Las lecturas y copias lejanas son síncronas y usan memoria de trabajo compartida del compilador. No dejes que una interrupción ejecute otra transferencia sobre esa memoria mientras está en uso. En GB, la copia también guarda el banco anterior en una posición HRAM compartida. El ejemplo ejecuta las operaciones desde código fijo, sin un manejador de transferencia que compita.
Estas interfaces GB manejan ocho bits de banco y no ajustan el noveno bit de MBC5. Siguen vigentes las reglas del cartucho, incluido el tratamiento del banco cero. El ejemplo usa explícitamente los bancos MBC5 1–3; no mezcles este estado con escrituras al mapper sin registrar.
Ejemplo de uso
word_value=far_data_read16(3,payload+1); // Little-endian 7A 5C -> 0x5C7A.
bank_expect(word_value==0x5C7A,6);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Este fragmento usa far_data_read16 para leer payload+1 del banco 3 y comprueba 5C7A. El programa completo también lee home2 con un puntero cercano para confirmar que se ha restaurado el banco 2.
El programa completo enseña a identificar datos con un banco y una dirección cercana, a llamar callbacks entre bancos y a distinguir el registro de la biblioteca del mapa real. Todos los números se muestran en hexadecimal. BANK IN y BANK OUT deben ser 02; BYTE HEX, D3; WORD HEX, 5C7A; FAILED CHECKS y FIRST FAILURE, 00. CGB y FC muestran texto azul; DMG, negro.
CALL COUNT muestra 03: far_call, __farcall y __farcall_ptr invocan el callback una vez cada uno.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\banked_data_calls.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\banked_data_calls.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/bank.h:25
Read a 16-bit value from the supplied bank and address through the far-read intrinsic.
kitaqgb/lib/bank.c:27
u16 far_data_read16(u8 bank, const void* addr)
{
return __farpeek16(bank, addr);
}far_data_read8
Lee un byte del banco ROM y la dirección indicados mediante __farpeek8; restaura el banco anterior y devuelve el valor.
Sintaxis
u8 far_data_read8(u8 bank, const void* addr);Parámetros
bankNúmero de banco ROM de 8 bits sin signo. En una llamada debe coincidir con la ubicación de la función; en una lectura selecciona el origen. Usa el intervalo válido para el cartucho.
addrPuntero cercano a bytes legibles del banco de ROM seleccionado. No incluye el número de banco.
Valor devuelto
El byte leído, como u8 (0–255).
Condiciones y límites
El byte o la palabra completos deben ser legibles en el mapa CPU seleccionado. No se validan punteros, no se recortan direcciones ni se cambia automáticamente de banco al cruzar una ventana. Una palabra necesita dos bytes consecutivos válidos.
Las lecturas y copias lejanas son síncronas y usan memoria de trabajo compartida del compilador. No dejes que una interrupción ejecute otra transferencia sobre esa memoria mientras está en uso. En GB, la copia también guarda el banco anterior en una posición HRAM compartida. El ejemplo ejecuta las operaciones desde código fijo, sin un manejador de transferencia que compita.
Estas interfaces GB manejan ocho bits de banco y no ajustan el noveno bit de MBC5. Siguen vigentes las reglas del cartucho, incluido el tratamiento del banco cero. El ejemplo usa explícitamente los bancos MBC5 1–3; no mezcles este estado con escrituras al mapper sin registrar.
Ejemplo de uso
byte_value=far_data_read8(3,payload); // One byte: 0xD3.
bank_expect(byte_value==0xD3,5);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Este fragmento usa far_data_read8 para leer payload del banco 3 y comprueba D3. El programa completo también lee home2 con un puntero cercano para confirmar que se ha restaurado el banco 2.
El programa completo enseña a identificar datos con un banco y una dirección cercana, a llamar callbacks entre bancos y a distinguir el registro de la biblioteca del mapa real. Todos los números se muestran en hexadecimal. BANK IN y BANK OUT deben ser 02; BYTE HEX, D3; WORD HEX, 5C7A; FAILED CHECKS y FIRST FAILURE, 00. CGB y FC muestran texto azul; DMG, negro.
CALL COUNT muestra 03: far_call, __farcall y __farcall_ptr invocan el callback una vez cada uno.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\banked_data_calls.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\banked_data_calls.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/bank.h:23
Read one byte through the compiler intrinsic that accepts an explicit ROM bank.
kitaqgb/lib/bank.c:21
u8 far_data_read8(u8 bank, const void* addr)
{
return __farpeek8(bank, addr);
}farptr_make
Guarda un byte de banco y un puntero visible para la CPU en el BankPtr del llamador. Construye un descriptor; no cambia de banco ni lee los datos apuntados.
Sintaxis
void farptr_make(BankPtr* out, u8 bank, const u8* ptr);Parámetros
outPuntero a espacio escribible para un BankPtr de tres bytes. Si out es nulo, no se escribe nada.
bankNúmero de banco ROM de 8 bits sin signo. En una llamada debe coincidir con la ubicación de la función; en una lectura selecciona el origen. Usa el intervalo válido para el cartucho.
ptrDirección de 16 bits visible para la CPU que se guardará en el descriptor. Se copia sin cambios; no se comprueba su validez en el banco elegido.
Valor devuelto
Ninguno (void).
Ejemplo de uso
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.Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El descriptor se fija en banco 3 y payload+1. Sus lectores obtienen 7A, 5C7A y los tres bytes 7A 5C 96. La llamada con salida nula no debe cambiar el estado.
El programa completo enseña a identificar datos con un banco y una dirección cercana, a llamar callbacks entre bancos y a distinguir el registro de la biblioteca del mapa real. Todos los números se muestran en hexadecimal. BANK IN y BANK OUT deben ser 02; BYTE HEX, D3; WORD HEX, 5C7A; FAILED CHECKS y FIRST FAILURE, 00. CGB y FC muestran texto azul; DMG, negro.
CALL COUNT muestra 03: far_call, __farcall y __farcall_ptr invocan el callback una vez cada uno.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\banked_data_calls.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\banked_data_calls.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/bank.h:32
Store a bank/address pair without accessing ROM; a null output pointer is ignored.
kitaqgb/lib/bank.c:46
void farptr_make(BankPtr* out, u8 bank, const u8* ptr)
{
if (out == 0) return;
out->bank = bank;
out->ptr = ptr;
}farptr_read
Copia len bytes desde un BankPtr a RAM escribible. El descriptor se pasa por valor, por lo que el puntero del llamador sigue señalando el inicio del origen.
Sintaxis
void farptr_read(BankPtr ptr, void* dst, u16 len);Parámetros
ptrUn valor BankPtr con los campos bank y ptr. Pasa el descriptor, no su dirección. El descriptor del llamador no se modifica.
dstDestino en memoria escribible, con espacio para todos los bytes copiados. Salvo en una transferencia de cero bytes, no se comprueba si el destino es nulo o inválido.
lenCantidad de bytes, de 0 a 65535. Con cero no se copia memoria, pero sí se selecciona y restaura el banco.
Valor devuelto
Ninguno (void).
Condiciones y límites
Mantenga todo el origen en el mapeo de ROM previsto y todo el destino en memoria escribible. La copia no cambia automáticamente de banco al cruzar una ventana, no trata solapamientos como memmove ni sincroniza escrituras en VRAM. Para VRAM, use las API de transferencia gráfica.
Las lecturas y copias lejanas son síncronas y usan memoria de trabajo compartida del compilador. No dejes que una interrupción ejecute otra transferencia sobre esa memoria mientras está en uso. En GB, la copia también guarda el banco anterior en una posición HRAM compartida. El ejemplo ejecuta las operaciones desde código fijo, sin un manejador de transferencia que compita.
Estas interfaces GB manejan ocho bits de banco y no ajustan el noveno bit de MBC5. Siguen vigentes las reglas del cartucho, incluido el tratamiento del banco cero. El ejemplo usa explícitamente los bancos MBC5 1–3; no mezcles este estado con escrituras al mapper sin registrar.
Ejemplo de uso
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);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Este fragmento copia 3 bytes mediante farptr_read y contrasta el búfer con 7A 5C 96. El llamador conserva su descriptor o puntero de origen; el programa completo comprueba aparte una copia de longitud cero y la restauración del banco.
El programa completo enseña a identificar datos con un banco y una dirección cercana, a llamar callbacks entre bancos y a distinguir el registro de la biblioteca del mapa real. Todos los números se muestran en hexadecimal. BANK IN y BANK OUT deben ser 02; BYTE HEX, D3; WORD HEX, 5C7A; FAILED CHECKS y FIRST FAILURE, 00. CGB y FC muestran texto azul; DMG, negro.
CALL COUNT muestra 03: far_call, __farcall y __farcall_ptr invocan el callback una vez cada uno.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\banked_data_calls.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\banked_data_calls.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/bank.h:38
Copy len bytes from a bank-qualified pointer; dst must have room for the full copy.
kitaqgb/lib/bank.c:66
void farptr_read(BankPtr ptr, void* dst, u16 len)
{
__farmemcpy(dst, ptr.bank, ptr.ptr, len);
}farptr_read16
Lee una palabra little-endian del banco y la dirección del BankPtr. El descriptor se pasa por valor y su puntero no avanza.
Sintaxis
u16 farptr_read16(BankPtr ptr);Parámetros
ptrUn valor BankPtr con los campos bank y ptr. Pasa el descriptor, no su dirección. El descriptor del llamador no se modifica.
Valor devuelto
La palabra little-endian leída, como u16 (0–65535).
Condiciones y límites
El byte o la palabra completos deben ser legibles en el mapa CPU seleccionado. No se validan punteros, no se recortan direcciones ni se cambia automáticamente de banco al cruzar una ventana. Una palabra necesita dos bytes consecutivos válidos.
Las lecturas y copias lejanas son síncronas y usan memoria de trabajo compartida del compilador. No dejes que una interrupción ejecute otra transferencia sobre esa memoria mientras está en uso. En GB, la copia también guarda el banco anterior en una posición HRAM compartida. El ejemplo ejecuta las operaciones desde código fijo, sin un manejador de transferencia que compita.
Estas interfaces GB manejan ocho bits de banco y no ajustan el noveno bit de MBC5. Siguen vigentes las reglas del cartucho, incluido el tratamiento del banco cero. El ejemplo usa explícitamente los bancos MBC5 1–3; no mezcles este estado con escrituras al mapper sin registrar.
Ejemplo de uso
bank_expect(farptr_read16(pointer)==0x5C7A,10);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Este fragmento usa farptr_read16 para leer pointer.ptr del banco 3 y comprueba 5C7A. El programa completo también lee home2 con un puntero cercano para confirmar que se ha restaurado el banco 2.
El programa completo enseña a identificar datos con un banco y una dirección cercana, a llamar callbacks entre bancos y a distinguir el registro de la biblioteca del mapa real. Todos los números se muestran en hexadecimal. BANK IN y BANK OUT deben ser 02; BYTE HEX, D3; WORD HEX, 5C7A; FAILED CHECKS y FIRST FAILURE, 00. CGB y FC muestran texto azul; DMG, negro.
CALL COUNT muestra 03: far_call, __farcall y __farcall_ptr invocan el callback una vez cada uno.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\banked_data_calls.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\banked_data_calls.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/bank.h:36
Read a 16-bit value using both components of the bank-qualified pointer.
kitaqgb/lib/bank.c:60
u16 farptr_read16(BankPtr ptr)
{
return __farpeek16(ptr.bank, ptr.ptr);
}farptr_read8
Lee un byte usando ambos campos de un BankPtr pasado por valor. El descriptor aporta el banco que un puntero cercano no contiene.
Sintaxis
u8 farptr_read8(BankPtr ptr);Parámetros
ptrUn valor BankPtr con los campos bank y ptr. Pasa el descriptor, no su dirección. El descriptor del llamador no se modifica.
Valor devuelto
El byte leído, como u8 (0–255).
Condiciones y límites
El byte o la palabra completos deben ser legibles en el mapa CPU seleccionado. No se validan punteros, no se recortan direcciones ni se cambia automáticamente de banco al cruzar una ventana. Una palabra necesita dos bytes consecutivos válidos.
Las lecturas y copias lejanas son síncronas y usan memoria de trabajo compartida del compilador. No dejes que una interrupción ejecute otra transferencia sobre esa memoria mientras está en uso. En GB, la copia también guarda el banco anterior en una posición HRAM compartida. El ejemplo ejecuta las operaciones desde código fijo, sin un manejador de transferencia que compita.
Estas interfaces GB manejan ocho bits de banco y no ajustan el noveno bit de MBC5. Siguen vigentes las reglas del cartucho, incluido el tratamiento del banco cero. El ejemplo usa explícitamente los bancos MBC5 1–3; no mezcles este estado con escrituras al mapper sin registrar.
Ejemplo de uso
bank_expect(farptr_read8(pointer)==0x7A,9);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Este fragmento usa farptr_read8 para leer pointer.ptr del banco 3 y comprueba 7A. El programa completo también lee home2 con un puntero cercano para confirmar que se ha restaurado el banco 2.
El programa completo enseña a identificar datos con un banco y una dirección cercana, a llamar callbacks entre bancos y a distinguir el registro de la biblioteca del mapa real. Todos los números se muestran en hexadecimal. BANK IN y BANK OUT deben ser 02; BYTE HEX, D3; WORD HEX, 5C7A; FAILED CHECKS y FIRST FAILURE, 00. CGB y FC muestran texto azul; DMG, negro.
CALL COUNT muestra 03: far_call, __farcall y __farcall_ptr invocan el callback una vez cada uno.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\banked_data_calls.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\banked_data_calls.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/bank.h:34
Read one byte using both components of the bank-qualified pointer.
kitaqgb/lib/bank.c:54
u8 farptr_read8(BankPtr ptr)
{
return __farpeek8(ptr.bank, ptr.ptr);
}camera.h — Coordenadas del mundo y áreas visibles
Gestiona posiciones, objetivos y límites de cámara Q8.8 y convierte coordenadas de mundo y pantalla. Elige objetos Camera8_8 propios del código que llama o la API en minúsculas para una cámara compartida.
Camera_Add
Suma desplazamientos Q8.8 a la posición actual y después aplica los límites activados.
Sintaxis
void Camera_Add(Camera8_8* cam, s16 dfx, s16 dfy);Parámetros
camPuntero válido a un
Camera8_8inicializado y propiedad del código que llama.dfxDesplazamiento Q8.8 con signo; 256 equivale a un píxel.
dfyDesplazamiento Q8.8 con signo; 256 equivale a un píxel.
Valor devuelto
No devuelve ningún valor. Esta entrada describe el estado afectado y cuándo surte efecto.
Condiciones y límites
Las coordenadas tienen ocho bits fraccionarios. Mantén las posiciones, los objetivos y las sumas o diferencias intermedias dentro de s16. Actualiza la pantalla por separado con Camera_ApplyBg o aplicando los valores pendientes del búfer.
Ejemplo de uso
Camera_Add(&cam,256,512);result[13]=cam.fx;result[14]=cam.fy;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo enseña seguimiento Q8.8, límites y conversión de coordenadas. El seguimiento produce X/Y=3584/4096 y los límites dan 3072/3584. BG X permanece en 13 mientras el cambio está pendiente y pasa a 8 al aplicar el búfer. La imagen adicional muestra cómo una cámara en (8,16) sitúa en pantalla (24,16) un rectángulo de 32×24 ubicado en el mundo en (32,32).


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kEjemplo de uso
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Con la cámara en (8,16), el rectángulo rojo de 32×24 aparece en pantalla en (24,16). La ventana muestra un marco azul de 64×64 en (96,80) y un cuadrado verde de 16×16 en (112,96). En DMG todas las figuras son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/camera.h:34
Add Q8.8 deltas and clamp afterward. Keep the intermediate sums within s16; clamping cannot repair arithmetic that already overflowed.
kitaqgb/lib/camera.c:79
void Camera_Add(Camera8_8* cam, s16 dfx, s16 dfy)
{
cam->fx += dfx;
cam->fy += dfy;
Camera_ApplyBounds(cam);
}camera_apply
Aplica de inmediato la posición actual de la cámara compartida al desplazamiento del fondo.
Sintaxis
void camera_apply();Valor devuelto
No devuelve ningún valor. Esta entrada describe el estado afectado y cuándo surte efecto.
Condiciones y límites
No espera a VBlank; sincroniza desde el código que llama si no quieres cambios a mitad de fotograma. Las fracciones negativas se redondean hacia abajo: −1/256 pasa a −1 píxel, es decir, al valor 255 del registro.
Ejemplo de uso
camera_apply();result[31]=M_SCX;result[32]=M_SCY;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo enseña seguimiento Q8.8, límites y conversión de coordenadas. El seguimiento produce X/Y=3584/4096 y los límites dan 3072/3584. BG X permanece en 13 mientras el cambio está pendiente y pasa a 8 al aplicar el búfer. La imagen adicional muestra cómo una cámara en (8,16) sitúa en pantalla (24,16) un rectángulo de 32×24 ubicado en el mundo en (32,32).


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kEjemplo de uso
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Con la cámara en (8,16), el rectángulo rojo de 32×24 aparece en pantalla en (24,16). La ventana muestra un marco azul de 64×64 en (96,80) y un cuadrado verde de 16×16 en (112,96). En DMG todas las figuras son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/camera.h:64
Write the shared camera's current integer position to background scroll registers.
kitaqgb/lib/camera.c:179
void camera_apply()
{
Camera_ApplyBg(&camera_default);
}Camera_ApplyBg
Redondea hacia abajo la posición de la cámara a píxeles enteros y escribe inmediatamente los ocho bits bajos en el desplazamiento del fondo.
Sintaxis
void Camera_ApplyBg(const Camera8_8* cam);Parámetros
camPuntero válido a un
Camera8_8inicializado y propiedad del código que llama.
Valor devuelto
No devuelve ningún valor. Esta entrada describe el estado afectado y cuándo surte efecto.
Condiciones y límites
No espera a VBlank; sincroniza desde el código que llama si no quieres cambios a mitad de fotograma. Las fracciones negativas se redondean hacia abajo: −1/256 pasa a −1 píxel, es decir, al valor 255 del registro.
Ejemplo de uso
Camera_ApplyBg(&cam);result[21]=M_SCX;result[22]=M_SCY;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo enseña seguimiento Q8.8, límites y conversión de coordenadas. El seguimiento produce X/Y=3584/4096 y los límites dan 3072/3584. BG X permanece en 13 mientras el cambio está pendiente y pasa a 8 al aplicar el búfer. La imagen adicional muestra cómo una cámara en (8,16) sitúa en pantalla (24,16) un rectángulo de 32×24 ubicado en el mundo en (32,32).


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kEjemplo de uso
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Con la cámara en (8,16), el rectángulo rojo de 32×24 aparece en pantalla en (24,16). La ventana muestra un marco azul de 64×64 en (96,80) y un cuadrado verde de 16×16 en (112,96). En DMG todas las figuras son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/camera.h:40
Discard fractional bits and write the low eight integer bits to background scroll registers.
kitaqgb/lib/camera.c:109
void Camera_ApplyBg(const Camera8_8* cam)
{
__scroll_bg_set((u8)(cam->fx >> 8), (u8)(cam->fy >> 8));
}Camera_ApplyBgBuffered
Redondea hacia abajo la posición de la cámara a píxeles enteros y la deja pendiente como desplazamiento del fondo.
Sintaxis
void Camera_ApplyBgBuffered(const Camera8_8* cam);Parámetros
camPuntero válido a un
Camera8_8inicializado y propiedad del código que llama.
Valor devuelto
No devuelve ningún valor. Esta entrada describe el estado afectado y cuándo surte efecto.
Condiciones y límites
El hardware y los valores actuales registrados no cambian hasta llamar a Scroll_Flush o __scroll_flush. Esta llamada no espera a VBlank.
Ejemplo de uso
Camera_Set(&cam,2048,4096);Camera_ApplyBgBuffered(&cam);result[23]=M_SCX;Scroll_Flush();result[24]=M_SCX;result[25]=M_SCY;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo enseña seguimiento Q8.8, límites y conversión de coordenadas. El seguimiento produce X/Y=3584/4096 y los límites dan 3072/3584. BG X permanece en 13 mientras el cambio está pendiente y pasa a 8 al aplicar el búfer. La imagen adicional muestra cómo una cámara en (8,16) sitúa en pantalla (24,16) un rectángulo de 32×24 ubicado en el mundo en (32,32).


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kEjemplo de uso
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Con la cámara en (8,16), el rectángulo rojo de 32×24 aparece en pantalla en (24,16). La ventana muestra un marco azul de 64×64 en (96,80) y un cuadrado verde de 16×16 en (112,96). En DMG todas las figuras son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/camera.h:42
Convert the Q8.8 position to byte scroll values and stage them for a later flush.
kitaqgb/lib/camera.c:115
void Camera_ApplyBgBuffered(const Camera8_8* cam)
{
__scroll_bg_set_buffered((u8)(cam->fx >> 8), (u8)(cam->fy >> 8));
}camera_clamp
Aplica a la cámara compartida los límites obtenidos al restar la pantalla del mundo.
Sintaxis
void camera_clamp(u16 world_w_px, u16 world_h_px, u8 screen_w_px, u8 screen_h_px);Parámetros
world_w_pxDimensión del mundo en píxeles enteros; la diferencia positiva respecto a la pantalla debe quedar entre 0 y 127.
world_h_pxDimensión del mundo en píxeles enteros; la diferencia positiva respecto a la pantalla debe quedar entre 0 y 127.
screen_w_pxTamaño del área visible en píxeles enteros; si es igual o mayor que el mundo, el recorrido en ese eje es cero.
screen_h_pxTamaño del área visible en píxeles enteros; si es igual o mayor que el mundo, el recorrido en ese eje es cero.
Valor devuelto
No devuelve ningún valor. Esta entrada describe el estado afectado y cuándo surte efecto.
Condiciones y límites
Si el mundo es menor que el área visible, el recorrido es cero. Una diferencia positiva de 128 o más supera el rango Q8.8 con signo al convertirla. Que los parámetros sean u16 no implica que la cámara pueda recorrer mundos de cualquier tamaño. Estas llamadas comparten una cámara; usa la API que empieza por mayúscula para objetos de cámara independientes. Las posiciones convertidas de píxeles enteros a Q8.8 deben estar entre −128 y 127.
Ejemplo de uso
camera_clamp(176,160,160,144);result[29]=camera_world_to_screen_x(100);result[30]=camera_world_to_screen_y(90);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo enseña seguimiento Q8.8, límites y conversión de coordenadas. El seguimiento produce X/Y=3584/4096 y los límites dan 3072/3584. BG X permanece en 13 mientras el cambio está pendiente y pasa a 8 al aplicar el búfer. La imagen adicional muestra cómo una cámara en (8,16) sitúa en pantalla (24,16) un rectángulo de 32×24 ubicado en el mundo en (32,32).


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kEjemplo de uso
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Con la cámara en (8,16), el rectángulo rojo de 32×24 aparece en pantalla en (24,16). La ventana muestra un marco azul de 64×64 en (96,80) y un cuadrado verde de 16×16 en (112,96). En DMG todas las figuras son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/camera.h:62
Derive and apply world/screen bounds to the shared convenience camera.
kitaqgb/lib/camera.c:173
void camera_clamp(u16 world_w_px, u16 world_h_px, u8 screen_w_px, u8 screen_h_px)
{
Camera_ClampToSize(&camera_default, world_w_px, world_h_px, screen_w_px, screen_h_px);
}Camera_ClampToSize
Resta las dimensiones de la pantalla a las del mundo y establece los límites no negativos resultantes para la cámara.
Sintaxis
void Camera_ClampToSize(Camera8_8* cam, u16 world_w_px, u16 world_h_px, u8 screen_w_px, u8 screen_h_px);Parámetros
camPuntero válido a un
Camera8_8inicializado y propiedad del código que llama.world_w_pxDimensión del mundo en píxeles enteros; la diferencia positiva respecto a la pantalla debe quedar entre 0 y 127.
world_h_pxDimensión del mundo en píxeles enteros; la diferencia positiva respecto a la pantalla debe quedar entre 0 y 127.
screen_w_pxTamaño del área visible en píxeles enteros; si es igual o mayor que el mundo, el recorrido en ese eje es cero.
screen_h_pxTamaño del área visible en píxeles enteros; si es igual o mayor que el mundo, el recorrido en ese eje es cero.
Valor devuelto
No devuelve ningún valor. Esta entrada describe el estado afectado y cuándo surte efecto.
Condiciones y límites
Si el mundo es menor que el área visible, el recorrido es cero. Una diferencia positiva de 128 o más supera el rango Q8.8 con signo al convertirla. Que los parámetros sean u16 no implica que la cámara pueda recorrer mundos de cualquier tamaño.
Ejemplo de uso
Camera_ClampToSize(&cam,176,160,160,144);result[15]=cam.max_fx;result[16]=cam.max_fy;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo enseña seguimiento Q8.8, límites y conversión de coordenadas. El seguimiento produce X/Y=3584/4096 y los límites dan 3072/3584. BG X permanece en 13 mientras el cambio está pendiente y pasa a 8 al aplicar el búfer. La imagen adicional muestra cómo una cámara en (8,16) sitúa en pantalla (24,16) un rectángulo de 32×24 ubicado en el mundo en (32,32).


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kEjemplo de uso
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Con la cámara en (8,16), el rectángulo rojo de 32×24 aparece en pantalla en (24,16). La ventana muestra un marco azul de 64×64 en (96,80) y un cuadrado verde de 16×16 en (112,96). En DMG todas las figuras son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/camera.h:46
Derive nonnegative camera extents from world minus screen size, then convert them to Q8.8 bounds. Extents must fit signed Q8.8; the u16 input type does not imply support for arbitrary large worlds.
kitaqgb/lib/camera.c:123
void Camera_ClampToSize(Camera8_8* cam, u16 world_w_px, u16 world_h_px, u8 screen_w_px, u8 screen_h_px)
{
s16 max_x = 0;
s16 max_y = 0;
if (world_w_px > screen_w_px) max_x = (s16)((u16)(world_w_px - screen_w_px) << 8);
if (world_h_px > screen_h_px) max_y = (s16)((u16)(world_h_px - screen_h_px) << 8);
Camera_SetBounds(cam, (s16)0, (s16)0, max_x, max_y);
}Camera_ClearBounds
Desactiva los límites sin cambiar la posición, el objetivo ni los límites guardados.
Sintaxis
void Camera_ClearBounds(Camera8_8* cam);Parámetros
camPuntero válido a un
Camera8_8inicializado y propiedad del código que llama.
Valor devuelto
No devuelve ningún valor. Esta entrada describe el estado afectado y cuándo surte efecto.
Condiciones y límites
Las coordenadas tienen ocho bits fraccionarios. Mantén las posiciones, los objetivos y las sumas o diferencias intermedias dentro de s16. Actualiza la pantalla por separado con Camera_ApplyBg o aplicando los valores pendientes del búfer.
Ejemplo de uso
Camera_ClearBounds(&cam);result[12]=cam.use_bounds;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo enseña seguimiento Q8.8, límites y conversión de coordenadas. El seguimiento produce X/Y=3584/4096 y los límites dan 3072/3584. BG X permanece en 13 mientras el cambio está pendiente y pasa a 8 al aplicar el búfer. La imagen adicional muestra cómo una cámara en (8,16) sitúa en pantalla (24,16) un rectángulo de 32×24 ubicado en el mundo en (32,32).


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kEjemplo de uso
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Con la cámara en (8,16), el rectángulo rojo de 32×24 aparece en pantalla en (24,16). La ventana muestra un marco azul de 64×64 en (96,80) y un cuadrado verde de 16×16 en (112,96). En DMG todas las figuras son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/camera.h:31
Disable clamping while retaining the stored bounds and current position.
kitaqgb/lib/camera.c:72
void Camera_ClearBounds(Camera8_8* cam)
{
cam->use_bounds = 0;
}Camera_ClearTarget
Desactiva el seguimiento conservando la posición actual y el objetivo guardado.
Sintaxis
void Camera_ClearTarget(Camera8_8* cam);Parámetros
camPuntero válido a un
Camera8_8inicializado y propiedad del código que llama.
Valor devuelto
No devuelve ningún valor. Esta entrada describe el estado afectado y cuándo surte efecto.
Condiciones y límites
Las coordenadas tienen ocho bits fraccionarios. Mantén las posiciones, los objetivos y las sumas o diferencias intermedias dentro de s16. Actualiza la pantalla por separado con Camera_ApplyBg o aplicando los valores pendientes del búfer.
Ejemplo de uso
Camera_ClearTarget(&cam);result[8]=cam.use_target;result[9]=cam.target_fx;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo enseña seguimiento Q8.8, límites y conversión de coordenadas. El seguimiento produce X/Y=3584/4096 y los límites dan 3072/3584. BG X permanece en 13 mientras el cambio está pendiente y pasa a 8 al aplicar el búfer. La imagen adicional muestra cómo una cámara en (8,16) sitúa en pantalla (24,16) un rectángulo de 32×24 ubicado en el mundo en (32,32).


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kEjemplo de uso
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Con la cámara en (8,16), el rectángulo rojo de 32×24 aparece en pantalla en (24,16). La ventana muestra un marco azul de 64×64 en (96,80) y un cuadrado verde de 16×16 en (112,96). En DMG todas las figuras son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/camera.h:27
Disable target following without moving the camera or erasing the stored target.
kitaqgb/lib/camera.c:55
void Camera_ClearTarget(Camera8_8* cam)
{
cam->use_target = 0;
}camera_follow_xy
Mueve de inmediato la cámara compartida para que un punto del mundo aparezca en el punto de anclaje indicado en pantalla.
Sintaxis
void camera_follow_xy(s16 x, s16 y, u8 screen_cx, u8 screen_cy);Parámetros
xCoordenada X del mundo en píxeles enteros; el resultado y la diferencia intermedia deben caber en
s16.yCoordenada Y del mundo en píxeles enteros; el resultado y la diferencia intermedia deben caber en
s16.screen_cxCoordenada del punto de anclaje en pantalla en píxeles enteros, de 0 a 255.
screen_cyCoordenada del punto de anclaje en pantalla en píxeles enteros, de 0 a 255.
Valor devuelto
No devuelve ningún valor. Esta entrada describe el estado afectado y cuándo surte efecto.
Condiciones y límites
Las coordenadas tienen ocho bits fraccionarios. Mantén las posiciones, los objetivos y las sumas o diferencias intermedias dentro de s16. Actualiza la pantalla por separado con Camera_ApplyBg o aplicando los valores pendientes del búfer. Estas llamadas comparten una cámara; usa la API que empieza por mayúscula para objetos de cámara independientes. Las posiciones convertidas de píxeles enteros a Q8.8 deben estar entre −128 y 127.
Ejemplo de uso
camera_follow_xy(100,90,80,72);result[27]=camera_world_to_screen_x(100);result[28]=camera_world_to_screen_y(90);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo enseña seguimiento Q8.8, límites y conversión de coordenadas. El seguimiento produce X/Y=3584/4096 y los límites dan 3072/3584. BG X permanece en 13 mientras el cambio está pendiente y pasa a 8 al aplicar el búfer. La imagen adicional muestra cómo una cámara en (8,16) sitúa en pantalla (24,16) un rectángulo de 32×24 ubicado en el mundo en (32,32).


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kEjemplo de uso
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Con la cámara en (8,16), el rectángulo rojo de 32×24 aparece en pantalla en (24,16). La ventana muestra un marco azul de 64×64 en (96,80) y un cuadrado verde de 16×16 en (112,96). En DMG todas las figuras son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/camera.h:60
Position the shared camera so the world point appears at the requested screen anchor. This is an immediate move, not the smoothed target-following path.
kitaqgb/lib/camera.c:165
void camera_follow_xy(s16 x, s16 y, u8 screen_cx, u8 screen_cy)
{
s16 cx = (s16)(x - screen_cx);
s16 cy = (s16)(y - screen_cy);
Camera_Set(&camera_default, (s16)(cx << 8), (s16)(cy << 8));
}Camera_Init
Pone a cero la posición, el objetivo y los límites, y desactiva el seguimiento y la limitación al rango.
Sintaxis
void Camera_Init(Camera8_8* cam);Parámetros
camCamera8_8accesible para escritura que se va a inicializar; no debe ser NULL.
Valor devuelto
No devuelve ningún valor. Esta entrada describe el estado afectado y cuándo surte efecto.
Condiciones y límites
Las coordenadas tienen ocho bits fraccionarios. Mantén las posiciones, los objetivos y las sumas o diferencias intermedias dentro de s16. Actualiza la pantalla por separado con Camera_ApplyBg o aplicando los valores pendientes del búfer.
Ejemplo de uso
Camera_Init(&cam);result[0]=cam.fx;result[1]=cam.use_target;result[2]=cam.use_bounds;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo enseña seguimiento Q8.8, límites y conversión de coordenadas. El seguimiento produce X/Y=3584/4096 y los límites dan 3072/3584. BG X permanece en 13 mientras el cambio está pendiente y pasa a 8 al aplicar el búfer. La imagen adicional muestra cómo una cámara en (8,16) sitúa en pantalla (24,16) un rectángulo de 32×24 ubicado en el mundo en (32,32).


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kEjemplo de uso
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Con la cámara en (8,16), el rectángulo rojo de 32×24 aparece en pantalla en (24,16). La ventana muestra un marco azul de 64×64 en (96,80) y un cuadrado verde de 16×16 en (112,96). En DMG todas las figuras son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/camera.h:21
Zero all position/target/bound fields and disable targeting and bounds.
kitaqgb/lib/camera.c:24
void Camera_Init(Camera8_8* cam)
{
cam->fx = 0;
cam->fy = 0;
cam->target_fx = 0;
cam->target_fy = 0;
cam->min_fx = 0;
cam->min_fy = 0;
cam->max_fx = 0;
cam->max_fy = 0;
cam->use_target = 0;
cam->use_bounds = 0;
}Camera_ScreenToWorldX
Suma la parte entera de X de la cámara a la X entera de pantalla para obtener la X del mundo.
Sintaxis
s16 Camera_ScreenToWorldX(const Camera8_8* cam, s16 screen_x);Parámetros
camPuntero válido a un
Camera8_8inicializado y propiedad del código que llama.screen_xCoordenada X de pantalla en píxeles enteros; el resultado y la diferencia intermedia deben caber en
s16.
Valor devuelto
Devuelve la coordenada convertida en píxeles enteros como s16; no comprueba su visibilidad ni la recorta.
Condiciones y límites
Las coordenadas tienen ocho bits fraccionarios. Mantén las posiciones, los objetivos y las sumas o diferencias intermedias dentro de s16. Actualiza la pantalla por separado con Camera_ApplyBg o aplicando los valores pendientes del búfer.
Ejemplo de uso
result[19]=Camera_ScreenToWorldX(&cam,27);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo enseña seguimiento Q8.8, límites y conversión de coordenadas. El seguimiento produce X/Y=3584/4096 y los límites dan 3072/3584. BG X permanece en 13 mientras el cambio está pendiente y pasa a 8 al aplicar el búfer. La imagen adicional muestra cómo una cámara en (8,16) sitúa en pantalla (24,16) un rectángulo de 32×24 ubicado en el mundo en (32,32).


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kEjemplo de uso
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Con la cámara en (8,16), el rectángulo rojo de 32×24 aparece en pantalla en (24,16). La ventana muestra un marco azul de 64×64 en (96,80) y un cuadrado verde de 16×16 en (112,96). En DMG todas las figuras son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/camera.h:52
Convert integer-pixel screen X back to world X using the camera's integer component.
kitaqgb/lib/camera.c:146
s16 Camera_ScreenToWorldX(const Camera8_8* cam, s16 screen_x)
{
return (s16)(screen_x + (cam->fx >> 8));
}Camera_ScreenToWorldY
Suma la parte entera de Y de la cámara a la Y entera de pantalla para obtener la Y del mundo.
Sintaxis
s16 Camera_ScreenToWorldY(const Camera8_8* cam, s16 screen_y);Parámetros
camPuntero válido a un
Camera8_8inicializado y propiedad del código que llama.screen_yCoordenada Y de pantalla en píxeles enteros; el resultado y la diferencia intermedia deben caber en
s16.
Valor devuelto
Devuelve la coordenada convertida en píxeles enteros como s16; no comprueba su visibilidad ni la recorta.
Condiciones y límites
Las coordenadas tienen ocho bits fraccionarios. Mantén las posiciones, los objetivos y las sumas o diferencias intermedias dentro de s16. Actualiza la pantalla por separado con Camera_ApplyBg o aplicando los valores pendientes del búfer.
Ejemplo de uso
result[20]=Camera_ScreenToWorldY(&cam,24);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo enseña seguimiento Q8.8, límites y conversión de coordenadas. El seguimiento produce X/Y=3584/4096 y los límites dan 3072/3584. BG X permanece en 13 mientras el cambio está pendiente y pasa a 8 al aplicar el búfer. La imagen adicional muestra cómo una cámara en (8,16) sitúa en pantalla (24,16) un rectángulo de 32×24 ubicado en el mundo en (32,32).


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kEjemplo de uso
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Con la cámara en (8,16), el rectángulo rojo de 32×24 aparece en pantalla en (24,16). La ventana muestra un marco azul de 64×64 en (96,80) y un cuadrado verde de 16×16 en (112,96). En DMG todas las figuras son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/camera.h:54
Convert integer-pixel screen Y back to world Y using the camera's integer component.
kitaqgb/lib/camera.c:152
s16 Camera_ScreenToWorldY(const Camera8_8* cam, s16 screen_y)
{
return (s16)(screen_y + (cam->fy >> 8));
}Camera_Set
Sustituye la posición actual de la cámara y la ajusta inmediatamente a los límites que estén activados.
Sintaxis
void Camera_Set(Camera8_8* cam, s16 fx, s16 fy);Parámetros
camPuntero válido a un
Camera8_8inicializado y propiedad del código que llama.fxCoordenada X. Coordenada Q8.8 con signo: 256 equivale a un píxel; el rango va de −128 a 127+255/256 píxeles.
fyCoordenada Y. Coordenada Q8.8 con signo: 256 equivale a un píxel; el rango va de −128 a 127+255/256 píxeles.
Valor devuelto
No devuelve ningún valor. Esta entrada describe el estado afectado y cuándo surte efecto.
Condiciones y límites
Las coordenadas tienen ocho bits fraccionarios. Mantén las posiciones, los objetivos y las sumas o diferencias intermedias dentro de s16. Actualiza la pantalla por separado con Camera_ApplyBg o aplicando los valores pendientes del búfer.
Ejemplo de uso
Camera_Set(&cam,2560,5120);result[3]=cam.fx;result[4]=cam.fy;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo enseña seguimiento Q8.8, límites y conversión de coordenadas. El seguimiento produce X/Y=3584/4096 y los límites dan 3072/3584. BG X permanece en 13 mientras el cambio está pendiente y pasa a 8 al aplicar el búfer. La imagen adicional muestra cómo una cámara en (8,16) sitúa en pantalla (24,16) un rectángulo de 32×24 ubicado en el mundo en (32,32).


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kEjemplo de uso
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Con la cámara en (8,16), el rectángulo rojo de 32×24 aparece en pantalla en (24,16). La ventana muestra un marco azul de 64×64 en (96,80) y un cuadrado verde de 16×16 en (112,96). En DMG todas las figuras son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/camera.h:23
Replace the current Q8.8 position and immediately apply enabled bounds.
kitaqgb/lib/camera.c:39
void Camera_Set(Camera8_8* cam, s16 fx, s16 fy)
{
cam->fx = fx;
cam->fy = fy;
Camera_ApplyBounds(cam);
}camera_set
Mueve la cámara compartida con coordenadas de píxeles enteros y aplica sus límites activados.
Sintaxis
void camera_set(s16 x, s16 y);Parámetros
xCoordenada X del mundo en píxeles enteros; el resultado y la diferencia intermedia deben caber en
s16.yCoordenada Y del mundo en píxeles enteros; el resultado y la diferencia intermedia deben caber en
s16.
Valor devuelto
No devuelve ningún valor. Esta entrada describe el estado afectado y cuándo surte efecto.
Condiciones y límites
Las coordenadas tienen ocho bits fraccionarios. Mantén las posiciones, los objetivos y las sumas o diferencias intermedias dentro de s16. Actualiza la pantalla por separado con Camera_ApplyBg o aplicando los valores pendientes del búfer. Estas llamadas comparten una cámara; usa la API que empieza por mayúscula para objetos de cámara independientes. Las posiciones convertidas de píxeles enteros a Q8.8 deben estar entre −128 y 127.
Ejemplo de uso
camera_set(5,6);result[26]=camera_world_to_screen_x(20);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo enseña seguimiento Q8.8, límites y conversión de coordenadas. El seguimiento produce X/Y=3584/4096 y los límites dan 3072/3584. BG X permanece en 13 mientras el cambio está pendiente y pasa a 8 al aplicar el búfer. La imagen adicional muestra cómo una cámara en (8,16) sitúa en pantalla (24,16) un rectángulo de 32×24 ubicado en el mundo en (32,32).


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kEjemplo de uso
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Con la cámara en (8,16), el rectángulo rojo de 32×24 aparece en pantalla en (24,16). La ventana muestra un marco azul de 64×64 en (96,80) y un cuadrado verde de 16×16 en (112,96). En DMG todas las figuras son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/camera.h:57
Set the shared camera from integer pixels, converting to the representable Q8.8 range.
kitaqgb/lib/camera.c:158
void camera_set(s16 x, s16 y)
{
Camera_Set(&camera_default, (s16)(x << 8), (s16)(y << 8));
}Camera_SetBounds
Establece las coordenadas mínimas y máximas, activa los límites y ajusta de inmediato la posición actual.
Sintaxis
void Camera_SetBounds(Camera8_8* cam, s16 min_fx, s16 min_fy, s16 max_fx, s16 max_fy);Parámetros
camPuntero válido a un
Camera8_8inicializado y propiedad del código que llama.min_fxCoordenada X mínima. Coordenada Q8.8 con signo: 256 equivale a un píxel; el rango va de −128 a 127+255/256 píxeles.
min_fyCoordenada Y mínima. Coordenada Q8.8 con signo: 256 equivale a un píxel; el rango va de −128 a 127+255/256 píxeles.
max_fxCoordenada X máxima. Coordenada Q8.8 con signo: 256 equivale a un píxel; el rango va de −128 a 127+255/256 píxeles.
max_fyCoordenada Y máxima. Coordenada Q8.8 con signo: 256 equivale a un píxel; el rango va de −128 a 127+255/256 píxeles.
Valor devuelto
No devuelve ningún valor. Esta entrada describe el estado afectado y cuándo surte efecto.
Condiciones y límites
Proporciona un mínimo ≤ máximo en cada eje; los límites no se reordenan. El objetivo guardado no se ajusta a ellos.
Ejemplo de uso
Camera_SetBounds(&cam,0,0,3072,3584);result[10]=cam.fx;result[11]=cam.fy;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo enseña seguimiento Q8.8, límites y conversión de coordenadas. El seguimiento produce X/Y=3584/4096 y los límites dan 3072/3584. BG X permanece en 13 mientras el cambio está pendiente y pasa a 8 al aplicar el búfer. La imagen adicional muestra cómo una cámara en (8,16) sitúa en pantalla (24,16) un rectángulo de 32×24 ubicado en el mundo en (32,32).


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kEjemplo de uso
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Con la cámara en (8,16), el rectángulo rojo de 32×24 aparece en pantalla en (24,16). La ventana muestra un marco azul de 64×64 en (96,80) y un cuadrado verde de 16×16 en (112,96). En DMG todas las figuras son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/camera.h:29
Install ordered Q8.8 bounds, enable them and clamp the current position immediately.
kitaqgb/lib/camera.c:61
void Camera_SetBounds(Camera8_8* cam, s16 min_fx, s16 min_fy, s16 max_fx, s16 max_fy)
{
cam->min_fx = min_fx;
cam->min_fy = min_fy;
cam->max_fx = max_fx;
cam->max_fy = max_fy;
cam->use_bounds = 1;
Camera_ApplyBounds(cam);
}Camera_SetTarget
Guarda un objetivo y activa el seguimiento sin mover la posición actual.
Sintaxis
void Camera_SetTarget(Camera8_8* cam, s16 fx, s16 fy);Parámetros
camPuntero válido a un
Camera8_8inicializado y propiedad del código que llama.fxCoordenada X. Coordenada Q8.8 con signo: 256 equivale a un píxel; el rango va de −128 a 127+255/256 píxeles.
fyCoordenada Y. Coordenada Q8.8 con signo: 256 equivale a un píxel; el rango va de −128 a 127+255/256 píxeles.
Valor devuelto
No devuelve ningún valor. Esta entrada describe el estado afectado y cuándo surte efecto.
Condiciones y límites
Las coordenadas tienen ocho bits fraccionarios. Mantén las posiciones, los objetivos y las sumas o diferencias intermedias dentro de s16. Actualiza la pantalla por separado con Camera_ApplyBg o aplicando los valores pendientes del búfer.
Ejemplo de uso
Camera_SetTarget(&cam,4608,3072);result[5]=cam.use_target;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo enseña seguimiento Q8.8, límites y conversión de coordenadas. El seguimiento produce X/Y=3584/4096 y los límites dan 3072/3584. BG X permanece en 13 mientras el cambio está pendiente y pasa a 8 al aplicar el búfer. La imagen adicional muestra cómo una cámara en (8,16) sitúa en pantalla (24,16) un rectángulo de 32×24 ubicado en el mundo en (32,32).


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kEjemplo de uso
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Con la cámara en (8,16), el rectángulo rojo de 32×24 aparece en pantalla en (24,16). La ventana muestra un marco azul de 64×64 en (96,80) y un cuadrado verde de 16×16 en (112,96). En DMG todas las figuras son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/camera.h:25
Store a Q8.8 target and enable subsequent step-toward-target updates.
kitaqgb/lib/camera.c:47
void Camera_SetTarget(Camera8_8* cam, s16 fx, s16 fy)
{
cam->target_fx = fx;
cam->target_fy = fy;
cam->use_target = 1;
}Camera_StepTowardTarget
Se acerca al objetivo una fracción de la distancia restante, calculada mediante un desplazamiento a la derecha; no hace nada si el seguimiento está desactivado.
Sintaxis
void Camera_StepTowardTarget(Camera8_8* cam, u8 shift);Parámetros
camPuntero válido a un
Camera8_8inicializado y propiedad del código que llama.shiftExponente de la potencia de dos que divide la diferencia: 0 usa toda la diferencia y 1 usa la mitad. Los valores superiores a 7 se limitan a 7.
Valor devuelto
No devuelve ningún valor. Esta entrada describe el estado afectado y cuándo surte efecto.
Condiciones y límites
Una diferencia positiva pequeña puede truncarse a cero; un desplazamiento aritmético a la derecha puede convertir una diferencia negativa pequeña en −1. La igualdad con el objetivo se comprueba antes de aplicar los límites. Por ello, un objetivo fuera de rango puede mantener activo el seguimiento o desactivarlo aunque la posición final limitada sea distinta del objetivo.
Ejemplo de uso
Camera_StepTowardTarget(&cam,1);result[6]=cam.fx;result[7]=cam.fy;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo enseña seguimiento Q8.8, límites y conversión de coordenadas. El seguimiento produce X/Y=3584/4096 y los límites dan 3072/3584. BG X permanece en 13 mientras el cambio está pendiente y pasa a 8 al aplicar el búfer. La imagen adicional muestra cómo una cámara en (8,16) sitúa en pantalla (24,16) un rectángulo de 32×24 ubicado en el mundo en (32,32).


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kEjemplo de uso
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Con la cámara en (8,16), el rectángulo rojo de 32×24 aparece en pantalla en (24,16). La ventana muestra un marco azul de 64×64 en (96,80) y un cuadrado verde de 16×16 en (112,96). En DMG todas las figuras son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/camera.h:38
Move by the signed target delta shifted by 0..7 bits, then apply bounds. Quantization can make a small delta produce no movement; only exact equality clears targeting, and a target outside the bounds may remain active indefinitely.
kitaqgb/lib/camera.c:89
void Camera_StepTowardTarget(Camera8_8* cam, u8 shift)
{
s16 dx;
s16 dy;
if (cam->use_target == 0) return;
if (shift > 7) shift = 7;
// Keep target-minus-position differences within s16 as well as the individual positions.
dx = cam->target_fx - cam->fx;
dy = cam->target_fy - cam->fy;
if (dx != 0) cam->fx += (dx >> shift);
if (dy != 0) cam->fy += (dy >> shift);
if (cam->fx == cam->target_fx && cam->fy == cam->target_fy) cam->use_target = 0;
Camera_ApplyBounds(cam);
}camera_world_to_screen_x
Convierte la X del mundo en X de pantalla restando la parte entera de X de la cámara compartida.
Sintaxis
s16 camera_world_to_screen_x(s16 world_x);Parámetros
world_xCoordenada X del mundo en píxeles enteros; el resultado y la diferencia intermedia deben caber en
s16.
Valor devuelto
Devuelve la coordenada convertida en píxeles enteros como s16; no comprueba su visibilidad ni la recorta.
Condiciones y límites
Las coordenadas tienen ocho bits fraccionarios. Mantén las posiciones, los objetivos y las sumas o diferencias intermedias dentro de s16. Actualiza la pantalla por separado con Camera_ApplyBg o aplicando los valores pendientes del búfer. Estas llamadas comparten una cámara; usa la API que empieza por mayúscula para objetos de cámara independientes. Las posiciones convertidas de píxeles enteros a Q8.8 deben estar entre −128 y 127.
Ejemplo de uso
result[33]=camera_world_to_screen_x(20);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo enseña seguimiento Q8.8, límites y conversión de coordenadas. El seguimiento produce X/Y=3584/4096 y los límites dan 3072/3584. BG X permanece en 13 mientras el cambio está pendiente y pasa a 8 al aplicar el búfer. La imagen adicional muestra cómo una cámara en (8,16) sitúa en pantalla (24,16) un rectángulo de 32×24 ubicado en el mundo en (32,32).


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kEjemplo de uso
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Con la cámara en (8,16), el rectángulo rojo de 32×24 aparece en pantalla en (24,16). La ventana muestra un marco azul de 64×64 en (96,80) y un cuadrado verde de 16×16 en (112,96). En DMG todas las figuras son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/camera.h:66
Convert integer-pixel world X using the shared convenience camera.
kitaqgb/lib/camera.c:185
s16 camera_world_to_screen_x(s16 world_x)
{
return Camera_WorldToScreenX(&camera_default, world_x);
}camera_world_to_screen_y
Convierte la Y del mundo en Y de pantalla restando la parte entera de Y de la cámara compartida.
Sintaxis
s16 camera_world_to_screen_y(s16 world_y);Parámetros
world_yCoordenada Y del mundo en píxeles enteros; el resultado y la diferencia intermedia deben caber en
s16.
Valor devuelto
Devuelve la coordenada convertida en píxeles enteros como s16; no comprueba su visibilidad ni la recorta.
Condiciones y límites
Las coordenadas tienen ocho bits fraccionarios. Mantén las posiciones, los objetivos y las sumas o diferencias intermedias dentro de s16. Actualiza la pantalla por separado con Camera_ApplyBg o aplicando los valores pendientes del búfer. Estas llamadas comparten una cámara; usa la API que empieza por mayúscula para objetos de cámara independientes. Las posiciones convertidas de píxeles enteros a Q8.8 deben estar entre −128 y 127.
Ejemplo de uso
result[34]=camera_world_to_screen_y(20);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo enseña seguimiento Q8.8, límites y conversión de coordenadas. El seguimiento produce X/Y=3584/4096 y los límites dan 3072/3584. BG X permanece en 13 mientras el cambio está pendiente y pasa a 8 al aplicar el búfer. La imagen adicional muestra cómo una cámara en (8,16) sitúa en pantalla (24,16) un rectángulo de 32×24 ubicado en el mundo en (32,32).


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kEjemplo de uso
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Con la cámara en (8,16), el rectángulo rojo de 32×24 aparece en pantalla en (24,16). La ventana muestra un marco azul de 64×64 en (96,80) y un cuadrado verde de 16×16 en (112,96). En DMG todas las figuras son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/camera.h:68
Convert integer-pixel world Y using the shared convenience camera.
kitaqgb/lib/camera.c:191
s16 camera_world_to_screen_y(s16 world_y)
{
return Camera_WorldToScreenY(&camera_default, world_y);
}Camera_WorldToScreenX
Resta la parte entera de X de la cámara a una coordenada X entera del mundo para obtener la X en pantalla.
Sintaxis
s16 Camera_WorldToScreenX(const Camera8_8* cam, s16 world_x);Parámetros
camPuntero válido a un
Camera8_8inicializado y propiedad del código que llama.world_xCoordenada X del mundo en píxeles enteros; el resultado y la diferencia intermedia deben caber en
s16.
Valor devuelto
Devuelve la coordenada convertida en píxeles enteros como s16; no comprueba su visibilidad ni la recorta.
Condiciones y límites
Las coordenadas tienen ocho bits fraccionarios. Mantén las posiciones, los objetivos y las sumas o diferencias intermedias dentro de s16. Actualiza la pantalla por separado con Camera_ApplyBg o aplicando los valores pendientes del búfer.
Ejemplo de uso
result[17]=Camera_WorldToScreenX(&cam,40);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo enseña seguimiento Q8.8, límites y conversión de coordenadas. El seguimiento produce X/Y=3584/4096 y los límites dan 3072/3584. BG X permanece en 13 mientras el cambio está pendiente y pasa a 8 al aplicar el búfer. La imagen adicional muestra cómo una cámara en (8,16) sitúa en pantalla (24,16) un rectángulo de 32×24 ubicado en el mundo en (32,32).


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kEjemplo de uso
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Con la cámara en (8,16), el rectángulo rojo de 32×24 aparece en pantalla en (24,16). La ventana muestra un marco azul de 64×64 en (96,80) y un cuadrado verde de 16×16 en (112,96). En DMG todas las figuras son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/camera.h:48
Convert an integer-pixel world X by subtracting the camera's integer X component.
kitaqgb/lib/camera.c:134
s16 Camera_WorldToScreenX(const Camera8_8* cam, s16 world_x)
{
return (s16)(world_x - (cam->fx >> 8));
}Camera_WorldToScreenY
Resta la parte entera de Y de la cámara a una coordenada Y entera del mundo para obtener la Y en pantalla.
Sintaxis
s16 Camera_WorldToScreenY(const Camera8_8* cam, s16 world_y);Parámetros
camPuntero válido a un
Camera8_8inicializado y propiedad del código que llama.world_yCoordenada Y del mundo en píxeles enteros; el resultado y la diferencia intermedia deben caber en
s16.
Valor devuelto
Devuelve la coordenada convertida en píxeles enteros como s16; no comprueba su visibilidad ni la recorta.
Condiciones y límites
Las coordenadas tienen ocho bits fraccionarios. Mantén las posiciones, los objetivos y las sumas o diferencias intermedias dentro de s16. Actualiza la pantalla por separado con Camera_ApplyBg o aplicando los valores pendientes del búfer.
Ejemplo de uso
result[18]=Camera_WorldToScreenY(&cam,40);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo enseña seguimiento Q8.8, límites y conversión de coordenadas. El seguimiento produce X/Y=3584/4096 y los límites dan 3072/3584. BG X permanece en 13 mientras el cambio está pendiente y pasa a 8 al aplicar el búfer. La imagen adicional muestra cómo una cámara en (8,16) sitúa en pantalla (24,16) un rectángulo de 32×24 ubicado en el mundo en (32,32).


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kEjemplo de uso
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Con la cámara en (8,16), el rectángulo rojo de 32×24 aparece en pantalla en (24,16). La ventana muestra un marco azul de 64×64 en (96,80) y un cuadrado verde de 16×16 en (112,96). En DMG todas las figuras son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/camera.h:50
Convert an integer-pixel world Y by subtracting the camera's integer Y component.
kitaqgb/lib/camera.c:140
s16 Camera_WorldToScreenY(const Camera8_8* cam, s16 world_y)
{
return (s16)(world_y - (cam->fy >> 8));
}cgb_palette.h — Paletas de fondo y OBJ de CGB
cgb_palette.h y cgb_palette.c ofrecen empaquetado RGB15 y actualización inmediata de paletas CGB. Usa BG para fondo/ventana y OBJ para sprites. Las funciones de color único o componentes cambian un color; las de rango escriben palabras consecutivas; las de paleta completa escriben cuatro. Los rangos raw usan posiciones absolutas de color, y los intrínsecos de registro, posiciones de byte. Asigna la paleta mediante atributos del mapa u OAM. Incluye la implementación una sola vez, como en el ejemplo completo.
Las escrituras de paleta y de registros protegidos no escriben nada en modo DMG. Safe indica una comprobación de modo CGB, no una espera de acceso a PPU ni una sección crítica. Configura con LCD apagado o realiza una actualización breve durante una fase accesible. No espera VBlank ni protege una escritura de varios bytes frente a interrupciones.
Las paletas BG/ventana y OBJ son almacenes separados. Las escrituras de la biblioteca activan el incremento y dejan modificado el registro de índice. El color OBJ cero es transparente al dibujar sprites, aunque sus bytes se puedan guardar y leer.
cgb_bg_color
Consulte los cambios y la verificación del 2026-10-03 para las diferencias locales de esta API.
Escribe inmediatamente un color RGB15 empaquetado en las paletas de fondo/ventana. Los índices de paleta y color eligen una de las 32 posiciones de color; no modifica los patrones ni la paleta asignada a una casilla.
Sintaxis
void cgb_bg_color(u8 palette_index, u8 color_index, u16 rgb15);Parámetros
palette_indexNúmero de paleta, 0–7; solo usa los tres bits bajos (
& 7).color_indexÍndice de color dentro de la paleta, 0–3; solo usa los dos bits bajos (
& 3).rgb15Color RGB de 15 bits empaquetado, normalmente 0–32767. Se escriben ambos bytes del
u16, primero el bajo; la biblioteca no borra explícitamente el bit 15. UsaCGB_RGB15ocgb_rgb15para construirlo.
Valor devuelto
Ninguno (void).
Condiciones y límites
Las escrituras de paleta y de registros protegidos no escriben nada en modo DMG. Safe indica una comprobación de modo CGB, no una espera de acceso a PPU ni una sección crítica. Configura con LCD apagado o realiza una actualización breve durante una fase accesible. No espera VBlank ni protege una escritura de varios bytes frente a interrupciones.
Las paletas BG/ventana y OBJ son almacenes separados. Las escrituras de la biblioteca activan el incremento y dejan modificado el registro de índice. El color OBJ cero es transparente al dibujar sprites, aunque sus bytes se puedan guardar y leer.
Ejemplo de uso
cgb_bg_color(1,3,31); // Red background color 3 of palette 1.
expect_color(0,7,31);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El programa muestra cómo las paletas BG y OBJ colorean de forma independiente el mismo patrón. Cada triángulo ocupa 8 × 8 píxeles: comienza con un píxel a la izquierda arriba y termina con una fila completa abajo. En x = 16, 32, 48, 64, 80, 96, 112, la fila BG de y = 24 es roja, azul, verde, roja, azul, verde, roja; la OBJ de y = 64 es azul, verde, roja, azul, verde, roja, azul. Las columnas usan, respectivamente, color único, componentes, rango indexado, paleta completa, rango absoluto, registro canónico y alias de registro.
En y = 88 hay siete casillas de 8 × 8: triángulo rojo (x = 16), contorno cuadrado azul de un píxel del banco 1 (32), triángulo verde reflejado horizontalmente (48), rojo reflejado verticalmente (64), azul reflejado en ambos ejes (80), triángulo verde sobre un sprite rojo visible a través del color cero (96), y sprite rojo sólido delante del triángulo BG como control sin prioridad (112). Las coordenadas son píxeles desde la esquina superior izquierda. Fondo blanco y texto negro.
FAILED CHECKS 000 confirma máscaras RGB, booleanos (incluido 2), índices de paleta normalizados, cruce de paletas, límite en posición 31, punteros nulos y longitud cero sin escrituras, y lectura de colores con LCD apagado. Se prueban cuatro combinaciones: ROM dual en DMG/CGB, ROM solo DMG en DMG y solo CGB en CGB. En DMG, CGB MODE vale 0, los triángulos son negros, banco/reflejos no afectan a la imagen y las dos últimas casillas inferiores son cuadrados negros. En CGB, CGB MODE vale 1. No se prueban hardware real ni conflictos de paleta con LCD encendido.




Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/cgb_palette.h:22
Set one background color through the indexed palette wrapper.
kitaqgb/lib/cgb_palette.c:110
void cgb_bg_color(u8 palette_index, u8 color_index, u16 rgb15)
{
cgb__write_color_bg_raw(cgb__palette_color_slot(palette_index, color_index), rgb15);
}cgb_bg_colors
Escribe palabras RGB15 consecutivas en las paletas de fondo/ventana, a partir de la pareja de índices indicada. Puede atravesar el límite de una paleta de cuatro colores; se detiene al final de las 32 posiciones.
Sintaxis
void cgb_bg_colors(u8 palette_index, u8 start_color_index, const u16* colors, u8 color_count);Parámetros
palette_indexNúmero de paleta, 0–7; solo usa los tres bits bajos (
& 7).start_color_indexÍndice de color dentro de la paleta, 0–3; solo usa los dos bits bajos (
& 3).colorsconst u16*legible con las palabras de color necesarias. Los datos se consumen durante la llamada, sin encolarlos. Mantén accesibles la fuente y su banco ROM; no se cambia de banco automáticamente. Un puntero nulo no produce escrituras.color_countCantidad de palabras de color, no de bytes, como
u8(0–255). Cero no hace nada. Se limita a32 - posición_inicial_normalizada; solo se leen esas palabras de la fuente.
Valor devuelto
Ninguno (void).
Condiciones y límites
Las escrituras de paleta y de registros protegidos no escriben nada en modo DMG. Safe indica una comprobación de modo CGB, no una espera de acceso a PPU ni una sección crítica. Configura con LCD apagado o realiza una actualización breve durante una fase accesible. No espera VBlank ni protege una escritura de varios bytes frente a interrupciones.
Las paletas BG/ventana y OBJ son almacenes separados. Las escrituras de la biblioteca activan el incremento y dejan modificado el registro de índice. El color OBJ cero es transparente al dibujar sprites, aunque sus bytes se puedan guardar y leer.
Ejemplo de uso
cgb_bg_colors(3,2,tail_green,2); // Two color words; color 3 becomes green.
expect_color(0,14,0); expect_color(0,15,992);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El programa muestra cómo las paletas BG y OBJ colorean de forma independiente el mismo patrón. Cada triángulo ocupa 8 × 8 píxeles: comienza con un píxel a la izquierda arriba y termina con una fila completa abajo. En x = 16, 32, 48, 64, 80, 96, 112, la fila BG de y = 24 es roja, azul, verde, roja, azul, verde, roja; la OBJ de y = 64 es azul, verde, roja, azul, verde, roja, azul. Las columnas usan, respectivamente, color único, componentes, rango indexado, paleta completa, rango absoluto, registro canónico y alias de registro.
En y = 88 hay siete casillas de 8 × 8: triángulo rojo (x = 16), contorno cuadrado azul de un píxel del banco 1 (32), triángulo verde reflejado horizontalmente (48), rojo reflejado verticalmente (64), azul reflejado en ambos ejes (80), triángulo verde sobre un sprite rojo visible a través del color cero (96), y sprite rojo sólido delante del triángulo BG como control sin prioridad (112). Las coordenadas son píxeles desde la esquina superior izquierda. Fondo blanco y texto negro.
FAILED CHECKS 000 confirma máscaras RGB, booleanos (incluido 2), índices de paleta normalizados, cruce de paletas, límite en posición 31, punteros nulos y longitud cero sin escrituras, y lectura de colores con LCD apagado. Se prueban cuatro combinaciones: ROM dual en DMG/CGB, ROM solo DMG en DMG y solo CGB en CGB. En DMG, CGB MODE vale 0, los triángulos son negros, banco/reflejos no afectan a la imagen y las dos últimas casillas inferiores son cuadrados negros. En CGB, CGB MODE vale 1. No se prueban hardware real ni conflictos de paleta con LCD encendido.




Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/cgb_palette.h:32
Write background colors starting at the indexed slot. The range may cross palette boundaries and is clamped only at the end of all 32 slots.
kitaqgb/lib/cgb_palette.c:135
void cgb_bg_colors(u8 palette_index, u8 start_color_index, const u16* colors, u8 color_count)
{
cgb__write_colors_bg_raw(cgb__palette_color_slot(palette_index, start_color_index), colors, color_count);
}cgb_bg_colors_raw
Escribe palabras RGB15 consecutivas en las paletas de fondo/ventana usando una posición absoluta de color. El inicio es un único índice de 0 a 31, no una pareja paleta/color. Los datos son palabras de color, no bytes de patrones.
Sintaxis
void cgb_bg_colors_raw(u8 start_color_slot, const u16* colors, u8 color_count);Parámetros
start_color_slotPosición absoluta de color, 0–31; se normaliza con
& 31antes de limitar la longitud. Posición = paleta × 4 + color. No es un desplazamiento en bytes.colorsconst u16*legible con las palabras de color necesarias. Los datos se consumen durante la llamada, sin encolarlos. Mantén accesibles la fuente y su banco ROM; no se cambia de banco automáticamente. Un puntero nulo no produce escrituras.color_countCantidad de palabras de color, no de bytes, como
u8(0–255). Cero no hace nada. Se limita a32 - posición_inicial_normalizada; solo se leen esas palabras de la fuente.
Valor devuelto
Ninguno (void).
Condiciones y límites
Las escrituras de paleta y de registros protegidos no escriben nada en modo DMG. Safe indica una comprobación de modo CGB, no una espera de acceso a PPU ni una sección crítica. Configura con LCD apagado o realiza una actualización breve durante una fase accesible. No espera VBlank ni protege una escritura de varios bytes frente a interrupciones.
Las paletas BG/ventana y OBJ son almacenes separados. Las escrituras de la biblioteca activan el incremento y dejan modificado el registro de índice. El color OBJ cero es transparente al dibujar sprites, aunque sus bytes se puedan guardar y leer.
Ejemplo de uso
cgb_bg_colors_raw(23,blue_word,1); // Absolute slot 23 = palette 5, color 3.
expect_color(0,23,31744);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El programa muestra cómo las paletas BG y OBJ colorean de forma independiente el mismo patrón. Cada triángulo ocupa 8 × 8 píxeles: comienza con un píxel a la izquierda arriba y termina con una fila completa abajo. En x = 16, 32, 48, 64, 80, 96, 112, la fila BG de y = 24 es roja, azul, verde, roja, azul, verde, roja; la OBJ de y = 64 es azul, verde, roja, azul, verde, roja, azul. Las columnas usan, respectivamente, color único, componentes, rango indexado, paleta completa, rango absoluto, registro canónico y alias de registro.
En y = 88 hay siete casillas de 8 × 8: triángulo rojo (x = 16), contorno cuadrado azul de un píxel del banco 1 (32), triángulo verde reflejado horizontalmente (48), rojo reflejado verticalmente (64), azul reflejado en ambos ejes (80), triángulo verde sobre un sprite rojo visible a través del color cero (96), y sprite rojo sólido delante del triángulo BG como control sin prioridad (112). Las coordenadas son píxeles desde la esquina superior izquierda. Fondo blanco y texto negro.
FAILED CHECKS 000 confirma máscaras RGB, booleanos (incluido 2), índices de paleta normalizados, cruce de paletas, límite en posición 31, punteros nulos y longitud cero sin escrituras, y lectura de colores con LCD apagado. Se prueban cuatro combinaciones: ROM dual en DMG/CGB, ROM solo DMG en DMG y solo CGB en CGB. En DMG, CGB MODE vale 0, los triángulos son negros, banco/reflejos no afectan a la imagen y las dos últimas casillas inferiores son cuadrados negros. En CGB, CGB MODE vale 1. No se prueban hardware real ni conflictos de paleta con LCD encendido.




Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/cgb_palette.h:42
Expose sequential background writes using an absolute color-slot index.
kitaqgb/lib/cgb_palette.c:159
void cgb_bg_colors_raw(u8 start_color_slot, const u16* colors, u8 color_count)
{
cgb__write_colors_bg_raw(start_color_slot, colors, color_count);
}cgb_bg_palette
Sustituye los cuatro colores de una paleta de fondo/ventana con cuatro palabras RGB15. Equivale a escribir un rango desde el color cero con cantidad cuatro; no asigna la paleta a casillas ni sprites.
Sintaxis
void cgb_bg_palette(u8 palette_index, const u16* colors);Parámetros
palette_indexNúmero de paleta, 0–7; solo usa los tres bits bajos (
& 7).colorsconst u16*legible con las palabras de color necesarias. Los datos se consumen durante la llamada, sin encolarlos. Mantén accesibles la fuente y su banco ROM; no se cambia de banco automáticamente. Un puntero nulo no produce escrituras.
Valor devuelto
Ninguno (void).
Condiciones y límites
Las escrituras de paleta y de registros protegidos no escriben nada en modo DMG. Safe indica una comprobación de modo CGB, no una espera de acceso a PPU ni una sección crítica. Configura con LCD apagado o realiza una actualización breve durante una fase accesible. No espera VBlank ni protege una escritura de varios bytes frente a interrupciones.
Las paletas BG/ventana y OBJ son almacenes separados. Las escrituras de la biblioteca activan el incremento y dejan modificado el registro de índice. El color OBJ cero es transparente al dibujar sprites, aunque sus bytes se puedan guardar y leer.
Ejemplo de uso
cgb_bg_palette(4,red_palette); // Exactly four color words for BG palette 4.
expect_color(0,16,32767); expect_color(0,19,31);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El programa muestra cómo las paletas BG y OBJ colorean de forma independiente el mismo patrón. Cada triángulo ocupa 8 × 8 píxeles: comienza con un píxel a la izquierda arriba y termina con una fila completa abajo. En x = 16, 32, 48, 64, 80, 96, 112, la fila BG de y = 24 es roja, azul, verde, roja, azul, verde, roja; la OBJ de y = 64 es azul, verde, roja, azul, verde, roja, azul. Las columnas usan, respectivamente, color único, componentes, rango indexado, paleta completa, rango absoluto, registro canónico y alias de registro.
En y = 88 hay siete casillas de 8 × 8: triángulo rojo (x = 16), contorno cuadrado azul de un píxel del banco 1 (32), triángulo verde reflejado horizontalmente (48), rojo reflejado verticalmente (64), azul reflejado en ambos ejes (80), triángulo verde sobre un sprite rojo visible a través del color cero (96), y sprite rojo sólido delante del triángulo BG como control sin prioridad (112). Las coordenadas son píxeles desde la esquina superior izquierda. Fondo blanco y texto negro.
FAILED CHECKS 000 confirma máscaras RGB, booleanos (incluido 2), índices de paleta normalizados, cruce de paletas, límite en posición 31, punteros nulos y longitud cero sin escrituras, y lectura de colores con LCD apagado. Se prueban cuatro combinaciones: ROM dual en DMG/CGB, ROM solo DMG en DMG y solo CGB en CGB. En DMG, CGB MODE vale 0, los triángulos son negros, banco/reflejos no afectan a la imagen y las dos últimas casillas inferiores son cuadrados negros. En CGB, CGB MODE vale 1. No se prueban hardware real ni conflictos de paleta con LCD encendido.




Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/cgb_palette.h:37
Write four consecutive colors for one background palette.
kitaqgb/lib/cgb_palette.c:147
void cgb_bg_palette(u8 palette_index, const u16* colors)
{
cgb_bg_colors(palette_index, 0, colors, 4);
}cgb_bg_rgb
Consulte los cambios y la verificación del 2026-10-03 para las diferencias locales de esta API.
Empaqueta los componentes rojo, verde y azul con cgb_rgb15 y escribe un color en las paletas de fondo/ventana. Úsalo para proporcionar los componentes por separado en lugar de una palabra empaquetada.
Sintaxis
void cgb_bg_rgb(u8 palette_index, u8 color_index, u8 r5, u8 g5, u8 b5);Parámetros
palette_indexNúmero de paleta, 0–7; solo usa los tres bits bajos (
& 7).color_indexÍndice de color dentro de la paleta, 0–3; solo usa los dos bits bajos (
& 3).r5, g5, b5Componentes rojo, verde y azul respectivamente, normalmente 0–31 cada uno. Se enmascaran sin saturación; cada argumento aparece una sola vez en la expansión de la macro.
Valor devuelto
Ninguno (void).
Condiciones y límites
Las escrituras de paleta y de registros protegidos no escriben nada en modo DMG. Safe indica una comprobación de modo CGB, no una espera de acceso a PPU ni una sección crítica. Configura con LCD apagado o realiza una actualización breve durante una fase accesible. No espera VBlank ni protege una escritura de varios bytes frente a interrupciones.
Las paletas BG/ventana y OBJ son almacenes separados. Las escrituras de la biblioteca activan el incremento y dejan modificado el registro de índice. El color OBJ cero es transparente al dibujar sprites, aunque sus bytes se puedan guardar y leer.
Ejemplo de uso
cgb_bg_rgb(2,3,0,0,31); // Blue, supplied as three five-bit components.
expect_color(0,11,31744);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El programa muestra cómo las paletas BG y OBJ colorean de forma independiente el mismo patrón. Cada triángulo ocupa 8 × 8 píxeles: comienza con un píxel a la izquierda arriba y termina con una fila completa abajo. En x = 16, 32, 48, 64, 80, 96, 112, la fila BG de y = 24 es roja, azul, verde, roja, azul, verde, roja; la OBJ de y = 64 es azul, verde, roja, azul, verde, roja, azul. Las columnas usan, respectivamente, color único, componentes, rango indexado, paleta completa, rango absoluto, registro canónico y alias de registro.
En y = 88 hay siete casillas de 8 × 8: triángulo rojo (x = 16), contorno cuadrado azul de un píxel del banco 1 (32), triángulo verde reflejado horizontalmente (48), rojo reflejado verticalmente (64), azul reflejado en ambos ejes (80), triángulo verde sobre un sprite rojo visible a través del color cero (96), y sprite rojo sólido delante del triángulo BG como control sin prioridad (112). Las coordenadas son píxeles desde la esquina superior izquierda. Fondo blanco y texto negro.
FAILED CHECKS 000 confirma máscaras RGB, booleanos (incluido 2), índices de paleta normalizados, cruce de paletas, límite en posición 31, punteros nulos y longitud cero sin escrituras, y lectura de colores con LCD apagado. Se prueban cuatro combinaciones: ROM dual en DMG/CGB, ROM solo DMG en DMG y solo CGB en CGB. En DMG, CGB MODE vale 0, los triángulos son negros, banco/reflejos no afectan a la imagen y las dos últimas casillas inferiores son cuadrados negros. En CGB, CGB MODE vale 1. No se prueban hardware real ni conflictos de paleta con LCD encendido.




Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/cgb_palette.h:26
Pack component values and write one background color.
kitaqgb/lib/cgb_palette.c:122
void cgb_bg_rgb(u8 palette_index, u8 color_index, u8 r5, u8 g5, u8 b5)
{
cgb_bg_color(palette_index, color_index, cgb_rgb15(r5, g5, b5));
}cgb_obj_color
Consulte los cambios y la verificación del 2026-10-03 para las diferencias locales de esta API.
Escribe inmediatamente un color RGB15 empaquetado en las paletas de sprites (OBJ). Los índices de paleta y color eligen una de las 32 posiciones de color; no modifica los patrones ni la paleta asignada a una casilla.
Sintaxis
void cgb_obj_color(u8 palette_index, u8 color_index, u16 rgb15);Parámetros
palette_indexNúmero de paleta, 0–7; solo usa los tres bits bajos (
& 7).color_indexÍndice de color dentro de la paleta, 0–3; solo usa los dos bits bajos (
& 3).rgb15Color RGB de 15 bits empaquetado, normalmente 0–32767. Se escriben ambos bytes del
u16, primero el bajo; la biblioteca no borra explícitamente el bit 15. UsaCGB_RGB15ocgb_rgb15para construirlo.
Valor devuelto
Ninguno (void).
Condiciones y límites
Las escrituras de paleta y de registros protegidos no escriben nada en modo DMG. Safe indica una comprobación de modo CGB, no una espera de acceso a PPU ni una sección crítica. Configura con LCD apagado o realiza una actualización breve durante una fase accesible. No espera VBlank ni protege una escritura de varios bytes frente a interrupciones.
Las paletas BG/ventana y OBJ son almacenes separados. Las escrituras de la biblioteca activan el incremento y dejan modificado el registro de índice. El color OBJ cero es transparente al dibujar sprites, aunque sus bytes se puedan guardar y leer.
Ejemplo de uso
cgb_obj_color(1,3,31744); // Blue sprite color at the same palette/color indices.
expect_color(1,7,31744);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El programa muestra cómo las paletas BG y OBJ colorean de forma independiente el mismo patrón. Cada triángulo ocupa 8 × 8 píxeles: comienza con un píxel a la izquierda arriba y termina con una fila completa abajo. En x = 16, 32, 48, 64, 80, 96, 112, la fila BG de y = 24 es roja, azul, verde, roja, azul, verde, roja; la OBJ de y = 64 es azul, verde, roja, azul, verde, roja, azul. Las columnas usan, respectivamente, color único, componentes, rango indexado, paleta completa, rango absoluto, registro canónico y alias de registro.
En y = 88 hay siete casillas de 8 × 8: triángulo rojo (x = 16), contorno cuadrado azul de un píxel del banco 1 (32), triángulo verde reflejado horizontalmente (48), rojo reflejado verticalmente (64), azul reflejado en ambos ejes (80), triángulo verde sobre un sprite rojo visible a través del color cero (96), y sprite rojo sólido delante del triángulo BG como control sin prioridad (112). Las coordenadas son píxeles desde la esquina superior izquierda. Fondo blanco y texto negro.
FAILED CHECKS 000 confirma máscaras RGB, booleanos (incluido 2), índices de paleta normalizados, cruce de paletas, límite en posición 31, punteros nulos y longitud cero sin escrituras, y lectura de colores con LCD apagado. Se prueban cuatro combinaciones: ROM dual en DMG/CGB, ROM solo DMG en DMG y solo CGB en CGB. En DMG, CGB MODE vale 0, los triángulos son negros, banco/reflejos no afectan a la imagen y las dos últimas casillas inferiores son cuadrados negros. En CGB, CGB MODE vale 1. No se prueban hardware real ni conflictos de paleta con LCD encendido.




Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/cgb_palette.h:24
Set one object color through the indexed palette wrapper.
kitaqgb/lib/cgb_palette.c:116
void cgb_obj_color(u8 palette_index, u8 color_index, u16 rgb15)
{
cgb__write_color_obj_raw(cgb__palette_color_slot(palette_index, color_index), rgb15);
}cgb_obj_colors
Escribe palabras RGB15 consecutivas en las paletas de sprites (OBJ), a partir de la pareja de índices indicada. Puede atravesar el límite de una paleta de cuatro colores; se detiene al final de las 32 posiciones.
Sintaxis
void cgb_obj_colors(u8 palette_index, u8 start_color_index, const u16* colors, u8 color_count);Parámetros
palette_indexNúmero de paleta, 0–7; solo usa los tres bits bajos (
& 7).start_color_indexÍndice de color dentro de la paleta, 0–3; solo usa los dos bits bajos (
& 3).colorsconst u16*legible con las palabras de color necesarias. Los datos se consumen durante la llamada, sin encolarlos. Mantén accesibles la fuente y su banco ROM; no se cambia de banco automáticamente. Un puntero nulo no produce escrituras.color_countCantidad de palabras de color, no de bytes, como
u8(0–255). Cero no hace nada. Se limita a32 - posición_inicial_normalizada; solo se leen esas palabras de la fuente.
Valor devuelto
Ninguno (void).
Condiciones y límites
Las escrituras de paleta y de registros protegidos no escriben nada en modo DMG. Safe indica una comprobación de modo CGB, no una espera de acceso a PPU ni una sección crítica. Configura con LCD apagado o realiza una actualización breve durante una fase accesible. No espera VBlank ni protege una escritura de varios bytes frente a interrupciones.
Las paletas BG/ventana y OBJ son almacenes separados. Las escrituras de la biblioteca activan el incremento y dejan modificado el registro de índice. El color OBJ cero es transparente al dibujar sprites, aunque sus bytes se puedan guardar y leer.
Ejemplo de uso
cgb_obj_colors(3,2,tail_red,2); // Sprite color 3 becomes red.
expect_color(1,14,0); expect_color(1,15,31);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El programa muestra cómo las paletas BG y OBJ colorean de forma independiente el mismo patrón. Cada triángulo ocupa 8 × 8 píxeles: comienza con un píxel a la izquierda arriba y termina con una fila completa abajo. En x = 16, 32, 48, 64, 80, 96, 112, la fila BG de y = 24 es roja, azul, verde, roja, azul, verde, roja; la OBJ de y = 64 es azul, verde, roja, azul, verde, roja, azul. Las columnas usan, respectivamente, color único, componentes, rango indexado, paleta completa, rango absoluto, registro canónico y alias de registro.
En y = 88 hay siete casillas de 8 × 8: triángulo rojo (x = 16), contorno cuadrado azul de un píxel del banco 1 (32), triángulo verde reflejado horizontalmente (48), rojo reflejado verticalmente (64), azul reflejado en ambos ejes (80), triángulo verde sobre un sprite rojo visible a través del color cero (96), y sprite rojo sólido delante del triángulo BG como control sin prioridad (112). Las coordenadas son píxeles desde la esquina superior izquierda. Fondo blanco y texto negro.
FAILED CHECKS 000 confirma máscaras RGB, booleanos (incluido 2), índices de paleta normalizados, cruce de paletas, límite en posición 31, punteros nulos y longitud cero sin escrituras, y lectura de colores con LCD apagado. Se prueban cuatro combinaciones: ROM dual en DMG/CGB, ROM solo DMG en DMG y solo CGB en CGB. En DMG, CGB MODE vale 0, los triángulos son negros, banco/reflejos no afectan a la imagen y las dos últimas casillas inferiores son cuadrados negros. En CGB, CGB MODE vale 1. No se prueban hardware real ni conflictos de paleta con LCD encendido.




Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/cgb_palette.h:34
Write object colors from the indexed slot, potentially crossing into later palettes.
kitaqgb/lib/cgb_palette.c:141
void cgb_obj_colors(u8 palette_index, u8 start_color_index, const u16* colors, u8 color_count)
{
cgb__write_colors_obj_raw(cgb__palette_color_slot(palette_index, start_color_index), colors, color_count);
}cgb_obj_colors_raw
Escribe palabras RGB15 consecutivas en las paletas de sprites (OBJ) usando una posición absoluta de color. El inicio es un único índice de 0 a 31, no una pareja paleta/color. Los datos son palabras de color, no bytes de patrones.
Sintaxis
void cgb_obj_colors_raw(u8 start_color_slot, const u16* colors, u8 color_count);Parámetros
start_color_slotPosición absoluta de color, 0–31; se normaliza con
& 31antes de limitar la longitud. Posición = paleta × 4 + color. No es un desplazamiento en bytes.colorsconst u16*legible con las palabras de color necesarias. Los datos se consumen durante la llamada, sin encolarlos. Mantén accesibles la fuente y su banco ROM; no se cambia de banco automáticamente. Un puntero nulo no produce escrituras.color_countCantidad de palabras de color, no de bytes, como
u8(0–255). Cero no hace nada. Se limita a32 - posición_inicial_normalizada; solo se leen esas palabras de la fuente.
Valor devuelto
Ninguno (void).
Condiciones y límites
Las escrituras de paleta y de registros protegidos no escriben nada en modo DMG. Safe indica una comprobación de modo CGB, no una espera de acceso a PPU ni una sección crítica. Configura con LCD apagado o realiza una actualización breve durante una fase accesible. No espera VBlank ni protege una escritura de varios bytes frente a interrupciones.
Las paletas BG/ventana y OBJ son almacenes separados. Las escrituras de la biblioteca activan el incremento y dejan modificado el registro de índice. El color OBJ cero es transparente al dibujar sprites, aunque sus bytes se puedan guardar y leer.
Ejemplo de uso
cgb_obj_colors_raw(23,green_word,1); // Same absolute slot in the separate OBJ store.
expect_color(1,23,992);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El programa muestra cómo las paletas BG y OBJ colorean de forma independiente el mismo patrón. Cada triángulo ocupa 8 × 8 píxeles: comienza con un píxel a la izquierda arriba y termina con una fila completa abajo. En x = 16, 32, 48, 64, 80, 96, 112, la fila BG de y = 24 es roja, azul, verde, roja, azul, verde, roja; la OBJ de y = 64 es azul, verde, roja, azul, verde, roja, azul. Las columnas usan, respectivamente, color único, componentes, rango indexado, paleta completa, rango absoluto, registro canónico y alias de registro.
En y = 88 hay siete casillas de 8 × 8: triángulo rojo (x = 16), contorno cuadrado azul de un píxel del banco 1 (32), triángulo verde reflejado horizontalmente (48), rojo reflejado verticalmente (64), azul reflejado en ambos ejes (80), triángulo verde sobre un sprite rojo visible a través del color cero (96), y sprite rojo sólido delante del triángulo BG como control sin prioridad (112). Las coordenadas son píxeles desde la esquina superior izquierda. Fondo blanco y texto negro.
FAILED CHECKS 000 confirma máscaras RGB, booleanos (incluido 2), índices de paleta normalizados, cruce de paletas, límite en posición 31, punteros nulos y longitud cero sin escrituras, y lectura de colores con LCD apagado. Se prueban cuatro combinaciones: ROM dual en DMG/CGB, ROM solo DMG en DMG y solo CGB en CGB. En DMG, CGB MODE vale 0, los triángulos son negros, banco/reflejos no afectan a la imagen y las dos últimas casillas inferiores son cuadrados negros. En CGB, CGB MODE vale 1. No se prueban hardware real ni conflictos de paleta con LCD encendido.




Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/cgb_palette.h:44
Expose sequential object writes using an absolute color-slot index.
kitaqgb/lib/cgb_palette.c:165
void cgb_obj_colors_raw(u8 start_color_slot, const u16* colors, u8 color_count)
{
cgb__write_colors_obj_raw(start_color_slot, colors, color_count);
}cgb_obj_palette
Sustituye los cuatro colores de una paleta de sprites (OBJ) con cuatro palabras RGB15. Equivale a escribir un rango desde el color cero con cantidad cuatro; no asigna la paleta a casillas ni sprites.
Sintaxis
void cgb_obj_palette(u8 palette_index, const u16* colors);Parámetros
palette_indexNúmero de paleta, 0–7; solo usa los tres bits bajos (
& 7).colorsconst u16*legible con las palabras de color necesarias. Los datos se consumen durante la llamada, sin encolarlos. Mantén accesibles la fuente y su banco ROM; no se cambia de banco automáticamente. Un puntero nulo no produce escrituras.
Valor devuelto
Ninguno (void).
Condiciones y límites
Las escrituras de paleta y de registros protegidos no escriben nada en modo DMG. Safe indica una comprobación de modo CGB, no una espera de acceso a PPU ni una sección crítica. Configura con LCD apagado o realiza una actualización breve durante una fase accesible. No espera VBlank ni protege una escritura de varios bytes frente a interrupciones.
Las paletas BG/ventana y OBJ son almacenes separados. Las escrituras de la biblioteca activan el incremento y dejan modificado el registro de índice. El color OBJ cero es transparente al dibujar sprites, aunque sus bytes se puedan guardar y leer.
Ejemplo de uso
cgb_obj_palette(4,blue_palette); // Exactly four words; OBJ color zero is transparent on screen.
expect_color(1,16,32767); expect_color(1,19,31744);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El programa muestra cómo las paletas BG y OBJ colorean de forma independiente el mismo patrón. Cada triángulo ocupa 8 × 8 píxeles: comienza con un píxel a la izquierda arriba y termina con una fila completa abajo. En x = 16, 32, 48, 64, 80, 96, 112, la fila BG de y = 24 es roja, azul, verde, roja, azul, verde, roja; la OBJ de y = 64 es azul, verde, roja, azul, verde, roja, azul. Las columnas usan, respectivamente, color único, componentes, rango indexado, paleta completa, rango absoluto, registro canónico y alias de registro.
En y = 88 hay siete casillas de 8 × 8: triángulo rojo (x = 16), contorno cuadrado azul de un píxel del banco 1 (32), triángulo verde reflejado horizontalmente (48), rojo reflejado verticalmente (64), azul reflejado en ambos ejes (80), triángulo verde sobre un sprite rojo visible a través del color cero (96), y sprite rojo sólido delante del triángulo BG como control sin prioridad (112). Las coordenadas son píxeles desde la esquina superior izquierda. Fondo blanco y texto negro.
FAILED CHECKS 000 confirma máscaras RGB, booleanos (incluido 2), índices de paleta normalizados, cruce de paletas, límite en posición 31, punteros nulos y longitud cero sin escrituras, y lectura de colores con LCD apagado. Se prueban cuatro combinaciones: ROM dual en DMG/CGB, ROM solo DMG en DMG y solo CGB en CGB. En DMG, CGB MODE vale 0, los triángulos son negros, banco/reflejos no afectan a la imagen y las dos últimas casillas inferiores son cuadrados negros. En CGB, CGB MODE vale 1. No se prueban hardware real ni conflictos de paleta con LCD encendido.




Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/cgb_palette.h:39
Write four consecutive colors for one object palette.
kitaqgb/lib/cgb_palette.c:153
void cgb_obj_palette(u8 palette_index, const u16* colors)
{
cgb_obj_colors(palette_index, 0, colors, 4);
}cgb_obj_rgb
Consulte los cambios y la verificación del 2026-10-03 para las diferencias locales de esta API.
Empaqueta los componentes rojo, verde y azul con cgb_rgb15 y escribe un color en las paletas de sprites (OBJ). Úsalo para proporcionar los componentes por separado en lugar de una palabra empaquetada.
Sintaxis
void cgb_obj_rgb(u8 palette_index, u8 color_index, u8 r5, u8 g5, u8 b5);Parámetros
palette_indexNúmero de paleta, 0–7; solo usa los tres bits bajos (
& 7).color_indexÍndice de color dentro de la paleta, 0–3; solo usa los dos bits bajos (
& 3).r5, g5, b5Componentes rojo, verde y azul respectivamente, normalmente 0–31 cada uno. Se enmascaran sin saturación; cada argumento aparece una sola vez en la expansión de la macro.
Valor devuelto
Ninguno (void).
Condiciones y límites
Las escrituras de paleta y de registros protegidos no escriben nada en modo DMG. Safe indica una comprobación de modo CGB, no una espera de acceso a PPU ni una sección crítica. Configura con LCD apagado o realiza una actualización breve durante una fase accesible. No espera VBlank ni protege una escritura de varios bytes frente a interrupciones.
Las paletas BG/ventana y OBJ son almacenes separados. Las escrituras de la biblioteca activan el incremento y dejan modificado el registro de índice. El color OBJ cero es transparente al dibujar sprites, aunque sus bytes se puedan guardar y leer.
Ejemplo de uso
cgb_obj_rgb(2,3,0,31,0); // Green sprite color.
expect_color(1,11,992);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El programa muestra cómo las paletas BG y OBJ colorean de forma independiente el mismo patrón. Cada triángulo ocupa 8 × 8 píxeles: comienza con un píxel a la izquierda arriba y termina con una fila completa abajo. En x = 16, 32, 48, 64, 80, 96, 112, la fila BG de y = 24 es roja, azul, verde, roja, azul, verde, roja; la OBJ de y = 64 es azul, verde, roja, azul, verde, roja, azul. Las columnas usan, respectivamente, color único, componentes, rango indexado, paleta completa, rango absoluto, registro canónico y alias de registro.
En y = 88 hay siete casillas de 8 × 8: triángulo rojo (x = 16), contorno cuadrado azul de un píxel del banco 1 (32), triángulo verde reflejado horizontalmente (48), rojo reflejado verticalmente (64), azul reflejado en ambos ejes (80), triángulo verde sobre un sprite rojo visible a través del color cero (96), y sprite rojo sólido delante del triángulo BG como control sin prioridad (112). Las coordenadas son píxeles desde la esquina superior izquierda. Fondo blanco y texto negro.
FAILED CHECKS 000 confirma máscaras RGB, booleanos (incluido 2), índices de paleta normalizados, cruce de paletas, límite en posición 31, punteros nulos y longitud cero sin escrituras, y lectura de colores con LCD apagado. Se prueban cuatro combinaciones: ROM dual en DMG/CGB, ROM solo DMG en DMG y solo CGB en CGB. En DMG, CGB MODE vale 0, los triángulos son negros, banco/reflejos no afectan a la imagen y las dos últimas casillas inferiores son cuadrados negros. En CGB, CGB MODE vale 1. No se prueban hardware real ni conflictos de paleta con LCD encendido.




Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/cgb_palette.h:28
Pack component values and write one object color.
kitaqgb/lib/cgb_palette.c:128
void cgb_obj_rgb(u8 palette_index, u8 color_index, u8 r5, u8 g5, u8 b5)
{
cgb_obj_color(palette_index, color_index, cgb_rgb15(r5, g5, b5));
}CGB_RGB15
Empaqueta RGB en un u16: rojo en bits 0–4, verde en 5–9 y azul en 10–14; el bit 15 queda a cero. Cada componente se enmascara con 31: se conservan sus cinco bits bajos, sin saturación. Solo calcula el valor, tanto en DMG como en CGB; no escribe en el hardware.
Sintaxis
#define CGB_RGB15(r5, g5, b5) ((u16)((u16)((r5) & 31) | ((u16)((g5) & 31) << 5) | ((u16)((b5) & 31) << 10)))Parámetros
r5, g5, b5Componentes rojo, verde y azul respectivamente, normalmente 0–31 cada uno. Se enmascaran sin saturación; cada argumento aparece una sola vez en la expansión de la macro.
Valor devuelto
Valor RGB15 empaquetado como u16, de 0 a 32767.
Ejemplo de uso
if (CGB_RGB15(component,64,95)!=31775) failures++; // (31,0,31), not saturation.Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El programa muestra cómo las paletas BG y OBJ colorean de forma independiente el mismo patrón. Cada triángulo ocupa 8 × 8 píxeles: comienza con un píxel a la izquierda arriba y termina con una fila completa abajo. En x = 16, 32, 48, 64, 80, 96, 112, la fila BG de y = 24 es roja, azul, verde, roja, azul, verde, roja; la OBJ de y = 64 es azul, verde, roja, azul, verde, roja, azul. Las columnas usan, respectivamente, color único, componentes, rango indexado, paleta completa, rango absoluto, registro canónico y alias de registro.
En y = 88 hay siete casillas de 8 × 8: triángulo rojo (x = 16), contorno cuadrado azul de un píxel del banco 1 (32), triángulo verde reflejado horizontalmente (48), rojo reflejado verticalmente (64), azul reflejado en ambos ejes (80), triángulo verde sobre un sprite rojo visible a través del color cero (96), y sprite rojo sólido delante del triángulo BG como control sin prioridad (112). Las coordenadas son píxeles desde la esquina superior izquierda. Fondo blanco y texto negro.
FAILED CHECKS 000 confirma máscaras RGB, booleanos (incluido 2), índices de paleta normalizados, cruce de paletas, límite en posición 31, punteros nulos y longitud cero sin escrituras, y lectura de colores con LCD apagado. Se prueban cuatro combinaciones: ROM dual en DMG/CGB, ROM solo DMG en DMG y solo CGB en CGB. En DMG, CGB MODE vale 0, los triángulos son negros, banco/reflejos no afectan a la imagen y las dos últimas casillas inferiores son cuadrados negros. En CGB, CGB MODE vale 1. No se prueban hardware real ni conflictos de paleta con LCD encendido.




Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/cgb_palette.h:16
cgb_rgb15
Empaqueta RGB en un u16: rojo en bits 0–4, verde en 5–9 y azul en 10–14; el bit 15 queda a cero. Cada componente se enmascara con 31: se conservan sus cinco bits bajos, sin saturación. Solo calcula el valor, tanto en DMG como en CGB; no escribe en el hardware.
Sintaxis
u16 cgb_rgb15(u8 r5, u8 g5, u8 b5);Parámetros
r5, g5, b5Componentes rojo, verde y azul respectivamente, normalmente 0–31 cada uno. Se enmascaran sin saturación; cada argumento aparece una sola vez en la expansión de la macro.
Valor devuelto
Valor RGB15 empaquetado como u16, de 0 a 32767.
Ejemplo de uso
if (cgb_rgb15(component,64,95)!=31775) failures++; // Same packed value through a function.Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El programa muestra cómo las paletas BG y OBJ colorean de forma independiente el mismo patrón. Cada triángulo ocupa 8 × 8 píxeles: comienza con un píxel a la izquierda arriba y termina con una fila completa abajo. En x = 16, 32, 48, 64, 80, 96, 112, la fila BG de y = 24 es roja, azul, verde, roja, azul, verde, roja; la OBJ de y = 64 es azul, verde, roja, azul, verde, roja, azul. Las columnas usan, respectivamente, color único, componentes, rango indexado, paleta completa, rango absoluto, registro canónico y alias de registro.
En y = 88 hay siete casillas de 8 × 8: triángulo rojo (x = 16), contorno cuadrado azul de un píxel del banco 1 (32), triángulo verde reflejado horizontalmente (48), rojo reflejado verticalmente (64), azul reflejado en ambos ejes (80), triángulo verde sobre un sprite rojo visible a través del color cero (96), y sprite rojo sólido delante del triángulo BG como control sin prioridad (112). Las coordenadas son píxeles desde la esquina superior izquierda. Fondo blanco y texto negro.
FAILED CHECKS 000 confirma máscaras RGB, booleanos (incluido 2), índices de paleta normalizados, cruce de paletas, límite en posición 31, punteros nulos y longitud cero sin escrituras, y lectura de colores con LCD apagado. Se prueban cuatro combinaciones: ROM dual en DMG/CGB, ROM solo DMG en DMG y solo CGB en CGB. En DMG, CGB MODE vale 0, los triángulos son negros, banco/reflejos no afectan a la imagen y las dos últimas casillas inferiores son cuadrados negros. En CGB, CGB MODE vale 1. No se prueban hardware real ni conflictos de paleta con LCD encendido.




Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/cgb_palette.h:19
Pack the red, green and blue components using the public RGB15 macro.
kitaqgb/lib/cgb_palette.c:104
u16 cgb_rgb15(u8 r5, u8 g5, u8 b5)
{
return CGB_RGB15(r5, g5, b5);
}cgb_tile.h — Números y atributos de tiles de CGB
cgb_tile.h agrupa las declaraciones de funciones intrínsecas de mapas de tiles y las macros para construir atributos CGB. El número de tile selecciona un patrón; su atributo selecciona paleta, banco VRAM del patrón, volteos y prioridad del fondo. Cambiar atributos no altera los píxeles del patrón.
La familia __settile usa el mapa 0x9800; __settileat usa una base explícita; __settilebg, el mapa de fondo elegido por LCDC; y __settilewin, su mapa de ventana. Las formas attr solo escriben atributos; las cgb escriben números de tile y atributos. Las formas bulk transfieren bytes consecutivos en la dirección indicada. Elige la función según el destino y los datos que escribe.
Usa macros como KQ_CGB_ATTR_PAL para bits individuales o KQ_CGB_ATTR para combinar campos. El campo bank selecciona el banco VRAM del patrón, no un banco ROM. Las escrituras normales de números de tile usan el banco VRAM actual; selecciona el banco cero antes de operaciones combinadas de tile/atributo. En DMG, las operaciones solo de atributos no hacen nada; las combinadas siguen escribiendo los números.
El compilador genera la implementación de las funciones intrínsecas __; no requieren enlazar cgb_tile.c. Las rutas normales de escritura esperan acceso a VRAM, pero algunas también cambian la habilitación de interrupciones. Las formas _unsafe y _fast omiten las esperas: úsalas solo si el código que llama garantiza VRAM escribible, por ejemplo con el LCD apagado. Comprueba las condiciones de interrupciones, banco y longitud de cada entrada.
KQ_CGB_ATTR
Construye el byte completo de atributo de mapa CGB con paleta, banco de patrones, reflejo horizontal, reflejo vertical y prioridad BG. La paleta ocupa bits 0–2; los cuatro booleanos activan bits 3, 5, 6 y 7. El bit 4 queda a cero.
Sintaxis
#define KQ_CGB_ATTR(palette, bank, xflip, yflip, priority) ((u8)(((palette) & KQ_CGB_ATTR_PAL_MASK) | ((bank) ? KQ_CGB_ATTR_BANK1 : 0) | ((xflip) ? KQ_CGB_ATTR_XFLIP : 0) | ((yflip) ? KQ_CGB_ATTR_YFLIP : 0) | ((priority) ? KQ_CGB_ATTR_PRIORITY : 0)))Parámetros
paletteNúmero de paleta, 0–7; solo usa los tres bits bajos (
& 7).bank, xflip, yflip, priorityCero desactiva el campo; cualquier valor no nulo lo activa. El 2 también lo activa: se comprueba si es distinto de cero, no su bit bajo.
Valor devuelto
Campo o byte de atributo combinado como u8, con la disposición de bits descrita.
Condiciones y límites
Estas macros solo calculan valores u8; no escriben VRAM ni registros. Cada argumento aparece una vez. Aplica el resultado con una API de atributos CGB o escribiendo explícitamente en el mapa del banco 1. DMG no muestra los atributos CGB.
Construye el bit 3 del atributo de mapa CGB: devuelve 0x08 si bank no es cero y 0 en caso contrario. Elige el banco VRAM del patrón mostrado; no escribe VBK ni cambia el banco de la CPU.
Construye la marca de reflejo horizontal: 0x20 si enabled no es cero, o 0. En un atributo de mapa CGB, invierte los ocho píxeles de cada fila del patrón al mostrarlo, sin modificarlo en memoria.
Construye la marca de reflejo vertical: 0x40 si enabled no es cero, o 0. En el mapa CGB, muestra las ocho filas en orden inverso sin cambiar el patrón almacenado.
Construye la prioridad BG sobre OBJ: 0x80 si enabled no es cero, o 0. Con la prioridad general CGB activa (bit 0 de LCDC), los índices de color BG distintos de cero cubren los sprites. El índice cero deja verlos; la marca no vuelve opaca toda la casilla.
Ejemplo de uso
attr=KQ_CGB_ATTR(10,0,2,2,0); // Palette 2, bank 0, both reflections: 0x62.
if (attr!=98 || KQ_CGB_ATTR(10,2,3,4,5)!=234) failures++;
cell(10,11,1,attr);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El programa muestra cómo las paletas BG y OBJ colorean de forma independiente el mismo patrón. Cada triángulo ocupa 8 × 8 píxeles: comienza con un píxel a la izquierda arriba y termina con una fila completa abajo. En x = 16, 32, 48, 64, 80, 96, 112, la fila BG de y = 24 es roja, azul, verde, roja, azul, verde, roja; la OBJ de y = 64 es azul, verde, roja, azul, verde, roja, azul. Las columnas usan, respectivamente, color único, componentes, rango indexado, paleta completa, rango absoluto, registro canónico y alias de registro.
En y = 88 hay siete casillas de 8 × 8: triángulo rojo (x = 16), contorno cuadrado azul de un píxel del banco 1 (32), triángulo verde reflejado horizontalmente (48), rojo reflejado verticalmente (64), azul reflejado en ambos ejes (80), triángulo verde sobre un sprite rojo visible a través del color cero (96), y sprite rojo sólido delante del triángulo BG como control sin prioridad (112). Las coordenadas son píxeles desde la esquina superior izquierda. Fondo blanco y texto negro.
FAILED CHECKS 000 confirma máscaras RGB, booleanos (incluido 2), índices de paleta normalizados, cruce de paletas, límite en posición 31, punteros nulos y longitud cero sin escrituras, y lectura de colores con LCD apagado. Se prueban cuatro combinaciones: ROM dual en DMG/CGB, ROM solo DMG en DMG y solo CGB en CGB. En DMG, CGB MODE vale 0, los triángulos son negros, banco/reflejos no afectan a la imagen y las dos últimas casillas inferiores son cuadrados negros. En CGB, CGB MODE vale 1. No se prueban hardware real ni conflictos de paleta con LCD encendido.




Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/cgb_tile.h:23
KQ_CGB_ATTR_BANK
Construye el bit 3 del atributo de mapa CGB: devuelve 0x08 si bank no es cero y 0 en caso contrario. Elige el banco VRAM del patrón mostrado; no escribe VBK ni cambia el banco de la CPU.
Sintaxis
#define KQ_CGB_ATTR_BANK(bank) ((u8)((bank) ? KQ_CGB_ATTR_BANK1 : 0))Parámetros
bankCero desactiva el campo; cualquier valor no nulo lo activa. El 2 también lo activa: se comprueba si es distinto de cero, no su bit bajo.
Valor devuelto
Campo o byte de atributo combinado como u8, con la disposición de bits descrita.
Condiciones y límites
Estas macros solo calculan valores u8; no escriben VRAM ni registros. Cada argumento aparece una vez. Aplica el resultado con una API de atributos CGB o escribiendo explícitamente en el mapa del banco 1. DMG no muestra los atributos CGB.
Ejemplo de uso
attr=(u8)(2|KQ_CGB_ATTR_BANK(enabled)); // Any nonzero value selects tile-data bank 1.
if (attr!=10) failures++;
cell(4,11,1,attr); // Blue hollow square, unlike the bank-0 triangle.Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El programa muestra cómo las paletas BG y OBJ colorean de forma independiente el mismo patrón. Cada triángulo ocupa 8 × 8 píxeles: comienza con un píxel a la izquierda arriba y termina con una fila completa abajo. En x = 16, 32, 48, 64, 80, 96, 112, la fila BG de y = 24 es roja, azul, verde, roja, azul, verde, roja; la OBJ de y = 64 es azul, verde, roja, azul, verde, roja, azul. Las columnas usan, respectivamente, color único, componentes, rango indexado, paleta completa, rango absoluto, registro canónico y alias de registro.
En y = 88 hay siete casillas de 8 × 8: triángulo rojo (x = 16), contorno cuadrado azul de un píxel del banco 1 (32), triángulo verde reflejado horizontalmente (48), rojo reflejado verticalmente (64), azul reflejado en ambos ejes (80), triángulo verde sobre un sprite rojo visible a través del color cero (96), y sprite rojo sólido delante del triángulo BG como control sin prioridad (112). Las coordenadas son píxeles desde la esquina superior izquierda. Fondo blanco y texto negro.
FAILED CHECKS 000 confirma máscaras RGB, booleanos (incluido 2), índices de paleta normalizados, cruce de paletas, límite en posición 31, punteros nulos y longitud cero sin escrituras, y lectura de colores con LCD apagado. Se prueban cuatro combinaciones: ROM dual en DMG/CGB, ROM solo DMG en DMG y solo CGB en CGB. En DMG, CGB MODE vale 0, los triángulos son negros, banco/reflejos no afectan a la imagen y las dos últimas casillas inferiores son cuadrados negros. En CGB, CGB MODE vale 1. No se prueban hardware real ni conflictos de paleta con LCD encendido.




Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/cgb_tile.h:19
KQ_CGB_ATTR_PAL
Construye el campo de paleta de un atributo de mapa CGB: n & 7, como u8. Combínalo con otras marcas mediante OR bit a bit.
Sintaxis
#define KQ_CGB_ATTR_PAL(n) ((u8)((n) & KQ_CGB_ATTR_PAL_MASK))Parámetros
nNúmero de paleta, 0–7; solo usa los tres bits bajos (
& 7).
Valor devuelto
Campo o byte de atributo combinado como u8, con la disposición de bits descrita.
Condiciones y límites
Estas macros solo calculan valores u8; no escriben VRAM ni registros. Cada argumento aparece una vez. Aplica el resultado con una API de atributos CGB o escribiendo explícitamente en el mapa del banco 1. DMG no muestra los atributos CGB.
Ejemplo de uso
attr=KQ_CGB_ATTR_PAL(9); // 9 & 7 = palette 1, red in this BG example.
if (attr!=1) failures++;
cell(2,11,1,attr);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El programa muestra cómo las paletas BG y OBJ colorean de forma independiente el mismo patrón. Cada triángulo ocupa 8 × 8 píxeles: comienza con un píxel a la izquierda arriba y termina con una fila completa abajo. En x = 16, 32, 48, 64, 80, 96, 112, la fila BG de y = 24 es roja, azul, verde, roja, azul, verde, roja; la OBJ de y = 64 es azul, verde, roja, azul, verde, roja, azul. Las columnas usan, respectivamente, color único, componentes, rango indexado, paleta completa, rango absoluto, registro canónico y alias de registro.
En y = 88 hay siete casillas de 8 × 8: triángulo rojo (x = 16), contorno cuadrado azul de un píxel del banco 1 (32), triángulo verde reflejado horizontalmente (48), rojo reflejado verticalmente (64), azul reflejado en ambos ejes (80), triángulo verde sobre un sprite rojo visible a través del color cero (96), y sprite rojo sólido delante del triángulo BG como control sin prioridad (112). Las coordenadas son píxeles desde la esquina superior izquierda. Fondo blanco y texto negro.
FAILED CHECKS 000 confirma máscaras RGB, booleanos (incluido 2), índices de paleta normalizados, cruce de paletas, límite en posición 31, punteros nulos y longitud cero sin escrituras, y lectura de colores con LCD apagado. Se prueban cuatro combinaciones: ROM dual en DMG/CGB, ROM solo DMG en DMG y solo CGB en CGB. En DMG, CGB MODE vale 0, los triángulos son negros, banco/reflejos no afectan a la imagen y las dos últimas casillas inferiores son cuadrados negros. En CGB, CGB MODE vale 1. No se prueban hardware real ni conflictos de paleta con LCD encendido.




Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/cgb_tile.h:18
KQ_CGB_ATTR_PRIORITY_IF
Construye la prioridad BG sobre OBJ: 0x80 si enabled no es cero, o 0. Con la prioridad general CGB activa (bit 0 de LCDC), los índices de color BG distintos de cero cubren los sprites. El índice cero deja verlos; la marca no vuelve opaca toda la casilla.
Sintaxis
#define KQ_CGB_ATTR_PRIORITY_IF(enabled) ((u8)((enabled) ? KQ_CGB_ATTR_PRIORITY : 0))Parámetros
enabledCero desactiva el campo; cualquier valor no nulo lo activa. El 2 también lo activa: se comprueba si es distinto de cero, no su bit bajo.
Valor devuelto
Campo o byte de atributo combinado como u8, con la disposición de bits descrita.
Condiciones y límites
Estas macros solo calculan valores u8; no escriben VRAM ni registros. Cada argumento aparece una vez. Aplica el resultado con una API de atributos CGB o escribiendo explícitamente en el mapa del banco 1. DMG no muestra los atributos CGB.
Ejemplo de uso
attr=(u8)(3|KQ_CGB_ATTR_PRIORITY_IF(enabled)); // Keep nonzero BG pixels in front of sprites.
if (attr!=131) failures++;
cell(12,11,1,attr);
sprite(7,96,88,2,3); // Red full tile behind the green priority triangle.Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El programa muestra cómo las paletas BG y OBJ colorean de forma independiente el mismo patrón. Cada triángulo ocupa 8 × 8 píxeles: comienza con un píxel a la izquierda arriba y termina con una fila completa abajo. En x = 16, 32, 48, 64, 80, 96, 112, la fila BG de y = 24 es roja, azul, verde, roja, azul, verde, roja; la OBJ de y = 64 es azul, verde, roja, azul, verde, roja, azul. Las columnas usan, respectivamente, color único, componentes, rango indexado, paleta completa, rango absoluto, registro canónico y alias de registro.
En y = 88 hay siete casillas de 8 × 8: triángulo rojo (x = 16), contorno cuadrado azul de un píxel del banco 1 (32), triángulo verde reflejado horizontalmente (48), rojo reflejado verticalmente (64), azul reflejado en ambos ejes (80), triángulo verde sobre un sprite rojo visible a través del color cero (96), y sprite rojo sólido delante del triángulo BG como control sin prioridad (112). Las coordenadas son píxeles desde la esquina superior izquierda. Fondo blanco y texto negro.
FAILED CHECKS 000 confirma máscaras RGB, booleanos (incluido 2), índices de paleta normalizados, cruce de paletas, límite en posición 31, punteros nulos y longitud cero sin escrituras, y lectura de colores con LCD apagado. Se prueban cuatro combinaciones: ROM dual en DMG/CGB, ROM solo DMG en DMG y solo CGB en CGB. En DMG, CGB MODE vale 0, los triángulos son negros, banco/reflejos no afectan a la imagen y las dos últimas casillas inferiores son cuadrados negros. En CGB, CGB MODE vale 1. No se prueban hardware real ni conflictos de paleta con LCD encendido.




Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/cgb_tile.h:22
KQ_CGB_ATTR_XFLIP_IF
Construye la marca de reflejo horizontal: 0x20 si enabled no es cero, o 0. En un atributo de mapa CGB, invierte los ocho píxeles de cada fila del patrón al mostrarlo, sin modificarlo en memoria.
Sintaxis
#define KQ_CGB_ATTR_XFLIP_IF(enabled) ((u8)((enabled) ? KQ_CGB_ATTR_XFLIP : 0))Parámetros
enabledCero desactiva el campo; cualquier valor no nulo lo activa. El 2 también lo activa: se comprueba si es distinto de cero, no su bit bajo.
Valor devuelto
Campo o byte de atributo combinado como u8, con la disposición de bits descrita.
Condiciones y límites
Estas macros solo calculan valores u8; no escriben VRAM ni registros. Cada argumento aparece una vez. Aplica el resultado con una API de atributos CGB o escribiendo explícitamente en el mapa del banco 1. DMG no muestra los atributos CGB.
Ejemplo de uso
attr=(u8)(3|KQ_CGB_ATTR_XFLIP_IF(enabled));
if (attr!=35) failures++;
cell(6,11,1,attr); // Green triangle reflected horizontally.Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El programa muestra cómo las paletas BG y OBJ colorean de forma independiente el mismo patrón. Cada triángulo ocupa 8 × 8 píxeles: comienza con un píxel a la izquierda arriba y termina con una fila completa abajo. En x = 16, 32, 48, 64, 80, 96, 112, la fila BG de y = 24 es roja, azul, verde, roja, azul, verde, roja; la OBJ de y = 64 es azul, verde, roja, azul, verde, roja, azul. Las columnas usan, respectivamente, color único, componentes, rango indexado, paleta completa, rango absoluto, registro canónico y alias de registro.
En y = 88 hay siete casillas de 8 × 8: triángulo rojo (x = 16), contorno cuadrado azul de un píxel del banco 1 (32), triángulo verde reflejado horizontalmente (48), rojo reflejado verticalmente (64), azul reflejado en ambos ejes (80), triángulo verde sobre un sprite rojo visible a través del color cero (96), y sprite rojo sólido delante del triángulo BG como control sin prioridad (112). Las coordenadas son píxeles desde la esquina superior izquierda. Fondo blanco y texto negro.
FAILED CHECKS 000 confirma máscaras RGB, booleanos (incluido 2), índices de paleta normalizados, cruce de paletas, límite en posición 31, punteros nulos y longitud cero sin escrituras, y lectura de colores con LCD apagado. Se prueban cuatro combinaciones: ROM dual en DMG/CGB, ROM solo DMG en DMG y solo CGB en CGB. En DMG, CGB MODE vale 0, los triángulos son negros, banco/reflejos no afectan a la imagen y las dos últimas casillas inferiores son cuadrados negros. En CGB, CGB MODE vale 1. No se prueban hardware real ni conflictos de paleta con LCD encendido.




Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/cgb_tile.h:20
KQ_CGB_ATTR_YFLIP_IF
Construye la marca de reflejo vertical: 0x40 si enabled no es cero, o 0. En el mapa CGB, muestra las ocho filas en orden inverso sin cambiar el patrón almacenado.
Sintaxis
#define KQ_CGB_ATTR_YFLIP_IF(enabled) ((u8)((enabled) ? KQ_CGB_ATTR_YFLIP : 0))Parámetros
enabledCero desactiva el campo; cualquier valor no nulo lo activa. El 2 también lo activa: se comprueba si es distinto de cero, no su bit bajo.
Valor devuelto
Campo o byte de atributo combinado como u8, con la disposición de bits descrita.
Condiciones y límites
Estas macros solo calculan valores u8; no escriben VRAM ni registros. Cada argumento aparece una vez. Aplica el resultado con una API de atributos CGB o escribiendo explícitamente en el mapa del banco 1. DMG no muestra los atributos CGB.
Ejemplo de uso
attr=(u8)(1|KQ_CGB_ATTR_YFLIP_IF(enabled));
if (attr!=65) failures++;
cell(8,11,1,attr); // Red triangle reflected vertically.Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El programa muestra cómo las paletas BG y OBJ colorean de forma independiente el mismo patrón. Cada triángulo ocupa 8 × 8 píxeles: comienza con un píxel a la izquierda arriba y termina con una fila completa abajo. En x = 16, 32, 48, 64, 80, 96, 112, la fila BG de y = 24 es roja, azul, verde, roja, azul, verde, roja; la OBJ de y = 64 es azul, verde, roja, azul, verde, roja, azul. Las columnas usan, respectivamente, color único, componentes, rango indexado, paleta completa, rango absoluto, registro canónico y alias de registro.
En y = 88 hay siete casillas de 8 × 8: triángulo rojo (x = 16), contorno cuadrado azul de un píxel del banco 1 (32), triángulo verde reflejado horizontalmente (48), rojo reflejado verticalmente (64), azul reflejado en ambos ejes (80), triángulo verde sobre un sprite rojo visible a través del color cero (96), y sprite rojo sólido delante del triángulo BG como control sin prioridad (112). Las coordenadas son píxeles desde la esquina superior izquierda. Fondo blanco y texto negro.
FAILED CHECKS 000 confirma máscaras RGB, booleanos (incluido 2), índices de paleta normalizados, cruce de paletas, límite en posición 31, punteros nulos y longitud cero sin escrituras, y lectura de colores con LCD apagado. Se prueban cuatro combinaciones: ROM dual en DMG/CGB, ROM solo DMG en DMG y solo CGB en CGB. En DMG, CGB MODE vale 0, los triángulos son negros, banco/reflejos no afectan a la imagen y las dos últimas casillas inferiores son cuadrados negros. En CGB, CGB MODE vale 1. No se prueban hardware real ni conflictos de paleta con LCD encendido.




Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/cgb_tile.h:21
chain.h — Búferes circulares para el historial de posiciones
Usa ChainBody para serpientes o cuerdas articuladas y Chain para registrar un historial de posiciones. Cada articulación guarda su posición actual y una de 16 direcciones; los giros se propagan hacia atrás una articulación por actualización. Las operaciones del cuerpo admiten campos con continuidad entre bordes, crecimiento duplicando la cola y correcciones de hasta dos píxeles por eje.
chain_wrap_delta
Calcula el desplazamiento con signo más corto desde la posición actual al objetivo en un eje cuyos extremos se unen. Úsalo para seguimiento o comparación de distancias a través del borde del campo.
Sintaxis
s16 chain_wrap_delta(u8 target, u8 current, u16 size);Parámetros
targetCoordenada objetivo, de 0 a size−1.
currentCoordenada actual, de 0 a size−1.
sizeLongitud del eje circular, de 1 a 256: ancho para X y alto para Y. Es un argumento de 16 bits para poder representar 256.
Valor devuelto
Devuelve el desplazamiento más corto como s16: positivo hacia coordenadas crecientes, negativo hacia decrecientes y cero en la misma posición. Las entradas válidas dan −128..+128. En pantalla, derecha y abajo son positivos.
Condiciones y límites
Incluye chain.h y compila chain.c exactamente una vez. No hace falta inicializar Chain ni ChainBody. La función solo calcula un desplazamiento; no modifica arrays de coordenadas, número de articulaciones ni pantalla.
La función no valida ni normaliza entradas. No pases size=0, size>256 ni coordenadas iguales o mayores que size. Ajusta de forma circular las de un sistema mayor a 0..size−1 antes de llamar.
Si ambas rutas tienen la misma longitud, conserva el signo del desplazamiento directo target−current. Con size=160, 0→80 devuelve +80 y 80→0 devuelve −80. Con size=1, cero es la única coordenada válida y el resultado es cero.
Ejemplo de uso
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.Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Este ejemplo muestra coordenadas circulares. Cada flecha va de la posición actual al objetivo. Muestra +02/−02 al cruzar un borde de ancho 160, +80/−80 para medio campo y +00 para ancho 1. El cero inicial es relleno decimal. El ejemplo no dibuja ni mueve un objeto.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\chain_wrap.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\chain_wrap.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/chain.h:35
Return target minus current along the shortest wrapped route. Supply size 1..256 and coordinates in 0..size-1; inputs are not normalized. Exactly half a field retains the direct displacement sign.
kitaqgb/lib/chain.c:98
s16 chain_wrap_delta(u8 target, u8 current, u16 size)
{
s16 delta;
s16 half;
delta = (s16)((s16)target - (s16)current);
half = (s16)(size >> 1);
// At exactly half a field, retain the sign of the direct displacement.
if (delta > half) delta = (s16)(delta - (s16)size);
else if (delta < (s16)(0 - half)) delta = (s16)(delta + (s16)size);
return delta;
}chain_body_init
Asocia tres arrays de articulaciones del código que llama y pone el número a cero, sin reservar memoria.
Sintaxis
u8 chain_body_init(ChainBody* body, u8* x, u8* y, u8* heading, u8 capacity, u16 width, u16 height);Parámetros
bodyChainBodyde destino; se ignora null. Salvo al inicializar, pasa un estado inicializado.xArray de coordenadas X de las articulaciones.
yArray de coordenadas Y de las articulaciones.
headingArray de direcciones de las articulaciones.
capacityLongitud reservada del array, de 1 a 255.
widthAncho del campo con bordes conectados, de 1 a 256.
heightAlto del campo con bordes conectados, de 1 a 256.
Valor devuelto
Devuelve 1 si tiene éxito y 0 si los argumentos no son válidos. Si falla con un cuerpo no nulo, pone capacity y count a cero y desactiva las actualizaciones.
Condiciones y límites
Incluye chain.h y compila chain.c exactamente una vez. ChainBody guarda la posición y dirección actuales de cada articulación. Es un tipo de estado distinto del historial circular de posiciones Chain.
Proporciona tres arrays escribibles separados, x, y y heading, de capacity bytes cada uno. Mantenlos válidos mientras se use el cuerpo. El índice cero es la cabeza, incluida en count. No cambies los punteros, la capacidad ni las dimensiones del campo tras inicializar.
Las direcciones usan 16 sectores en sentido horario: 0=derecha, 4=abajo, 8=izquierda, 12=arriba. Solo se usan los cuatro bits bajos. Las coordenadas crecen hacia la derecha y abajo; cada dimensión va de 1 a 256 píxeles.
Ejemplo de uso
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.Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La imagen muestra arriba un cuerpo recto, en medio una actualización después de girar hacia abajo y abajo cuatro actualizaciones tras el giro. Las coordenadas se dibujan al doble de su tamaño lógico. El giro se propaga hacia atrás desde la cabeza a la derecha. CGB y FC usan rojo para la cabeza, azul para el cuerpo y verde para la cola; DMG usa negro. Cuatro actualizaciones de estabilización separan la cola duplicada tras crecer. Son tres vistas de las mismas ocho articulaciones, no un cuerpo de 24.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\chain_body.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\chain_body.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/chain.h:53
Attach three non-overlapping capacity-byte arrays. Return 1 on success. Invalid storage, zero capacity or dimensions outside 1..256 disable the body.
kitaqgb/lib/chain.c:119
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
Construye una postura inicial recta colocando articulaciones detrás de la cabeza indicada.
Sintaxis
u8 chain_body_reset(ChainBody* body, u8 count, u8 head_x, u8 head_y, u8 heading);Parámetros
bodyChainBodyde destino; se ignora null. Salvo al inicializar, pasa un estado inicializado.countNúmero de articulaciones, incluida la cabeza, de 1 a capacity.
head_xCoordenada X de la cabeza, ajustada de forma circular al ancho del campo.
head_yCoordenada Y de la cabeza, ajustada de forma circular al alto del campo.
headingDirección de la cabeza en el sistema de 16 sectores.
Valor devuelto
Devuelve 1 si tiene éxito. Un número cero o excesivo, o un cuerpo nulo, devuelve 0 sin cambiar la postura.
Condiciones y límites
Incluye chain.h y compila chain.c exactamente una vez. ChainBody guarda la posición y dirección actuales de cada articulación. Es un tipo de estado distinto del historial circular de posiciones Chain.
Proporciona tres arrays escribibles separados, x, y y heading, de capacity bytes cada uno. Mantenlos válidos mientras se use el cuerpo. El índice cero es la cabeza, incluida en count. No cambies los punteros, la capacidad ni las dimensiones del campo tras inicializar.
Las direcciones usan 16 sectores en sentido horario: 0=derecha, 4=abajo, 8=izquierda, 12=arriba. Solo se usan los cuatro bits bajos. Las coordenadas crecen hacia la derecha y abajo; cada dimensión va de 1 a 256 píxeles.
La separación cardinal es de cuatro píxeles. Las direcciones intermedias usan vectores enteros como (4,1), (3,3) y (1,4), así que la distancia euclídea no es exactamente cuatro píxeles. La postura inicial puede cruzar un borde del campo.
Ejemplo de uso
chain_body_reset(&body,7,48,16,0); // Seven joints, facing right.Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La imagen muestra arriba un cuerpo recto, en medio una actualización después de girar hacia abajo y abajo cuatro actualizaciones tras el giro. Las coordenadas se dibujan al doble de su tamaño lógico. El giro se propaga hacia atrás desde la cabeza a la derecha. CGB y FC usan rojo para la cabeza, azul para el cuerpo y verde para la cola; DMG usa negro. Cuatro actualizaciones de estabilización separan la cola duplicada tras crecer. Son tres vistas de las mismas ocho articulaciones, no un cuerpo de 24.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\chain_body.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\chain_body.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/chain.h:57
Seed count joints in a straight pose behind the head; count includes the head. Return 0 without changing the pose if count is zero or exceeds capacity. Coordinates wrap to the playfield and headings are masked to 0..15.
kitaqgb/lib/chain.c:135
u8 chain_body_reset(ChainBody* body, u8 count, u8 head_x, u8 head_y, u8 heading)
{
u8 i;
u8 x;
u8 y;
s16 ox;
s16 oy;
if (body == 0) return 0;
if (count == 0 || count > body->capacity) return 0;
heading = (u8)(heading & 15);
x = chain_body_wrap((s16)head_x, body->width);
y = chain_body_wrap((s16)head_y, body->height);
ox = chain_body_offset_x(heading);
oy = chain_body_offset_y(heading);
i = 0;
while (i < count) {
body->x[(__safe_index u8)i] = x;
body->y[(__safe_index u8)i] = y;
body->heading[(__safe_index u8)i] = heading;
x = chain_body_wrap((s16)((s16)x - ox), body->width);
y = chain_body_wrap((s16)((s16)y - oy), body->height);
i = (u8)(i + 1);
}
body->count = count;
return 1;
}chain_body_step
Establece la postura de la cabeza y acerca gradualmente cada articulación al punto de unión detrás de su predecesora. Los cambios de dirección se propagan una articulación por actualización.
Sintaxis
void chain_body_step(ChainBody* body, u8 head_x, u8 head_y, u8 heading);Parámetros
bodyChainBodyde destino; se ignora null. Salvo al inicializar, pasa un estado inicializado.head_xCoordenada X de la cabeza, ajustada de forma circular al ancho del campo.
head_yCoordenada Y de la cabeza, ajustada de forma circular al alto del campo.
headingDirección de la cabeza en el sistema de 16 sectores.
Valor devuelto
No devuelve ningún valor.
Condiciones y límites
Incluye chain.h y compila chain.c exactamente una vez. ChainBody guarda la posición y dirección actuales de cada articulación. Es un tipo de estado distinto del historial circular de posiciones Chain.
Proporciona tres arrays escribibles separados, x, y y heading, de capacity bytes cada uno. Mantenlos válidos mientras se use el cuerpo. El índice cero es la cabeza, incluida en count. No cambies los punteros, la capacidad ni las dimensiones del campo tras inicializar.
Las direcciones usan 16 sectores en sentido horario: 0=derecha, 4=abajo, 8=izquierda, 12=arriba. Solo se usan los cuatro bits bajos. Las coordenadas crecen hacia la derecha y abajo; cada dimensión va de 1 a 256 píxeles.
Usa la posición actualizada del predecesor para hallar el punto de unión objetivo y calcula el desplazamiento circular más corto en cada eje. Cero no mueve; una magnitud de 1 a 4 mueve un píxel y de 5 o más, dos. A exactamente medio campo, conserva el signo original.
Pasa a la siguiente articulación la dirección guardada de cada una antes de actualizarla, para propagar el giro por el cuerpo. Un cuerpo vacío no cambia.
El código que llama gestiona velocidad y aceleración de la cabeza, colisiones, dibujo y espera. Normalmente actualiza primero la cabeza y llama una vez a chain_body_step por paso de simulación. Es seguimiento de articulaciones, no un solucionador de cuerpos rígidos ni de restricciones exactas de longitud.
Ejemplo de uso
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.Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La imagen muestra arriba un cuerpo recto, en medio una actualización después de girar hacia abajo y abajo cuatro actualizaciones tras el giro. Las coordenadas se dibujan al doble de su tamaño lógico. El giro se propaga hacia atrás desde la cabeza a la derecha. CGB y FC usan rojo para la cabeza, azul para el cuerpo y verde para la cola; DMG usa negro. Cuatro actualizaciones de estabilización separan la cola duplicada tras crecer. Son tres vistas de las mismas ocho articulaciones, no un cuerpo de 24.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\chain_body.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\chain_body.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/chain.h:62
Install the caller's head pose, then pull joints from front to rear. Each joint aims four pixels behind its updated predecessor and receives that predecessor's OLD heading. Each axis moves 1 pixel, or 2 when error exceeds 4. Call once per simulation tick; this does not advance head physics or render.
kitaqgb/lib/chain.c:162
void chain_body_step(ChainBody* body, u8 head_x, u8 head_y, u8 heading)
{
u8 i;
u8 previous;
u8 pull;
u8 old;
u8 x;
u8 y;
u8 tx;
u8 ty;
s16 sx;
s16 sy;
if (body == 0) return;
if (body->count == 0) return;
heading = (u8)(heading & 15);
body->x[0] = chain_body_wrap((s16)head_x, body->width);
body->y[0] = chain_body_wrap((s16)head_y, body->height);
body->heading[0] = heading;
pull = heading;
i = 1;
while (i < body->count) {
previous = (u8)(i - 1);
old = body->heading[(__safe_index u8)i];
x = body->x[(__safe_index u8)i];
y = body->y[(__safe_index u8)i];
tx = chain_body_wrap((s16)((s16)body->x[(__safe_index u8)previous] - chain_body_offset_x(pull)), body->width);
ty = chain_body_wrap((s16)((s16)body->y[(__safe_index u8)previous] - chain_body_offset_y(pull)), body->height);
sx = chain_body_correction(chain_wrap_delta(tx, x, body->width));
sy = chain_body_correction(chain_wrap_delta(ty, y, body->height));
body->heading[(__safe_index u8)i] = pull;
body->x[(__safe_index u8)i] = chain_body_wrap((s16)((s16)x + sx), body->width);
body->y[(__safe_index u8)i] = chain_body_wrap((s16)((s16)y + sy), body->height);
// Save before overwriting: a bend advances by one joint per update.
pull = old;
i = (u8)(i + 1);
}
}chain_body_grow
Copia la posición y dirección actuales de la cola al siguiente hueco libre y aumenta el número en uno.
Sintaxis
u8 chain_body_grow(ChainBody* body);Parámetros
bodyChainBodyde destino; se ignora null. Salvo al inicializar, pasa un estado inicializado.
Valor devuelto
Devuelve 1 si se añade una articulación; 0 si el cuerpo está vacío, lleno, desactivado o es nulo.
Condiciones y límites
Incluye chain.h y compila chain.c exactamente una vez. ChainBody guarda la posición y dirección actuales de cada articulación. Es un tipo de estado distinto del historial circular de posiciones Chain.
Proporciona tres arrays escribibles separados, x, y y heading, de capacity bytes cada uno. Mantenlos válidos mientras se use el cuerpo. El índice cero es la cabeza, incluida en count. No cambies los punteros, la capacidad ni las dimensiones del campo tras inicializar.
Las direcciones usan 16 sectores en sentido horario: 0=derecha, 4=abajo, 8=izquierda, 12=arriba. Solo se usan los cuatro bits bajos. Las coordenadas crecen hacia la derecha y abajo; cada dimensión va de 1 a 256 píxeles.
La nueva cola se solapa inicialmente con la anterior y se separa en llamadas posteriores a chain_body_step. Crecer no mueve por sí mismo la cabeza ni las demás articulaciones.
Ejemplo de uso
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.Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La imagen muestra arriba un cuerpo recto, en medio una actualización después de girar hacia abajo y abajo cuatro actualizaciones tras el giro. Las coordenadas se dibujan al doble de su tamaño lógico. El giro se propaga hacia atrás desde la cabeza a la derecha. CGB y FC usan rojo para la cabeza, azul para el cuerpo y verde para la cola; DMG usa negro. Cuatro actualizaciones de estabilización separan la cola duplicada tras crecer. Son tres vistas de las mismas ocho articulaciones, no un cuerpo de 24.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\chain_body.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\chain_body.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/chain.h:65
Append a copy of the current tail; later steps separate the new joint. Return 1 on growth, or 0 for an empty, disabled or full body.
kitaqgb/lib/chain.c:200
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
Pone a cero el número de articulaciones y conserva los arrays y la configuración del campo.
Sintaxis
void chain_body_clear(ChainBody* body);Parámetros
bodyChainBodyde destino; se ignora null. Salvo al inicializar, pasa un estado inicializado.
Valor devuelto
No devuelve ningún valor.
Condiciones y límites
Incluye chain.h y compila chain.c exactamente una vez. ChainBody guarda la posición y dirección actuales de cada articulación. Es un tipo de estado distinto del historial circular de posiciones Chain.
Proporciona tres arrays escribibles separados, x, y y heading, de capacity bytes cada uno. Mantenlos válidos mientras se use el cuerpo. El índice cero es la cabeza, incluida en count. No cambies los punteros, la capacidad ni las dimensiones del campo tras inicializar.
Las direcciones usan 16 sectores en sentido horario: 0=derecha, 4=abajo, 8=izquierda, 12=arriba. Solo se usan los cuatro bits bajos. Las coordenadas crecen hacia la derecha y abajo; cada dimensión va de 1 a 256 píxeles.
No borra los bytes de los arrays. Usa chain_body_reset para empezar de nuevo; llamar a chain_body_grow justo después de vaciar no añade una articulación.
Ejemplo de uso
chain_body_clear(&body); // Forget the pose; the three arrays remain owned by us.Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La imagen muestra arriba un cuerpo recto, en medio una actualización después de girar hacia abajo y abajo cuatro actualizaciones tras el giro. Las coordenadas se dibujan al doble de su tamaño lógico. El giro se propaga hacia atrás desde la cabeza a la derecha. CGB y FC usan rojo para la cabeza, azul para el cuerpo y verde para la cola; DMG usa negro. Cuatro actualizaciones de estabilización separan la cola duplicada tras crecer. Son tres vistas de las mismas ocho articulaciones, no un cuerpo de 24.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\chain_body.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\chain_body.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/chain.h:67
Remove all joints while retaining caller-owned storage and playfield settings.
kitaqgb/lib/chain.c:215
void chain_body_clear(ChainBody* body)
{
if (body == 0) return;
body->count = 0;
}chain_clear
Descarta el historial registrado para reutilizar la misma matriz de almacenamiento.
Sintaxis
void chain_clear(Chain* chain);Parámetros
chainPuntero al
Chaininicializado.
Valor devuelto
No devuelve ningún valor.
Condiciones y límites
Pone a cero el recuento y head sin borrar ni liberar la matriz. El código que llama es propietario de Chain y de su matriz de puntos, y debe mantener ambos válidos. Limita la capacidad a 128 para evitar el desbordamiento de la suma de índices de ocho bits durante la lectura.
La versión GB requiere un puntero chain válido.
Ejemplo de uso
chain_clear(&trail);result[11]=chain_get_count(&trail);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo vacía un historial de cuatro puntos y comprueba que su recuento pase a cero.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_chain.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_chain.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/chain.h:21
Forget the recorded points without clearing or freeing the backing storage.
kitaqgb/lib/chain.c:14
void chain_clear(Chain* chain)
{
chain->count = 0;
chain->head = 0;
}chain_get_count
Lee el número de posiciones disponibles actualmente en el historial.
Sintaxis
u8 chain_get_count(const Chain* chain);Parámetros
chainPuntero al
Chaininicializado.
Valor devuelto
Devuelve un recuento entre cero y la capacidad, o cero si la cadena es nula.
Condiciones y límites
El código que llama es propietario de Chain y de su matriz de puntos, y debe mantener ambos válidos. Usa una capacidad máxima de 128 para evitar el desbordamiento de la suma de índices de ocho bits en la función de lectura.
Ejemplo de uso
result[4]=chain_get_count(&trail);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Tras cinco inserciones en cuatro posiciones, el recuento sigue siendo cuatro. Pasa a cero al vaciar el historial y permanece en cero si la capacidad es nula.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_chain.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_chain.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/chain.h:30
Return the number of stored points, or zero for a null chain.
kitaqgb/lib/chain.c:63
u8 chain_get_count(const Chain* chain)
{
if (chain == 0) return 0;
return chain->count;
}chain_get_segment
Lee una posición almacenada según su antigüedad en el historial.
Sintaxis
u8 chain_get_segment(const Chain* chain, u8 index, ChainPoint* out);Parámetros
chainPuntero al
Chaininicializado.indexAntigüedad del punto: 0 es el más reciente y
count - 1el más antiguo conservado.outChainPointindependiente y escribible para el resultado; un puntero nulo provoca un fallo.
Valor devuelto
Devuelve 1 si tiene éxito o 0 si la solicitud no es válida. Si out no es nulo, se pone a (0,0) antes de validar la solicitud.
Condiciones y límites
out no debe compartir memoria con la matriz de almacenamiento ni con Chain: poner la salida a cero destruiría datos de origen. El código que llama es propietario de Chain y de su matriz de puntos, y debe mantener ambos válidos. Limita la capacidad a 128 para evitar el desbordamiento de la suma de índices de ocho bits durante la lectura.
Ejemplo de uso
result[1]=chain_get_segment(&trail,0,&point);result[2]=point.x;result[3]=point.y;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El índice 0 lee el punto más reciente (40,24), el índice 3 el más antiguo (16,8), y el índice no válido 4 devuelve un fallo con salida (0,0).


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_chain.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_chain.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/chain.h:28
Read a point by age, with index zero denoting the newest point. Return zero for an invalid request and clear a non-null output first. Keep head + index within the 8-bit range: addition is narrowed before the capacity wrap.
kitaqgb/lib/chain.c:40
u8 chain_get_segment(const Chain* chain, u8 index, ChainPoint* out)
{
u8 pos;
if (out != 0) {
out->x = 0;
out->y = 0;
}
if (out == 0) return 0;
if (chain == 0) return 0;
if (chain->capacity == 0) return 0;
if (index >= chain->count) return 0;
pos = (u8)(chain->head + index);
while (pos >= chain->capacity) {
pos = (u8)(pos - chain->capacity);
}
out->x = chain->points[pos].x;
out->y = chain->points[pos].y;
return 1;
}chain_init
Asocia almacenamiento a un historial circular de posiciones y comienza sin puntos registrados.
Sintaxis
void chain_init(Chain* chain, ChainPoint* storage, u8 capacity);Parámetros
chainChainescribible que se va a inicializar.storageMatriz con espacio para
capacityelementosChainPoint.capacityNúmero de posiciones para puntos. Usa de 1 a 128 para un historial utilizable; cero desactiva el registro.
Valor devuelto
No devuelve ningún valor.
Condiciones y límites
El código que llama es propietario de Chain y de su matriz de puntos, y debe mantener ambos válidos. Usa una capacidad máxima de 128 para evitar el desbordamiento de la suma de índices de ocho bits en la función de lectura.
La versión GB requiere un puntero chain válido.
Ejemplo de uso
chain_init(&trail,storage,4);result[0]=chain_get_count(&trail);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo asocia cuatro posiciones de puntos y comprueba que el recuento inicial sea cero.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_chain.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_chain.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/chain.h:19
Attach caller-owned ring storage and start with no recorded points. The storage must remain valid for the lifetime of the chain. Use a valid chain pointer and capacity entries of caller-owned storage. Capacity at most 128 keeps every head+age sum in the byte range used by the reader.
kitaqgb/lib/chain.c:5
void chain_init(Chain* chain, ChainPoint* storage, u8 capacity)
{
chain->points = storage;
chain->capacity = capacity;
chain->count = 0;
chain->head = 0;
}chain_push_head
Añade la posición más reciente a la cabeza del historial y sustituye el punto más antiguo si está lleno.
Sintaxis
void chain_push_head(Chain* chain, s16 x, s16 y);Parámetros
chainPuntero al
Chaininicializado.xCoordenada X con signo del punto nuevo.
yCoordenada Y con signo del punto nuevo.
Valor devuelto
No devuelve ningún valor.
Condiciones y límites
Una cadena nula o una capacidad cero no produce ningún efecto. El código que llama es propietario de Chain y de su matriz de puntos, y debe mantener ambos válidos. Limita la capacidad a 128 para evitar el desbordamiento de la suma de índices de ocho bits durante la lectura.
Ejemplo de uso
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);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Tras cinco inserciones en cuatro posiciones, (40,24) es el punto más reciente y (16,8) el más antiguo conservado; el (8,8) original se ha sustituido.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_chain.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_chain.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/chain.h:24
Move the ring head backward and store the newest point. Once full, each push replaces the oldest point; zero capacity is a no-op.
kitaqgb/lib/chain.c:22
void chain_push_head(Chain* chain, s16 x, s16 y)
{
if (chain == 0) return;
if (chain->capacity == 0) return;
if (chain->head == 0) chain->head = (u8)(chain->capacity - 1);
else chain->head--;
chain->points[chain->head].x = x;
chain->points[chain->head].y = y;
if (chain->count < chain->capacity) chain->count++;
}danmaku.h — Grupos de proyectiles, abanicos, impactos y roces
Campo de hasta 96 proyectiles en 160×128 píxeles sin asignación dinámica. Ofrece movimiento en dieciseisavos de píxel, abanicos de 32 direcciones, impactos/roces y composición de tiles de cuatro cuadrantes. La simulación funciona en GB; la transferencia present_now es exclusiva de CGB.
danmaku_clear
Desactiva todos los proyectiles y borra el número activo, los eventos actuales de impacto/roce y el cursor de asignación.
Sintaxis
void danmaku_clear();Valor devuelto
No devuelve ningún valor.
Condiciones y límites
Conserva el máximo y los contadores acumulados. Borra y transfiere el mapa de RAM para quitar los proyectiles de la pantalla.
Ejemplo de uso
danmaku_clear();result[6]=dm_count;result[7]=dm_spawned;result[8]=dm_peak;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Ejemplo de dibujo exclusivo de CGB. Genera ocho direcciones en (80,64), actualiza ocho veces y muestra ocho puntos rojos de 3×3 en disposición radial. Los proyectiles cardinales recorren 32 píxeles; las diagonales usan una aproximación entera. También comprueba el vaciado del pool y la conservación del total de creaciones.

Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_danmaku.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_danmaku.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=noneImplementación y código fuente
kitaqgb/lib/danmaku.h:35
Deactivate the pool while retaining peak/spawn/rejection counters and the RAM map.
kitaqgb/lib/danmaku.c:28
void danmaku_clear() {
u8 i;
for (i=0; i<DANMAKU_MAX; i++) dm_bullets[i].active=0;
dm_count=0; dm_hit=0; dm_graze=0; dm_cursor=0;
}danmaku_clear_map
Borra los 576 bytes del mapa de tiles de RAM de 32×18.
Sintaxis
void danmaku_clear_map();Valor devuelto
No devuelve ningún valor.
Condiciones y límites
No cambia el estado de los proyectiles ni la VRAM. En cada fotograma, ejecuta clear_map, escribe la decoración, llama a step y después transfiere.
Ejemplo de uso
danmaku_clear_map();result[11]=dm_map[0];Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Ejemplo de dibujo exclusivo de CGB. Genera ocho direcciones en (80,64), actualiza ocho veces y muestra ocho puntos rojos de 3×3 en disposición radial. Los proyectiles cardinales recorren 32 píxeles; las diagonales usan una aproximación entera. También comprueba el vaciado del pool y la conservación del total de creaciones.

Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_danmaku.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_danmaku.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=noneImplementación y código fuente
kitaqgb/lib/danmaku.h:42
32 directions, 0=right, 8=down, 16=left, 24=up. speed in 1/16 px. Clear the 32x18 RAM map before drawing the next frame; no transfer is performed.
kitaqgb/lib/danmaku.c:78
void danmaku_clear_map() {
__asm {
LD_HL_IMM dm_map
LD_B_IMM 72
XOR_A
dm_clm_loop:
LDI_HL_A
LDI_HL_A
LDI_HL_A
LDI_HL_A
LDI_HL_A
LDI_HL_A
LDI_HL_A
LDI_HL_A
DEC_B
JR_NZ dm_clm_loop
RET
}
}danmaku_fan
Genera un abanico con una tabla de velocidades de 32 direcciones y un paso angular fijo.
Sintaxis
void danmaku_fan(u8 x, u8 y, u8 direction, u8 step, u8 count, u8 speed);Parámetros
xX inicial en píxeles, de 0 a 159.
yY inicial en píxeles, de 0 a 127.
directionÁngulo inicial, limitado a cinco bits: 0=derecha, 8=abajo, 16=izquierda, 24=arriba.
stepIncremento angular por proyectil, circular sobre 32 direcciones.
countNúmero de intentos, limitado a 96.
speedVelocidad en dieciseisavos de píxel, limitada a 64, equivalente a cuatro píxeles por actualización.
Valor devuelto
No devuelve ningún valor.
Condiciones y límites
Sigue intentando las creaciones restantes aunque el pool esté lleno. Los valores enteros de las tablas sin/cos introducen redondeos en el movimiento diagonal.
Ejemplo de uso
danmaku_fan(80,64,0,4,8,64);result[9]=dm_count;result[10]=dm_spawned;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Ejemplo de dibujo exclusivo de CGB. Genera ocho direcciones en (80,64), actualiza ocho veces y muestra ocho puntos rojos de 3×3 en disposición radial. Los proyectiles cardinales recorren 32 píxeles; las diagonales usan una aproximación entera. También comprueba el vaciado del pool y la conservación del total de creaciones.

Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_danmaku.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_danmaku.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=noneImplementación y código fuente
kitaqgb/lib/danmaku.h:39
Attempt a fan using wrapping 32-step angles; count is capped at 96 and speed at 64.
kitaqgb/lib/danmaku.c:62
void danmaku_fan(u8 x,u8 y,u8 direction,u8 step,u8 count,u8 speed) {
u8 n;
u8 a;
s8 vx;
s8 vy;
if(count>DANMAKU_MAX) count=DANMAKU_MAX;
if(speed>64) speed=64;
a=direction&31;
for(n=0;n<count;n++) {
vx=(s8)(((s16)dm_cos[a]*(s16)speed)>>6);
vy=(s8)(((s16)dm_sin[a]*(s16)speed)>>6);
danmaku_spawn(x,y,vx,vy);
a=(u8)((a+step)&31);
}
}danmaku_present_now
Transfiere de forma síncrona los 576 bytes de dm_map al mapa de fondo $9800 mediante GDMA de CGB.
Sintaxis
void danmaku_present_now();Valor devuelto
No devuelve ningún valor.
Condiciones y límites
Solo para CGB; no la llames en DMG. Úsala con el LCD apagado o al inicio de VBlank. Selecciona el banco VRAM cero sin restaurar el VBK anterior. La aplicación debe proporcionar los gráficos de proyectiles en los tiles 0..15.
Ejemplo de uso
// CGB general DMA; the LCD is stopped for this complete-map upload.
danmaku_present_now();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Ejemplo de dibujo exclusivo de CGB. Genera ocho direcciones en (80,64), actualiza ocho veces y muestra ocho puntos rojos de 3×3 en disposición radial. Los proyectiles cardinales recorren 32 píxeles; las diagonales usan una aproximación entera. También comprueba el vaciado del pool y la conservación del total de creaciones.

Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_danmaku.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_danmaku.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=noneImplementación y código fuente
kitaqgb/lib/danmaku.h:48
Requires CGB and LCD off or the beginning of VBlank. VBK restored to 0. Transfers 18 rows (32-byte stride) to BG map 9800 with 36-block GDMA.
kitaqgb/lib/danmaku.c:301
void danmaku_present_now() {
__asm {
XOR_A
LDH_MEM_A 0x4F
LD_HL_IMM dm_map
LD_A_H
LDH_MEM_A 0x51
LD_A_L
LDH_MEM_A 0x52
LD_A_IMM 0x18
LDH_MEM_A 0x53
XOR_A
LDH_MEM_A 0x54
LD_A_IMM 35
LDH_MEM_A 0x55
RET
}
}danmaku_reset
Vacía el pool de 96 proyectiles y restablece los contadores de máximo simultáneo, creaciones acumuladas y rechazos por pool lleno.
Sintaxis
void danmaku_reset();Valor devuelto
No devuelve ningún valor.
Condiciones y límites
No cambia las coordenadas del jugador, la invulnerabilidad ni el mapa de tiles en RAM; configúralos por separado al empezar el juego.
Ejemplo de uso
danmaku_reset();result[0]=dm_count;result[1]=dm_peak;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Ejemplo de dibujo exclusivo de CGB. Genera ocho direcciones en (80,64), actualiza ocho veces y muestra ocho puntos rojos de 3×3 en disposición radial. Los proyectiles cardinales recorren 32 píxeles; las diagonales usan una aproximación entera. También comprueba el vaciado del pool y la conservación del total de creaciones.

Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_danmaku.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_danmaku.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=noneImplementación y código fuente
kitaqgb/lib/danmaku.h:33
Reset pool, peak and lifetime counters; player fields and map contents remain caller-owned state.
kitaqgb/lib/danmaku.c:34
void danmaku_reset() {
danmaku_clear(); dm_peak=0; dm_spawned=0; dm_rejected=0;
}danmaku_spawn
Busca un hueco libre de forma circular y crea un proyectil con la posición y velocidad indicadas.
Sintaxis
u8 danmaku_spawn(u8 x, u8 y, s8 vx, s8 vy);Parámetros
xX inicial en píxeles, de 0 a 159.
yY inicial en píxeles, de 0 a 127.
vxVelocidad Q4.4 con signo de −128 a 127; 16 mueve un píxel a la derecha por actualización.
vyVelocidad Q4.4 con signo; un valor positivo mueve hacia abajo.
Valor devuelto
Devuelve 1 al asignar y 0 si las coordenadas están fuera o el pool está lleno. Las solicitudes exteriores no incrementan dm_rejected.
Condiciones y límites
Las posiciones se guardan en dieciseisavos de píxel. Los totales u16 de creaciones/rechazos vuelven a cero después de 65535. No se usa asignación dinámica.
Ejemplo de uso
result[2]=danmaku_spawn(40,40,16,0);result[3]=danmaku_spawn(160,40,0,0);result[4]=dm_count;result[5]=dm_rejected;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Ejemplo de dibujo exclusivo de CGB. Genera ocho direcciones en (80,64), actualiza ocho veces y muestra ocho puntos rojos de 3×3 en disposición radial. Los proyectiles cardinales recorren 32 píxeles; las diagonales usan una aproximación entera. También comprueba el vaciado del pool y la conservación del total de creaciones.

Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_danmaku.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_danmaku.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=noneImplementación y código fuente
kitaqgb/lib/danmaku.h:37
Use pixel origins inside 160x128 and signed sixteenth-pixel velocities; return one if a slot was allocated.
kitaqgb/lib/danmaku.c:39
u8 danmaku_spawn(u8 x, u8 y, s8 vx, s8 vy) {
u8 n;
u8 i;
if (x>=160 || y>=128) return 0;
for(n=0;n<DANMAKU_MAX;n++) {
i=dm_cursor;
dm_cursor++;
if(dm_cursor>=DANMAKU_MAX) dm_cursor=0;
if(dm_bullets[i].active==0) {
dm_bullets[i].x=(s16)((u16)x<<4);
dm_bullets[i].y=(s16)((u16)y<<4);
dm_bullets[i].vx=vx; dm_bullets[i].vy=vy;
dm_bullets[i].active=1; dm_bullets[i].grazed=0;
dm_count++; dm_spawned++;
if(dm_count>dm_peak) dm_peak=dm_count;
return 1;
}
}
dm_rejected++;
return 0;
}danmaku_step
Avanza cada proyectil una vez, elimina los que salen del área, compone los tiles de proyectiles y detecta impactos y roces.
Sintaxis
void danmaku_step();Valor devuelto
No devuelve ningún valor.
Condiciones y límites
Los centros dibujados se ajustan a celdas de cuatro píxeles. Diferencias de hasta ocho en cada eje producen un primer roce; de hasta tres, un impacto. La invulnerabilidad solo impide los impactos. dm_hit/dm_graze se restablecen en cada llamada; cada proyectil solo registra un roce. Los ID de tile 0..15 codifican los cuatro bits de cuadrante; se sustituyen los tiles de decoración ocupados con ID 16 o superior.
Ejemplo de uso
dm_player_x=0;dm_player_y=0;dm_invulnerable=0;for(i=0;i<8;i++){danmaku_clear_map();danmaku_step();}result[12]=dm_count;result[13]=dm_hit;result[14]=dm_graze;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Ejemplo de dibujo exclusivo de CGB. Genera ocho direcciones en (80,64), actualiza ocho veces y muestra ocho puntos rojos de 3×3 en disposición radial. Los proyectiles cardinales recorren 32 píxeles; las diagonales usan una aproximación entera. También comprueba el vaciado del pool y la conservación del total de creaciones.

Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_danmaku.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_danmaku.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=noneImplementación y código fuente
kitaqgb/lib/danmaku.h:45
Caller fills decoration after clear_map, then calls step to overlay bullets. hit and graze are events for this step. Collision uses rendered centers.
kitaqgb/lib/danmaku.c:99
void danmaku_step() {
// One linear pass. No per-bullet bank calls, multiplication or division.
// The 8-byte packed public layout is x16,y16,vx8,vy8,active,graze.
__asm {
XOR_A
LD_MEM_A dm_hit
LD_MEM_A dm_graze
LD_A_IMM 96
LD_MEM_A dm_remaining
LD_HL_IMM dm_bullets
dm_tick_loop:
PUSH_HL
LD_BC_IMM 6
ADD_HL_BC
LD_A_HL
OR_A
JP_Z dm_tick_next
DEC_HL
LD_A_HL
LD_MEM_A dm_vy
DEC_HL
LD_A_HL
LD_C_A
LD_B_IMM 0
AND_IMM 128
JR_Z dm_tick_xsign
DEC_B
// B:C is the sign-extended X velocity. Add to Q12.4 position; high byte >=10 also rejects negative X.
dm_tick_xsign:
POP_HL
PUSH_HL
LD_A_HL
ADD_C
LDI_HL_A
LD_E_A
LD_A_HL
ADC_B
LDI_HL_A
CP_IMM 10
JP_NC dm_tick_kill
RRCA
RRCA
RRCA
RRCA
LD_D_A
LD_A_E
RRCA
RRCA
RRCA
RRCA
AND_IMM 15
OR_D
LD_MEM_A dm_px
LD_A_MEM dm_vy
LD_C_A
LD_B_IMM 0
AND_IMM 128
JR_Z dm_tick_ysign
DEC_B
// Apply signed Y velocity similarly; high byte >=8 rejects negative Y and positions at or below 128 pixels.
dm_tick_ysign:
LD_A_HL
ADD_C
LDI_HL_A
LD_E_A
LD_A_HL
ADC_B
LDI_HL_A
CP_IMM 8
JP_NC dm_tick_kill
RRCA
RRCA
RRCA
RRCA
LD_D_A
LD_A_E
RRCA
RRCA
RRCA
RRCA
AND_IMM 15
OR_D
LD_MEM_A dm_py
// Signed differences shifted into 0..16 for a wrap-safe range test.
// Rendered centers are (pixel & FC)+2. Test a square of radius eight around the player for graze eligibility.
LD_A_MEM dm_player_x
LD_C_A
LD_A_MEM dm_px
AND_IMM 252
ADD_A_IMM 10
SUB_C
CP_IMM 17
JR_NC dm_tick_plot
LD_B_A
LD_A_MEM dm_player_y
LD_C_A
LD_A_MEM dm_py
AND_IMM 252
ADD_A_IMM 10
SUB_C
CP_IMM 17
JR_NC dm_tick_plot
LD_C_A
INC_HL
INC_HL
INC_HL
LD_A_HL
OR_A
JR_NZ dm_tick_check_hit
LD_A_IMM 1
LD_HL_A
LD_A_MEM dm_graze
INC_A
LD_MEM_A dm_graze
// A bullet grazes at most once during its lifetime. Invulnerability suppresses hits, but not first-graze events.
// The inner hit test uses a square of radius three around the same quantized center.
dm_tick_check_hit:
LD_A_MEM dm_invulnerable
OR_A
JR_NZ dm_tick_plot
LD_A_B
SUB_IMM 5
CP_IMM 7
JR_NC dm_tick_plot
LD_A_C
SUB_IMM 5
CP_IMM 7
JR_NC dm_tick_plot
LD_A_IMM 1
LD_MEM_A dm_hit
// Select one of four quadrant bits from pixel bit 2, then address map[(y>>3)*32+(x>>3)].
// Decoration IDs >=16 are replaced at occupied cells; bullet IDs 0..15 merge with OR.
dm_tick_plot:
LD_A_MEM dm_py
AND_IMM 4
AND_IMM 254
RRCA
LD_B_A
LD_A_MEM dm_px
AND_IMM 4
AND_IMM 254
RRCA
AND_IMM 254
RRCA
OR_B
LD_E_A
LD_D_IMM 0
LD_HL_IMM dm_bits
ADD_HL_DE
LD_A_HL
LD_C_A
LD_A_MEM dm_py
AND_IMM 120
LD_L_A
LD_H_IMM 0
ADD_HL_HL
ADD_HL_HL
LD_A_MEM dm_px
AND_IMM 254
RRCA
AND_IMM 254
RRCA
AND_IMM 254
RRCA
LD_E_A
LD_D_IMM 0
ADD_HL_DE
LD_DE_IMM dm_map
ADD_HL_DE
LD_A_HL
CP_IMM 16
JR_C dm_tick_merge
XOR_A
dm_tick_merge:
OR_C
LD_HL_A
JR dm_tick_next
// Restore the saved record base, clear active at offset six and decrement the live count exactly once.
dm_tick_kill:
POP_HL
PUSH_HL
LD_BC_IMM 6
ADD_HL_BC
XOR_A
LD_HL_A
LD_A_MEM dm_count
DEC_A
LD_MEM_A dm_count
// Restore the saved base even for inactive or culled bullets, then advance by the fixed eight-byte record size.
dm_tick_next:
POP_HL
LD_BC_IMM 8
ADD_HL_BC
LD_A_MEM dm_remaining
DEC_A
LD_MEM_A dm_remaining
JP_NZ dm_tick_loop
RET
}
}debug.h — Registros y aserciones en RAM
Registra nombres, valores y etiquetas de fotograma en un registro de RAM de capacidad fija. Las aserciones conservan información de diagnóstico y permiten continuar la ejecución.
debug_assert_fail
Conserva un código de fallo de aserción e intenta añadir una entrada ASSERT.
Sintaxis
void debug_assert_fail(u16 code);Parámetros
codeIdentificador de error de 16 bits que se va a conservar.
Valor devuelto
No devuelve ningún valor.
Condiciones y límites
La ejecución continúa. El último código de aserción se actualiza incluso si el registro está lleno. El registro admite 32 entradas de forma predeterminada y descarta las nuevas cuando está lleno. Si redefines DEBUG_TRACE_MAX, usa el mismo valor de 1 a 255 en todas las unidades de traducción. Los nombres se conservan como punteros, sin copiarse; su memoria debe seguir siendo legible hasta finalizar la inspección. Coordina las escrituras del código principal y las interrupciones para que no se solapen.
Ejemplo de uso
debug_assert_fail(42);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo registra el código 42, llena el registro y después registra el código 999. El recuento permanece en 32, pero el último código pasa a ser 999.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_debug.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_debug.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/debug.h:33
Record the assertion code and attempt to append an ASSERT entry. This helper does not halt execution, and the code is retained even if the log is full.
kitaqgb/lib/debug.c:56
void debug_assert_fail(u16 code)
{
kq_debug_last_assert = code;
debug_push((const u8*)"ASSERT", code);
}debug_get_last_assert
Lee el último código de aserción independientemente del espacio disponible en el registro.
Sintaxis
u16 debug_get_last_assert();Valor devuelto
Devuelve el último código de 16 bits; tras la inicialización, su valor es cero.
Condiciones y límites
Cero también es el valor inicial, por lo que no permite distinguir un fallo registrado con código cero. La lectura no borra el código.
Ejemplo de uso
result[22]=debug_get_last_assert();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo comprueba 77 desde la macro de aserción, 999 después de llenar el registro y cero tras reinicializarlo.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_debug.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_debug.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/debug.h:39
Read the last recorded assertion code, or the zero value installed by initialization.
kitaqgb/lib/debug.c:75
u16 debug_get_last_assert()
{
return kq_debug_last_assert;
}debug_get_trace_count
Lee el número de entradas válidas de la matriz de trazas.
Sintaxis
u8 debug_get_trace_count();Valor devuelto
Devuelve un recuento entre cero y DEBUG_TRACE_MAX.
Condiciones y límites
El registro admite 32 entradas de forma predeterminada y descarta las nuevas cuando está lleno. Si redefines DEBUG_TRACE_MAX, usa el mismo valor de 1 a 255 en todas las unidades de traducción. Los nombres se conservan como punteros, sin copiarse; su memoria debe seguir siendo legible hasta finalizar la inspección. Coordina las escrituras del código principal y las interrupciones para que no se solapen.
Ejemplo de uso
result[1]=debug_get_trace_count();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo verifica las diez entradas iniciales y el límite de 32 tras más escrituras; el recuento no vuelve a cero cuando se llena.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_debug.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_debug.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/debug.h:35
Return the number of valid entries in the fixed trace buffer.
kitaqgb/lib/debug.c:63
u8 debug_get_trace_count()
{
return kq_debug_trace_count;
}debug_get_trace_log
Obtiene una referencia a la matriz interna para inspeccionar los nombres, valores y etiquetas de fotograma registrados.
Sintaxis
const DebugTraceEntry* debug_get_trace_log();Valor devuelto
Devuelve un puntero de solo lectura a la matriz interna DebugTraceEntry.
Condiciones y límites
No es una copia. Lee solo el número de entradas indicado por debug_get_trace_count(). Los bytes antiguos que quedan tras inicializar no son registros válidos. El registro admite 32 entradas de forma predeterminada y descarta las nuevas cuando está lleno. Si redefines DEBUG_TRACE_MAX, usa el mismo valor de 1 a 255 en todas las unidades de traducción. Los nombres se conservan como punteros, sin copiarse; su memoria debe seguir siendo legible hasta finalizar la inspección. Coordina las escrituras del código principal y las interrupciones para que no se solapen.
Ejemplo de uso
entries=debug_get_trace_log();for(i=0;i<10;i++){result[2+i]=entries[i].value;result[12+i]=entries[i].frame;}Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo lee los diez campos de valor y fotograma y comprueba la B inicial de la etiqueta BEGIN.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_debug.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_debug.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/debug.h:37
Expose the internal trace array for inspection; use the count to bound reads.
kitaqgb/lib/debug.c:69
const DebugTraceEntry* debug_get_trace_log()
{
return kq_debug_trace_log;
}debug_init
Inicializa la longitud válida del registro, la etiqueta de fotograma y el último código de aserción.
Sintaxis
void debug_init();Valor devuelto
No devuelve ningún valor.
Condiciones y límites
No borra los bytes de las entradas existentes. Llama a esta función antes de registrar la primera entrada. El registro admite 32 entradas de forma predeterminada y descarta las nuevas cuando está lleno. Si redefines DEBUG_TRACE_MAX, usa el mismo valor de 1 a 255 en todas las unidades de traducción. Los nombres se conservan como punteros, sin copiarse; su memoria debe seguir siendo legible hasta finalizar la inspección. Coordina las escrituras del código principal y las interrupciones para que no se solapen.
Ejemplo de uso
debug_init();result[0]=debug_get_trace_count();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo comprueba que el recuento inicial sea cero y después reinicia un registro con datos. Verifica que se borren el recuento y el código de aserción, mientras se conservan los valores anteriores de la matriz.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_debug.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_debug.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/debug.h:22
Reset log length, frame tag and last assertion code; existing entry bytes are not erased.
kitaqgb/lib/debug.c:10
void debug_init()
{
kq_debug_trace_count = 0;
kq_debug_frame = 0;
kq_debug_last_assert = 0;
}debug_mark_frame
Registra un marcador de fotograma con nombre para identificar un punto del flujo de ejecución.
Sintaxis
void debug_mark_frame(const u8* label);Parámetros
labelEtiqueta terminada en cero cuya memoria debe permanecer legible hasta la inspección.
Valor devuelto
No devuelve ningún valor.
Condiciones y límites
El registro admite 32 entradas de forma predeterminada y descarta las nuevas cuando está lleno. Si redefines DEBUG_TRACE_MAX, usa el mismo valor de 1 a 255 en todas las unidades de traducción. Los nombres se conservan como punteros, sin copiarse; su memoria debe seguir siendo legible hasta finalizar la inspección. Coordina las escrituras del código principal y las interrupciones para que no se solapen.
Ejemplo de uso
debug_mark_frame("BEGIN");Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Al añadir el marcador BEGIN, se registra el valor 65535 (0xFFFF) con la etiqueta de fotograma 513.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_debug.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_debug.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/debug.h:26
Append a named frame marker using 0xFFFF as its value.
kitaqgb/lib/debug.c:37
void debug_mark_frame(const u8* label)
{
debug_push(label, 0xFFFF);
}debug_set_frame
Establece la etiqueta de fotograma que se copiará en las entradas posteriores.
Sintaxis
void debug_set_frame(u16 frame);Parámetros
frameNúmero de fotograma de 16 bits para las entradas posteriores.
Valor devuelto
No devuelve ningún valor.
Condiciones y límites
No espera un fotograma ni incrementa la etiqueta automáticamente. Pasa explícitamente el contador de fotogramas del juego. El registro admite 32 entradas de forma predeterminada y descarta las nuevas cuando está lleno. Si redefines DEBUG_TRACE_MAX, usa el mismo valor de 1 a 255 en todas las unidades de traducción. Los nombres se conservan como punteros, sin copiarse; su memoria debe seguir siendo legible hasta finalizar la inspección. Coordina las escrituras del código principal y las interrupciones para que no se solapen.
Ejemplo de uso
debug_set_frame(513);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo establece 513, registra diez entradas y lee sus diez campos de fotograma para verificar la etiqueta.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_debug.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_debug.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/debug.h:24
Set the frame tag copied into subsequently recorded entries.
kitaqgb/lib/debug.c:18
void debug_set_frame(u16 frame)
{
kq_debug_frame = frame;
}debug_trace_u16
Registra una puntuación o contador de 16 bits con nombre.
Sintaxis
void debug_trace_u16(const u8* name, u16 value);Parámetros
nameEtiqueta terminada en cero cuya memoria debe permanecer legible hasta la inspección.
valueValor de 0 a 65535 que se va a registrar.
Valor devuelto
No devuelve ningún valor.
Condiciones y límites
El registro admite 32 entradas de forma predeterminada y descarta las nuevas cuando está lleno. Si redefines DEBUG_TRACE_MAX, usa el mismo valor de 1 a 255 en todas las unidades de traducción. Los nombres se conservan como punteros, sin copiarse; su memoria debe seguir siendo legible hasta finalizar la inspección. Coordina las escrituras del código principal y las interrupciones para que no se solapen.
Ejemplo de uso
debug_trace_u16("WORD",4660);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La entrada WORD almacena 4660 (0x1234), y el ejemplo vuelve a leerla para comprobar ambos bytes.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_debug.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_debug.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/debug.h:30
Append a 16-bit value with the current frame tag.
kitaqgb/lib/debug.c:49
void debug_trace_u16(const u8* name, u16 value)
{
debug_push(name, value);
}debug_trace_u8
Registra un valor de estado de ocho bits con su nombre y la etiqueta de fotograma actual.
Sintaxis
void debug_trace_u8(const u8* name, u8 value);Parámetros
nameEtiqueta terminada en cero cuya memoria debe permanecer legible hasta la inspección.
valueValor de 0 a 255, extendido con ceros al campo de 16 bits del registro.
Valor devuelto
No devuelve ningún valor.
Condiciones y límites
El registro admite 32 entradas de forma predeterminada y descarta las nuevas cuando está lleno. Si redefines DEBUG_TRACE_MAX, usa el mismo valor de 1 a 255 en todas las unidades de traducción. Los nombres se conservan como punteros, sin copiarse; su memoria debe seguir siendo legible hasta finalizar la inspección. Coordina las escrituras del código principal y las interrupciones para que no se solapen.
Ejemplo de uso
debug_trace_u8("BYTE",255);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La entrada BYTE registra 255 y comprueba que el campo de valor de 16 bits contenga 255.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_debug.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_debug.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/debug.h:28
Append an unsigned byte value, widened to the log's 16-bit value field.
kitaqgb/lib/debug.c:43
void debug_trace_u8(const u8* name, u8 value)
{
debug_push(name, (u16)value);
}KITAQGB_ASSERT
Macro que se usa como una sentencia y registra el código de aserción 1 cuando su condición es falsa.
Sintaxis
#define KITAQGB_ASSERT(cond) do { if (!(cond)) debug_assert_fail((u16)1); } while (0)Parámetros
condCondición que debería cumplirse; cero significa un fallo.
Valor devuelto
No devuelve ningún valor.
Condiciones y límites
La condición se evalúa una vez. Si es verdadera no registra nada; si es falsa registra el fallo sin detener la ejecución. Su forma do…while (0) permite usarla como una sola sentencia en un if…else.
Ejemplo de uso
KITAQGB_ASSERT(1);KITAQGB_ASSERT(0);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Una aserción verdadera y otra falsa producen exactamente una entrada con código 1.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_debug.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_debug.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/debug.h:45
#define KITAQGB_ASSERT(cond) do { if (!(cond)) debug_assert_fail((u16)1); } while (0)KITAQGB_ASSERT_CODE
Registra el código de aserción elegido solo si la condición es falsa.
Sintaxis
#define KITAQGB_ASSERT_CODE(cond, code) do { if (!(cond)) debug_assert_fail((u16)(code)); } while (0)Parámetros
condCondición que debería cumplirse.
codeExpresión del código que se evalúa al fallar y se convierte a 16 bits.
Valor devuelto
No devuelve ningún valor.
Condiciones y límites
La condición se evalúa una vez; la expresión del código solo se evalúa si falla. La ejecución continúa después de registrar el resultado.
Ejemplo de uso
KITAQGB_ASSERT_CODE(1,++side_effect);KITAQGB_ASSERT_CODE(0,77);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Si la condición es verdadera, no se evalúa la expresión de código ++side_effect y la variable permanece en cero. Una condición falsa registra el código 77.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_debug.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_debug.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/debug.h:46
#define KITAQGB_ASSERT_CODE(cond, code) do { if (!(cond)) debug_assert_fail((u16)(code)); } while (0)KITAQGB_MARK_FRAME
Convierte una etiqueta a puntero de cadena y añade un marcador de fotograma con valor 0xFFFF.
Sintaxis
#define KITAQGB_MARK_FRAME(label) debug_mark_frame((const u8*)(label))Parámetros
labelEtiqueta terminada en cero cuya memoria debe permanecer legible hasta la inspección.
Valor devuelto
No devuelve ningún valor.
Condiciones y límites
El registro admite 32 entradas de forma predeterminada y descarta las nuevas cuando está lleno. Si redefines DEBUG_TRACE_MAX, usa el mismo valor de 1 a 255 en todas las unidades de traducción. Los nombres se conservan como punteros, sin copiarse; su memoria debe seguir siendo legible hasta finalizar la inspección. Coordina las escrituras del código principal y las interrupciones para que no se solapen.
Ejemplo de uso
KITAQGB_MARK_FRAME("END");Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Se comprueba que el marcador END tenga el valor 65535 y la etiqueta de fotograma 513.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_debug.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_debug.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/debug.h:44
#define KITAQGB_MARK_FRAME(label) debug_mark_frame((const u8*)(label))KITAQGB_TRACE
Convierte explícitamente un valor a 16 bits y lo registra con su nombre.
Sintaxis
#define KITAQGB_TRACE(name, value) debug_trace_u16((const u8*)(name), (u16)(value))Parámetros
nameEtiqueta terminada en cero cuya memoria debe permanecer legible hasta la inspección.
valueExpresión que se convierte a 16 bits antes de registrarse.
Valor devuelto
No devuelve ningún valor.
Condiciones y límites
La macro siempre está activa; la configuración de compilación no la desactiva automáticamente. Registra valores de 16 bits igual que KITAQGB_TRACE_U16. El registro admite 32 entradas de forma predeterminada y descarta las nuevas cuando está lleno. Si redefines DEBUG_TRACE_MAX, usa el mismo valor de 1 a 255 en todas las unidades de traducción. Los nombres se conservan como punteros, sin copiarse; su memoria debe seguir siendo legible hasta finalizar la inspección. Coordina las escrituras del código principal y las interrupciones para que no se solapen.
Ejemplo de uso
KITAQGB_TRACE("SCORE",600);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo registra 600 y vuelve a leer el valor para verificarlo.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_debug.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_debug.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/debug.h:43
#define KITAQGB_TRACE(name, value) debug_trace_u16((const u8*)(name), (u16)(value))KITAQGB_TRACE_U16
Convierte explícitamente un valor a 16 bits y lo registra con su nombre.
Sintaxis
#define KITAQGB_TRACE_U16(name, value) debug_trace_u16((const u8*)(name), (u16)(value))Parámetros
nameEtiqueta terminada en cero cuya memoria debe permanecer legible hasta la inspección.
valueExpresión que se convierte a 16 bits antes de registrarse.
Valor devuelto
No devuelve ningún valor.
Condiciones y límites
La macro siempre está activa; la configuración de compilación no la desactiva automáticamente. El registro admite 32 entradas de forma predeterminada y descarta las nuevas cuando está lleno. Si redefines DEBUG_TRACE_MAX, usa el mismo valor de 1 a 255 en todas las unidades de traducción. Los nombres se conservan como punteros, sin copiarse; su memoria debe seguir siendo legible hasta finalizar la inspección. Coordina las escrituras del código principal y las interrupciones para que no se solapen.
Ejemplo de uso
KITAQGB_TRACE_U16("WORD2",500);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo registra 500 y vuelve a leer el valor para verificarlo.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_debug.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_debug.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/debug.h:42
#define KITAQGB_TRACE_U16(name, value) debug_trace_u16((const u8*)(name), (u16)(value))KITAQGB_TRACE_U8
Convierte explícitamente un valor a ocho bits y lo registra con su nombre.
Sintaxis
#define KITAQGB_TRACE_U8(name, value) debug_trace_u8((const u8*)(name), (u8)(value))Parámetros
nameEtiqueta terminada en cero cuya memoria debe permanecer legible hasta la inspección.
valueExpresión que se convierte a ocho bits antes de registrarse.
Valor devuelto
No devuelve ningún valor.
Condiciones y límites
La macro siempre está activa; la configuración de compilación no la desactiva automáticamente. El registro admite 32 entradas de forma predeterminada y descarta las nuevas cuando está lleno. Si redefines DEBUG_TRACE_MAX, usa el mismo valor de 1 a 255 en todas las unidades de traducción. Los nombres se conservan como punteros, sin copiarse; su memoria debe seguir siendo legible hasta finalizar la inspección. Coordina las escrituras del código principal y las interrupciones para que no se solapen.
Ejemplo de uso
KITAQGB_TRACE_U8("CAST",0x1234);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo registra 52. Solo se conserva el byte menos significativo 0x34 de 0x1234.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_debug.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_debug.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/debug.h:41
#define KITAQGB_TRACE_U8(name, value) debug_trace_u8((const u8*)(name), (u8)(value))dmg3d.h — Gráficos de alambre monocromos de 128×120 para DMG
Dibujo de líneas 3D monocromas. Proporciona vértices, aristas y caras del modelo, además de posición, rotación y escala del objeto. Sigue el orden de inicialización, inicio del fotograma, dibujo y transferencia. La física se gestiona aparte. Los ángulos tienen dieciséis pasos por vuelta; la escala 256 equivale a la unidad.
Vec3 contiene x/y/z, Edge los índices de vértice a/b y Face los índices del triángulo a/b/c. Los campos vertices, edges y faces de Model apuntan a esos arrays; cada contador indica su longitud. edge_faces contiene los índices de caras adyacentes f0/f1, con FACE_NONE para una cara ausente. MODEL_HIDDEN_LINES en flags solicita selección de aristas basada en caras. El área proyectada con signo determina la orientación de la cara, por lo que importa el orden de los vértices.
Object guarda una referencia al modelo, posición x/y/z, ángulos rx/ry/rz, scale_q8 y visible. Los objetos pueden compartir un modelo, pero el dibujo no copia tablas ni cambia automáticamente sus bancos ROM. Mantén legibles los datos referenciados durante todo el dibujo. Object de CGB también tiene un índice de color.
DMG3D_BeginFrame
Inicia el dibujo de un fotograma y desactiva la prueba de oclusión.
Sintaxis
void DMG3D_BeginFrame();Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 120. Solo desactiva el filtrado de oclusión. El área de preparación suele borrarse durante la transferencia; Init proporciona la primera área limpia. No descarta un fotograma aún no enviado, no borra la máscara ni reinicia las escrituras BG pendientes o las marcas de cambios.
Este ejemplo usa el perfil 128×120; su ventana gráfica empieza en (16,8) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
Ejemplo de uso
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
DMG3D_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
DMG3D_SetCamera(8,0,0,0,0,0);
result[1]=DMG3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
result[2]=projected_x; result[3]=projected_y;
projected_x=91; projected_y=92;
result[4]=DMG3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
result[5]=projected_x; result[6]=projected_y;
DMG3D_SetCamera(0,0,0,0,0,0);
DMG3D_BeginFrame();
DMG3D_DrawLine2D(8,8,56,8);
DMG3D_DrawLine2D(56,8,56,40);
DMG3D_DrawLine2D(56,40,8,40);
DMG3D_DrawLine2D(8,40,8,8);
DMG3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
DMG3D_DrawLine3D(-24,-24,96,24,24,96);
// Copy the viewport's top-left frame corner to a separate map cell.
DMG3D_PutBgTile(1,1,160);
DMG3D_EndFrame();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Este ejemplo muestra líneas, puntos, borrado y proyección en un fotograma. Se borra el centro del borde superior del marco de arriba a la izquierda y se proyecta una diagonal cerca del centro. Una proyección rechazada conserva las salidas 91 y 92.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_raster.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/dmg3d.h:17
WIRE3D_DMG_HEIGHT = 120. Disable occlusion filtering only. Stage clearing normally happens during transfer, and Init supplies the first clean stage. This does not discard an unsubmitted frame, clear the mask, or reset pending BG writes/dirty flags.
kitaqgb/lib/wire3d_dmg.c:2641
void Wire3DDMG_BeginFrame()
{
/* The consuming stage transfer clears D000 as it uploads, so BeginFrame only
resets draw state. Wire3DDMG_Init supplies the first clean buffer. */
w3ddmg_occlusion_active = 0;
}DMG3D_DrawIndexedEdges
Dibuja un modelo de líneas con escala entera a partir de vértices y pares de índices de arista de dos bytes.
Sintaxis
void DMG3D_DrawIndexedEdges(const Wire3DDMG_Vec3* vertices, w3ddmg_u8 vertex_count, const w3ddmg_u8* edges, w3ddmg_u8 edge_count, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 scale);Parámetros
verticesArray de vértices 3D.
vertex_countCantidad de entradas del array de vértices.
edgesÍndices de los vértices de cada arista, en el formato declarado de estructura o de pares de bytes.
edge_countCantidad de aristas.
xComponente X del punto o del origen del objeto en coordenadas del mundo.
yComponente Y del punto o del origen del objeto en coordenadas del mundo.
zComponente Z del punto o del origen del objeto en coordenadas del mundo.
scaleEscala entera; cero se interpreta como uno.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 120. Dibuja aristas indexadas por pares de bytes tras escalado entero y traslación; escala cero significa uno y no hay rotación de objeto ni filtrado de caras. Proyecta hasta 24 vértices. Proporciona como máximo 128 pares de aristas, ya que los desplazamientos de byte vuelven a cero después de 255. Omite ID de vértice inválidos y extremos rechazados por profundidad; ignora arrays null. Los productos y sumas de coordenadas deben poder representarse en s16.
Este ejemplo usa el perfil 128×120; su ventana gráfica empieza en (16,8) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
Ejemplo de uso
#pragma bank 0
// Upload a main line and an auxiliary block separately; verify source consumption.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom DMG3D_Vec3 vertices[2]={{-32,0,0},{32,0,0}};
__prg_rom u8 edge_pairs[2]={0,1};
u8* stage_byte;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
DMG3D_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
DMG3D_BeginFrame();
DMG3D_DrawIndexedEdges(vertices,2,edge_pairs,1,-64,104,96,1);
DMG3D_TransferMainNow();
// Direct auxiliary transfer writes a separate tile after the main upload.
for(i=24;i<=31;i++) DMG3D_DrawLine2D(40,i,47,i);
stage_byte=(u8*)0xD518;result[1]=*stage_byte;
DMG3D_TransferAuxNow();result[2]=*stage_byte;
// Do not upload the consumed stage again.
result[7]=0xA55A; while(1) {}
}Resultado esperado
Una línea horizontal proyectada y un bloque auxiliar de 8×8 muestran las transferencias directas; un byte fuente pasa de 255 a 0 al consumirse.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_direct.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_direct.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/dmg3d.h:20
WIRE3D_DMG_HEIGHT = 120. Draw byte-pair edge indices after integer scaling and translation; scale zero means one, and there is no object rotation or face filtering. Project at most 24 vertices. Supply at most 128 edge pairs because byte offsets wrap after 255. Invalid vertex IDs/depth-rejected endpoints are skipped; null arrays are ignored. Keep coordinate products/sums representable as s16.
kitaqgb/lib/wire3d_dmg.c:3824
void Wire3DDMG_DrawIndexedEdges(const Wire3DDMG_Vec3* vertices, w3ddmg_u8 vertex_count, const w3ddmg_u8* edges, w3ddmg_u8 edge_count, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 scale)
{
w3ddmg_u8 i;
w3ddmg_u8 count;
if (vertices == 0) return;
if (edges == 0) return;
count = vertex_count;
if (count > WIRE3D_DMG_MODEL_VERTEX_LIMIT) count = WIRE3D_DMG_MODEL_VERTEX_LIMIT;
if (scale == 0) scale = 1;
i = 0;
while (i < count)
{
const Wire3DDMG_Vec3* v;
w3ddmg_i16 vx;
w3ddmg_i16 vy;
w3ddmg_i16 vz;
w3ddmg_u8 sx;
w3ddmg_u8 sy;
v = &vertices[(__safe_index w3ddmg_u8)i];
vx = (w3ddmg_i16)(x + (w3ddmg_i16)(v->x * scale));
vy = (w3ddmg_i16)(y + (w3ddmg_i16)(v->y * scale));
vz = (w3ddmg_i16)(z + (w3ddmg_i16)(v->z * scale));
if (w3ddmg_project_world(vx, vy, vz, &sx, &sy))
{
w3ddmg_screen_x[(__safe_index w3ddmg_u8)i] = sx;
w3ddmg_screen_y[(__safe_index w3ddmg_u8)i] = sy;
w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 1;
}
else
{
w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 0;
}
i = (w3ddmg_u8)(i + 1);
}
i = 0;
while (i < edge_count)
{
w3ddmg_u8 a;
w3ddmg_u8 b;
a = edges[(__safe_index w3ddmg_u8)((w3ddmg_u8)(i << 1))];
b = edges[(__safe_index w3ddmg_u8)((w3ddmg_u8)((i << 1) + 1))];
if ((a < count) && (b < count) &&
w3ddmg_screen_visible[(__safe_index w3ddmg_u8)a] &&
w3ddmg_screen_visible[(__safe_index w3ddmg_u8)b])
{
Wire3DDMG_DrawLine2D(
w3ddmg_screen_x[(__safe_index w3ddmg_u8)a],
w3ddmg_screen_y[(__safe_index w3ddmg_u8)a],
w3ddmg_screen_x[(__safe_index w3ddmg_u8)b],
w3ddmg_screen_y[(__safe_index w3ddmg_u8)b]);
}
i = (w3ddmg_u8)(i + 1);
}
}DMG3D_DrawLine2D
Dibuja en el área de preparación una línea de pantalla con conectividad de cuatro vecinos, incluidos los extremos.
Sintaxis
void DMG3D_DrawLine2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by);Parámetros
axCoordenada X del vértice A en píxeles de la ventana gráfica.
ayCoordenada Y del vértice A en píxeles de la ventana gráfica.
bxCoordenada X del vértice B en píxeles de la ventana gráfica.
byCoordenada Y del vértice B en píxeles de la ventana gráfica.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 120. Si está habilitada la transferencia de zonas modificadas, marca el rectángulo envolvente de tiles y dibuja una línea conectada en el área de preparación. El dibujo de escenas puede rechazarla mediante cinco muestras de máscara. Proporciona extremos dentro de la ventana gráfica de 128×120; las comprobaciones de límites de píxel de bajo nivel no recortan geométricamente el segmento.
Este ejemplo usa el perfil 128×120; su ventana gráfica empieza en (16,8) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
Ejemplo de uso
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
DMG3D_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
DMG3D_SetCamera(8,0,0,0,0,0);
result[1]=DMG3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
result[2]=projected_x; result[3]=projected_y;
projected_x=91; projected_y=92;
result[4]=DMG3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
result[5]=projected_x; result[6]=projected_y;
DMG3D_SetCamera(0,0,0,0,0,0);
DMG3D_BeginFrame();
DMG3D_DrawLine2D(8,8,56,8);
DMG3D_DrawLine2D(56,8,56,40);
DMG3D_DrawLine2D(56,40,8,40);
DMG3D_DrawLine2D(8,40,8,8);
DMG3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
DMG3D_DrawLine3D(-24,-24,96,24,24,96);
// Copy the viewport's top-left frame corner to a separate map cell.
DMG3D_PutBgTile(1,1,160);
DMG3D_EndFrame();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Este ejemplo muestra líneas, puntos, borrado y proyección en un fotograma. Se borra el centro del borde superior del marco de arriba a la izquierda y se proyecta una diagonal cerca del centro. Una proyección rechazada conserva las salidas 91 y 92.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_raster.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/dmg3d.h:21
WIRE3D_DMG_HEIGHT = 120. Mark the bounding tile rectangle when dirty transfer is enabled, then draw a connected staged line. Scene drawing may reject it using five mask samples. Supply 128x120 viewport endpoints; low-level pixel bounds checks do not clip the segment geometrically.
kitaqgb/lib/wire3d_dmg.c:2685
void Wire3DDMG_DrawLine2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by)
{
w3ddmg_mark_line_dirty(ax, ay, bx, by);
if (w3ddmg_occlusion_active)
{
w3ddmg_line_stage_masked_c(ax, ay, bx, by);
return;
}
w3ddmg_line_x0 = ax;
w3ddmg_line_y0 = ay;
w3ddmg_line_x1 = bx;
w3ddmg_line_y1 = by;
if (ax < 128 && bx < 128 && ay < WIRE3D_DMG_SCREEN_H && by < WIRE3D_DMG_SCREEN_H)
w3ddmg_line_inside_asm();
else
w3ddmg_line_stage_asm();
}DMG3D_DrawLine3D
Proyecta dos extremos en coordenadas del mundo y dibuja una línea entre ellos.
Sintaxis
void DMG3D_DrawLine3D(w3ddmg_i16 ax, w3ddmg_i16 ay, w3ddmg_i16 az, w3ddmg_i16 bx, w3ddmg_i16 by, w3ddmg_i16 bz);Parámetros
axComponente X del punto inicial en coordenadas del mundo.
ayComponente Y del punto inicial en coordenadas del mundo.
azComponente Z del punto inicial en coordenadas del mundo.
bxComponente X del punto final en coordenadas del mundo.
byComponente Y del punto final en coordenadas del mundo.
bzComponente Z del punto final en coordenadas del mundo.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 120. Proyecta ambos extremos del mundo y solo dibuja si los dos pasan el rango de profundidad. No calcula intersecciones de segmentos que crucen los planos cercano o lejano; cada extremo proyectado se limita por separado a los bordes de pantalla.
Este ejemplo usa el perfil 128×120; su ventana gráfica empieza en (16,8) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
Ejemplo de uso
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
DMG3D_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
DMG3D_SetCamera(8,0,0,0,0,0);
result[1]=DMG3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
result[2]=projected_x; result[3]=projected_y;
projected_x=91; projected_y=92;
result[4]=DMG3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
result[5]=projected_x; result[6]=projected_y;
DMG3D_SetCamera(0,0,0,0,0,0);
DMG3D_BeginFrame();
DMG3D_DrawLine2D(8,8,56,8);
DMG3D_DrawLine2D(56,8,56,40);
DMG3D_DrawLine2D(56,40,8,40);
DMG3D_DrawLine2D(8,40,8,8);
DMG3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
DMG3D_DrawLine3D(-24,-24,96,24,24,96);
// Copy the viewport's top-left frame corner to a separate map cell.
DMG3D_PutBgTile(1,1,160);
DMG3D_EndFrame();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Este ejemplo muestra líneas, puntos, borrado y proyección en un fotograma. Se borra el centro del borde superior del marco de arriba a la izquierda y se proyecta una diagonal cerca del centro. Una proyección rechazada conserva las salidas 91 y 92.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_raster.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/dmg3d.h:22
WIRE3D_DMG_HEIGHT = 120. Project both world endpoints and draw only when both pass the depth range. Do not intersect a crossing segment with near/far planes; projected endpoints are independently clamped to the screen edges.
kitaqgb/lib/wire3d_dmg.c:2808
void Wire3DDMG_DrawLine3D(w3ddmg_i16 ax, w3ddmg_i16 ay, w3ddmg_i16 az, w3ddmg_i16 bx, w3ddmg_i16 by, w3ddmg_i16 bz)
{
w3ddmg_u8 sx0;
w3ddmg_u8 sy0;
w3ddmg_u8 sx1;
w3ddmg_u8 sy1;
if (w3ddmg_project_world(ax, ay, az, &sx0, &sy0) == 0) return;
if (w3ddmg_project_world(bx, by, bz, &sx1, &sy1) == 0) return;
Wire3DDMG_DrawLine2D(sx0, sy0, sx1, sy1);
}DMG3D_DrawModel
Dibuja un modelo de vértices y aristas en la posición y con la rotación indicadas, a escala unitaria.
Sintaxis
void DMG3D_DrawModel(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz);Parámetros
modelModelo que contiene los arrays de vértices, aristas y caras y sus cantidades; las tablas deben permanecer legibles durante la llamada.
xComponente X del punto o del origen del objeto en coordenadas del mundo.
yComponente Y del punto o del origen del objeto en coordenadas del mundo.
zComponente Z del punto o del origen del objeto en coordenadas del mundo.
rxRotación alrededor de X; dieciséis pasos forman una vuelta completa.
ryRotación alrededor de Y; dieciséis pasos forman una vuelta completa.
rzRotación alrededor de Z; dieciséis pasos forman una vuelta completa.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 120. Dibuja un modelo sin cambiar su tamaño mediante DrawModelScaled con escala 256.
Este ejemplo usa el perfil 128×120; su ventana gráfica empieza en (16,8) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
Ejemplo de uso
#pragma bank 0
// Compare direct model scaling with an object-array scene.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom DMG3D_Vec3 vertices[8]={{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}};
__prg_rom DMG3D_Edge edges[12]={{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}};
DMG3D_Model cube;
DMG3D_Object objects[2];
s16 px; s16 py; s16 pz;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
DMG3D_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
cube.vertices=vertices;cube.edges=edges;cube.faces=0;cube.edge_faces=0;
cube.vertex_count=8;cube.edge_count=12;cube.face_count=0;cube.flags=0;
DMG3D_BeginFrame();
// Upper pair: direct model calls at unity and half scale.
DMG3D_DrawModel(&cube,-32,32,96,0,0,0);
DMG3D_DrawModelScaled(&cube,32,32,96,0,0,0,128);
// Lower pair: the caller owns both object records and the model tables.
for(i=0;i<2;i++) {
objects[i].model=&cube;objects[i].x=-32+(s16)i*64;
objects[i].y=-32;objects[i].z=96;
objects[i].rx=0;objects[i].ry=0;objects[i].rz=0;
objects[i].scale_q8=256-(s16)i*128;objects[i].visible=1;
}
DMG3D_DrawScene(objects,2);
// Numeric checks cover the operation supplied by this viewport profile.
px=16;py=0;pz=0;DMG3D_RotatePoint(&px,&py,&pz,0,4,0);
result[1]=px; result[2]=py; result[3]=pz;
DMG3D_EndFrame(); result[7]=0xA55A;
while(1) {}
}Resultado esperado
Los modelos a escala unitaria y a media escala aparecen sobre una escena de un array de objetos con esas mismas escalas, para mostrar la proyección y el escalado.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_models.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/dmg3d.h:23
WIRE3D_DMG_HEIGHT = 120. Draw an unscaled model by delegating to DrawModelScaled with scale 256.
kitaqgb/lib/wire3d_dmg.c:2827
void Wire3DDMG_DrawModel(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz)
{
Wire3DDMG_DrawModelScaled(model, x, y, z, rx, ry, rz, 256);
}DMG3D_DrawModelScaled
Escala un modelo, lo rota en orden Y/X/Z, traslada y proyecta sus vértices y dibuja las aristas.
Sintaxis
void DMG3D_DrawModelScaled(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz, w3ddmg_i16 scale_q8);Parámetros
modelModelo que contiene los arrays de vértices, aristas y caras y sus cantidades; las tablas deben permanecer legibles durante la llamada.
xComponente X del punto o del origen del objeto en coordenadas del mundo.
yComponente Y del punto o del origen del objeto en coordenadas del mundo.
zComponente Z del punto o del origen del objeto en coordenadas del mundo.
rxRotación alrededor de X; dieciséis pasos forman una vuelta completa.
ryRotación alrededor de Y; dieciséis pasos forman una vuelta completa.
rzRotación alrededor de Z; dieciséis pasos forman una vuelta completa.
scale_q8Escala con 256 como unidad; los valores no positivos también equivalen a la unidad.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 120. Escala hasta 24 vértices, los rota Y/X/Z, los traslada y proyecta, y recorre todas las entradas de edge_count, un contador de tipo byte, con filtrado opcional por caras adyacentes. El búfer de caras está limitado a 16; las tablas de aristas deben incluir todas las entradas declaradas. Una escala no positiva significa 256. Ignora punteros null de modelo, vértices o aristas. Mantén productos y traslaciones en 16 bits con signo; se descartan las aristas que cruzan límites de profundidad.
Este ejemplo usa el perfil 128×120; su ventana gráfica empieza en (16,8) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
Ejemplo de uso
#pragma bank 0
// Compare direct model scaling with an object-array scene.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom DMG3D_Vec3 vertices[8]={{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}};
__prg_rom DMG3D_Edge edges[12]={{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}};
DMG3D_Model cube;
DMG3D_Object objects[2];
s16 px; s16 py; s16 pz;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
DMG3D_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
cube.vertices=vertices;cube.edges=edges;cube.faces=0;cube.edge_faces=0;
cube.vertex_count=8;cube.edge_count=12;cube.face_count=0;cube.flags=0;
DMG3D_BeginFrame();
// Upper pair: direct model calls at unity and half scale.
DMG3D_DrawModel(&cube,-32,32,96,0,0,0);
DMG3D_DrawModelScaled(&cube,32,32,96,0,0,0,128);
// Lower pair: the caller owns both object records and the model tables.
for(i=0;i<2;i++) {
objects[i].model=&cube;objects[i].x=-32+(s16)i*64;
objects[i].y=-32;objects[i].z=96;
objects[i].rx=0;objects[i].ry=0;objects[i].rz=0;
objects[i].scale_q8=256-(s16)i*128;objects[i].visible=1;
}
DMG3D_DrawScene(objects,2);
// Numeric checks cover the operation supplied by this viewport profile.
px=16;py=0;pz=0;DMG3D_RotatePoint(&px,&py,&pz,0,4,0);
result[1]=px; result[2]=py; result[3]=pz;
DMG3D_EndFrame(); result[7]=0xA55A;
while(1) {}
}Resultado esperado
Los modelos a escala unitaria y a media escala aparecen sobre una escena de un array de objetos con esas mismas escalas, para mostrar la proyección y el escalado.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_models.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/dmg3d.h:24
WIRE3D_DMG_HEIGHT = 120. Scale up to 24 vertices, rotate Y/X/Z, translate and project, then traverse all edge_count entries (a byte count) with optional adjacent-face filtering. Face scratch is capped at 16; edge tables must contain all declared entries. Nonpositive scale means 256. Null model/vertex/edge pointers are ignored. Keep products/translations in signed 16-bit range; depth-crossing edges are dropped.
kitaqgb/lib/wire3d_dmg.c:2972
void Wire3DDMG_DrawModelScaled(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz, w3ddmg_i16 scale_q8)
{
w3ddmg_u8 i;
w3ddmg_u8 count;
w3ddmg_u8 edge_count;
w3ddmg_u8 face_count;
if (model == 0) return;
if (model->vertices == 0) return;
if (model->edges == 0) return;
if (scale_q8 <= 0) scale_q8 = 256;
count = model->vertex_count;
if (count > WIRE3D_DMG_MODEL_VERTEX_LIMIT) count = WIRE3D_DMG_MODEL_VERTEX_LIMIT;
i = 0;
while (i < count)
{
const Wire3DDMG_Vec3* v;
w3ddmg_i16 vx;
w3ddmg_i16 vy;
w3ddmg_i16 vz;
w3ddmg_u8 sx;
w3ddmg_u8 sy;
v = &model->vertices[(__safe_index w3ddmg_u8)i];
vx = (w3ddmg_i16)((v->x * scale_q8) >> 8);
vy = (w3ddmg_i16)((v->y * scale_q8) >> 8);
vz = (w3ddmg_i16)((v->z * scale_q8) >> 8);
w3ddmg_rotate_y(&vx, &vz, ry);
w3ddmg_rotate_x(&vy, &vz, rx);
w3ddmg_rotate_z(&vx, &vy, rz);
vx = (w3ddmg_i16)(vx + x);
vy = (w3ddmg_i16)(vy + y);
vz = (w3ddmg_i16)(vz + z);
if (w3ddmg_project_world(vx, vy, vz, &sx, &sy))
{
w3ddmg_screen_x[(__safe_index w3ddmg_u8)i] = sx;
w3ddmg_screen_y[(__safe_index w3ddmg_u8)i] = sy;
w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 1;
}
else
{
w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 0;
}
i = (w3ddmg_u8)(i + 1);
}
face_count = model->face_count;
if (face_count > WIRE3D_DMG_MODEL_FACE_LIMIT) face_count = WIRE3D_DMG_MODEL_FACE_LIMIT;
if ((model->flags & WIRE3D_DMG_MODEL_HIDDEN_LINES) && (model->faces != 0) && (model->edge_faces != 0))
{
w3ddmg_build_face_visibility(model, count, face_count);
}
edge_count = model->edge_count;
i = 0;
while (i < edge_count)
{
const Wire3DDMG_Edge* e;
e = &model->edges[(__safe_index w3ddmg_u8)i];
if ((e->a < count) && (e->b < count))
{
if (w3ddmg_screen_visible[(__safe_index w3ddmg_u8)e->a] &&
w3ddmg_screen_visible[(__safe_index w3ddmg_u8)e->b] &&
w3ddmg_is_edge_visible(model, i, face_count))
{
Wire3DDMG_DrawLine2D(
w3ddmg_screen_x[(__safe_index w3ddmg_u8)e->a],
w3ddmg_screen_y[(__safe_index w3ddmg_u8)e->a],
w3ddmg_screen_x[(__safe_index w3ddmg_u8)e->b],
w3ddmg_screen_y[(__safe_index w3ddmg_u8)e->b]);
}
}
i = (w3ddmg_u8)(i + 1);
}
}DMG3D_DrawScene
Dibuja hasta ocho objetos de cerca a lejos, usando las caras cercanas para ocultar las aristas posteriores.
Sintaxis
void DMG3D_DrawScene(Wire3DDMG_Object* objects, w3ddmg_u8 count);Parámetros
objectsArray de objetos con posiciones, rotaciones, escalas e indicadores de visibilidad.
countCantidad de entradas proporcionadas; consulta el límite de procesamiento de cada operación.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 120. Ordena hasta ocho orígenes de objeto de cerca a lejos por su profundidad de cámara. Dibuja modelos visibles y válidos y marca rectángulos envolventes de caras frontales para los objetos posteriores. La primera posición ordenada omite las pruebas de máscara y la última no añade un nuevo oclusor. Es un rechazo aproximado de líneas, no un búfer de profundidad. Ignora null y entradas vacías; los datos del código que llama y la caché de proyección actual deben ser válidos durante el recorrido.
Este ejemplo usa el perfil 128×120; su ventana gráfica empieza en (16,8) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
Ejemplo de uso
#pragma bank 0
// Compare direct model scaling with an object-array scene.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom DMG3D_Vec3 vertices[8]={{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}};
__prg_rom DMG3D_Edge edges[12]={{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}};
DMG3D_Model cube;
DMG3D_Object objects[2];
s16 px; s16 py; s16 pz;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
DMG3D_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
cube.vertices=vertices;cube.edges=edges;cube.faces=0;cube.edge_faces=0;
cube.vertex_count=8;cube.edge_count=12;cube.face_count=0;cube.flags=0;
DMG3D_BeginFrame();
// Upper pair: direct model calls at unity and half scale.
DMG3D_DrawModel(&cube,-32,32,96,0,0,0);
DMG3D_DrawModelScaled(&cube,32,32,96,0,0,0,128);
// Lower pair: the caller owns both object records and the model tables.
for(i=0;i<2;i++) {
objects[i].model=&cube;objects[i].x=-32+(s16)i*64;
objects[i].y=-32;objects[i].z=96;
objects[i].rx=0;objects[i].ry=0;objects[i].rz=0;
objects[i].scale_q8=256-(s16)i*128;objects[i].visible=1;
}
DMG3D_DrawScene(objects,2);
// Numeric checks cover the operation supplied by this viewport profile.
px=16;py=0;pz=0;DMG3D_RotatePoint(&px,&py,&pz,0,4,0);
result[1]=px; result[2]=py; result[3]=pz;
DMG3D_EndFrame(); result[7]=0xA55A;
while(1) {}
}Resultado esperado
Los modelos a escala unitaria y a media escala aparecen sobre una escena de un array de objetos con esas mismas escalas, para mostrar la proyección y el escalado.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_models.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/dmg3d.h:25
WIRE3D_DMG_HEIGHT = 120. Sort at most eight object origins by camera depth, near to far. Draw visible valid models and mark front-face bounding rectangles for later objects. The first sorted slot bypasses mask tests and the last needs no new occluder. This is coarse line rejection, not a depth buffer. Null/empty input is ignored; caller data and the current projection cache must remain valid during traversal.
kitaqgb/lib/wire3d_dmg.c:2723
void Wire3DDMG_DrawScene(Wire3DDMG_Object* objects, w3ddmg_u8 count)
{
w3ddmg_u8 scene_count;
w3ddmg_u8 i;
if (objects == 0) return;
scene_count = count;
if (scene_count > WIRE3D_DMG_SCENE_OBJECT_LIMIT) scene_count = WIRE3D_DMG_SCENE_OBJECT_LIMIT;
if (scene_count == 0) return;
i = 0;
while (i < scene_count)
{
w3ddmg_scene_order[(__safe_index w3ddmg_u8)i] = i;
w3ddmg_scene_depth[(__safe_index w3ddmg_u8)i] = w3ddmg_scene_object_depth(&objects[(__safe_index w3ddmg_u8)i]);
i = (w3ddmg_u8)(i + 1);
}
i = 0;
while (i < scene_count)
{
w3ddmg_u8 j;
j = (w3ddmg_u8)(i + 1);
while (j < scene_count)
{
w3ddmg_u8 oi;
w3ddmg_u8 oj;
oi = w3ddmg_scene_order[(__safe_index w3ddmg_u8)i];
oj = w3ddmg_scene_order[(__safe_index w3ddmg_u8)j];
if (w3ddmg_scene_depth[(__safe_index w3ddmg_u8)oj] < w3ddmg_scene_depth[(__safe_index w3ddmg_u8)oi])
{
w3ddmg_scene_order[(__safe_index w3ddmg_u8)i] = oj;
w3ddmg_scene_order[(__safe_index w3ddmg_u8)j] = oi;
}
j = (w3ddmg_u8)(j + 1);
}
i = (w3ddmg_u8)(i + 1);
}
w3ddmg_clear_occlusion_mask();
w3ddmg_occlusion_active = 0;
i = 0;
while (i < scene_count)
{
Wire3DDMG_Object* obj;
obj = &objects[(__safe_index w3ddmg_u8)w3ddmg_scene_order[(__safe_index w3ddmg_u8)i]];
if ((obj->visible != 0) && (obj->model != 0))
{
w3ddmg_occlusion_active = i == 0 ? 0 : 1;
Wire3DDMG_DrawModelScaled(obj->model, obj->x, obj->y, obj->z, obj->rx, obj->ry, obj->rz, obj->scale_q8);
if ((w3ddmg_u8)(i + 1) < scene_count)
{
w3ddmg_mark_model_occluder(obj->model);
}
}
i = (w3ddmg_u8)(i + 1);
}
w3ddmg_occlusion_active = 0;
}DMG3D_EndFrame
Envía a VRAM las escrituras del fondo pendientes y el dibujo preparado.
Sintaxis
void DMG3D_EndFrame();Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 120. Espera al siguiente VBlank y aplica las escrituras BG; después, si está habilitado, consume las franjas auxiliares antes de transferir los tiles modificados o toda el área principal. El solapamiento entre ambas fuentes hace importante ese orden. La consulta de STAT continúa entre intervalos de acceso; la actualización puede no caber en un solo VBlank.
Este ejemplo usa el perfil 128×120; su ventana gráfica empieza en (16,8) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
Ejemplo de uso
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
DMG3D_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
DMG3D_SetCamera(8,0,0,0,0,0);
result[1]=DMG3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
result[2]=projected_x; result[3]=projected_y;
projected_x=91; projected_y=92;
result[4]=DMG3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
result[5]=projected_x; result[6]=projected_y;
DMG3D_SetCamera(0,0,0,0,0,0);
DMG3D_BeginFrame();
DMG3D_DrawLine2D(8,8,56,8);
DMG3D_DrawLine2D(56,8,56,40);
DMG3D_DrawLine2D(56,40,8,40);
DMG3D_DrawLine2D(8,40,8,8);
DMG3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
DMG3D_DrawLine3D(-24,-24,96,24,24,96);
// Copy the viewport's top-left frame corner to a separate map cell.
DMG3D_PutBgTile(1,1,160);
DMG3D_EndFrame();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Este ejemplo muestra líneas, puntos, borrado y proyección en un fotograma. Se borra el centro del borde superior del marco de arriba a la izquierda y se proyecta una diagonal cerca del centro. Una proyección rechazada conserva las salidas 91 y 92.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_raster.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/dmg3d.h:28
WIRE3D_DMG_HEIGHT = 120. Wait for the next VBlank and flush BG writes, then optionally consume the auxiliary strips before uploading either dirty tiles or the entire main stage. Auxiliary/main source overlap makes that ordering significant. STAT polling continues across access windows; the update need not fit one VBlank.
kitaqgb/lib/wire3d_dmg.c:3081
void Wire3DDMG_EndFrame()
{
w3ddmg_wait_vblank_start();
w3ddmg_flush_bg_queue();
if (w3ddmg_aux_transfer_enabled)
{
w3ddmg_transfer_stage_aux_asm();
}
if (w3ddmg_dirty_transfer_enabled)
{
w3ddmg_transfer_dirty_stage();
}
else
{
w3ddmg_transfer_stage_asm();
}
}DMG3D_EraseModelFaces
Proyecta los triángulos frontales del modelo y borra los píxeles preparados de su interior.
Sintaxis
void DMG3D_EraseModelFaces(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz, w3ddmg_i16 scale_q8);Parámetros
modelModelo que contiene los arrays de vértices, aristas y caras y sus cantidades; las tablas deben permanecer legibles durante la llamada.
xComponente X del punto o del origen del objeto en coordenadas del mundo.
yComponente Y del punto o del origen del objeto en coordenadas del mundo.
zComponente Z del punto o del origen del objeto en coordenadas del mundo.
rxRotación alrededor de X; dieciséis pasos forman una vuelta completa.
ryRotación alrededor de Y; dieciséis pasos forman una vuelta completa.
rzRotación alrededor de Z; dieciséis pasos forman una vuelta completa.
scale_q8Escala con 256 como unidad; los valores no positivos también equivalen a la unidad.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 120. Proyecta hasta 24 vértices y borra del área de preparación el interior de los triángulos frontales de un modelo con indicadores de líneas ocultas y datos de caras. Una escala no positiva significa 256, la unidad. Examina hasta 16 caras y omite las que cruzan límites de profundidad. También sustituye las cachés de proyección compartidas, pero no actualiza VRAM.
Este ejemplo usa el perfil 128×120; su ventana gráfica empieza en (16,8) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
Ejemplo de uso
#pragma bank 0
// Erase a screen triangle and a projected model face from separate filled panels.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom DMG3D_Vec3 vertices[4]={{-24,-24,0},{24,-24,0},{24,24,0},{-24,24,0}};
__prg_rom DMG3D_Edge edges[4]={{0,1},{1,2},{2,3},{3,0}};
__prg_rom DMG3D_Face faces[2]={{0,2,1},{0,3,2}};
DMG3D_Model plane;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
DMG3D_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
plane.vertices=vertices;plane.edges=edges;plane.faces=faces;plane.edge_faces=0;
plane.vertex_count=4;plane.edge_count=4;plane.face_count=2;plane.flags=1;
DMG3D_BeginFrame();
// Separate panels show a direct screen triangle and a projected square face.
for(i=8;i<=32;i++) DMG3D_DrawLine2D(8,i,32,i);
for(i=36;i<=84;i++) DMG3D_DrawLine2D(40,i,88,i);
DMG3D_EraseTriangle2D(12,12,28,12,12,28);
DMG3D_EraseModelFaces(&plane,0,0,64,0,0,0,256);
DMG3D_EndFrame(); result[7]=0xA55A; while(1) {}
}Resultado esperado
Las caras proyectadas borran una región rellena y permiten distinguir las zonas conservadas de las borradas.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_faces.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_faces.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/dmg3d.h:29
WIRE3D_DMG_HEIGHT = 120. Project up to 24 vertices and erase front-facing triangle interiors from the stage for a model with hidden-line flags and face data. Nonpositive scale means 256 (unity). Up to 16 faces are considered; depth-crossing faces are skipped. This also replaces shared projection caches, but does not update VRAM.
kitaqgb/lib/wire3d_dmg.c:2843
void Wire3DDMG_EraseModelFaces(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz, w3ddmg_i16 scale_q8)
{
w3ddmg_u8 i;
w3ddmg_u8 count;
w3ddmg_u8 face_count;
if (model == 0) return;
if (model->vertices == 0) return;
if (model->faces == 0) return;
if ((model->flags & WIRE3D_DMG_MODEL_HIDDEN_LINES) == 0) return;
if (scale_q8 <= 0) scale_q8 = 256;
count = model->vertex_count;
if (count > WIRE3D_DMG_MODEL_VERTEX_LIMIT) count = WIRE3D_DMG_MODEL_VERTEX_LIMIT;
i = 0;
while (i < count)
{
const Wire3DDMG_Vec3* v;
w3ddmg_i16 vx;
w3ddmg_i16 vy;
w3ddmg_i16 vz;
w3ddmg_u8 sx;
w3ddmg_u8 sy;
v = &model->vertices[(__safe_index w3ddmg_u8)i];
vx = (w3ddmg_i16)((v->x * scale_q8) >> 8);
vy = (w3ddmg_i16)((v->y * scale_q8) >> 8);
vz = (w3ddmg_i16)((v->z * scale_q8) >> 8);
w3ddmg_rotate_y(&vx, &vz, ry);
w3ddmg_rotate_x(&vy, &vz, rx);
w3ddmg_rotate_z(&vx, &vy, rz);
vx = (w3ddmg_i16)(vx + x);
vy = (w3ddmg_i16)(vy + y);
vz = (w3ddmg_i16)(vz + z);
if (w3ddmg_project_world(vx, vy, vz, &sx, &sy))
{
w3ddmg_screen_x[(__safe_index w3ddmg_u8)i] = sx;
w3ddmg_screen_y[(__safe_index w3ddmg_u8)i] = sy;
w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 1;
}
else
{
w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 0;
}
i = (w3ddmg_u8)(i + 1);
}
face_count = model->face_count;
if (face_count > WIRE3D_DMG_MODEL_FACE_LIMIT) face_count = WIRE3D_DMG_MODEL_FACE_LIMIT;
w3ddmg_build_face_visibility(model, count, face_count);
i = 0;
while (i < face_count)
{
const Wire3DDMG_Face* f;
f = &model->faces[(__safe_index w3ddmg_u8)i];
if (w3ddmg_face_visible[(__safe_index w3ddmg_u8)i] &&
w3ddmg_screen_visible[(__safe_index w3ddmg_u8)f->a] &&
w3ddmg_screen_visible[(__safe_index w3ddmg_u8)f->b] &&
w3ddmg_screen_visible[(__safe_index w3ddmg_u8)f->c])
{
w3ddmg_clear_triangle(
w3ddmg_screen_x[(__safe_index w3ddmg_u8)f->a],
w3ddmg_screen_y[(__safe_index w3ddmg_u8)f->a],
w3ddmg_screen_x[(__safe_index w3ddmg_u8)f->b],
w3ddmg_screen_y[(__safe_index w3ddmg_u8)f->b],
w3ddmg_screen_x[(__safe_index w3ddmg_u8)f->c],
w3ddmg_screen_y[(__safe_index w3ddmg_u8)f->c]);
}
i = (w3ddmg_u8)(i + 1);
}
}DMG3D_EraseSpan2D
Borra un tramo horizontal, con ambos extremos incluidos, de una fila preparada.
Sintaxis
void DMG3D_EraseSpan2D(w3ddmg_u8 y, w3ddmg_u8 x0, w3ddmg_u8 x1);Parámetros
yCoordenada Y en píxeles de la fila que se va a borrar.
x0Extremo X inferior, en píxeles de la ventana gráfica; el orden y el recorte siguen las notas de esta operación.
x1Extremo X superior, en píxeles de la ventana gráfica; el orden y el recorte siguen las notas de esta operación.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 120. Ordena los extremos X y borra el tramo preparado, incluidos ambos extremos. Los dos deben estar en 0..127; un Y inválido se ignora. La rutina no recorta X automáticamente.
Este ejemplo usa el perfil 128×120; su ventana gráfica empieza en (16,8) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
Ejemplo de uso
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
DMG3D_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
DMG3D_SetCamera(8,0,0,0,0,0);
result[1]=DMG3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
result[2]=projected_x; result[3]=projected_y;
projected_x=91; projected_y=92;
result[4]=DMG3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
result[5]=projected_x; result[6]=projected_y;
DMG3D_SetCamera(0,0,0,0,0,0);
DMG3D_BeginFrame();
DMG3D_DrawLine2D(8,8,56,8);
DMG3D_DrawLine2D(56,8,56,40);
DMG3D_DrawLine2D(56,40,8,40);
DMG3D_DrawLine2D(8,40,8,8);
DMG3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
DMG3D_DrawLine3D(-24,-24,96,24,24,96);
// Copy the viewport's top-left frame corner to a separate map cell.
DMG3D_PutBgTile(1,1,160);
DMG3D_EndFrame();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Este ejemplo muestra líneas, puntos, borrado y proyección en un fotograma. Se borra el centro del borde superior del marco de arriba a la izquierda y se proyecta una diagonal cerca del centro. Una proyección rechazada conserva las salidas 91 y 92.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_raster.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/dmg3d.h:30
WIRE3D_DMG_HEIGHT = 120. Order the X endpoints and erase the inclusive staged span. Both endpoints must be in 0..127; invalid Y is ignored. The routine does not clip X for you.
kitaqgb/lib/wire3d_dmg.c:2943
void Wire3DDMG_EraseSpan2D(w3ddmg_u8 y, w3ddmg_u8 x0, w3ddmg_u8 x1)
{
w3ddmg_u8 tx;
if (x0 > x1)
{
tx = x0;
x0 = x1;
x1 = tx;
}
w3ddmg_stage_clear_span(y, x0, x1);
}DMG3D_EraseTriangle2D
Borra un triángulo de pantalla del área de preparación mediante tramos horizontales de líneas de barrido.
Sintaxis
void DMG3D_EraseTriangle2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by, w3ddmg_u8 cx, w3ddmg_u8 cy);Parámetros
axCoordenada X del vértice A en píxeles de la ventana gráfica.
ayCoordenada Y del vértice A en píxeles de la ventana gráfica.
bxCoordenada X del vértice B en píxeles de la ventana gráfica.
byCoordenada Y del vértice B en píxeles de la ventana gráfica.
cxCoordenada X del vértice C en píxeles de la ventana gráfica.
cyCoordenada Y del vértice C en píxeles de la ventana gráfica.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 120. Borra un triángulo de los píxeles preparados usando intersecciones enteras con líneas de barrido. Proporciona coordenadas de la ventana gráfica. Ignora triángulos degenerados; la máscara de oclusión y VRAM no cambian.
Este ejemplo usa el perfil 128×120; su ventana gráfica empieza en (16,8) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
Ejemplo de uso
#pragma bank 0
// Erase a screen triangle and a projected model face from separate filled panels.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom DMG3D_Vec3 vertices[4]={{-24,-24,0},{24,-24,0},{24,24,0},{-24,24,0}};
__prg_rom DMG3D_Edge edges[4]={{0,1},{1,2},{2,3},{3,0}};
__prg_rom DMG3D_Face faces[2]={{0,2,1},{0,3,2}};
DMG3D_Model plane;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
DMG3D_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
plane.vertices=vertices;plane.edges=edges;plane.faces=faces;plane.edge_faces=0;
plane.vertex_count=4;plane.edge_count=4;plane.face_count=2;plane.flags=1;
DMG3D_BeginFrame();
// Separate panels show a direct screen triangle and a projected square face.
for(i=8;i<=32;i++) DMG3D_DrawLine2D(8,i,32,i);
for(i=36;i<=84;i++) DMG3D_DrawLine2D(40,i,88,i);
DMG3D_EraseTriangle2D(12,12,28,12,12,28);
DMG3D_EraseModelFaces(&plane,0,0,64,0,0,0,256);
DMG3D_EndFrame(); result[7]=0xA55A; while(1) {}
}Resultado esperado
Las caras proyectadas borran una región rellena y permiten distinguir las zonas conservadas de las borradas.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_faces.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_faces.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/dmg3d.h:31
WIRE3D_DMG_HEIGHT = 120. Erase a triangle from staged pixels using integer scanline intersections. Supply viewport coordinates. Degenerate triangles are ignored; the occlusion mask and VRAM are unchanged.
kitaqgb/lib/wire3d_dmg.c:2933
void Wire3DDMG_EraseTriangle2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by, w3ddmg_u8 cx, w3ddmg_u8 cy)
{
w3ddmg_clear_triangle(ax, ay, bx, by, cx, cy);
}DMG3D_Init
Inicializa el LCD, los tiles y el mapa del fondo para una ventana gráfica de alambre monocroma.
Sintaxis
void DMG3D_Init();Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 120. Toma el control del LCD, borra la VRAM de tiles y el mapa BG e instala una ventana gráfica de 16×15 desde el tile (3,1). Configura desplazamiento (8,0), BGP=0xB4 y la visualización BG. Reinicia cámara, colas, modos de transferencia, ambas tablas de cambios y el área de preparación. Reserva 0xD000..0xDFFF y conserva su mapeo WRAM; el almacenamiento auxiliar comparte esas direcciones. Llama a BeginFrame antes de dibujar para establecer el estado de oclusión.
Este ejemplo usa el perfil 128×120; su ventana gráfica empieza en (16,8) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
Ejemplo de uso
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
DMG3D_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
DMG3D_SetCamera(8,0,0,0,0,0);
result[1]=DMG3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
result[2]=projected_x; result[3]=projected_y;
projected_x=91; projected_y=92;
result[4]=DMG3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
result[5]=projected_x; result[6]=projected_y;
DMG3D_SetCamera(0,0,0,0,0,0);
DMG3D_BeginFrame();
DMG3D_DrawLine2D(8,8,56,8);
DMG3D_DrawLine2D(56,8,56,40);
DMG3D_DrawLine2D(56,40,8,40);
DMG3D_DrawLine2D(8,40,8,8);
DMG3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
DMG3D_DrawLine3D(-24,-24,96,24,24,96);
// Copy the viewport's top-left frame corner to a separate map cell.
DMG3D_PutBgTile(1,1,160);
DMG3D_EndFrame();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Este ejemplo muestra líneas, puntos, borrado y proyección en un fotograma. Se borra el centro del borde superior del marco de arriba a la izquierda y se proyecta una diagonal cerca del centro. Una proyección rechazada conserva las salidas 91 y 92.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_raster.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/dmg3d.h:35
WIRE3D_DMG_HEIGHT = 120. Take over LCD state, clear tile VRAM and the BG map, and install a 16x15 viewport beginning at map tile (3,1). Set scroll (8,0), BGP=0xB4 and BG display. Reset camera, queues, transfer modes, both dirty tables and stage. Reserve 0xD000..0xDFFF and retain its WRAM mapping; auxiliary storage aliases it. Call BeginFrame before drawing to establish occlusion state.
kitaqgb/lib/wire3d_dmg.c:2572
void Wire3DDMG_Init()
{
w3ddmg_u8 row;
w3ddmg_u8 col;
w3ddmg_u8 tid;
w3ddmg_u16 off;
w3ddmg_wait_vblank_start();
w3ddmg_reg_lcdc = 0;
w3ddmg_clear_vram_asm();
w3ddmg_fill_bg_map_asm();
row = 0;
tid = 0x90;
while (row < WIRE3D_DMG_TILE_H)
{
off = (w3ddmg_u16)(0x23 + ((w3ddmg_u16)row << 5));
col = 0;
while (col < WIRE3D_DMG_TILE_W)
{
w3ddmg_bg_map_9800[(w3ddmg_u16)(off + (w3ddmg_u16)col)] = tid;
tid = (w3ddmg_u8)(tid + WIRE3D_DMG_TILE_H);
col = (w3ddmg_u8)(col + 1);
}
row = (w3ddmg_u8)(row + 1);
tid = (w3ddmg_u8)(0x90 + row);
}
w3ddmg_reg_scx = 8;
w3ddmg_reg_scy = 0;
w3ddmg_reg_bgp = 0xB4;
w3ddmg_reg_lcdc = 0x81;
w3ddmg_bgq_count = 0;
w3ddmg_aux_transfer_enabled = 0;
w3ddmg_dirty_transfer_enabled = 0;
Wire3DDMG_SetCamera(0, 0, 0, 0, 0, 0);
w3ddmg_clear_stage_asm();
w3ddmg_clear_stage_aux_asm();
w3ddmg_clear_dirty_tables();
}DMG3D_ProjectPoint
Proyecta un punto del mundo mediante la cámara a coordenadas de la ventana gráfica.
Sintaxis
w3ddmg_u8 DMG3D_ProjectPoint(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8* sx, w3ddmg_u8* sy);Parámetros
xComponente X del punto o del origen del objeto en coordenadas del mundo.
yComponente Y del punto o del origen del objeto en coordenadas del mundo.
zComponente Z del punto o del origen del objeto en coordenadas del mundo.
sxPuntero u8 válido y escribible que recibe la coordenada X proyectada.
syPuntero u8 válido y escribible que recibe la coordenada Y proyectada.
Valor devuelto
Devuelve 1 si la proyección tiene éxito o 0 si se rechaza por profundidad.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 120. Proyecta un punto del mundo con la cámara actual. Una profundidad inválida devuelve cero sin cambiar las salidas; si tiene éxito, escribe coordenadas limitadas a 128×120. Ambos punteros de salida deben ser válidos. Las diferencias de coordenadas deben caber en s16.
Este ejemplo usa el perfil 128×120; su ventana gráfica empieza en (16,8) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
Ejemplo de uso
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
DMG3D_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
DMG3D_SetCamera(8,0,0,0,0,0);
result[1]=DMG3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
result[2]=projected_x; result[3]=projected_y;
projected_x=91; projected_y=92;
result[4]=DMG3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
result[5]=projected_x; result[6]=projected_y;
DMG3D_SetCamera(0,0,0,0,0,0);
DMG3D_BeginFrame();
DMG3D_DrawLine2D(8,8,56,8);
DMG3D_DrawLine2D(56,8,56,40);
DMG3D_DrawLine2D(56,40,8,40);
DMG3D_DrawLine2D(8,40,8,8);
DMG3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
DMG3D_DrawLine3D(-24,-24,96,24,24,96);
// Copy the viewport's top-left frame corner to a separate map cell.
DMG3D_PutBgTile(1,1,160);
DMG3D_EndFrame();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Este ejemplo muestra líneas, puntos, borrado y proyección en un fotograma. Se borra el centro del borde superior del marco de arriba a la izquierda y se proyecta una diagonal cerca del centro. Una proyección rechazada conserva las salidas 91 y 92.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_raster.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/dmg3d.h:43
WIRE3D_DMG_HEIGHT = 120. Project a world point with the current camera. Return zero for invalid depth without changing outputs; success writes clamped 128x120 coordinates. Both output pointers must be valid. Coordinate differences must fit s16.
kitaqgb/lib/wire3d_dmg.c:549
w3ddmg_u8 Wire3DDMG_ProjectPoint(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8* sx, w3ddmg_u8* sy)
{
return w3ddmg_project_world(x, y, z, sx, sy);
}DMG3D_PutBgTile
Encola una escritura de número de tile en una celda del mapa del fondo.
Sintaxis
void DMG3D_PutBgTile(w3ddmg_u8 x, w3ddmg_u8 y, w3ddmg_u8 tile);Parámetros
xCoordenada X de tile en el mapa del fondo de 32×32.
yCoordenada Y de tile en el mapa del fondo de 32×32.
tileNúmero de tile de ocho bits para la celda del fondo.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 120. Encola una escritura de tile en el mapa de 32×32 en 0x9800 para EndFrame. Ignora sin aviso las coordenadas inválidas y las solicitudes que superen las 48 escrituras pendientes. Esta cola es independiente de la cola general de la biblioteca vram.
Este ejemplo usa el perfil 128×120; su ventana gráfica empieza en (16,8) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
Ejemplo de uso
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
DMG3D_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
DMG3D_SetCamera(8,0,0,0,0,0);
result[1]=DMG3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
result[2]=projected_x; result[3]=projected_y;
projected_x=91; projected_y=92;
result[4]=DMG3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
result[5]=projected_x; result[6]=projected_y;
DMG3D_SetCamera(0,0,0,0,0,0);
DMG3D_BeginFrame();
DMG3D_DrawLine2D(8,8,56,8);
DMG3D_DrawLine2D(56,8,56,40);
DMG3D_DrawLine2D(56,40,8,40);
DMG3D_DrawLine2D(8,40,8,8);
DMG3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
DMG3D_DrawLine3D(-24,-24,96,24,24,96);
// Copy the viewport's top-left frame corner to a separate map cell.
DMG3D_PutBgTile(1,1,160);
DMG3D_EndFrame();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Este ejemplo muestra líneas, puntos, borrado y proyección en un fotograma. Se borra el centro del borde superior del marco de arriba a la izquierda y se proyecta una diagonal cerca del centro. Una proyección rechazada conserva las salidas 91 y 92.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_raster.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/dmg3d.h:44
WIRE3D_DMG_HEIGHT = 120. Queue a tile write to the 32x32 map at 0x9800 for EndFrame. Invalid map coordinates and submissions beyond 48 pending writes are silently ignored. This queue is separate from the general vram library queue.
kitaqgb/lib/wire3d_dmg.c:582
void Wire3DDMG_PutBgTile(w3ddmg_u8 x, w3ddmg_u8 y, w3ddmg_u8 tile)
{
if (x >= 32) return;
if (y >= 32) return;
if (w3ddmg_bgq_count >= WIRE3D_DMG_BG_QUEUE_LIMIT) return;
w3ddmg_bgq_x[(__safe_index w3ddmg_u8)w3ddmg_bgq_count] = x;
w3ddmg_bgq_y[(__safe_index w3ddmg_u8)w3ddmg_bgq_count] = y;
w3ddmg_bgq_tile[(__safe_index w3ddmg_u8)w3ddmg_bgq_count] = tile;
w3ddmg_bgq_count = (w3ddmg_u8)(w3ddmg_bgq_count + 1);
}DMG3D_RotatePoint
Rota un punto en sus propias variables según los ángulos indicados.
Sintaxis
void DMG3D_RotatePoint(w3ddmg_i16* x, w3ddmg_i16* y, w3ddmg_i16* z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz);Parámetros
xPuntero s16 escribible y distinto de los demás para la componente X.
yPuntero s16 escribible y distinto de los demás para la componente Y.
zPuntero s16 escribible y distinto de los demás para la componente Z.
rxRotación alrededor de X; dieciséis pasos forman una vuelta completa.
ryRotación alrededor de Y; dieciséis pasos forman una vuelta completa.
rzRotación alrededor de Z; dieciséis pasos forman una vuelta completa.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 120. Rota sobre las mismas variables en orden Y/X/Z, con 16 pasos por vuelta. Si algún puntero de componente es null, toda la llamada queda sin efecto; usa punteros distintos. Cada rotación de eje limita sus entradas a ±220.
Este ejemplo usa el perfil 128×120; su ventana gráfica empieza en (16,8) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
Ejemplo de uso
#pragma bank 0
// Compare direct model scaling with an object-array scene.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom DMG3D_Vec3 vertices[8]={{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}};
__prg_rom DMG3D_Edge edges[12]={{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}};
DMG3D_Model cube;
DMG3D_Object objects[2];
s16 px; s16 py; s16 pz;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
DMG3D_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
cube.vertices=vertices;cube.edges=edges;cube.faces=0;cube.edge_faces=0;
cube.vertex_count=8;cube.edge_count=12;cube.face_count=0;cube.flags=0;
DMG3D_BeginFrame();
// Upper pair: direct model calls at unity and half scale.
DMG3D_DrawModel(&cube,-32,32,96,0,0,0);
DMG3D_DrawModelScaled(&cube,32,32,96,0,0,0,128);
// Lower pair: the caller owns both object records and the model tables.
for(i=0;i<2;i++) {
objects[i].model=&cube;objects[i].x=-32+(s16)i*64;
objects[i].y=-32;objects[i].z=96;
objects[i].rx=0;objects[i].ry=0;objects[i].rz=0;
objects[i].scale_q8=256-(s16)i*128;objects[i].visible=1;
}
DMG3D_DrawScene(objects,2);
// Numeric checks cover the operation supplied by this viewport profile.
px=16;py=0;pz=0;DMG3D_RotatePoint(&px,&py,&pz,0,4,0);
result[1]=px; result[2]=py; result[3]=pz;
DMG3D_EndFrame(); result[7]=0xA55A;
while(1) {}
}Resultado esperado
Los modelos a escala unitaria y a media escala aparecen sobre una escena de un array de objetos con esas mismas escalas, para mostrar la proyección y el escalado.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_models.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/dmg3d.h:46
WIRE3D_DMG_HEIGHT = 120. Rotate in place in Y/X/Z order using 16 steps per full turn. A null component pointer makes the whole call a no-op; use distinct pointers. Each axis rotation clamps its inputs to +/-220.
kitaqgb/lib/wire3d_dmg.c:3121
void Wire3DDMG_RotatePoint(w3ddmg_i16* x, w3ddmg_i16* y, w3ddmg_i16* z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz)
{
if (x == 0) return;
if (y == 0) return;
if (z == 0) return;
w3ddmg_rotate_y(x, z, ry);
w3ddmg_rotate_x(y, z, rx);
w3ddmg_rotate_z(x, y, rz);
}DMG3D_SetAuxTransfer
Elige si EndFrame también transfiere las franjas auxiliares.
Sintaxis
void DMG3D_SetAuxTransfer(w3ddmg_u8 flag);Parámetros
flagCero desactiva la función de transferencia; cualquier otro valor la activa.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 120. Guarda la habilitación de transferencia auxiliar de EndFrame; cualquier valor no nulo la activa. Aquí no copia ni borra datos. Los bytes fuente auxiliares comparten direcciones con el área principal.
Este ejemplo usa el perfil 128×120; su ventana gráfica empieza en (16,8) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
Ejemplo de uso
#pragma bank 0
// Use the auxiliary-transfer gate to consume an overlapping stage strip.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
DMG3D_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
DMG3D_SetDirtyTransfer(1); DMG3D_SetAuxTransfer(1);
DMG3D_BeginFrame();
for(i=24;i<=31;i++) DMG3D_DrawLine2D(40,i,47,i);
// Auxiliary upload consumes this source before the dirty main tile is sent.
DMG3D_EndFrame(); result[7]=0xA55A; while(1) {}
}Resultado esperado
La transferencia auxiliar consume parte del área principal y produce un bloque negro de 8×8 en las coordenadas de pantalla (80,24).


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_aux_gate.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_aux_gate.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/dmg3d.h:50
WIRE3D_DMG_HEIGHT = 120. Store the EndFrame auxiliary-transfer gate; any nonzero value enables it. No data is copied or cleared here. Auxiliary source bytes alias the main stage.
kitaqgb/lib/wire3d_dmg.c:3895
void Wire3DDMG_SetAuxTransfer(w3ddmg_u8 flag)
{
w3ddmg_aux_transfer_enabled = flag;
}DMG3D_SetCamera
Guarda la posición y la orientación de la cámara para las proyecciones posteriores.
Sintaxis
void DMG3D_SetCamera(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 pitch, w3ddmg_u8 yaw, w3ddmg_u8 roll);Parámetros
xComponente X de la cámara en coordenadas del mundo.
yComponente Y de la cámara en coordenadas del mundo.
zComponente Z de la cámara en coordenadas del mundo.
pitchRotación alrededor de X; dieciséis pasos forman una vuelta completa.
yawRotación alrededor de Y; dieciséis pasos forman una vuelta completa.
rollRotación alrededor de Z; dieciséis pasos forman una vuelta completa.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 120. Guarda la posición y los ángulos de cámara para dibujos posteriores; una vuelta tiene 16 pasos angulares. No vuelve a proyectar lo ya dibujado ni valida los rangos de entrada.
Este ejemplo usa el perfil 128×120; su ventana gráfica empieza en (16,8) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
Ejemplo de uso
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
DMG3D_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
DMG3D_SetCamera(8,0,0,0,0,0);
result[1]=DMG3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
result[2]=projected_x; result[3]=projected_y;
projected_x=91; projected_y=92;
result[4]=DMG3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
result[5]=projected_x; result[6]=projected_y;
DMG3D_SetCamera(0,0,0,0,0,0);
DMG3D_BeginFrame();
DMG3D_DrawLine2D(8,8,56,8);
DMG3D_DrawLine2D(56,8,56,40);
DMG3D_DrawLine2D(56,40,8,40);
DMG3D_DrawLine2D(8,40,8,8);
DMG3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
DMG3D_DrawLine3D(-24,-24,96,24,24,96);
// Copy the viewport's top-left frame corner to a separate map cell.
DMG3D_PutBgTile(1,1,160);
DMG3D_EndFrame();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Este ejemplo muestra líneas, puntos, borrado y proyección en un fotograma. Se borra el centro del borde superior del marco de arriba a la izquierda y se proyecta una diagonal cerca del centro. Una proyección rechazada conserva las salidas 91 y 92.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_raster.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/dmg3d.h:51
WIRE3D_DMG_HEIGHT = 120. Store camera position and angles for later draws; a full turn is 16 angle steps. No existing drawing is reprojected and no input range validation occurs.
kitaqgb/lib/wire3d_dmg.c:2661
void Wire3DDMG_SetCamera(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 pitch, w3ddmg_u8 yaw, w3ddmg_u8 roll)
{
w3ddmg_cam_x = x;
w3ddmg_cam_y = y;
w3ddmg_cam_z = z;
w3ddmg_cam_pitch = pitch;
w3ddmg_cam_yaw = yaw;
w3ddmg_cam_roll = roll;
}DMG3D_SetDirtyTransfer
Selecciona la transferencia de tiles modificados para la ventana gráfica principal de 120 filas.
Sintaxis
void DMG3D_SetDirtyTransfer(w3ddmg_u8 flag);Parámetros
flagCero desactiva la función de transferencia; cualquier otro valor la activa.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 120. Guarda la habilitación de transferencia de zonas modificadas y borra ambos historiales de cambios y el área principal, aunque el valor no cambie. Conserva VRAM; activarla sobre una imagen anterior puede dejar tiles antiguos sin marcar, así que prepara una imagen inicial limpia.
Este ejemplo usa el perfil 128×120; su ventana gráfica empieza en (16,8) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
Ejemplo de uso
#pragma bank 0
// Remove the previous frame and upload only the tracked current/previous tiles.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
DMG3D_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
DMG3D_SetDirtyTransfer(1); DMG3D_SetAuxTransfer(0);
DMG3D_BeginFrame();
DMG3D_DrawLine2D(8,8,24,8); DMG3D_DrawLine2D(24,8,24,24);
DMG3D_DrawLine2D(24,24,8,24); DMG3D_DrawLine2D(8,24,8,8);
DMG3D_EndFrame();
DMG3D_BeginFrame();
DMG3D_DrawLine2D(80,80,104,80); DMG3D_DrawLine2D(104,80,104,104);
DMG3D_DrawLine2D(104,104,80,104); DMG3D_DrawLine2D(80,104,80,80);
DMG3D_EndFrame(); result[7]=0xA55A; while(1) {}
}Resultado esperado
Desaparece el marco anterior de arriba a la izquierda y solo queda el nuevo en las coordenadas de pantalla (96,88)..(120,112).


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_dirty.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_dirty.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/dmg3d.h:52
WIRE3D_DMG_HEIGHT = 120. Store the dirty-transfer gate and clear both dirty histories and the main stage, even if the value is unchanged. VRAM is retained; enabling this over an old image can leave unmarked old tiles, so arrange a clean displayed baseline.
kitaqgb/lib/wire3d_dmg.c:3955
void Wire3DDMG_SetDirtyTransfer(w3ddmg_u8 flag)
{
w3ddmg_dirty_transfer_enabled = flag;
w3ddmg_clear_dirty_tables();
w3ddmg_clear_stage_asm();
}DMG3D_SetPalette
Escribe la correspondencia de cuatro tonos en el registro de paleta del fondo monocromo BGP.
Sintaxis
void DMG3D_SetPalette(w3ddmg_u8 bgp);Parámetros
bgpValor del registro BGP con cuatro asignaciones de tono de dos bits.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 120. Escribe inmediatamente la codificación directa de la paleta DMG BGP, sin sincronización de fotograma.
Este ejemplo usa el perfil 128×120; su ventana gráfica empieza en (16,8) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
Ejemplo de uso
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
DMG3D_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
DMG3D_SetCamera(8,0,0,0,0,0);
result[1]=DMG3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
result[2]=projected_x; result[3]=projected_y;
projected_x=91; projected_y=92;
result[4]=DMG3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
result[5]=projected_x; result[6]=projected_y;
DMG3D_SetCamera(0,0,0,0,0,0);
DMG3D_BeginFrame();
DMG3D_DrawLine2D(8,8,56,8);
DMG3D_DrawLine2D(56,8,56,40);
DMG3D_DrawLine2D(56,40,8,40);
DMG3D_DrawLine2D(8,40,8,8);
DMG3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
DMG3D_DrawLine3D(-24,-24,96,24,24,96);
// Copy the viewport's top-left frame corner to a separate map cell.
DMG3D_PutBgTile(1,1,160);
DMG3D_EndFrame();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Este ejemplo muestra líneas, puntos, borrado y proyección en un fotograma. Se borra el centro del borde superior del marco de arriba a la izquierda y se proyecta una diagonal cerca del centro. Una proyección rechazada conserva las salidas 91 y 92.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_raster.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/dmg3d.h:53
WIRE3D_DMG_HEIGHT = 120. Write the raw DMG BGP palette encoding immediately; no frame synchronization occurs.
kitaqgb/lib/wire3d_dmg.c:597
void Wire3DDMG_SetPalette(w3ddmg_u8 bgp)
{
w3ddmg_reg_bgp = bgp;
}DMG3D_TransferAuxNow
Transfiere inmediatamente seis franjas auxiliares y borra sus bytes fuente.
Sintaxis
void DMG3D_TransferAuxNow();Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 120. Transfiere y consume inmediatamente las franjas fuente auxiliares, independientemente de su habilitación. No espera al inicio de VBlank ni actualiza el historial de cambios o la cola BG. La fuente se solapa con el área principal y debe coordinarse con su transferencia.
Este ejemplo usa el perfil 128×120; su ventana gráfica empieza en (16,8) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
Ejemplo de uso
#pragma bank 0
// Upload a main line and an auxiliary block separately; verify source consumption.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom DMG3D_Vec3 vertices[2]={{-32,0,0},{32,0,0}};
__prg_rom u8 edge_pairs[2]={0,1};
u8* stage_byte;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
DMG3D_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
DMG3D_BeginFrame();
DMG3D_DrawIndexedEdges(vertices,2,edge_pairs,1,-64,104,96,1);
DMG3D_TransferMainNow();
// Direct auxiliary transfer writes a separate tile after the main upload.
for(i=24;i<=31;i++) DMG3D_DrawLine2D(40,i,47,i);
stage_byte=(u8*)0xD518;result[1]=*stage_byte;
DMG3D_TransferAuxNow();result[2]=*stage_byte;
// Do not upload the consumed stage again.
result[7]=0xA55A; while(1) {}
}Resultado esperado
Una línea horizontal proyectada y un bloque auxiliar de 8×8 muestran las transferencias directas; un byte fuente pasa de 255 a 0 al consumirse.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_direct.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_direct.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/dmg3d.h:57
WIRE3D_DMG_HEIGHT = 120. Upload and consume auxiliary source strips immediately, independent of the auxiliary gate. No VBlank-start wait or dirty-history/BG-queue update occurs. The source overlaps the main stage and must be coordinated with its upload.
kitaqgb/lib/wire3d_dmg.c:3983
void Wire3DDMG_TransferAuxNow()
{
w3ddmg_transfer_stage_aux_asm();
}DMG3D_TransferMainNow
Transfiere inmediatamente toda el área principal y borra los píxeles fuente consumidos.
Sintaxis
void DMG3D_TransferMainNow();Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 120. Transfiere y consume inmediatamente toda el área principal, consultando STAT sin esperar al siguiente VBlank. Ignora las habilitaciones de transferencia y conserva los historiales de cambios y la cola de tiles BG; el código que llama coordina el ciclo del fotograma.
Este ejemplo usa el perfil 128×120; su ventana gráfica empieza en (16,8) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
Ejemplo de uso
#pragma bank 0
// Upload a main line and an auxiliary block separately; verify source consumption.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom DMG3D_Vec3 vertices[2]={{-32,0,0},{32,0,0}};
__prg_rom u8 edge_pairs[2]={0,1};
u8* stage_byte;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
DMG3D_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
DMG3D_BeginFrame();
DMG3D_DrawIndexedEdges(vertices,2,edge_pairs,1,-64,104,96,1);
DMG3D_TransferMainNow();
// Direct auxiliary transfer writes a separate tile after the main upload.
for(i=24;i<=31;i++) DMG3D_DrawLine2D(40,i,47,i);
stage_byte=(u8*)0xD518;result[1]=*stage_byte;
DMG3D_TransferAuxNow();result[2]=*stage_byte;
// Do not upload the consumed stage again.
result[7]=0xA55A; while(1) {}
}Resultado esperado
Una línea horizontal proyectada y un bloque auxiliar de 8×8 muestran las transferencias directas; un byte fuente pasa de 255 a 0 al consumirse.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_direct.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_direct.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/dmg3d.h:58
WIRE3D_DMG_HEIGHT = 120. Upload and consume the full main stage immediately, polling STAT but not waiting for the next VBlank. Ignore transfer gates and leave dirty histories and BG tile queue unchanged; the caller coordinates the frame lifecycle.
kitaqgb/lib/wire3d_dmg.c:3970
void Wire3DDMG_TransferMainNow()
{
w3ddmg_transfer_stage_asm();
}entity.h — Grupos de objetos basados en arrays fijos
entity es un conjunto de objetos almacenados en un array de tamaño fijo para representar enemigos, proyectiles, objetos recogibles, etc. Reservas una posición libre, accedes a ella por su ID y la reutilizas cuando el objeto deja de ser necesario. No se reserva memoria en el montón. El juego define las unidades de las coordenadas y velocidades, el movimiento, las colisiones y la actualización de temporizadores.
Incluye entity.h y compila entity.c exactamente una vez. Llama primero a entity_init y comprueba que entity_create no devuelva 0xFF. El valor predeterminado de ENTITY_MAX es 16. Los ID admiten una capacidad de 1 a 255 posiciones, aunque la cantidad utilizable depende de la RAM disponible. Usa la misma definición de capacidad en todas las unidades de compilación.
El puntero que devuelve entity_get apunta a una posición reutilizable del conjunto. Tras liberarla, el mismo ID puede identificar otro objeto; ni el ID ni el puntero constituyen una identidad permanente. entity_destroy solo desactiva la posición. Quien llama debe ocultar o liberar los sprites y limpiar los demás recursos. El campo sprite sirve para llevar el control; no actualiza la OAM automáticamente.
entity_update_all y entity_draw_all recorren las posiciones activas en orden ascendente de ID y llaman a fn(id). Coloca el trabajo de actualización o dibujo en la función de retrollamada. Una retrollamada nula no hace nada. Crear o liberar desde ella una posición posterior afecta al recorrido actual. Ejecutar primero la actualización y después el dibujo permite separar ambas tareas.
entity_clear_all
Libera todas las entidades y restablece sus campos, incluida la marca de sprite no asignado.
Sintaxis
void entity_clear_all();Valor devuelto
Ninguno (void).
Condiciones y límites
El pool es un array fijo, sin asignación dinámica en el heap. ENTITY_MAX vale 16 por defecto y debe estar entre 1 y 255, con la misma definición en todas las unidades de compilación. Los ID empiezan en cero; 0xFF indica fallo.
Pone a cero active,type,x,y,vx,vy,state,timer y deja sprite en 0xFF en todos los espacios. No oculta ni libera sprites de hardware; esos recursos se limpian por separado.
Ejemplo de uso
entity_clear_all();
after_clear = entity_count_active();
if (after_clear != 0 || entity_get(reused) != 0) { failures++; }Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El programa completo enseña el ciclo de vida de un espacio reutilizable. Lee cada número con su etiqueta: CREATED 002 tras reservar dos entidades; AFTER FREE 001 al liberar la primera; REUSED ID 000 al reutilizar el ID libre más bajo; AFTER CLEAR 000 al vaciar el pool. Comprueba también la consulta null tras liberar y la reinicialización de campos al reutilizar. FAILED CHECKS 000 indica que los valores coinciden.
El recorrido GB llama a cada callback para las dos entidades activas: UPDATE CALLS 002 y DRAW CALLS 002. El callback de actualización mueve ambas un tile a la derecha. El de dibujo coloca A en (3,12) y B en (7,12) para representarlas. Son tiles de fuente del fondo dibujados por el callback, no sprites asignados automáticamente.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\entity.c .\kitaq-docs\samples\api-examples\gb\entity_pool.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\entity_pool.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasmImplementación y código fuente
kitaqgb/lib/entity.h:43
Release every entity and restore deterministic defaults, including the no-sprite sentinel.
kitaqgb/lib/entity.c:14
void entity_clear_all()
{
u8 i = 0;
while (i < ENTITY_MAX) {
entity_pool[i].active = 0;
entity_pool[i].type = 0;
entity_pool[i].x = 0;
entity_pool[i].y = 0;
entity_pool[i].vx = 0;
entity_pool[i].vy = 0;
entity_pool[i].state = 0;
entity_pool[i].timer = 0;
entity_pool[i].sprite = 0xFF;
i++;
}
}entity_count_active
Cuenta los espacios ocupados por entidades sin modificarlos.
Sintaxis
u8 entity_count_active();Valor devuelto
Número de espacios con active distinto de cero, entre 0 y ENTITY_MAX. Es la ocupación, no el ID más alto ni el número de sprites en pantalla.
Condiciones y límites
El pool es un array fijo, sin asignación dinámica en el heap. ENTITY_MAX vale 16 por defecto y debe estar entre 1 y 255, con la misma definición en todas las unidades de compilación. Los ID empiezan en cero; 0xFF indica fallo.
Ejemplo de uso
created = entity_count_active();
if (created != 2) { failures++; }Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El programa completo enseña el ciclo de vida de un espacio reutilizable. Lee cada número con su etiqueta: CREATED 002 tras reservar dos entidades; AFTER FREE 001 al liberar la primera; REUSED ID 000 al reutilizar el ID libre más bajo; AFTER CLEAR 000 al vaciar el pool. Comprueba también la consulta null tras liberar y la reinicialización de campos al reutilizar. FAILED CHECKS 000 indica que los valores coinciden.
El recorrido GB llama a cada callback para las dos entidades activas: UPDATE CALLS 002 y DRAW CALLS 002. El callback de actualización mueve ambas un tile a la derecha. El de dibujo coloca A en (3,12) y B en (7,12) para representarlas. Son tiles de fuente del fondo dibujados por el callback, no sprites asignados automáticamente.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\entity.c .\kitaq-docs\samples\api-examples\gb\entity_pool.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\entity_pool.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasmImplementación y código fuente
kitaqgb/lib/entity.h:41
Count occupied slots without changing entity state.
kitaqgb/lib/entity.c:93
u8 entity_count_active()
{
u8 i = 0;
u8 count = 0;
while (i < ENTITY_MAX) {
if (entity_pool[i].active != 0) count++;
i++;
}
return count;
}entity_create
Reserva una entidad del tipo y posición indicados; devuelve su ID reutilizable o 0xFF si el pool está lleno.
Sintaxis
u8 entity_create(u8 type, s16 x, s16 y);Parámetros
typeEtiqueta de tipo definida por el juego, de 0 a 255. El pool la guarda, pero no selecciona comportamientos ni rutinas de dibujo a partir de ella.
x, yCoordenadas de 16 bits con signo (
-32768–32767). El juego elige la unidad, por ejemplo píxeles o Q8.8; el pool no convierte unidades, recorta posiciones ni aplica velocidades automáticamente.
Valor devuelto
El ID del primer espacio libre (0–ENTITY_MAX-1), o 0xFF si no queda ninguno. Al reservar, fija active=1, guarda tipo y posición, borra velocidad/estado/temporizador y pone sprite=0xFF.
Condiciones y límites
El pool es un array fijo, sin asignación dinámica en el heap. ENTITY_MAX vale 16 por defecto y debe estar entre 1 y 255, con la misma definición en todas las unidades de compilación. Los ID empiezan en cero; 0xFF indica fallo.
Ejemplo de uso
first = entity_create(1, 2, 12);
second = entity_create(2, 6, 12);
if (first == 0xFF || second == 0xFF) { failures++; }Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El programa completo enseña el ciclo de vida de un espacio reutilizable. Lee cada número con su etiqueta: CREATED 002 tras reservar dos entidades; AFTER FREE 001 al liberar la primera; REUSED ID 000 al reutilizar el ID libre más bajo; AFTER CLEAR 000 al vaciar el pool. Comprueba también la consulta null tras liberar y la reinicialización de campos al reutilizar. FAILED CHECKS 000 indica que los valores coinciden.
El recorrido GB llama a cada callback para las dos entidades activas: UPDATE CALLS 002 y DRAW CALLS 002. El callback de actualización mueve ambas un tile a la derecha. El de dibujo coloca A en (3,12) y B en (7,12) para representarlas. Son tiles de fuente del fondo dibujados por el callback, no sprites asignados automáticamente.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\entity.c .\kitaq-docs\samples\api-examples\gb\entity_pool.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\entity_pool.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasmImplementación y código fuente
kitaqgb/lib/entity.h:29
Returns a reusable slot ID, or 0xFF if no slot is free.
kitaqgb/lib/entity.c:33
u8 entity_create(u8 type, s16 x, s16 y)
{
u8 i = 0;
while (i < ENTITY_MAX) {
if (entity_pool[i].active == 0) {
entity_pool[i].active = 1;
entity_pool[i].type = type;
entity_pool[i].x = x;
entity_pool[i].y = y;
entity_pool[i].vx = 0;
entity_pool[i].vy = 0;
entity_pool[i].state = 0;
entity_pool[i].timer = 0;
entity_pool[i].sprite = 0xFF;
return i;
}
i++;
}
return 0xFF;
}entity_destroy
Libera la entidad id; sus datos se conservan hasta que se reutiliza el espacio.
Sintaxis
void entity_destroy(u8 id);Parámetros
idÍndice de espacio reutilizable entre 0 y
ENTITY_MAX-1. Fuera de ese rango es inválido. Destruir un ID inválido no hace nada; consultarlo devuelve null.
Valor devuelto
Ninguno (void).
Condiciones y límites
El pool es un array fijo, sin asignación dinámica en el heap. ENTITY_MAX vale 16 por defecto y debe estar entre 1 y 255, con la misma definición en todas las unidades de compilación. Los ID empiezan en cero; 0xFF indica fallo.
Destruir solo borra active; no elimina los demás campos ni libera sprites o recursos. Una reserva posterior puede reutilizar el mismo ID y dirección para otra entidad. El juego debe limpiar los recursos asociados.
Ejemplo de uso
entity_destroy(first);
after_free = entity_count_active();
if (entity_get(first) != 0 || after_free != 1) { failures++; }Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El programa completo enseña el ciclo de vida de un espacio reutilizable. Lee cada número con su etiqueta: CREATED 002 tras reservar dos entidades; AFTER FREE 001 al liberar la primera; REUSED ID 000 al reutilizar el ID libre más bajo; AFTER CLEAR 000 al vaciar el pool. Comprueba también la consulta null tras liberar y la reinicialización de campos al reutilizar. FAILED CHECKS 000 indica que los valores coinciden.
El recorrido GB llama a cada callback para las dos entidades activas: UPDATE CALLS 002 y DRAW CALLS 002. El callback de actualización mueve ambas un tile a la derecha. El de dibujo coloca A en (3,12) y B en (7,12) para representarlas. Son tiles de fuente del fondo dibujados por el callback, no sprites asignados automáticamente.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\entity.c .\kitaq-docs\samples\api-examples\gb\entity_pool.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\entity_pool.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasmImplementación y código fuente
kitaqgb/lib/entity.h:32
Release a valid slot without clearing its payload. Reallocation resets the payload; a saved pointer or ID must not be treated as a persistent entity identity.
kitaqgb/lib/entity.c:56
void entity_destroy(u8 id)
{
if (id >= ENTITY_MAX) return;
// Deactivation only releases this pool slot; the caller handles sprite/resource cleanup.
entity_pool[id].active = 0;
}entity_draw_all
Recorre las entidades activas y pasa cada ID al callback de dibujo. Usa el mismo recorrido que entity_update_all; no se dibuja ningún sprite ni píxel si el callback no envía datos de dibujo.
Sintaxis
void entity_draw_all(EntityFn fn);Parámetros
fnPuntero a función con firma
void fn(u8 id). Recibe un ID; usaentity_get(id)para acceder a los campos. Se acepta null y no se realizan llamadas.
Valor devuelto
Ninguno (void).
Condiciones y límites
El pool es un array fijo, sin asignación dinámica en el heap. ENTITY_MAX vale 16 por defecto y debe estar entre 1 y 255, con la misma definición en todas las unidades de compilación. Los ID empiezan en cero; 0xFF indica fallo.
Comprueba la actividad al llegar a cada espacio. El callback puede desactivar uno posterior para omitirlo o activarlo para procesarlo en esta pasada. No usa una instantánea del conjunto activo inicial.
Ejemplo de uso
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++; }Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El programa completo enseña el ciclo de vida de un espacio reutilizable. Lee cada número con su etiqueta: CREATED 002 tras reservar dos entidades; AFTER FREE 001 al liberar la primera; REUSED ID 000 al reutilizar el ID libre más bajo; AFTER CLEAR 000 al vaciar el pool. Comprueba también la consulta null tras liberar y la reinicialización de campos al reutilizar. FAILED CHECKS 000 indica que los valores coinciden.
El recorrido GB llama a cada callback para las dos entidades activas: UPDATE CALLS 002 y DRAW CALLS 002. El callback de actualización mueve ambas un tile a la derecha. El de dibujo coloca A en (3,12) y B en (7,12) para representarlas. Son tiles de fuente del fondo dibujados por el callback, no sprites asignados automáticamente.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\entity.c .\kitaq-docs\samples\api-examples\gb\entity_pool.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\entity_pool.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasmImplementación y código fuente
kitaqgb/lib/entity.h:39
Use the same active-slot traversal for drawing; the callback supplies all rendering.
kitaqgb/lib/entity.c:87
void entity_draw_all(EntityFn fn)
{
entity_update_all(fn);
}entity_get
Devuelve un puntero a la entidad activa, o null si el ID no es válido o está libre. El almacenamiento se reutiliza.
Sintaxis
Entity* entity_get(u8 id);Parámetros
idÍndice de espacio reutilizable entre 0 y
ENTITY_MAX-1. Fuera de ese rango es inválido. Destruir un ID inválido no hace nada; consultarlo devuelve null.
Valor devuelto
Puntero modificable al espacio activo, o null si el ID es inválido o está libre. La memoria pertenece al pool; no la liberes ni uses el puntero como identidad permanente tras destruir y recrear entidades.
Condiciones y límites
El pool es un array fijo, sin asignación dinámica en el heap. ENTITY_MAX vale 16 por defecto y debe estar entre 1 y 255, con la misma definición en todas las unidades de compilación. Los ID empiezan en cero; 0xFF indica fallo.
Destruir solo borra active; no elimina los demás campos ni libera sprites o recursos. Una reserva posterior puede reutilizar el mismo ID y dirección para otra entidad. El juego debe limpiar los recursos asociados.
Ejemplo de uso
current_entity = entity_get(first);
if (current_entity != 0) { current_entity->vx = 5; }
else { failures++; }Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El programa completo enseña el ciclo de vida de un espacio reutilizable. Lee cada número con su etiqueta: CREATED 002 tras reservar dos entidades; AFTER FREE 001 al liberar la primera; REUSED ID 000 al reutilizar el ID libre más bajo; AFTER CLEAR 000 al vaciar el pool. Comprueba también la consulta null tras liberar y la reinicialización de campos al reutilizar. FAILED CHECKS 000 indica que los valores coinciden.
El recorrido GB llama a cada callback para las dos entidades activas: UPDATE CALLS 002 y DRAW CALLS 002. El callback de actualización mueve ambas un tile a la derecha. El de dibujo coloca A en (3,12) y B en (7,12) para representarlas. Son tiles de fuente del fondo dibujados por el callback, no sprites asignados automáticamente.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\entity.c .\kitaq-docs\samples\api-examples\gb\entity_pool.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\entity_pool.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasmImplementación y código fuente
kitaqgb/lib/entity.h:34
Returns null for an invalid or inactive ID; the returned pointer aliases reusable pool storage.
kitaqgb/lib/entity.c:65
Entity* entity_get(u8 id)
{
if (id >= ENTITY_MAX) return 0;
if (entity_pool[id].active == 0) return 0;
return &entity_pool[(__safe_index u8)id];
}entity_init
Inicializa todos los espacios del pool de entidades.
Sintaxis
void entity_init();Valor devuelto
Ninguno (void).
Condiciones y límites
El pool es un array fijo, sin asignación dinámica en el heap. ENTITY_MAX vale 16 por defecto y debe estar entre 1 y 255, con la misma definición en todas las unidades de compilación. Los ID empiezan en cero; 0xFF indica fallo.
Pone a cero active,type,x,y,vx,vy,state,timer y deja sprite en 0xFF en todos los espacios. No oculta ni libera sprites de hardware; esos recursos se limpian por separado.
Ejemplo de uso
entity_init();
if (entity_count_active() != 0) { failures++; }Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El programa completo enseña el ciclo de vida de un espacio reutilizable. Lee cada número con su etiqueta: CREATED 002 tras reservar dos entidades; AFTER FREE 001 al liberar la primera; REUSED ID 000 al reutilizar el ID libre más bajo; AFTER CLEAR 000 al vaciar el pool. Comprueba también la consulta null tras liberar y la reinicialización de campos al reutilizar. FAILED CHECKS 000 indica que los valores coinciden.
El recorrido GB llama a cada callback para las dos entidades activas: UPDATE CALLS 002 y DRAW CALLS 002. El callback de actualización mueve ambas un tile a la derecha. El de dibujo coloca A en (3,12) y B en (7,12) para representarlas. Son tiles de fuente del fondo dibujados por el callback, no sprites asignados automáticamente.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\entity.c .\kitaq-docs\samples\api-examples\gb\entity_pool.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\entity_pool.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasmImplementación y código fuente
kitaqgb/lib/entity.h:27
Reset every slot before the game starts using the pool.
kitaqgb/lib/entity.c:8
void entity_init()
{
entity_clear_all();
}entity_update_all
Recorre los espacios activos por ID ascendente y llama una vez a fn(id) para cada uno. El callback implementa movimiento, colisiones o temporizadores; el pool no aporta esa lógica. Un callback null no hace nada.
Sintaxis
void entity_update_all(EntityFn fn);Parámetros
fnPuntero a función con firma
void fn(u8 id). Recibe un ID; usaentity_get(id)para acceder a los campos. Se acepta null y no se realizan llamadas.
Valor devuelto
Ninguno (void).
Condiciones y límites
El pool es un array fijo, sin asignación dinámica en el heap. ENTITY_MAX vale 16 por defecto y debe estar entre 1 y 255, con la misma definición en todas las unidades de compilación. Los ID empiezan en cero; 0xFF indica fallo.
Comprueba la actividad al llegar a cada espacio. El callback puede desactivar uno posterior para omitirlo o activarlo para procesarlo en esta pasada. No usa una instantánea del conjunto activo inicial.
Ejemplo de uso
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++; }Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El programa completo enseña el ciclo de vida de un espacio reutilizable. Lee cada número con su etiqueta: CREATED 002 tras reservar dos entidades; AFTER FREE 001 al liberar la primera; REUSED ID 000 al reutilizar el ID libre más bajo; AFTER CLEAR 000 al vaciar el pool. Comprueba también la consulta null tras liberar y la reinicialización de campos al reutilizar. FAILED CHECKS 000 indica que los valores coinciden.
El recorrido GB llama a cada callback para las dos entidades activas: UPDATE CALLS 002 y DRAW CALLS 002. El callback de actualización mueve ambas un tile a la derecha. El de dibujo coloca A en (3,12) y B en (7,12) para representarlas. Son tiles de fuente del fondo dibujados por el callback, no sprites asignados automáticamente.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\entity.c .\kitaq-docs\samples\api-examples\gb\entity_pool.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\entity_pool.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasmImplementación y código fuente
kitaqgb/lib/entity.h:37
Call fn for each slot that is active when the scan reaches it; null is a no-op. Callbacks may change the pool, so newly activated later slots can run in this pass.
kitaqgb/lib/entity.c:74
void entity_update_all(EntityFn fn)
{
u8 i = 0;
if (fn == 0) return;
while (i < ENTITY_MAX) {
if (entity_pool[i].active != 0) {
fn(i);
}
i++;
}
}fixed.h — Aritmética de punto fijo Q8.8 y rectángulos
La aritmética Q8.8 representa coordenadas y velocidades fraccionarias mediante enteros, junto con pruebas de colisión entre rectángulos y puntos. Comprueba la precisión y los límites de cada operación.
fix_div
Divide valores Q8.8 después de reducir la precisión de los operandos.
Sintaxis
fix8 fix_div(fix8 a, fix8 b);Parámetros
aOperando izquierdo en Q8.8.
bOperando derecho en Q8.8.
Valor devuelto
Devuelve un cociente Q8.8, o cero si b == 0.
Condiciones y límites
La expresión es ((a >> 4) * 256) / (b >> 4). Un divisor distinto de cero debe seguir siéndolo después del desplazamiento: no pases valores brutos positivos de 1 a 15. El numerador escalado también debe caber en 16 bits.
Ejemplo de uso
result[3]=fix_div(768,512);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Dividir 3,0 entre 2,0 produce 1,5 (valor bruto 384). Otra comprobación verifica el retorno explícito cuando el divisor es cero.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_math.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_math.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/fixed.h:32
Scale the reduced-precision quotient back to 8.8 and return zero for b == 0. Callers must also ensure (b >> 4) is nonzero; the explicit check only tests b. The intermediate product must fit the compiler's integer arithmetic.
kitaqgb/lib/fixed.c:26
fix8 fix_div(fix8 a, fix8 b)
{
if (b == 0) return 0;
return (fix8)(((a >> 4) * 256) / (b >> 4));
}fix_from_int
Convierte una coordenada o velocidad entera a Q8.8 para conservar la parte fraccionaria en los cálculos posteriores.
Sintaxis
fix8 fix_from_int(s16 n);Parámetros
nEntero que se va a convertir, entre −128 y 127.
Valor devuelto
Devuelve el valor bruto n × 256.
Condiciones y límites
fix8 usa Q8.8 con signo: el valor bruto 256 representa 1,0. Mantén los valores intermedios y los resultados dentro del rango de 16 bits.
Ejemplo de uso
result[0]=fix_from_int(-3);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo convierte −3. El texto −00768 muestra el resultado bruto Q8.8, −768.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_math.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_math.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/fixed.h:23
Convert an integer to signed 8.8 fixed point by moving it into the high byte. The caller must keep the result within the representable 16-bit range.
kitaqgb/lib/fixed.c:5
fix8 fix_from_int(s16 n)
{
return (fix8)(n << 8);
}fix_lerp
Interpola de un valor Q8.8 hacia otro usando un peso de ocho bits.
Sintaxis
fix8 fix_lerp(fix8 a, fix8 b, u8 t_q8);Parámetros
aOperando izquierdo en Q8.8.
bOperando derecho en Q8.8.
t_q8Peso de interpolación, de 0 a 255.
Valor devuelto
Devuelve el valor Q8.8 de la interpolación aproximada.
Condiciones y límites
La diferencia y el peso se desplazan cuatro bits a la derecha. Esto deja 16 niveles de peso, de modo que ni siquiera 255 garantiza alcanzar el extremo final. Mantén b - a y el resultado dentro del rango de 16 bits.
Ejemplo de uso
result[4]=fix_lerp(0,1024,128);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Entre 0 y 4,0, un peso de 128 produce 2,0 (valor bruto 512). El peso 255 produce 3,75 (valor bruto 960), lo que demuestra que no se alcanza el extremo final.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_math.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_math.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/fixed.h:35
Interpolate toward b using a quantized Q0.8 weight. Both shifts discard low bits, so small changes may vanish and a weight of 255 need not reach b.
kitaqgb/lib/fixed.c:34
fix8 fix_lerp(fix8 a, fix8 b, u8 t_q8)
{
// The endpoint difference must fit s16 before the reduced-precision multiplication.
fix8 d = (fix8)(b - a);
return (fix8)(a + (fix8)((d >> 4) * (s16)(t_q8 >> 4)));
}fix_mul
Multiplica dos valores Q8.8 mediante una aproximación de bajo coste.
Sintaxis
fix8 fix_mul(fix8 a, fix8 b);Parámetros
aOperando izquierdo en Q8.8.
bOperando derecho en Q8.8.
Valor devuelto
Devuelve el producto en Q8.8.
Condiciones y límites
Antes de multiplicar, ambos operandos se desplazan cuatro bits a la derecha y pierden sus cuatro bits menos significativos. La precisión es menor que en una multiplicación completa de 16 por 16 bits. fix8 usa Q8.8 con signo, donde el valor bruto 256 representa 1,0. Mantén los valores intermedios y los resultados dentro del rango de 16 bits.
Ejemplo de uso
result[2]=fix_mul(384,512);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Multiplicar 1,5 por 2,0 produce 3,0 (valor bruto 768). El programa también comprueba un caso de cuantización: multiplicar el valor bruto 271 por 271 da 256.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_math.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_math.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/fixed.h:28
Approximate 8.8 multiplication by discarding four low bits from each operand before multiplying. This trades precision for a smaller intermediate product.
kitaqgb/lib/fixed.c:18
fix8 fix_mul(fix8 a, fix8 b)
{
return (fix8)((a >> 4) * (b >> 4));
}fix_to_int
Extrae una coordenada entera de Q8.8 descartando los bits fraccionarios. Los valores negativos se redondean hacia menos infinito.
Sintaxis
s16 fix_to_int(fix8 x);Parámetros
xValor Q8.8 que se va a convertir a entero.
Valor devuelto
Devuelve un entero con signo.
Condiciones y límites
fix8 usa Q8.8 con signo: el valor bruto 256 representa 1,0. Mantén los valores intermedios y los resultados dentro del rango de 16 bits.
Ejemplo de uso
result[1]=fix_to_int(-384);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El valor bruto −384 (−1,5) produce −2, mostrado como −00002. Una comprobación de límites confirma también que el valor bruto −1 se convierte en −1.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_math.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_math.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/fixed.h:25
Discard the eight fractional bits using a signed right shift.
kitaqgb/lib/fixed.c:11
s16 fix_to_int(fix8 x)
{
return (s16)(x >> 8);
}kq_abs_s16
Calcula el valor absoluto de un entero de 16 bits con signo.
Sintaxis
s16 kq_abs_s16(s16 v);Parámetros
vValor de 16 bits con signo cuyo valor absoluto se necesita.
Valor devuelto
Devuelve una magnitud no negativa, salvo en el caso de −32768, cuyo valor absoluto no es representable.
Condiciones y límites
El valor positivo 32768 no cabe en s16. Excluye −32768 si necesitas un resultado no negativo.
Ejemplo de uso
result[0]=kq_abs_s16(-123);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo transforma −123 en 123, como al calcular la magnitud de una diferencia de coordenadas.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_math_limits.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_math_limits.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/fixed.h:38
Return the magnitude in s16. The most-negative s16 has no positive s16 representation and must be excluded by callers needing a nonnegative result.
kitaqgb/lib/fixed.c:43
s16 kq_abs_s16(s16 v)
{
if (v < 0) return (s16)(0 - v);
return v;
}kq_clamp_s16
Limita una coordenada o velocidad a un intervalo que incluye ambos extremos.
Sintaxis
s16 kq_clamp_s16(s16 v, s16 lo, s16 hi);Parámetros
vValor con signo que se va a limitar.
loLímite inferior incluido.
hiLímite superior incluido.
Valor devuelto
Devuelve lo si el valor está por debajo del intervalo, hi si lo supera o v si está dentro.
Condiciones y límites
Proporciona un intervalo válido con lo <= hi.
Ejemplo de uso
result[3]=kq_clamp_s16(25,-10,10);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Limitar 25 al intervalo −10…10 da 10. Las comprobaciones también cubren −11→−10 en el límite inferior y 3→3 dentro del intervalo.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_math_limits.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_math_limits.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/fixed.h:44
Clamp to an inclusive interval; callers must provide lo <= hi.
kitaqgb/lib/fixed.c:64
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
Selecciona el mayor de dos valores de 16 bits con signo.
Sintaxis
s16 kq_max_s16(s16 a, s16 b);Parámetros
aPrimer valor con signo que se va a comparar.
bSegundo valor con signo que se va a comparar.
Valor devuelto
Devuelve el operando seleccionado.
Condiciones y límites
La comparación tiene en cuenta el signo. Si los operandos son iguales, devuelve ese mismo valor; no modifica ninguna entrada.
Ejemplo de uso
result[2]=kq_max_s16(-7,4);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Comparar −7 y 4 da 4. Los resultados negativos se muestran con un signo menos.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_math_limits.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_math_limits.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/fixed.h:42
Select the larger signed value.
kitaqgb/lib/fixed.c:57
s16 kq_max_s16(s16 a, s16 b)
{
if (a > b) return a;
return b;
}kq_min_s16
Selecciona el menor de dos valores de 16 bits con signo.
Sintaxis
s16 kq_min_s16(s16 a, s16 b);Parámetros
aPrimer valor con signo que se va a comparar.
bSegundo valor con signo que se va a comparar.
Valor devuelto
Devuelve el operando seleccionado.
Condiciones y límites
La comparación tiene en cuenta el signo. Si los operandos son iguales, devuelve ese mismo valor; no modifica ninguna entrada.
Ejemplo de uso
result[1]=kq_min_s16(-7,4);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Comparar −7 y 4 da -7. Los resultados negativos se muestran con un signo menos.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_math_limits.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_math_limits.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/fixed.h:40
Select the smaller signed value.
kitaqgb/lib/fixed.c:50
s16 kq_min_s16(s16 a, s16 b)
{
if (a < b) return a;
return b;
}kq_point_in_rect
Comprueba si un punto está dentro de un rectángulo, incluidos sus bordes izquierdo y superior.
Sintaxis
u8 kq_point_in_rect(s16 x, s16 y, KQRect r);Parámetros
xCoordenada X del punto, en el sistema de coordenadas del rectángulo.
yCoordenada Y del punto.
rRectángulo que se va a comprobar, pasado por valor.
Valor devuelto
Devuelve 1 si está dentro y 0 si está fuera.
Condiciones y límites
Usa dimensiones positivas y asegúrate de que las sumas de coordenada y tamaño sean representables como s16. Se excluyen los bordes derecho e inferior. Los rectángulos de área cero no se rechazan explícitamente.
Ejemplo de uso
result[1]=kq_point_in_rect(9,1,a);
for(gy=0;gy<11;gy++){for(gx=0;gx<15;gx++){
inside_a=kq_point_in_rect(gx,gy,a);inside_b=kq_point_in_rect(gx,gy,b);
tile=0;if(inside_a){tile=65;result[3]=result[3]+1;}if(inside_b)tile=66;if(inside_a && inside_b){tile=79;result[4]=result[4]+1;}
m_put(1+gx,2+gy,tile);if(tile!=0)vram_example_color(1+gx,2+gy,1,1,tile==65?1:(tile==66?2:3));
}}Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Cada unidad de coordenada ocupa un tile. Los rectángulos A en (1,1) y B en (5,4) miden 8×6. Las celdas exclusivas de A muestran A; las exclusivas de B, B; y la zona de solapamiento de 4×3 muestra 12 celdas O. El borde derecho de A, x=9, queda excluido. En CGB, A es rojo, B azul y O verde.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_geometry.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_geometry.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/fixed.h:51
Test a half-open rectangle: left/top edges are included, right/bottom excluded. The coordinate-plus-size sums must remain representable as s16.
kitaqgb/lib/fixed.c:85
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
Comprueba si dos rectángulos alineados con los ejes se solapan con un área mayor que cero.
Sintaxis
u8 kq_rect_intersect(KQRect a, KQRect b);Parámetros
aPrimer rectángulo, pasado por valor:
x, yindican su esquina superior izquierda;w, hson su anchura y altura.bSegundo rectángulo, en el mismo sistema de coordenadas que A.
Valor devuelto
Devuelve 1 si hay solapamiento y 0 si están separados o solo se tocan los bordes.
Condiciones y límites
Usa dimensiones positivas y asegúrate de que las sumas de coordenada y tamaño sean representables como s16. Se excluyen los bordes derecho e inferior. Los rectángulos de área cero no se rechazan explícitamente.
Ejemplo de uso
result[0]=kq_rect_intersect(a,b);result[2]=kq_rect_intersect(a,touch);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Cada unidad de coordenada ocupa un tile. Los rectángulos A en (1,1) y B en (5,4) miden 8×6. Las celdas exclusivas de A muestran A; las exclusivas de B, B; y la zona de solapamiento de 4×3 muestra 12 celdas O. El borde derecho de A, x=9, queda excluido. En CGB, A es rojo, B azul y O verde.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_geometry.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_geometry.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/fixed.h:48
Test overlap using exclusive right/bottom edges; touching edges do not collide. Require positive dimensions and edge sums that fit s16; zero-sized rectangles are not explicitly rejected and may be reported as overlapping.
kitaqgb/lib/fixed.c:74
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 — Estado, pulsación, liberación y repetición de botones
Usa input_down para movimiento continuo, input_pressed para acciones únicas, input_released para actuar al soltar y input_repeat para repetir opciones de menú. Inicializa una vez, actualiza una vez por ciclo de entrada y consulta cuando lo necesites. btn_down, btn_pressed, btn_released y btn_repeat son alias de esas cuatro consultas.
Máscaras comunes: BTN_RIGHT=0x01, BTN_LEFT=0x02, BTN_UP=0x04, BTN_DOWN=0x08, BTN_A=0x10, BTN_B=0x20, BTN_SELECT=0x40, BTN_START=0x80. Un bit a 1 indica que el botón está mantenido. input_* usa este formato en GB y FC; las funciones FC de lectura directa emplean otro orden.
Los intervalos cuentan actualizaciones, no milisegundos. Una pulsación nueva genera un pulso inmediato. Con INPUT_REPEAT_DELAY=18 e INPUT_REPEAT_RATE=5, el siguiente llega 19 actualizaciones después y los demás cada 6. Cada botón tiene su contador. Aplica los mismos valores de las macros al compilar input.c; cambiar solo el encabezado del código llamante no reconfigura la biblioteca.
btn_down
btn_down es un alias de input_down. Comprueba si alguno de los botones seleccionados está pulsado actualmente.
Comprueba si está mantenido algún botón seleccionado por mask.
Sintaxis
u8 btn_down(u8 mask);Parámetros
maskUna máscara
BTN_*o varias combinadas con|. Basta con que coincida cualquiera de los botones seleccionados;BTN_A | BTN_Bno exige ambos. La máscara 0 siempre devuelve 0. Para exigir todos los botones mantenidos, compara(input_current() & mask) == mask.
Valor devuelto
Devuelve exactamente 1 si algún botón seleccionado cumple la condición; en caso contrario, 0. No devuelve una máscara de botones.
Condiciones y límites
La cabecera define una macro de tipo objeto que se expande al nombre de la implementación. Los argumentos, valores devueltos y acceso al estado son los mismos que en el destino; el alias no añade estado ni procesamiento propio. Usa input.h/input.c para entradas o system.h/system.c para servicios de fotograma, como en el ejemplo completo y su comando de compilación.
Máscaras comunes: BTN_RIGHT=0x01, BTN_LEFT=0x02, BTN_UP=0x04, BTN_DOWN=0x08, BTN_A=0x10, BTN_B=0x20, BTN_SELECT=0x40, BTN_START=0x80. Un bit a 1 indica que el botón está mantenido. input_* usa este formato en GB y FC; las funciones FC de lectura directa emplean otro orden.
Las consultas leen el último input_update() sin volver a leer el mando, consumir eventos ni avanzar temporizadores. Consultar varias veces en el mismo ciclo da el mismo resultado. Si llamas dos veces a input_update() manteniendo el botón, la segunda llamada borra el evento de nueva pulsación.
Ejemplo de uso
if (btn_down(BTN_A)!=0) held_ticks++;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Este programa distingue entre mantener pulsado un botón, pulsarlo por primera vez, soltarlo y generar repeticiones automáticas. Mantén A durante 40 actualizaciones y suéltalo. FIRST DOWN, FIRST PRESS y FIRST REPEAT valen 1; FIRST CURRENT vale 16. HELD TICKS vale 40, PRESS COUNT vale 1 y REPEAT COUNT vale 5. Al soltar A, RELEASE vale 1, LAST CURRENT vale 0 y LAST PREVIOUS vale 16. FAILED CHECKS debe ser 0. Si cambias la duración, cambian los recuentos; el programa comprueba los intervalos de repetición según la duración observada.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\input.c .\kitaq-docs\samples\api-examples\gb\input_aliases.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\input_aliases.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm --no-cacheImplementación y código fuente
kitaqgb/lib/input.h:48
#define btn_down input_downkitaqgb/lib/input.c:68
u8 input_down(u8 mask)
{
return (u8)((kq_input_keys & mask) != 0);
}btn_pressed
btn_pressed es un alias de input_pressed. Comprueba si alguno de los botones seleccionados se acaba de pulsar en la última actualización de entrada.
Detecta si un botón de la máscara pasó de suelto a pulsado en la última actualización.
Sintaxis
u8 btn_pressed(u8 mask);Parámetros
maskUna máscara
BTN_*o varias combinadas con|. Basta con que coincida cualquiera de los botones seleccionados;BTN_A | BTN_Bno exige ambos. La máscara 0 siempre devuelve 0. Para exigir todos los botones mantenidos, compara(input_current() & mask) == mask.
Valor devuelto
Devuelve exactamente 1 si algún botón seleccionado cumple la condición; en caso contrario, 0. No devuelve una máscara de botones.
Condiciones y límites
La cabecera define una macro de tipo objeto que se expande al nombre de la implementación. Los argumentos, valores devueltos y acceso al estado son los mismos que en el destino; el alias no añade estado ni procesamiento propio. Usa input.h/input.c para entradas o system.h/system.c para servicios de fotograma, como en el ejemplo completo y su comando de compilación.
Máscaras comunes: BTN_RIGHT=0x01, BTN_LEFT=0x02, BTN_UP=0x04, BTN_DOWN=0x08, BTN_A=0x10, BTN_B=0x20, BTN_SELECT=0x40, BTN_START=0x80. Un bit a 1 indica que el botón está mantenido. input_* usa este formato en GB y FC; las funciones FC de lectura directa emplean otro orden.
Las consultas leen el último input_update() sin volver a leer el mando, consumir eventos ni avanzar temporizadores. Consultar varias veces en el mismo ciclo da el mismo resultado. Si llamas dos veces a input_update() manteniendo el botón, la segunda llamada borra el evento de nueva pulsación.
Ejemplo de uso
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++;
}Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Este programa distingue entre mantener pulsado un botón, pulsarlo por primera vez, soltarlo y generar repeticiones automáticas. Mantén A durante 40 actualizaciones y suéltalo. FIRST DOWN, FIRST PRESS y FIRST REPEAT valen 1; FIRST CURRENT vale 16. HELD TICKS vale 40, PRESS COUNT vale 1 y REPEAT COUNT vale 5. Al soltar A, RELEASE vale 1, LAST CURRENT vale 0 y LAST PREVIOUS vale 16. FAILED CHECKS debe ser 0. Si cambias la duración, cambian los recuentos; el programa comprueba los intervalos de repetición según la duración observada.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\input.c .\kitaq-docs\samples\api-examples\gb\input_aliases.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\input_aliases.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm --no-cacheImplementación y código fuente
kitaqgb/lib/input.h:49
#define btn_pressed input_pressedkitaqgb/lib/input.c:74
u8 input_pressed(u8 mask)
{
return (u8)((kq_input_press_keys & mask) != 0);
}btn_released
btn_released es un alias de input_released. Comprueba si se ha soltado alguno de los botones seleccionados en la última actualización de entrada.
Detecta si un botón de la máscara pasó de pulsado a suelto en la última actualización.
Sintaxis
u8 btn_released(u8 mask);Parámetros
maskUna máscara
BTN_*o varias combinadas con|. Basta con que coincida cualquiera de los botones seleccionados;BTN_A | BTN_Bno exige ambos. La máscara 0 siempre devuelve 0. Para exigir todos los botones mantenidos, compara(input_current() & mask) == mask.
Valor devuelto
Devuelve exactamente 1 si algún botón seleccionado cumple la condición; en caso contrario, 0. No devuelve una máscara de botones.
Condiciones y límites
La cabecera define una macro de tipo objeto que se expande al nombre de la implementación. Los argumentos, valores devueltos y acceso al estado son los mismos que en el destino; el alias no añade estado ni procesamiento propio. Usa input.h/input.c para entradas o system.h/system.c para servicios de fotograma, como en el ejemplo completo y su comando de compilación.
Máscaras comunes: BTN_RIGHT=0x01, BTN_LEFT=0x02, BTN_UP=0x04, BTN_DOWN=0x08, BTN_A=0x10, BTN_B=0x20, BTN_SELECT=0x40, BTN_START=0x80. Un bit a 1 indica que el botón está mantenido. input_* usa este formato en GB y FC; las funciones FC de lectura directa emplean otro orden.
Las consultas leen el último input_update() sin volver a leer el mando, consumir eventos ni avanzar temporizadores. Consultar varias veces en el mismo ciclo da el mismo resultado. Si llamas dos veces a input_update() manteniendo el botón, la segunda llamada borra el evento de nueva pulsación.
Ejemplo de uso
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;
}Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Este programa distingue entre mantener pulsado un botón, pulsarlo por primera vez, soltarlo y generar repeticiones automáticas. Mantén A durante 40 actualizaciones y suéltalo. FIRST DOWN, FIRST PRESS y FIRST REPEAT valen 1; FIRST CURRENT vale 16. HELD TICKS vale 40, PRESS COUNT vale 1 y REPEAT COUNT vale 5. Al soltar A, RELEASE vale 1, LAST CURRENT vale 0 y LAST PREVIOUS vale 16. FAILED CHECKS debe ser 0. Si cambias la duración, cambian los recuentos; el programa comprueba los intervalos de repetición según la duración observada.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\input.c .\kitaq-docs\samples\api-examples\gb\input_aliases.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\input_aliases.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm --no-cacheImplementación y código fuente
kitaqgb/lib/input.h:50
#define btn_released input_releasedkitaqgb/lib/input.c:80
u8 input_released(u8 mask)
{
return (u8)((kq_input_release_keys & mask) != 0);
}btn_repeat
btn_repeat es un alias de input_repeat. Comprueba la pulsación inicial o un pulso de repetición programado mientras se mantiene el botón.
Detecta una pulsación inicial o un pulso de repetición de un botón de la máscara.
Sintaxis
u8 btn_repeat(u8 mask);Parámetros
maskUna máscara
BTN_*o varias combinadas con|. Basta con que coincida cualquiera de los botones seleccionados;BTN_A | BTN_Bno exige ambos. La máscara 0 siempre devuelve 0. Para exigir todos los botones mantenidos, compara(input_current() & mask) == mask.
Valor devuelto
Devuelve exactamente 1 si algún botón seleccionado cumple la condición; en caso contrario, 0. No devuelve una máscara de botones.
Condiciones y límites
La cabecera define una macro de tipo objeto que se expande al nombre de la implementación. Los argumentos, valores devueltos y acceso al estado son los mismos que en el destino; el alias no añade estado ni procesamiento propio. Usa input.h/input.c para entradas o system.h/system.c para servicios de fotograma, como en el ejemplo completo y su comando de compilación.
Máscaras comunes: BTN_RIGHT=0x01, BTN_LEFT=0x02, BTN_UP=0x04, BTN_DOWN=0x08, BTN_A=0x10, BTN_B=0x20, BTN_SELECT=0x40, BTN_START=0x80. Un bit a 1 indica que el botón está mantenido. input_* usa este formato en GB y FC; las funciones FC de lectura directa emplean otro orden.
Las consultas leen el último input_update() sin volver a leer el mando, consumir eventos ni avanzar temporizadores. Consultar varias veces en el mismo ciclo da el mismo resultado. Si llamas dos veces a input_update() manteniendo el botón, la segunda llamada borra el evento de nueva pulsación.
Los intervalos cuentan actualizaciones, no milisegundos. Una pulsación nueva genera un pulso inmediato. Con INPUT_REPEAT_DELAY=18 e INPUT_REPEAT_RATE=5, el siguiente llega 19 actualizaciones después y los demás cada 6. Cada botón tiene su contador. Aplica los mismos valores de las macros al compilar input.c; cambiar solo el encabezado del código llamante no reconfigura la biblioteca.
Ejemplo de uso
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.
}Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Este programa distingue entre mantener pulsado un botón, pulsarlo por primera vez, soltarlo y generar repeticiones automáticas. Mantén A durante 40 actualizaciones y suéltalo. FIRST DOWN, FIRST PRESS y FIRST REPEAT valen 1; FIRST CURRENT vale 16. HELD TICKS vale 40, PRESS COUNT vale 1 y REPEAT COUNT vale 5. Al soltar A, RELEASE vale 1, LAST CURRENT vale 0 y LAST PREVIOUS vale 16. FAILED CHECKS debe ser 0. Si cambias la duración, cambian los recuentos; el programa comprueba los intervalos de repetición según la duración observada.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\input.c .\kitaq-docs\samples\api-examples\gb\input_aliases.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\input_aliases.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm --no-cacheImplementación y código fuente
kitaqgb/lib/input.h:51
#define btn_repeat input_repeatkitaqgb/lib/input.c:86
u8 input_repeat(u8 mask)
{
return (u8)((kq_input_repeat_keys & mask) != 0);
}input_current
Devuelve la máscara completa de botones mantenidos de la última actualización.
Sintaxis
u8 input_current();Valor devuelto
Una máscara de 8 bits en formato común BTN_*. Puede contener varios botones a la vez; 0 significa ninguno.
Condiciones y límites
Máscaras comunes: BTN_RIGHT=0x01, BTN_LEFT=0x02, BTN_UP=0x04, BTN_DOWN=0x08, BTN_A=0x10, BTN_B=0x20, BTN_SELECT=0x40, BTN_START=0x80. Un bit a 1 indica que el botón está mantenido. input_* usa este formato en GB y FC; las funciones FC de lectura directa emplean otro orden.
Las consultas leen el último input_update() sin volver a leer el mando, consumir eventos ni avanzar temporizadores. Consultar varias veces en el mismo ciclo da el mismo resultado. Si llamas dos veces a input_update() manteniendo el botón, la segunda llamada borra el evento de nueva pulsación.
Ejemplo de uso
first_current=input_current(); // Only A held: BTN_A, or decimal 16.Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Este programa distingue entre mantener pulsado un botón, pulsarlo por primera vez, soltarlo y generar repeticiones automáticas. Mantén A durante 40 actualizaciones y suéltalo. FIRST DOWN, FIRST PRESS y FIRST REPEAT valen 1; FIRST CURRENT vale 16. HELD TICKS vale 40, PRESS COUNT vale 1 y REPEAT COUNT vale 5. Al soltar A, RELEASE vale 1, LAST CURRENT vale 0 y LAST PREVIOUS vale 16. FAILED CHECKS debe ser 0. Si cambias la duración, cambian los recuentos; el programa comprueba los intervalos de repetición según la duración observada.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\input.c .\kitaq-docs\samples\api-examples\gb\input_edges.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\input_edges.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm --no-cacheImplementación y código fuente
kitaqgb/lib/input.h:44
Return the complete held-button mask from the latest update.
kitaqgb/lib/input.c:92
u8 input_current()
{
return kq_input_keys;
}input_down
Comprueba si está mantenido algún botón seleccionado por mask.
Sintaxis
u8 input_down(u8 mask);Parámetros
maskUna máscara
BTN_*o varias combinadas con|. Basta con que coincida cualquiera de los botones seleccionados;BTN_A | BTN_Bno exige ambos. La máscara 0 siempre devuelve 0. Para exigir todos los botones mantenidos, compara(input_current() & mask) == mask.
Valor devuelto
Devuelve exactamente 1 si algún botón seleccionado cumple la condición; en caso contrario, 0. No devuelve una máscara de botones.
Condiciones y límites
Máscaras comunes: BTN_RIGHT=0x01, BTN_LEFT=0x02, BTN_UP=0x04, BTN_DOWN=0x08, BTN_A=0x10, BTN_B=0x20, BTN_SELECT=0x40, BTN_START=0x80. Un bit a 1 indica que el botón está mantenido. input_* usa este formato en GB y FC; las funciones FC de lectura directa emplean otro orden.
Las consultas leen el último input_update() sin volver a leer el mando, consumir eventos ni avanzar temporizadores. Consultar varias veces en el mismo ciclo da el mismo resultado. Si llamas dos veces a input_update() manteniendo el botón, la segunda llamada borra el evento de nueva pulsación.
Ejemplo de uso
if (input_down(BTN_A)!=0) held_ticks++;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Este programa distingue entre mantener pulsado un botón, pulsarlo por primera vez, soltarlo y generar repeticiones automáticas. Mantén A durante 40 actualizaciones y suéltalo. FIRST DOWN, FIRST PRESS y FIRST REPEAT valen 1; FIRST CURRENT vale 16. HELD TICKS vale 40, PRESS COUNT vale 1 y REPEAT COUNT vale 5. Al soltar A, RELEASE vale 1, LAST CURRENT vale 0 y LAST PREVIOUS vale 16. FAILED CHECKS debe ser 0. Si cambias la duración, cambian los recuentos; el programa comprueba los intervalos de repetición según la duración observada.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\input.c .\kitaq-docs\samples\api-examples\gb\input_edges.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\input_edges.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm --no-cacheImplementación y código fuente
kitaqgb/lib/input.h:36
Return whether any masked button is currently held.
kitaqgb/lib/input.c:68
u8 input_down(u8 mask)
{
return (u8)((kq_input_keys & mask) != 0);
}input_init
Pone a cero las máscaras actual, anterior, de pulsación, de liberación y de repetición, y reinicia los ocho temporizadores con INPUT_REPEAT_DELAY. No lee el mando. Un botón mantenido durante la primera actualización posterior se considera una nueva pulsación.
Sintaxis
void input_init();Valor devuelto
Ninguno (void).
Condiciones y límites
Máscaras comunes: BTN_RIGHT=0x01, BTN_LEFT=0x02, BTN_UP=0x04, BTN_DOWN=0x08, BTN_A=0x10, BTN_B=0x20, BTN_SELECT=0x40, BTN_START=0x80. Un bit a 1 indica que el botón está mantenido. input_* usa este formato en GB y FC; las funciones FC de lectura directa emplean otro orden.
Los intervalos cuentan actualizaciones, no milisegundos. Una pulsación nueva genera un pulso inmediato. Con INPUT_REPEAT_DELAY=18 e INPUT_REPEAT_RATE=5, el siguiente llega 19 actualizaciones después y los demás cada 6. Cada botón tiene su contador. Aplica los mismos valores de las macros al compilar input.c; cambiar solo el encabezado del código llamante no reconfigura la biblioteca.
Ejemplo de uso
input_init();
if (input_current()!=0 || input_previous()!=0) failures++;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Este programa distingue entre mantener pulsado un botón, pulsarlo por primera vez, soltarlo y generar repeticiones automáticas. Mantén A durante 40 actualizaciones y suéltalo. FIRST DOWN, FIRST PRESS y FIRST REPEAT valen 1; FIRST CURRENT vale 16. HELD TICKS vale 40, PRESS COUNT vale 1 y REPEAT COUNT vale 5. Al soltar A, RELEASE vale 1, LAST CURRENT vale 0 y LAST PREVIOUS vale 16. FAILED CHECKS debe ser 0. Si cambias la duración, cambian los recuentos; el programa comprueba los intervalos de repetición según la duración observada.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\input.c .\kitaq-docs\samples\api-examples\gb\input_edges.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\input_edges.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm --no-cacheImplementación y código fuente
kitaqgb/lib/input.h:31
Clear sampled/edge state and initialize an independent repeat timer for each button.
kitaqgb/lib/input.c:18
void input_init()
{
u8 i;
kq_input_prev_keys = 0;
kq_input_keys = 0;
kq_input_press_keys = 0;
kq_input_release_keys = 0;
kq_input_repeat_keys = 0;
i = 0;
while (i < 8) {
input_repeat_timer[i] = INPUT_REPEAT_DELAY;
i++;
}
}input_pressed
Detecta si un botón de la máscara pasó de suelto a pulsado en la última actualización.
Sintaxis
u8 input_pressed(u8 mask);Parámetros
maskUna máscara
BTN_*o varias combinadas con|. Basta con que coincida cualquiera de los botones seleccionados;BTN_A | BTN_Bno exige ambos. La máscara 0 siempre devuelve 0. Para exigir todos los botones mantenidos, compara(input_current() & mask) == mask.
Valor devuelto
Devuelve exactamente 1 si algún botón seleccionado cumple la condición; en caso contrario, 0. No devuelve una máscara de botones.
Condiciones y límites
Máscaras comunes: BTN_RIGHT=0x01, BTN_LEFT=0x02, BTN_UP=0x04, BTN_DOWN=0x08, BTN_A=0x10, BTN_B=0x20, BTN_SELECT=0x40, BTN_START=0x80. Un bit a 1 indica que el botón está mantenido. input_* usa este formato en GB y FC; las funciones FC de lectura directa emplean otro orden.
Las consultas leen el último input_update() sin volver a leer el mando, consumir eventos ni avanzar temporizadores. Consultar varias veces en el mismo ciclo da el mismo resultado. Si llamas dos veces a input_update() manteniendo el botón, la segunda llamada borra el evento de nueva pulsación.
Ejemplo de uso
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++;
}Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Este programa distingue entre mantener pulsado un botón, pulsarlo por primera vez, soltarlo y generar repeticiones automáticas. Mantén A durante 40 actualizaciones y suéltalo. FIRST DOWN, FIRST PRESS y FIRST REPEAT valen 1; FIRST CURRENT vale 16. HELD TICKS vale 40, PRESS COUNT vale 1 y REPEAT COUNT vale 5. Al soltar A, RELEASE vale 1, LAST CURRENT vale 0 y LAST PREVIOUS vale 16. FAILED CHECKS debe ser 0. Si cambias la duración, cambian los recuentos; el programa comprueba los intervalos de repetición según la duración observada.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\input.c .\kitaq-docs\samples\api-examples\gb\input_edges.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\input_edges.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm --no-cacheImplementación y código fuente
kitaqgb/lib/input.h:38
Return whether any masked button became pressed in the latest sample.
kitaqgb/lib/input.c:74
u8 input_pressed(u8 mask)
{
return (u8)((kq_input_press_keys & mask) != 0);
}input_previous
Devuelve la máscara de botones mantenidos anterior a la última actualización.
Sintaxis
u8 input_previous();Valor devuelto
Una máscara de 8 bits en formato común BTN_*. Puede contener varios botones a la vez; 0 significa ninguno.
Condiciones y límites
Máscaras comunes: BTN_RIGHT=0x01, BTN_LEFT=0x02, BTN_UP=0x04, BTN_DOWN=0x08, BTN_A=0x10, BTN_B=0x20, BTN_SELECT=0x40, BTN_START=0x80. Un bit a 1 indica que el botón está mantenido. input_* usa este formato en GB y FC; las funciones FC de lectura directa emplean otro orden.
Las consultas leen el último input_update() sin volver a leer el mando, consumir eventos ni avanzar temporizadores. Consultar varias veces en el mismo ciclo da el mismo resultado. Si llamas dos veces a input_update() manteniendo el botón, la segunda llamada borra el evento de nueva pulsación.
Ejemplo de uso
first_previous=input_previous(); // No buttons in the preceding sample: 0.Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Este programa distingue entre mantener pulsado un botón, pulsarlo por primera vez, soltarlo y generar repeticiones automáticas. Mantén A durante 40 actualizaciones y suéltalo. FIRST DOWN, FIRST PRESS y FIRST REPEAT valen 1; FIRST CURRENT vale 16. HELD TICKS vale 40, PRESS COUNT vale 1 y REPEAT COUNT vale 5. Al soltar A, RELEASE vale 1, LAST CURRENT vale 0 y LAST PREVIOUS vale 16. FAILED CHECKS debe ser 0. Si cambias la duración, cambian los recuentos; el programa comprueba los intervalos de repetición según la duración observada.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\input.c .\kitaq-docs\samples\api-examples\gb\input_edges.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\input_edges.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm --no-cacheImplementación y código fuente
kitaqgb/lib/input.h:46
Return the held-button mask that preceded the latest update.
kitaqgb/lib/input.c:98
u8 input_previous()
{
return kq_input_prev_keys;
}input_released
Detecta si un botón de la máscara pasó de pulsado a suelto en la última actualización.
Sintaxis
u8 input_released(u8 mask);Parámetros
maskUna máscara
BTN_*o varias combinadas con|. Basta con que coincida cualquiera de los botones seleccionados;BTN_A | BTN_Bno exige ambos. La máscara 0 siempre devuelve 0. Para exigir todos los botones mantenidos, compara(input_current() & mask) == mask.
Valor devuelto
Devuelve exactamente 1 si algún botón seleccionado cumple la condición; en caso contrario, 0. No devuelve una máscara de botones.
Condiciones y límites
Máscaras comunes: BTN_RIGHT=0x01, BTN_LEFT=0x02, BTN_UP=0x04, BTN_DOWN=0x08, BTN_A=0x10, BTN_B=0x20, BTN_SELECT=0x40, BTN_START=0x80. Un bit a 1 indica que el botón está mantenido. input_* usa este formato en GB y FC; las funciones FC de lectura directa emplean otro orden.
Las consultas leen el último input_update() sin volver a leer el mando, consumir eventos ni avanzar temporizadores. Consultar varias veces en el mismo ciclo da el mismo resultado. Si llamas dos veces a input_update() manteniendo el botón, la segunda llamada borra el evento de nueva pulsación.
Ejemplo de uso
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;
}Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Este programa distingue entre mantener pulsado un botón, pulsarlo por primera vez, soltarlo y generar repeticiones automáticas. Mantén A durante 40 actualizaciones y suéltalo. FIRST DOWN, FIRST PRESS y FIRST REPEAT valen 1; FIRST CURRENT vale 16. HELD TICKS vale 40, PRESS COUNT vale 1 y REPEAT COUNT vale 5. Al soltar A, RELEASE vale 1, LAST CURRENT vale 0 y LAST PREVIOUS vale 16. FAILED CHECKS debe ser 0. Si cambias la duración, cambian los recuentos; el programa comprueba los intervalos de repetición según la duración observada.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\input.c .\kitaq-docs\samples\api-examples\gb\input_edges.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\input_edges.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm --no-cacheImplementación y código fuente
kitaqgb/lib/input.h:40
Return whether any masked button became released in the latest sample.
kitaqgb/lib/input.c:80
u8 input_released(u8 mask)
{
return (u8)((kq_input_release_keys & mask) != 0);
}input_repeat
Detecta una pulsación inicial o un pulso de repetición de un botón de la máscara.
Sintaxis
u8 input_repeat(u8 mask);Parámetros
maskUna máscara
BTN_*o varias combinadas con|. Basta con que coincida cualquiera de los botones seleccionados;BTN_A | BTN_Bno exige ambos. La máscara 0 siempre devuelve 0. Para exigir todos los botones mantenidos, compara(input_current() & mask) == mask.
Valor devuelto
Devuelve exactamente 1 si algún botón seleccionado cumple la condición; en caso contrario, 0. No devuelve una máscara de botones.
Condiciones y límites
Máscaras comunes: BTN_RIGHT=0x01, BTN_LEFT=0x02, BTN_UP=0x04, BTN_DOWN=0x08, BTN_A=0x10, BTN_B=0x20, BTN_SELECT=0x40, BTN_START=0x80. Un bit a 1 indica que el botón está mantenido. input_* usa este formato en GB y FC; las funciones FC de lectura directa emplean otro orden.
Las consultas leen el último input_update() sin volver a leer el mando, consumir eventos ni avanzar temporizadores. Consultar varias veces en el mismo ciclo da el mismo resultado. Si llamas dos veces a input_update() manteniendo el botón, la segunda llamada borra el evento de nueva pulsación.
Los intervalos cuentan actualizaciones, no milisegundos. Una pulsación nueva genera un pulso inmediato. Con INPUT_REPEAT_DELAY=18 e INPUT_REPEAT_RATE=5, el siguiente llega 19 actualizaciones después y los demás cada 6. Cada botón tiene su contador. Aplica los mismos valores de las macros al compilar input.c; cambiar solo el encabezado del código llamante no reconfigura la biblioteca.
Ejemplo de uso
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.
}Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Este programa distingue entre mantener pulsado un botón, pulsarlo por primera vez, soltarlo y generar repeticiones automáticas. Mantén A durante 40 actualizaciones y suéltalo. FIRST DOWN, FIRST PRESS y FIRST REPEAT valen 1; FIRST CURRENT vale 16. HELD TICKS vale 40, PRESS COUNT vale 1 y REPEAT COUNT vale 5. Al soltar A, RELEASE vale 1, LAST CURRENT vale 0 y LAST PREVIOUS vale 16. FAILED CHECKS debe ser 0. Si cambias la duración, cambian los recuentos; el programa comprueba los intervalos de repetición según la duración observada.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\input.c .\kitaq-docs\samples\api-examples\gb\input_edges.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\input_edges.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm --no-cacheImplementación y código fuente
kitaqgb/lib/input.h:42
Return whether any masked button produced a fresh press or scheduled repeat pulse.
kitaqgb/lib/input.c:86
u8 input_repeat(u8 mask)
{
return (u8)((kq_input_repeat_keys & mask) != 0);
}input_update
Guarda la máscara actual como estado anterior, lee los botones de Game Boy mediante __readpadex, calcula las liberaciones y avanza un temporizador independiente por botón. Llámala una vez por ciclo de entrada antes de consultar el estado guardado.
Sintaxis
void input_update();Valor devuelto
Ninguno (void).
Condiciones y límites
Máscaras comunes: BTN_RIGHT=0x01, BTN_LEFT=0x02, BTN_UP=0x04, BTN_DOWN=0x08, BTN_A=0x10, BTN_B=0x20, BTN_SELECT=0x40, BTN_START=0x80. Un bit a 1 indica que el botón está mantenido. input_* usa este formato en GB y FC; las funciones FC de lectura directa emplean otro orden.
Los intervalos cuentan actualizaciones, no milisegundos. Una pulsación nueva genera un pulso inmediato. Con INPUT_REPEAT_DELAY=18 e INPUT_REPEAT_RATE=5, el siguiente llega 19 actualizaciones después y los demás cada 6. Cada botón tiene su contador. Aplica los mismos valores de las macros al compilar input.c; cambiar solo el encabezado del código llamante no reconfigura la biblioteca.
Ejemplo de uso
input_update(); // One update per input tick, followed by any number of queries.Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Este programa distingue entre mantener pulsado un botón, pulsarlo por primera vez, soltarlo y generar repeticiones automáticas. Mantén A durante 40 actualizaciones y suéltalo. FIRST DOWN, FIRST PRESS y FIRST REPEAT valen 1; FIRST CURRENT vale 16. HELD TICKS vale 40, PRESS COUNT vale 1 y REPEAT COUNT vale 5. Al soltar A, RELEASE vale 1, LAST CURRENT vale 0 y LAST PREVIOUS vale 16. FAILED CHECKS debe ser 0. Si cambias la duración, cambian los recuentos; el programa comprueba los intervalos de repetición según la duración observada.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\input.c .\kitaq-docs\samples\api-examples\gb\input_edges.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\input_edges.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm --no-cacheImplementación y código fuente
kitaqgb/lib/input.h:34
Sample input once per game tick and derive press, release and repeat masks. Repeat delays are measured in calls to this function, not elapsed wall-clock time.
kitaqgb/lib/input.c:35
void input_update()
{
u8 i;
u16 kt;
kq_input_prev_keys = kq_input_keys;
// The intrinsic packs held buttons in the low byte and new presses in the high byte.
kt = __readpadex(kq_input_prev_keys);
kq_input_keys = (u8)kt;
kq_input_press_keys = (u8)(kt >> 8);
kq_input_release_keys = (u8)(kq_input_prev_keys & (u8)(kq_input_keys ^ 0xFF));
kq_input_repeat_keys = kq_input_press_keys;
i = 0;
while (i < 8) {
u8 mask = input_mask_for_index(i);
if ((kq_input_keys & mask) != 0) {
if ((kq_input_press_keys & mask) != 0) {
input_repeat_timer[i] = INPUT_REPEAT_DELAY;
} else if (input_repeat_timer[i] != 0) {
input_repeat_timer[i]--;
} else {
kq_input_repeat_keys = (u8)(kq_input_repeat_keys | mask);
input_repeat_timer[i] = INPUT_REPEAT_RATE;
}
} else {
input_repeat_timer[i] = INPUT_REPEAT_DELAY;
}
i++;
}
}link.h — Comunicación serie y paquetes lógicos
La biblioteca ofrece tres niveles: intercambio de bytes, paquetes de hasta 24 bytes y colas por interlocutor. Empieza con BYTE MASTER/SLAVE, sigue con PACKET y luego LINK4 para aprender quién aporta el reloj y cuándo hay datos recibidos disponibles. Incluye exactamente una vez la unidad de registros de hardware, link.c y link_packet.c en el programa; gb_link_example.h proporciona ese orden.
Link4 gestiona la posición lógica de anfitrión 0 y las de interlocutor 1–3. SelectPeer no envía una orden que cambie el cableado físico. La topología link4 de KOKURA sigue al interlocutor seleccionado mediante los metadatos del compilador. Usa LinkDmg07 para el protocolo del adaptador físico DMG-07.
Mantén el sondeo en ambos extremos. El tiempo de espera cuenta 90 llamadas sin progreso, no fotogramas de hardware. Enviar 0xFF solo para dar reloj a un ACK no amplía ese plazo; se permiten como máximo tres intentos. Los reintentos pueden entregar duplicados, así que añade identificadores de aplicación si una orden debe ejecutarse exactamente una vez.
Link4_BeginTransferTo
Selecciona un destino e inicia un intercambio de un byte.
Sintaxis
u8 __stackcall Link4_BeginTransferTo(u8 peer_slot, u8 out);Parámetros
peer_slotPosición remota configurada: 1..slot_count−1 desde el anfitrión o 0 desde un interlocutor.
outValor saliente de ocho bits.
Valor devuelto
Devuelve el primer error de selección o inicio, o 0 si tiene éxito.
Condiciones y límites
Link4 gestiona la posición lógica de anfitrión 0 y las de interlocutor 1–3. SelectPeer no envía una orden que cambie el cableado físico. La topología link4 de KOKURA sigue al interlocutor seleccionado mediante los metadatos del compilador. Usa LinkDmg07 para el protocolo del adaptador físico DMG-07.
Códigos de error: 0=ninguno, 1=ocupado, 2=tiempo agotado, 3=desbordamiento de recepción, 4=configuración/protocolo no válido y 5=tiempo de ACK agotado con respuesta similar a una desconexión. Las llamadas de inicio/configuración tienen éxito con 0; las de recepción/extracción, con 1. Una llamada correcta no borra un error retenido.
Link4 copia cada byte recibido tanto al búfer general como a uno por interlocutor. Leer uno no vacía el otro. El sondeo de paquetes consume el búfer general; descarta también periódicamente los bytes sin procesar que no uses de cada interlocutor para evitar desbordamientos.
Las pantallas proceden de KOKURA. Los ejemplos con varios extremos comprueban valores en instancias de emulador enlazadas y capturan sus estados finales guardados. Estas comprobaciones no demuestran el comportamiento de un cable físico ni de un adaptador para cuatro jugadores.
Ejecuta estos comandos PowerShell desde la carpeta que contiene kitaqgb, kokura y kitaq-docs. Compila todas las ROM participantes antes de iniciar la sesión enlazada. Para Link4, conserva los metadatos de símbolos generados junto a las ROM. Para ejecutar en DMG, cambia en todos los comandos --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
result[6+slot]=Link4_BeginTransferTo(slot,16+slot);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Conecta las cuatro ROM con la topología link4 de KOKURA. El anfitrión recibe 161/162/163 de los interlocutores 1/2/3 y muestra LAST PEER=3. Después envía las órdenes 65/66/67 con carga útil 7/42/255; verifica también esos valores en la pantalla de cada interlocutor.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.pngImplementación y código fuente
kitaqgb/lib/link.h:129
Select the logical peer and start a byte exchange, returning the first error.
kitaqgb/lib/link.c:584
u8 __stackcall Link4_BeginTransferTo(u8 peer_slot, u8 out) {
u8 err = Link4_SelectPeer(peer_slot);
if (err != LINK_ERR_NONE) return err;
return Link_BeginTransfer(out);
}Link4_GetLastRxPeer
Lee el interlocutor atribuido al último byte completado.
Sintaxis
u8 Link4_GetLastRxPeer();Valor devuelto
El anfitrión devuelve el interlocutor seleccionado y un interlocutor, 0; antes de recibir devuelve 255.
Condiciones y límites
Link4 gestiona la posición lógica de anfitrión 0 y las de interlocutor 1–3. SelectPeer no envía una orden que cambie el cableado físico. La topología link4 de KOKURA sigue al interlocutor seleccionado mediante los metadatos del compilador. Usa LinkDmg07 para el protocolo del adaptador físico DMG-07.
Estas funciones leen configuración e historial. No detectan conexiones físicas, consultan a todos los interlocutores ni esperan a que terminen las transferencias.
Las pantallas proceden de KOKURA. Los ejemplos con varios extremos comprueban valores en instancias de emulador enlazadas y capturan sus estados finales guardados. Estas comprobaciones no demuestran el comportamiento de un cable físico ni de un adaptador para cuatro jugadores.
Ejecuta estos comandos PowerShell desde la carpeta que contiene kitaqgb, kokura y kitaq-docs. Compila todas las ROM participantes antes de iniciar la sesión enlazada. Para Link4, conserva los metadatos de símbolos generados junto a las ROM. Para ejecutar en DMG, cambia en todos los comandos --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
result[19]=Link4_GetLastRxPeer();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Conecta las cuatro ROM con la topología link4 de KOKURA. El anfitrión recibe 161/162/163 de los interlocutores 1/2/3 y muestra LAST PEER=3. Después envía las órdenes 65/66/67 con carga útil 7/42/255; verifica también esos valores en la pantalla de cada interlocutor.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.pngImplementación y código fuente
kitaqgb/lib/link.h:121
Return the peer attributed to the last completed byte transfer.
kitaqgb/lib/link.c:540
u8 Link4_GetLastRxPeer() {
return Link4_LastRxPeer;
}Link4_GetLastTxPeer
Lee el destino registrado al iniciar la última transferencia de byte.
Sintaxis
u8 Link4_GetLastTxPeer();Valor devuelto
Devuelve el destino registrado, o 255 si aún no se ha iniciado ninguno.
Condiciones y límites
Link4 gestiona la posición lógica de anfitrión 0 y las de interlocutor 1–3. SelectPeer no envía una orden que cambie el cableado físico. La topología link4 de KOKURA sigue al interlocutor seleccionado mediante los metadatos del compilador. Usa LinkDmg07 para el protocolo del adaptador físico DMG-07.
Estas funciones leen configuración e historial. No detectan conexiones físicas, consultan a todos los interlocutores ni esperan a que terminen las transferencias.
Las pantallas proceden de KOKURA. Los ejemplos con varios extremos comprueban valores en instancias de emulador enlazadas y capturan sus estados finales guardados. Estas comprobaciones no demuestran el comportamiento de un cable físico ni de un adaptador para cuatro jugadores.
Ejecuta estos comandos PowerShell desde la carpeta que contiene kitaqgb, kokura y kitaq-docs. Compila todas las ROM participantes antes de iniciar la sesión enlazada. Para Link4, conserva los metadatos de símbolos generados junto a las ROM. Para ejecutar en DMG, cambia en todos los comandos --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
result[20]=Link4_GetLastTxPeer();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Conecta las cuatro ROM con la topología link4 de KOKURA. El anfitrión recibe 161/162/163 de los interlocutores 1/2/3 y muestra LAST PEER=3. Después envía las órdenes 65/66/67 con carga útil 7/42/255; verifica también esos valores en la pantalla de cada interlocutor.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.pngImplementación y código fuente
kitaqgb/lib/link.h:123
Return the peer attributed when the last byte transfer was started.
kitaqgb/lib/link.c:545
u8 Link4_GetLastTxPeer() {
return Link4_LastTxPeer;
}Link4_GetLocalSlot
Lee la posición configurada de esta máquina.
Sintaxis
u8 Link4_GetLocalSlot();Valor devuelto
El anfitrión es 0 y los interlocutores, 1..3. Sin configurar también devuelve 0.
Condiciones y límites
Link4 gestiona la posición lógica de anfitrión 0 y las de interlocutor 1–3. SelectPeer no envía una orden que cambie el cableado físico. La topología link4 de KOKURA sigue al interlocutor seleccionado mediante los metadatos del compilador. Usa LinkDmg07 para el protocolo del adaptador físico DMG-07.
Estas funciones leen configuración e historial. No detectan conexiones físicas, consultan a todos los interlocutores ni esperan a que terminen las transferencias.
Las pantallas proceden de KOKURA. Los ejemplos con varios extremos comprueban valores en instancias de emulador enlazadas y capturan sus estados finales guardados. Estas comprobaciones no demuestran el comportamiento de un cable físico ni de un adaptador para cuatro jugadores.
Ejecuta estos comandos PowerShell desde la carpeta que contiene kitaqgb, kokura y kitaq-docs. Compila todas las ROM participantes antes de iniciar la sesión enlazada. Para Link4, conserva los metadatos de símbolos generados junto a las ROM. Para ejecutar en DMG, cambia en todos los comandos --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
result[2]=Link4_GetLocalSlot();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Conecta las cuatro ROM con la topología link4 de KOKURA. El anfitrión recibe 161/162/163 de los interlocutores 1/2/3 y muestra LAST PEER=3. Después envía las órdenes 65/66/67 con carga útil 7/42/255; verifica también esos valores en la pantalla de cada interlocutor.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.pngImplementación y código fuente
kitaqgb/lib/link.h:115
Return the configured zero-based local slot.
kitaqgb/lib/link.c:525
u8 Link4_GetLocalSlot() {
return Link4_LocalSlot;
}Link4_GetMode
Lee el rol lógico configurado.
Sintaxis
u8 Link4_GetMode();Valor devuelto
0=sin configurar, 1=anfitrión, 2=interlocutor.
Condiciones y límites
Link4 gestiona la posición lógica de anfitrión 0 y las de interlocutor 1–3. SelectPeer no envía una orden que cambie el cableado físico. La topología link4 de KOKURA sigue al interlocutor seleccionado mediante los metadatos del compilador. Usa LinkDmg07 para el protocolo del adaptador físico DMG-07.
Estas funciones leen configuración e historial. No detectan conexiones físicas, consultan a todos los interlocutores ni esperan a que terminen las transferencias.
Las pantallas proceden de KOKURA. Los ejemplos con varios extremos comprueban valores en instancias de emulador enlazadas y capturan sus estados finales guardados. Estas comprobaciones no demuestran el comportamiento de un cable físico ni de un adaptador para cuatro jugadores.
Ejecuta estos comandos PowerShell desde la carpeta que contiene kitaqgb, kokura y kitaq-docs. Compila todas las ROM participantes antes de iniciar la sesión enlazada. Para Link4, conserva los metadatos de símbolos generados junto a las ROM. Para ejecutar en DMG, cambia en todos los comandos --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
result[1]=Link4_GetMode();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Conecta las cuatro ROM con la topología link4 de KOKURA. El anfitrión recibe 161/162/163 de los interlocutores 1/2/3 y muestra LAST PEER=3. Después envía las órdenes 65/66/67 con carga útil 7/42/255; verifica también esos valores en la pantalla de cada interlocutor.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.pngImplementación y código fuente
kitaqgb/lib/link.h:113
Return the configured cooperative role; this is not a hardware connection probe.
kitaqgb/lib/link.c:520
u8 Link4_GetMode() {
return Link4_ModeState;
}Link4_GetSelectedPeer
Lee el destino lógico seleccionado actualmente.
Sintaxis
u8 Link4_GetSelectedPeer();Valor devuelto
El anfitrión devuelve el interlocutor seleccionado; un interlocutor devuelve 0; sin configurar devuelve 255.
Condiciones y límites
Link4 gestiona la posición lógica de anfitrión 0 y las de interlocutor 1–3. SelectPeer no envía una orden que cambie el cableado físico. La topología link4 de KOKURA sigue al interlocutor seleccionado mediante los metadatos del compilador. Usa LinkDmg07 para el protocolo del adaptador físico DMG-07.
Estas funciones leen configuración e historial. No detectan conexiones físicas, consultan a todos los interlocutores ni esperan a que terminen las transferencias.
Las pantallas proceden de KOKURA. Los ejemplos con varios extremos comprueban valores en instancias de emulador enlazadas y capturan sus estados finales guardados. Estas comprobaciones no demuestran el comportamiento de un cable físico ni de un adaptador para cuatro jugadores.
Ejecuta estos comandos PowerShell desde la carpeta que contiene kitaqgb, kokura y kitaq-docs. Compila todas las ROM participantes antes de iniciar la sesión enlazada. Para Link4, conserva los metadatos de símbolos generados junto a las ROM. Para ejecutar en DMG, cambia en todos los comandos --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
result[4]=Link4_GetSelectedPeer();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Conecta las cuatro ROM con la topología link4 de KOKURA. El anfitrión recibe 161/162/163 de los interlocutores 1/2/3 y muestra LAST PEER=3. Después envía las órdenes 65/66/67 con carga útil 7/42/255; verifica también esos valores en la pantalla de cada interlocutor.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.pngImplementación y código fuente
kitaqgb/lib/link.h:119
Return the current logical destination, or the invalid-slot sentinel when unset.
kitaqgb/lib/link.c:535
u8 Link4_GetSelectedPeer() {
return Link4_SelectedPeer;
}Link4_GetSlotCount
Lee el total de posiciones configurado.
Sintaxis
u8 Link4_GetSlotCount();Valor devuelto
Una configuración válida devuelve 2..4; sin configurar devuelve 0.
Condiciones y límites
Link4 gestiona la posición lógica de anfitrión 0 y las de interlocutor 1–3. SelectPeer no envía una orden que cambie el cableado físico. La topología link4 de KOKURA sigue al interlocutor seleccionado mediante los metadatos del compilador. Usa LinkDmg07 para el protocolo del adaptador físico DMG-07.
Estas funciones leen configuración e historial. No detectan conexiones físicas, consultan a todos los interlocutores ni esperan a que terminen las transferencias.
Las pantallas proceden de KOKURA. Los ejemplos con varios extremos comprueban valores en instancias de emulador enlazadas y capturan sus estados finales guardados. Estas comprobaciones no demuestran el comportamiento de un cable físico ni de un adaptador para cuatro jugadores.
Ejecuta estos comandos PowerShell desde la carpeta que contiene kitaqgb, kokura y kitaq-docs. Compila todas las ROM participantes antes de iniciar la sesión enlazada. Para Link4, conserva los metadatos de símbolos generados junto a las ROM. Para ejecutar en DMG, cambia en todos los comandos --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
result[3]=Link4_GetSlotCount();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Conecta las cuatro ROM con la topología link4 de KOKURA. El anfitrión recibe 161/162/163 de los interlocutores 1/2/3 y muestra LAST PEER=3. Después envía las órdenes 65/66/67 con carga útil 7/42/255; verifica también esos valores en la pantalla de cada interlocutor.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.pngImplementación y código fuente
kitaqgb/lib/link.h:117
Return the configured number of logical slots, not a live connection count.
kitaqgb/lib/link.c:530
u8 Link4_GetSlotCount() {
return Link4_SlotCount;
}Link4_HasByteFrom
Consulta los datos sin leer del búfer de recepción de un interlocutor.
Sintaxis
u8 __stackcall Link4_HasByteFrom(u8 peer_slot);Parámetros
peer_slotPosición remota configurada: 1..slot_count−1 desde el anfitrión o 0 desde un interlocutor.
Valor devuelto
Devuelve 1 si hay datos en cola y 0 si está vacío o el interlocutor no es válido.
Condiciones y límites
El búfer circular de recepción de ocho entradas admite siete bytes. Si está lleno, descarta el nuevo byte y retiene el error 3. Un byte recibido con valor cero es un dato válido.
Link4 copia cada byte recibido tanto al búfer general como a uno por interlocutor. Leer uno no vacía el otro. El sondeo de paquetes consume el búfer general; descarta también periódicamente los bytes sin procesar que no uses de cada interlocutor para evitar desbordamientos.
Esta consulta no sondea el hardware; un interlocutor no válido no cambia el error retenido.
Las pantallas proceden de KOKURA. Los ejemplos con varios extremos comprueban valores en instancias de emulador enlazadas y capturan sus estados finales guardados. Estas comprobaciones no demuestran el comportamiento de un cable físico ni de un adaptador para cuatro jugadores.
Ejecuta estos comandos PowerShell desde la carpeta que contiene kitaqgb, kokura y kitaq-docs. Compila todas las ROM participantes antes de iniciar la sesión enlazada. Para Link4, conserva los metadatos de símbolos generados junto a las ROM. Para ejecutar en DMG, cambia en todos los comandos --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
result[9+slot]=Link4_HasByteFrom(slot);value=0;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Conecta las cuatro ROM con la topología link4 de KOKURA. El anfitrión recibe 161/162/163 de los interlocutores 1/2/3 y muestra LAST PEER=3. Después envía las órdenes 65/66/67 con carga útil 7/42/255; verifica también esos valores en la pantalla de cada interlocutor.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.pngImplementación y código fuente
kitaqgb/lib/link.h:131
Inspect a valid peer ring without polling the hardware.
kitaqgb/lib/link.c:591
u8 __stackcall Link4_HasByteFrom(u8 peer_slot) {
if (Link4_IsValidRemoteSlotInternal(peer_slot) == 0) return 0;
if (Link4_RxHead[(__safe_index u8)peer_slot] == Link4_RxTail[(__safe_index u8)peer_slot]) return 0;
return 1;
}Link4_HasPacketFrom
Consulta el buzón de paquetes completados de una posición remota.
Sintaxis
u8 __stackcall Link4_HasPacketFrom(u8 peer_slot);Parámetros
peer_slotPosición remota configurada: 1..slot_count−1 desde el anfitrión o 0 desde un interlocutor.
Valor devuelto
Devuelve 1 si hay un paquete sin leer y 0 si está vacío o el interlocutor no es válido.
Condiciones y límites
Link4 gestiona la posición lógica de anfitrión 0 y las de interlocutor 1–3. SelectPeer no envía una orden que cambie el cableado físico. La topología link4 de KOKURA sigue al interlocutor seleccionado mediante los metadatos del compilador. Usa LinkDmg07 para el protocolo del adaptador físico DMG-07.
Un paquete contiene 0xA5, orden, longitud, de 0 a 24 bytes de carga útil y una suma de comprobación XOR. La respuesta es 0x79 (ACK, aceptado) o 0x1F (NAK, rechazado). La suma aplica XOR a la orden, la longitud y la carga útil. Cada máquina tiene un buzón de paquetes compartido; Link4 añade uno por interlocutor.
Esta consulta no sondea el hardware; un interlocutor no válido no cambia el error retenido.
Las pantallas proceden de KOKURA. Los ejemplos con varios extremos comprueban valores en instancias de emulador enlazadas y capturan sus estados finales guardados. Estas comprobaciones no demuestran el comportamiento de un cable físico ni de un adaptador para cuatro jugadores.
Ejecuta estos comandos PowerShell desde la carpeta que contiene kitaqgb, kokura y kitaq-docs. Compila todas las ROM participantes antes de iniciar la sesión enlazada. Para Link4, conserva los metadatos de símbolos generados junto a las ROM. Para ejecutar en DMG, cambia en todos los comandos --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
result[9]=Link4_HasPacketFrom(0);result[10]=Link4_ReadPacketFrom(0,&cmd,&len,data);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Como interlocutor 1 de cuatro posiciones, se esperan HOST BYTE=17, COMMAND=65, LENGTH=3 y PAYLOAD 2=42. CONSUMED=0 es la bandera del buzón del anfitrión tras consumirlo.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.pngImplementación y código fuente
kitaqgb/lib/link.h:142
Inspect the one-packet mailbox for a valid remote slot without consuming it.
kitaqgb/lib/link_packet.c:484
u8 __stackcall Link4_HasPacketFrom(u8 peer_slot) {
return Link4_PacketPeerReady(peer_slot);
}Link4_InitHost
Inicializa un anfitrión lógico con dos a cuatro posiciones y selecciona el interlocutor 1.
Sintaxis
u8 __stackcall Link4_InitHost(u8 slot_count);Parámetros
slot_countNúmero de posiciones incluido el anfitrión, de 2 a 4.
Valor devuelto
Devuelve 0 si la configuración es válida y 4 si la cantidad de posiciones no lo es.
Condiciones y límites
La inicialización descarta colas de bytes, paquetes, selección del interlocutor y errores, y deshabilita la transferencia y la fuente IRQ serie. No conserva un intercambio en curso.
Link4 gestiona la posición lógica de anfitrión 0 y las de interlocutor 1–3. SelectPeer no envía una orden que cambie el cableado físico. La topología link4 de KOKURA sigue al interlocutor seleccionado mediante los metadatos del compilador. Usa LinkDmg07 para el protocolo del adaptador físico DMG-07.
Las secciones críticas internas controlan la profundidad de anidamiento por software. Salir de la más externa habilita las interrupciones de CPU; no supongas que se conserva un estado IME previamente deshabilitado.
La inicialización se realiza antes de validar. Incluso una llamada fallida descarta la topología anterior y los datos sin leer.
Las pantallas proceden de KOKURA. Los ejemplos con varios extremos comprueban valores en instancias de emulador enlazadas y capturan sus estados finales guardados. Estas comprobaciones no demuestran el comportamiento de un cable físico ni de un adaptador para cuatro jugadores.
Ejecuta estos comandos PowerShell desde la carpeta que contiene kitaqgb, kokura y kitaq-docs. Compila todas las ROM participantes antes de iniciar la sesión enlazada. Para Link4, conserva los metadatos de símbolos generados junto a las ROM. Para ejecutar en DMG, cambia en todos los comandos --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
result[0]=Link4_InitHost(4);result[1]=Link4_GetMode();result[2]=Link4_GetLocalSlot();result[3]=Link4_GetSlotCount();result[4]=Link4_GetSelectedPeer();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Conecta las cuatro ROM con la topología link4 de KOKURA. El anfitrión recibe 161/162/163 de los interlocutores 1/2/3 y muestra LAST PEER=3. Después envía las órdenes 65/66/67 con carga útil 7/42/255; verifica también esos valores en la pantalla de cada interlocutor.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.pngImplementación y código fuente
kitaqgb/lib/link.h:108
Cooperative 4-player adapter helpers. This layer models the common host-selected adapter pattern: - Slot 0 is always the host. - The host selects one active peer slot at a time. - Packet mailboxes stay one-deep per peer. - The original Link_* API remains available for normal 2-player projects. Reset as master, validate slot count and select logical peer one. Invalid configuration still discards old link state.
kitaqgb/lib/link.c:489
u8 __stackcall Link4_InitHost(u8 slot_count) {
u8 err;
Link_InitMaster();
err = Link4_ValidateConfig(LINK4_MODE_HOST, LINK4_HOST_SLOT, slot_count);
if (err != LINK_ERR_NONE) {
Link_SetErrorInternal(err);
return err;
}
Link4_ApplyConfig(LINK4_MODE_HOST, LINK4_HOST_SLOT, slot_count);
return LINK_ERR_NONE;
}Link4_InitPeer
Inicializa un interlocutor con reloj externo y selecciona la posición de anfitrión 0.
Sintaxis
u8 __stackcall Link4_InitPeer(u8 local_slot, u8 slot_count);Parámetros
local_slotPosición local, de 1 a slot_count−1.
slot_countTotal de posiciones incluido el anfitrión, de 2 a 4.
Valor devuelto
Devuelve 0 si la configuración es válida y 4 si la cantidad de posiciones o la posición local no son válidas.
Condiciones y límites
La inicialización descarta colas de bytes, paquetes, selección del interlocutor y errores, y deshabilita la transferencia y la fuente IRQ serie. No conserva un intercambio en curso.
Link4 gestiona la posición lógica de anfitrión 0 y las de interlocutor 1–3. SelectPeer no envía una orden que cambie el cableado físico. La topología link4 de KOKURA sigue al interlocutor seleccionado mediante los metadatos del compilador. Usa LinkDmg07 para el protocolo del adaptador físico DMG-07.
Las secciones críticas internas controlan la profundidad de anidamiento por software. Salir de la más externa habilita las interrupciones de CPU; no supongas que se conserva un estado IME previamente deshabilitado.
La inicialización se realiza antes de validar. Incluso una llamada fallida descarta la topología anterior y los datos sin leer.
Las pantallas proceden de KOKURA. Los ejemplos con varios extremos comprueban valores en instancias de emulador enlazadas y capturan sus estados finales guardados. Estas comprobaciones no demuestran el comportamiento de un cable físico ni de un adaptador para cuatro jugadores.
Ejecuta estos comandos PowerShell desde la carpeta que contiene kitaqgb, kokura y kitaq-docs. Compila todas las ROM participantes antes de iniciar la sesión enlazada. Para Link4, conserva los metadatos de símbolos generados junto a las ROM. Para ejecutar en DMG, cambia en todos los comandos --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
result[0]=Link4_InitPeer(1,4);result[1]=Link4_GetMode();result[2]=Link4_GetLocalSlot();result[3]=Link4_GetSlotCount();result[4]=Link4_GetSelectedPeer();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Como interlocutor 1 de cuatro posiciones, se esperan HOST BYTE=17, COMMAND=65, LENGTH=3 y PAYLOAD 2=42. CONSUMED=0 es la bandera del buzón del anfitrión tras consumirlo.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.pngImplementación y código fuente
kitaqgb/lib/link.h:111
Reset as slave and validate the local nonzero slot and total slot count. An invalid configuration still discards the previous link state.
kitaqgb/lib/link.c:505
u8 __stackcall Link4_InitPeer(u8 local_slot, u8 slot_count) {
u8 err;
Link_InitSlave();
err = Link4_ValidateConfig(LINK4_MODE_PEER, local_slot, slot_count);
if (err != LINK_ERR_NONE) {
Link_SetErrorInternal(err);
return err;
}
Link4_ApplyConfig(LINK4_MODE_PEER, local_slot, slot_count);
return LINK_ERR_NONE;
}Link4_PollPacket
Avanza una vez el motor de paquetes compartido para el interlocutor seleccionado.
Sintaxis
void Link4_PollPacket();Valor devuelto
No devuelve ningún valor.
Condiciones y límites
Link4 gestiona la posición lógica de anfitrión 0 y las de interlocutor 1–3. SelectPeer no envía una orden que cambie el cableado físico. La topología link4 de KOKURA sigue al interlocutor seleccionado mediante los metadatos del compilador. Usa LinkDmg07 para el protocolo del adaptador físico DMG-07.
Un paquete contiene 0xA5, orden, longitud, de 0 a 24 bytes de carga útil y una suma de comprobación XOR. La respuesta es 0x79 (ACK, aceptado) o 0x1F (NAK, rechazado). La suma aplica XOR a la orden, la longitud y la carga útil. Cada máquina tiene un buzón de paquetes compartido; Link4 añade uno por interlocutor.
Mantén el sondeo en ambos extremos. El tiempo de espera cuenta 90 llamadas sin progreso, no fotogramas de hardware. Enviar 0xFF solo para dar reloj a un ACK no amplía ese plazo; se permiten como máximo tres intentos. Los reintentos pueden entregar duplicados, así que añade identificadores de aplicación si una orden debe ejecutarse exactamente una vez.
Link4 copia cada byte recibido tanto al búfer general como a uno por interlocutor. Leer uno no vacía el otro. El sondeo de paquetes consume el búfer general; descarta también periódicamente los bytes sin procesar que no uses de cada interlocutor para evitar desbordamientos.
No rota por todas las posiciones. Cambia de interlocutor solo cuando el intercambio haya terminado y se permita seleccionar.
Las pantallas proceden de KOKURA. Los ejemplos con varios extremos comprueban valores en instancias de emulador enlazadas y capturan sus estados finales guardados. Estas comprobaciones no demuestran el comportamiento de un cable físico ni de un adaptador para cuatro jugadores.
Ejecuta estos comandos PowerShell desde la carpeta que contiene kitaqgb, kokura y kitaq-docs. Compila todas las ROM participantes antes de iniciar la sesión enlazada. Para Link4, conserva los metadatos de símbolos generados junto a las ROM. Para ejecutar en DMG, cambia en todos los comandos --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
for(i=0;i<50;i++){Link4_PollPacket();while(Link4_TryReadByteFrom(slot,0)){}m_wait();}Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Conecta las cuatro ROM con la topología link4 de KOKURA. El anfitrión recibe 161/162/163 de los interlocutores 1/2/3 y muestra LAST PEER=3. Después envía las órdenes 65/66/67 con carga útil 7/42/255; verifica también esos valores en la pantalla de cada interlocutor.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.pngImplementación y código fuente
kitaqgb/lib/link.h:140
Advance the shared packet engine; this does not poll every logical peer in turn.
kitaqgb/lib/link_packet.c:479
void Link4_PollPacket() {
Link_PollPacket();
}Link4_ReadPacketFrom
Copia un paquete de un interlocutor concreto y lo consume de su buzón.
Sintaxis
u8 __stackcall Link4_ReadPacketFrom(u8 peer_slot, u8 *cmd, u8 *len, u8 *dst);Parámetros
peer_slotPosición remota configurada: 1..slot_count−1 desde el anfitrión o 0 desde un interlocutor.
cmdByte de orden escribible; null omite esta salida.
lenByte de longitud escribible, de 0 a 24; null omite esta salida.
dstBúfer de carga útil escribible con espacio para 24 bytes; null descarta la carga útil.
Valor devuelto
Devuelve 1 si consume el paquete y 0 si está vacío o el interlocutor no es válido.
Condiciones y límites
No hay parámetro de capacidad del destino. Proporciona 24 bytes escribibles si usas dst. cmd, len y dst pueden ser null de forma independiente. Serializa la consulta y el consumo del buzón respecto al resto del código y las interrupciones.
Vacía el buzón compartido solo si se refiere al paquete de ese mismo interlocutor. Los paquetes sin leer de otros interlocutores siguen disponibles.
Las pantallas proceden de KOKURA. Los ejemplos con varios extremos comprueban valores en instancias de emulador enlazadas y capturan sus estados finales guardados. Estas comprobaciones no demuestran el comportamiento de un cable físico ni de un adaptador para cuatro jugadores.
Ejecuta estos comandos PowerShell desde la carpeta que contiene kitaqgb, kokura y kitaq-docs. Compila todas las ROM participantes antes de iniciar la sesión enlazada. Para Link4, conserva los metadatos de símbolos generados junto a las ROM. Para ejecutar en DMG, cambia en todos los comandos --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
result[9]=Link4_HasPacketFrom(0);result[10]=Link4_ReadPacketFrom(0,&cmd,&len,data);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Como interlocutor 1 de cuatro posiciones, se esperan HOST BYTE=17, COMMAND=65, LENGTH=3 y PAYLOAD 2=42. CONSUMED=0 es la bandera del buzón del anfitrión tras consumirlo.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.pngImplementación y código fuente
kitaqgb/lib/link.h:146
Consume a peer mailbox, copying to optional outputs. A nonnull destination needs room for the entire payload. Clear the shared mailbox only when it refers to this same peer.
kitaqgb/lib/link_packet.c:491
u8 __stackcall Link4_ReadPacketFrom(u8 peer_slot, u8 *cmd, u8 *len, u8 *dst) {
u8 i;
u8 offset;
if (Link4_PacketPeerReady(peer_slot) == 0) return 0;
if (cmd != 0) *cmd = Link4_ReceivedPacketCmd[(__safe_index u8)peer_slot];
if (len != 0) *len = Link4_ReceivedPacketLen[(__safe_index u8)peer_slot];
if (dst != 0) {
for (i = 0; i < Link4_ReceivedPacketLen[(__safe_index u8)peer_slot]; ++i) {
offset = Link4_PacketOffset(peer_slot, i);
dst[(__safe_index u8)i] = Link4_ReceivedPacketBuf[(__safe_index u8)offset];
}
}
Link4_ReceivedPacketReady[(__safe_index u8)peer_slot] = 0;
if (Link4_LastPacketPeer == peer_slot) {
Link_ReceivedPacketReady = 0;
Link4_LastPacketPeer = LINK4_INVALID_SLOT;
}
return 1;
}Link4_SelectPeer
Consulta la finalización y cambia el destino lógico solo cuando está inactivo.
Sintaxis
u8 __stackcall Link4_SelectPeer(u8 peer_slot);Parámetros
peer_slotPosición remota configurada: 1..slot_count−1 desde el anfitrión o 0 desde un interlocutor.
Valor devuelto
Devuelve 0 al seleccionar, 1 si el estado de byte/paquete/ACK está ocupado y 4 si no está configurado o el interlocutor no es válido.
Condiciones y límites
Link4 gestiona la posición lógica de anfitrión 0 y las de interlocutor 1–3. SelectPeer no envía una orden que cambie el cableado físico. La topología link4 de KOKURA sigue al interlocutor seleccionado mediante los metadatos del compilador. Usa LinkDmg07 para el protocolo del adaptador físico DMG-07.
Códigos de error: 0=ninguno, 1=ocupado, 2=tiempo agotado, 3=desbordamiento de recepción, 4=configuración/protocolo no válido y 5=tiempo de ACK agotado con respuesta similar a una desconexión. Las llamadas de inicio/configuración tienen éxito con 0; las de recepción/extracción, con 1. Una llamada correcta no borra un error retenido.
Las pantallas proceden de KOKURA. Los ejemplos con varios extremos comprueban valores en instancias de emulador enlazadas y capturan sus estados finales guardados. Estas comprobaciones no demuestran el comportamiento de un cable físico ni de un adaptador para cuatro jugadores.
Ejecuta estos comandos PowerShell desde la carpeta que contiene kitaqgb, kokura y kitaq-docs. Compila todas las ROM participantes antes de iniciar la sesión enlazada. Para Link4, conserva los metadatos de símbolos generados junto a las ROM. Para ejecutar en DMG, cambia en todos los comandos --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
result[25]=Link4_SelectPeer(1);result[26]=Link_LastError();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Conecta las cuatro ROM con la topología link4 de KOKURA. El anfitrión recibe 161/162/163 de los interlocutores 1/2/3 y muestra LAST PEER=3. Después envía las órdenes 65/66/67 con carga útil 7/42/255; verifica también esos valores en la pantalla de cada interlocutor.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.pngImplementación y código fuente
kitaqgb/lib/link.h:127
Poll completion, then change the logical destination only while byte and packet state are idle. A peer can select only the host. No adapter-routing command is sent here; the transport must provide the matching physical route.
kitaqgb/lib/link.c:552
u8 __stackcall Link4_SelectPeer(u8 peer_slot) {
Link_Poll();
if (Link4_IsEnabledInternal() == 0) {
Link_SetErrorInternal(LINK_ERR_PROTOCOL);
return LINK_ERR_PROTOCOL;
}
if (Link_Busy != 0 || Link_PacketState != LINK_PKT_STATE_IDLE || Link_PendingAck != 0) {
Link_SetErrorInternal(LINK_ERR_BUSY);
return LINK_ERR_BUSY;
}
if (Link4_ModeState == LINK4_MODE_HOST) {
if (Link4_IsValidRemoteSlotInternal(peer_slot) == 0) {
Link_SetErrorInternal(LINK_ERR_PROTOCOL);
return LINK_ERR_PROTOCOL;
}
Link4_SelectedPeer = peer_slot;
return LINK_ERR_NONE;
}
if (Link4_ModeState == LINK4_MODE_PEER && peer_slot == LINK4_HOST_SLOT) {
Link4_SelectedPeer = LINK4_HOST_SLOT;
return LINK_ERR_NONE;
}
Link_SetErrorInternal(LINK_ERR_PROTOCOL);
return LINK_ERR_PROTOCOL;
}Link4_SendPacketTo
Selecciona un interlocutor lógico, copia el paquete y programa su transmisión.
Sintaxis
u8 __stackcall Link4_SendPacketTo(u8 peer_slot, const u8 *data, u8 len, u8 cmd);Parámetros
peer_slotPosición remota configurada: 1..slot_count−1 desde el anfitrión o 0 desde un interlocutor.
dataOrigen legible de len bytes; solo puede ser null si len es cero.
lenLongitud de la carga útil en bytes, de 0 a 24.
cmdOrden de ocho bits definida por la aplicación.
Valor devuelto
Devuelve el primer error de selección o encolado; 0 significa aceptado.
Condiciones y límites
Link4 gestiona la posición lógica de anfitrión 0 y las de interlocutor 1–3. SelectPeer no envía una orden que cambie el cableado físico. La topología link4 de KOKURA sigue al interlocutor seleccionado mediante los metadatos del compilador. Usa LinkDmg07 para el protocolo del adaptador físico DMG-07.
Códigos de error: 0=ninguno, 1=ocupado, 2=tiempo agotado, 3=desbordamiento de recepción, 4=configuración/protocolo no válido y 5=tiempo de ACK agotado con respuesta similar a una desconexión. Las llamadas de inicio/configuración tienen éxito con 0; las de recepción/extracción, con 1. Una llamada correcta no borra un error retenido.
Un paquete contiene 0xA5, orden, longitud, de 0 a 24 bytes de carga útil y una suma de comprobación XOR. La respuesta es 0x79 (ACK, aceptado) o 0x1F (NAK, rechazado). La suma aplica XOR a la orden, la longitud y la carga útil. Cada máquina tiene un buzón de paquetes compartido; Link4 añade uno por interlocutor.
Mantén el sondeo en ambos extremos. El tiempo de espera cuenta 90 llamadas sin progreso, no fotogramas de hardware. Enviar 0xFF solo para dar reloj a un ACK no amplía ese plazo; se permiten como máximo tres intentos. Los reintentos pueden entregar duplicados, así que añade identificadores de aplicación si una orden debe ejecutarse exactamente una vez.
Link4 copia cada byte recibido tanto al búfer general como a uno por interlocutor. Leer uno no vacía el otro. El sondeo de paquetes consume el búfer general; descarta también periódicamente los bytes sin procesar que no uses de cada interlocutor para evitar desbordamientos.
La selección ocurre antes de validar la carga útil; aunque se rechace, el nuevo destino puede quedar seleccionado.
Las pantallas proceden de KOKURA. Los ejemplos con varios extremos comprueban valores en instancias de emulador enlazadas y capturan sus estados finales guardados. Estas comprobaciones no demuestran el comportamiento de un cable físico ni de un adaptador para cuatro jugadores.
Ejecuta estos comandos PowerShell desde la carpeta que contiene kitaqgb, kokura y kitaq-docs. Compila todas las ROM participantes antes de iniciar la sesión enlazada. Para Link4, conserva los metadatos de símbolos generados junto a las ROM. Para ejecutar en DMG, cambia en todos los comandos --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
result[21+slot]=Link4_SendPacketTo(slot,data,3,64+slot);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Conecta las cuatro ROM con la topología link4 de KOKURA. El anfitrión recibe 161/162/163 de los interlocutores 1/2/3 y muestra LAST PEER=3. Después envía las órdenes 65/66/67 con carga útil 7/42/255; verifica también esos valores en la pantalla de cada interlocutor.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.pngImplementación y código fuente
kitaqgb/lib/link.h:138
Select a logical peer, then copy and schedule a packet; return the first error.
kitaqgb/lib/link_packet.c:472
u8 __stackcall Link4_SendPacketTo(u8 peer_slot, const u8 *data, u8 len, u8 cmd) {
u8 err = Link4_SelectPeer(peer_slot);
if (err != LINK_ERR_NONE) return err;
return Link_SendPacket(data, len, cmd);
}Link4_TryReadByteAny
Recorre las posiciones remotas en orden ascendente y extrae el primer byte disponible.
Sintaxis
u8 __stackcall Link4_TryReadByteAny(u8 *peer_slot, u8 *out);Parámetros
peer_slotByte escribible para la posición de origen; null omite esa salida.
outDestino escribible de un byte; null descarta el byte.
Valor devuelto
Devuelve 1 al recibir y 0 en otro caso.
Condiciones y límites
El búfer circular de recepción de ocho entradas admite siete bytes. Si está lleno, descarta el nuevo byte y retiene el error 3. Un byte recibido con valor cero es un dato válido.
Link4 copia cada byte recibido tanto al búfer general como a uno por interlocutor. Leer uno no vacía el otro. El sondeo de paquetes consume el búfer general; descarta también periódicamente los bytes sin procesar que no uses de cada interlocutor para evitar desbordamientos.
Las secciones críticas internas controlan la profundidad de anidamiento por software. Salir de la más externa habilita las interrupciones de CPU; no supongas que se conserva un estado IME previamente deshabilitado.
Omite la posición local. Las posiciones inferiores con datos continuos tienen prioridad; usa lecturas por interlocutor si necesitas un reparto equitativo por turnos.
Las pantallas proceden de KOKURA. Los ejemplos con varios extremos comprueban valores en instancias de emulador enlazadas y capturan sus estados finales guardados. Estas comprobaciones no demuestran el comportamiento de un cable físico ni de un adaptador para cuatro jugadores.
Ejecuta estos comandos PowerShell desde la carpeta que contiene kitaqgb, kokura y kitaq-docs. Compila todas las ROM participantes antes de iniciar la sesión enlazada. Para Link4, conserva los metadatos de símbolos generados junto a las ROM. Para ejecutar en DMG, cambia en todos los comandos --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
else {other=255;Link4_TryReadByteAny(&other,&value);result[12+slot]=other;}Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Conecta las cuatro ROM con la topología link4 de KOKURA. El anfitrión recibe 161/162/163 de los interlocutores 1/2/3 y muestra LAST PEER=3. Después envía las órdenes 65/66/67 con carga útil 7/42/255; verifica también esos valores en la pantalla de cada interlocutor.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.pngImplementación y código fuente
kitaqgb/lib/link.h:136
Scan remote rings in increasing slot order and return the first available byte. Null output pointers are allowed; lower slots have polling priority.
kitaqgb/lib/link.c:604
u8 __stackcall Link4_TryReadByteAny(u8 *peer_slot, u8 *out) {
u8 slot;
if (Link4_IsEnabledInternal() == 0) return 0;
for (slot = 0; slot < Link4_SlotCount; ++slot) {
if (slot != Link4_LocalSlot) {
if (Link4_PopRxByte(slot, out) != 0) {
if (peer_slot != 0) *peer_slot = slot;
return 1;
}
}
}
return 0;
}Link4_TryReadByteFrom
Extrae un byte del búfer de recepción de un interlocutor concreto.
Sintaxis
u8 __stackcall Link4_TryReadByteFrom(u8 peer_slot, u8 *out);Parámetros
peer_slotPosición remota configurada: 1..slot_count−1 desde el anfitrión o 0 desde un interlocutor.
outDestino escribible de un byte; null descarta el byte.
Valor devuelto
Devuelve 1 al extraer; si está vacío o el interlocutor no es válido, devuelve 0 y conserva out.
Condiciones y límites
El búfer circular de recepción de ocho entradas admite siete bytes. Si está lleno, descarta el nuevo byte y retiene el error 3. Un byte recibido con valor cero es un dato válido.
Link4 copia cada byte recibido tanto al búfer general como a uno por interlocutor. Leer uno no vacía el otro. El sondeo de paquetes consume el búfer general; descarta también periódicamente los bytes sin procesar que no uses de cada interlocutor para evitar desbordamientos.
Las secciones críticas internas controlan la profundidad de anidamiento por software. Salir de la más externa habilita las interrupciones de CPU; no supongas que se conserva un estado IME previamente deshabilitado.
Las pantallas proceden de KOKURA. Los ejemplos con varios extremos comprueban valores en instancias de emulador enlazadas y capturan sus estados finales guardados. Estas comprobaciones no demuestran el comportamiento de un cable físico ni de un adaptador para cuatro jugadores.
Ejecuta estos comandos PowerShell desde la carpeta que contiene kitaqgb, kokura y kitaq-docs. Compila todas las ROM participantes antes de iniciar la sesión enlazada. Para Link4, conserva los metadatos de símbolos generados junto a las ROM. Para ejecutar en DMG, cambia en todos los comandos --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
if(slot==1)result[13]=Link4_TryReadByteFrom(slot,&value);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Conecta las cuatro ROM con la topología link4 de KOKURA. El anfitrión recibe 161/162/163 de los interlocutores 1/2/3 y muestra LAST PEER=3. Después envía las órdenes 65/66/67 con carga útil 7/42/255; verifica también esos valores en la pantalla de cada interlocutor.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.pngImplementación y código fuente
kitaqgb/lib/link.h:133
Pop one byte from the selected peer ring; null output discards it.
kitaqgb/lib/link.c:598
u8 __stackcall Link4_TryReadByteFrom(u8 peer_slot, u8 *out) {
return Link4_PopRxByte(peer_slot, out);
}Link_BeginTransfer
Carga SB e inicia o prepara un intercambio de un byte en dúplex completo.
Sintaxis
u8 __stackcall Link_BeginTransfer(u8 out);Parámetros
outValor saliente de ocho bits; todo intercambio envía un byte aunque solo interese recibir.
Valor devuelto
Devuelve 0 si se inicia o prepara, y 1 si ya está ocupado.
Condiciones y límites
Cada máquina tiene un estado de enlace compartido. Los intercambios de bytes son de dúplex completo: un lado aporta el reloj interno y el otro usa reloj externo. La velocidad normal requiere 512 ciclos por bit; la rápida de CGB, 16.
Códigos de error: 0=ninguno, 1=ocupado, 2=tiempo agotado, 3=desbordamiento de recepción, 4=configuración/protocolo no válido y 5=tiempo de ACK agotado con respuesta similar a una desconexión. Las llamadas de inicio/configuración tienen éxito con 0; las de recepción/extracción, con 1. Una llamada correcta no borra un error retenido.
Un extremo con reloj externo espera a que el otro aporte el reloj. Un rechazo por ocupado no sustituye el byte que ya está en tránsito.
Las pantallas proceden de KOKURA. Los ejemplos con varios extremos comprueban valores en instancias de emulador enlazadas y capturan sus estados finales guardados. Estas comprobaciones no demuestran el comportamiento de un cable físico ni de un adaptador para cuatro jugadores.
Ejecuta estos comandos PowerShell desde la carpeta que contiene kitaqgb, kokura y kitaq-docs. Compila todas las ROM participantes antes de iniciar la sesión enlazada. Para Link4, conserva los metadatos de símbolos generados junto a las ROM. Para ejecutar en DMG, cambia en todos los comandos --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
lesson_delay(12);result[0]=Link_BeginTransfer(42);value=0;result[1]=Link_WaitByte(8,&value);result[2]=value;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Conecta con BYTE SLAVE. Envía 42 y recibe 99; después intercambia cero en ambos sentidos. RECEIVED=1, PEER BYTE=99, ZERO READY=1 y ZERO BYTE=0 distinguen un cero válido de la ausencia de datos. Dos instancias CGB usan reloj rápido para el segundo intercambio.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_raw_master.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_raw_master.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_raw_slave.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_raw_slave.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology pair --run-frames 360 --link-session "name=raw_master|slot=0|rom=.\out\link_raw_master.gb|save_state=.\out\raw_master.kqs" --link-session "name=raw_slave|slot=1|rom=.\out\link_raw_slave.gb|save_state=.\out\raw_slave.kqs"
.\kokura\kokura-cli.exe .\out\link_raw_master.gb --hardware cgb --load-state .\out\raw_master.kqs --run-frames 2 --png .\out\raw_master.png
.\kokura\kokura-cli.exe .\out\link_raw_slave.gb --hardware cgb --load-state .\out\raw_slave.kqs --run-frames 2 --png .\out\raw_slave.pngImplementación y código fuente
kitaqgb/lib/link.h:66
Start one full-duplex byte exchange, or return BUSY without replacing an active transfer. Slave mode arms reception and waits for external clocks.
kitaqgb/lib/link.c:362
u8 __stackcall Link_BeginTransfer(u8 out) {
u8 sc = LINK_SC_START;
if (Link_Busy != 0) {
Link_SetErrorInternal(LINK_ERR_BUSY);
return LINK_ERR_BUSY;
}
LinkHw_WriteSB(out);
Link_LastTx = out;
Link4_LastTxPeer = Link4_CurrentTransferPeerInternal();
Link_Busy = 1;
LinkHw_WriteIF((u8)(LinkHw_ReadIF() & (u8)~LINK_IF_SERIAL));
if (Link_Mode == LINK_MODE_MASTER) {
sc = (u8)(sc | LINK_SC_INTERNAL);
if (Link_FastClock != 0) sc = (u8)(sc | LINK_SC_FAST);
}
LinkHw_WriteSC(sc);
return LINK_ERR_NONE;
}Link_Cancel
Detiene la transferencia de byte activa o a la espera de reloj externo.
Sintaxis
void Link_Cancel();Valor devuelto
No devuelve ningún valor.
Condiciones y límites
Las secciones críticas internas controlan la profundidad de anidamiento por software. Salir de la más externa habilita las interrupciones de CPU; no supongas que se conserva un estado IME previamente deshabilitado.
Escribe SC=0 y borra los estados de ocupado y petición serie. Conserva bytes recibidos, estado de paquetes y errores. Vuelve a inicializar también si reinicias el protocolo desde cero.
Las pantallas proceden de KOKURA. Los ejemplos con varios extremos comprueban valores en instancias de emulador enlazadas y capturan sus estados finales guardados. Estas comprobaciones no demuestran el comportamiento de un cable físico ni de un adaptador para cuatro jugadores.
Ejecuta estos comandos PowerShell desde la carpeta que contiene kitaqgb, kokura y kitaq-docs. Compila todas las ROM participantes antes de iniciar la sesión enlazada. Para Link4, conserva los metadatos de símbolos generados junto a las ROM. Para ejecutar en DMG, cambia en todos los comandos --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
Link_Cancel();result[12]=Link_IsBusy();result[13]=(SC&128)!=0;Link_ClearError();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Comprueba inicialización, rechazo por ocupación, tiempo agotado con reloj externo y capacidad del búfer. Se esperan BUSY ERROR=1, TIMEOUT=2, OPEN RX=255, OVERFLOW=3 y QUEUE BYTES=7. Tras observar IRQ REQUEST=1, la lección ejecuta explícitamente el cuerpo del manejador mientras la fuente IRQ serie permanece enmascarada.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_control.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_control.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe .\out\link_control.gb --hardware cgb --run-frames 330 --png .\out\control.pngImplementación y código fuente
kitaqgb/lib/link.h:71
Stop the hardware transfer under interrupt protection. Queued receive bytes and packet-layer state remain available; this is not a full protocol reset.
kitaqgb/lib/link.c:396
void Link_Cancel() {
u8 tok = __critical_enter();
Link_Busy = 0;
LinkHw_WriteSC(0x00);
LinkHw_WriteIF((u8)(LinkHw_ReadIF() & (u8)~LINK_IF_SERIAL));
__critical_leave(tok);
}Link_ClearError
Borra únicamente el error retenido.
Sintaxis
void Link_ClearError();Valor devuelto
No devuelve ningún valor.
Condiciones y límites
Códigos de error: 0=ninguno, 1=ocupado, 2=tiempo agotado, 3=desbordamiento de recepción, 4=configuración/protocolo no válido y 5=tiempo de ACK agotado con respuesta similar a una desconexión. Las llamadas de inicio/configuración tienen éxito con 0; las de recepción/extracción, con 1. Una llamada correcta no borra un error retenido.
Las transferencias, colas y estado de paquetes no cambian. Usa Link_Cancel para detener la transferencia de bytes o vuelve a inicializar para descartar todo el estado.
Las pantallas proceden de KOKURA. Los ejemplos con varios extremos comprueban valores en instancias de emulador enlazadas y capturan sus estados finales guardados. Estas comprobaciones no demuestran el comportamiento de un cable físico ni de un adaptador para cuatro jugadores.
Ejecuta estos comandos PowerShell desde la carpeta que contiene kitaqgb, kokura y kitaq-docs. Compila todas las ROM participantes antes de iniciar la sesión enlazada. Para Link4, conserva los metadatos de símbolos generados junto a las ROM. Para ejecutar en DMG, cambia en todos los comandos --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
Link_ClearError();result[8]=Link_LastError();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Comprueba inicialización, rechazo por ocupación, tiempo agotado con reloj externo y capacidad del búfer. Se esperan BUSY ERROR=1, TIMEOUT=2, OPEN RX=255, OVERFLOW=3 y QUEUE BYTES=7. Tras observar IRQ REQUEST=1, la lección ejecuta explícitamente el cuerpo del manejador mientras la fuente IRQ serie permanece enmascarada.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_control.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_control.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe .\out\link_control.gb --hardware cgb --run-frames 330 --png .\out\control.pngImplementación y código fuente
kitaqgb/lib/link.h:62
Clear the error latch without resetting queues or an active transfer.
kitaqgb/lib/link.c:356
void Link_ClearError() {
Link_LastErrorCode = LINK_ERR_NONE;
}Link_HasByte
Comprueba si el búfer circular general de recepción contiene datos sin leer.
Sintaxis
u8 Link_HasByte();Valor devuelto
Devuelve 1 si hay datos en cola y 0 en otro caso.
Condiciones y límites
El búfer circular de recepción de ocho entradas admite siete bytes. Si está lleno, descarta el nuevo byte y retiene el error 3. Un byte recibido con valor cero es un dato válido.
No consulta el hardware. Recoge primero la finalización mediante Link_Poll o el manejador serie.
Las pantallas proceden de KOKURA. Los ejemplos con varios extremos comprueban valores en instancias de emulador enlazadas y capturan sus estados finales guardados. Estas comprobaciones no demuestran el comportamiento de un cable físico ni de un adaptador para cuatro jugadores.
Ejecuta estos comandos PowerShell desde la carpeta que contiene kitaqgb, kokura y kitaq-docs. Compila todas las ROM participantes antes de iniciar la sesión enlazada. Para Link4, conserva los metadatos de símbolos generados junto a las ROM. Para ejecutar en DMG, cambia en todos los comandos --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
result[1]=Link_HasByte();value=77;result[2]=Link_TryReadByte(&value);result[3]=value;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
BYTE MASTER aporta el reloj. Se esperan PEER BYTE=42, ZERO READY=1 y ZERO BYTE=0. Después EMPTY READ también es cero, por lo que hace falta el estado de disponibilidad o el valor devuelto por TryRead para distinguir una cola vacía.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_raw_master.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_raw_master.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_raw_slave.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_raw_slave.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology pair --run-frames 360 --link-session "name=raw_master|slot=0|rom=.\out\link_raw_master.gb|save_state=.\out\raw_master.kqs" --link-session "name=raw_slave|slot=1|rom=.\out\link_raw_slave.gb|save_state=.\out\raw_slave.kqs"
.\kokura\kokura-cli.exe .\out\link_raw_master.gb --hardware cgb --load-state .\out\raw_master.kqs --run-frames 2 --png .\out\raw_master.png
.\kokura\kokura-cli.exe .\out\link_raw_slave.gb --hardware cgb --load-state .\out\raw_slave.kqs --run-frames 2 --png .\out\raw_slave.pngImplementación y código fuente
kitaqgb/lib/link.h:58
Read the ordinary receive-ready flag without polling hardware.
kitaqgb/lib/link.c:346
u8 Link_HasByte() {
return Link_RxReady;
}Link_HasPacket
Consulta el buzón compartido de paquetes completados.
Sintaxis
u8 Link_HasPacket();Valor devuelto
Devuelve 1 si hay un paquete sin leer y 0 en otro caso.
Condiciones y límites
Un paquete contiene 0xA5, orden, longitud, de 0 a 24 bytes de carga útil y una suma de comprobación XOR. La respuesta es 0x79 (ACK, aceptado) o 0x1F (NAK, rechazado). La suma aplica XOR a la orden, la longitud y la carga útil. Cada máquina tiene un buzón de paquetes compartido; Link4 añade uno por interlocutor.
Lee una bandera sin avanzar el protocolo. No indica si el emisor ha recibido su ACK.
Las pantallas proceden de KOKURA. Los ejemplos con varios extremos comprueban valores en instancias de emulador enlazadas y capturan sus estados finales guardados. Estas comprobaciones no demuestran el comportamiento de un cable físico ni de un adaptador para cuatro jugadores.
Ejecuta estos comandos PowerShell desde la carpeta que contiene kitaqgb, kokura y kitaq-docs. Compila todas las ROM participantes antes de iniciar la sesión enlazada. Para Link4, conserva los metadatos de símbolos generados junto a las ROM. Para ejecutar en DMG, cambia en todos los comandos --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
result[0]=Link_HasPacket();cmd=0;len=0;result[1]=Link_ReadPacket(&cmd,&len,data);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Conecta con PACKET MASTER y comprueba COMMAND=49, LENGTH=3 y carga útil 7/42/255. CONSUMED=0 tras ReadPacket significa que el buzón ya está vacío.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_packet_master.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_packet_master.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_packet_slave.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_packet_slave.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology pair --run-frames 360 --link-session "name=packet_master|slot=0|rom=.\out\link_packet_master.gb|save_state=.\out\packet_master.kqs" --link-session "name=packet_slave|slot=1|rom=.\out\link_packet_slave.gb|save_state=.\out\packet_slave.kqs"
.\kokura\kokura-cli.exe .\out\link_packet_master.gb --hardware cgb --load-state .\out\packet_master.kqs --run-frames 2 --png .\out\packet_master.png
.\kokura\kokura-cli.exe .\out\link_packet_slave.gb --hardware cgb --load-state .\out\packet_slave.kqs --run-frames 2 --png .\out\packet_slave.pngImplementación y código fuente
kitaqgb/lib/link.h:94
Inspect the shared completed-packet flag without advancing the protocol.
kitaqgb/lib/link_packet.c:441
u8 Link_HasPacket() {
return Link_ReceivedPacketReady;
}Link_InitCommon
Reinicia el estado de enlace compartido a su configuración predeterminada de reloj externo.
Sintaxis
void Link_InitCommon();Valor devuelto
No devuelve ningún valor.
Condiciones y límites
Cada máquina tiene un estado de enlace compartido. Los intercambios de bytes son de dúplex completo: un lado aporta el reloj interno y el otro usa reloj externo. La velocidad normal requiere 512 ciclos por bit; la rápida de CGB, 16.
La inicialización descarta colas de bytes, paquetes, selección del interlocutor y errores, y deshabilita la transferencia y la fuente IRQ serie. No conserva un intercambio en curso.
Las secciones críticas internas controlan la profundidad de anidamiento por software. Salir de la más externa habilita las interrupciones de CPU; no supongas que se conserva un estado IME previamente deshabilitado.
Las pantallas proceden de KOKURA. Los ejemplos con varios extremos comprueban valores en instancias de emulador enlazadas y capturan sus estados finales guardados. Estas comprobaciones no demuestran el comportamiento de un cable físico ni de un adaptador para cuatro jugadores.
Ejecuta estos comandos PowerShell desde la carpeta que contiene kitaqgb, kokura y kitaq-docs. Compila todas las ROM participantes antes de iniciar la sesión enlazada. Para Link4, conserva los metadatos de símbolos generados junto a las ROM. Para ejecutar en DMG, cambia en todos los comandos --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
Link_InitCommon();result[0]=Link_IsBusy();result[1]=Link_HasByte();result[2]=Link_LastError();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Comprueba inicialización, rechazo por ocupación, tiempo agotado con reloj externo y capacidad del búfer. Se esperan BUSY ERROR=1, TIMEOUT=2, OPEN RX=255, OVERFLOW=3 y QUEUE BYTES=7. Tras observar IRQ REQUEST=1, la lección ejecuta explícitamente el cuerpo del manejador mientras la fuente IRQ serie permanece enmascarada.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_control.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_control.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe .\out\link_control.gb --hardware cgb --run-frames 330 --png .\out\control.pngImplementación y código fuente
kitaqgb/lib/link.h:43
Reset byte queues, packet mailboxes, cooperative-peer state and errors, then disable serial transfers and serial IRQ delivery. Existing data is discarded.
kitaqgb/lib/link.c:243
void Link_InitCommon() {
u8 i;
Link_Mode = LINK_MODE_SLAVE;
Link_UseInterrupt = 0;
Link_FastClock = LINK_CLOCK_NORMAL;
Link_Busy = 0;
Link_LastRx = 0xFF;
Link_LastTx = 0xFF;
Link_RxReady = 0;
Link_LastErrorCode = LINK_ERR_NONE;
Link_PacketState = LINK_PKT_STATE_IDLE;
Link_TxSeq = 0;
Link_RxSeq = 0;
Link4_ModeState = LINK4_MODE_NONE;
Link4_LocalSlot = LINK4_HOST_SLOT;
Link4_SlotCount = 0;
Link4_SelectedPeer = LINK4_INVALID_SLOT;
Link4_LastRxPeer = LINK4_INVALID_SLOT;
Link4_LastTxPeer = LINK4_INVALID_SLOT;
Link4_LastPacketPeer = LINK4_INVALID_SLOT;
Link_RxHead = 0;
Link_RxTail = 0;
Link_TxHead = 0;
Link_TxTail = 0;
Link_CurrentPacketCmd = 0;
Link_CurrentPacketLen = 0;
Link_CurrentPacketChecksum = 0;
Link_PendingAck = 0;
Link_ReceivedPacketReady = 0;
Link_ReceivedPacketCmd = 0;
Link_ReceivedPacketLen = 0;
Link_ReceivedPacketChecksum = 0;
Link_PacketRetryCount = 0;
Link_PacketTimer = 0;
for (i = 0; i < LINK_RX_QUEUE_SIZE; ++i) Link_RxQueue[(__safe_index u8)i] = 0;
for (i = 0; i < LINK_TX_QUEUE_SIZE; ++i) Link_TxQueue[(__safe_index u8)i] = 0;
for (i = 0; i < LINK4_MAX_PLAYERS; ++i) {
Link4_RxHead[(__safe_index u8)i] = 0;
Link4_RxTail[(__safe_index u8)i] = 0;
Link4_ReceivedPacketReady[(__safe_index u8)i] = 0;
Link4_ReceivedPacketCmd[(__safe_index u8)i] = 0;
Link4_ReceivedPacketLen[(__safe_index u8)i] = 0;
}
for (i = 0; i < (u8)(LINK4_MAX_PLAYERS * LINK_RX_QUEUE_SIZE); ++i) {
Link4_RxQueue[(__safe_index u8)i] = 0;
}
for (i = 0; i < LINK_PKT_MAX_PAYLOAD; ++i) {
Link_CurrentPacketBuf[(__safe_index u8)i] = 0;
Link_ReceivedPacketBuf[(__safe_index u8)i] = 0;
}
for (i = 0; i < (u8)(LINK4_MAX_PLAYERS * LINK_PKT_MAX_PAYLOAD); ++i) {
Link4_ReceivedPacketBuf[(__safe_index u8)i] = 0;
}
LinkHw_WriteSB(0xFF);
LinkHw_WriteSC(0x00);
LinkHw_WriteIF((u8)(LinkHw_ReadIF() & (u8)~LINK_IF_SERIAL));
Link_SetSerialInterruptEnabled(0);
}Link_InitMaster
Reinicia el estado y convierte esta máquina en la fuente de reloj.
Sintaxis
void Link_InitMaster();Valor devuelto
No devuelve ningún valor.
Condiciones y límites
Cada máquina tiene un estado de enlace compartido. Los intercambios de bytes son de dúplex completo: un lado aporta el reloj interno y el otro usa reloj externo. La velocidad normal requiere 512 ciclos por bit; la rápida de CGB, 16.
La inicialización descarta colas de bytes, paquetes, selección del interlocutor y errores, y deshabilita la transferencia y la fuente IRQ serie. No conserva un intercambio en curso.
Las secciones críticas internas controlan la profundidad de anidamiento por software. Salir de la más externa habilita las interrupciones de CPU; no supongas que se conserva un estado IME previamente deshabilitado.
Las pantallas proceden de KOKURA. Los ejemplos con varios extremos comprueban valores en instancias de emulador enlazadas y capturan sus estados finales guardados. Estas comprobaciones no demuestran el comportamiento de un cable físico ni de un adaptador para cuatro jugadores.
Ejecuta estos comandos PowerShell desde la carpeta que contiene kitaqgb, kokura y kitaq-docs. Compila todas las ROM participantes antes de iniciar la sesión enlazada. Para Link4, conserva los metadatos de símbolos generados junto a las ROM. Para ejecutar en DMG, cambia en todos los comandos --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
Link_InitMaster();Link_SetUseInterrupt(0);Link_SetFastClock(0);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Conecta con BYTE SLAVE. Envía 42 y recibe 99; después intercambia cero en ambos sentidos. RECEIVED=1, PEER BYTE=99, ZERO READY=1 y ZERO BYTE=0 distinguen un cero válido de la ausencia de datos. Dos instancias CGB usan reloj rápido para el segundo intercambio.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_raw_master.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_raw_master.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_raw_slave.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_raw_slave.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology pair --run-frames 360 --link-session "name=raw_master|slot=0|rom=.\out\link_raw_master.gb|save_state=.\out\raw_master.kqs" --link-session "name=raw_slave|slot=1|rom=.\out\link_raw_slave.gb|save_state=.\out\raw_slave.kqs"
.\kokura\kokura-cli.exe .\out\link_raw_master.gb --hardware cgb --load-state .\out\raw_master.kqs --run-frames 2 --png .\out\raw_master.png
.\kokura\kokura-cli.exe .\out\link_raw_slave.gb --hardware cgb --load-state .\out\raw_slave.kqs --run-frames 2 --png .\out\raw_slave.pngImplementación y código fuente
kitaqgb/lib/link.h:45
Reset link state and select the internal-clock role for subsequent transfers.
kitaqgb/lib/link.c:309
void Link_InitMaster() {
Link_InitCommon();
Link_Mode = LINK_MODE_MASTER;
}Link_InitSlave
Reinicia el estado y selecciona comunicación con reloj externo.
Sintaxis
void Link_InitSlave();Valor devuelto
No devuelve ningún valor.
Condiciones y límites
Cada máquina tiene un estado de enlace compartido. Los intercambios de bytes son de dúplex completo: un lado aporta el reloj interno y el otro usa reloj externo. La velocidad normal requiere 512 ciclos por bit; la rápida de CGB, 16.
La inicialización descarta colas de bytes, paquetes, selección del interlocutor y errores, y deshabilita la transferencia y la fuente IRQ serie. No conserva un intercambio en curso.
Las secciones críticas internas controlan la profundidad de anidamiento por software. Salir de la más externa habilita las interrupciones de CPU; no supongas que se conserva un estado IME previamente deshabilitado.
Las pantallas proceden de KOKURA. Los ejemplos con varios extremos comprueban valores en instancias de emulador enlazadas y capturan sus estados finales guardados. Estas comprobaciones no demuestran el comportamiento de un cable físico ni de un adaptador para cuatro jugadores.
Ejecuta estos comandos PowerShell desde la carpeta que contiene kitaqgb, kokura y kitaq-docs. Compila todas las ROM participantes antes de iniciar la sesión enlazada. Para Link4, conserva los metadatos de símbolos generados junto a las ROM. Para ejecutar en DMG, cambia en todos los comandos --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
Link_InitSlave();result[0]=Link_BeginTransfer(99);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
BYTE MASTER aporta el reloj. Se esperan PEER BYTE=42, ZERO READY=1 y ZERO BYTE=0. Después EMPTY READ también es cero, por lo que hace falta el estado de disponibilidad o el valor devuelto por TryRead para distinguir una cola vacía.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_raw_master.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_raw_master.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_raw_slave.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_raw_slave.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology pair --run-frames 360 --link-session "name=raw_master|slot=0|rom=.\out\link_raw_master.gb|save_state=.\out\raw_master.kqs" --link-session "name=raw_slave|slot=1|rom=.\out\link_raw_slave.gb|save_state=.\out\raw_slave.kqs"
.\kokura\kokura-cli.exe .\out\link_raw_master.gb --hardware cgb --load-state .\out\raw_master.kqs --run-frames 2 --png .\out\raw_master.png
.\kokura\kokura-cli.exe .\out\link_raw_slave.gb --hardware cgb --load-state .\out\raw_slave.kqs --run-frames 2 --png .\out\raw_slave.pngImplementación y código fuente
kitaqgb/lib/link.h:47
Reset link state and select the external-clock role for subsequent transfers.
kitaqgb/lib/link.c:315
void Link_InitSlave() {
Link_InitCommon();
Link_Mode = LINK_MODE_SLAVE;
}Link_IsBusy
Consulta una vez si ha terminado y después indica si sigue activo un intercambio.
Sintaxis
u8 Link_IsBusy();Valor devuelto
Devuelve 1 si está ocupado y 0 en otro caso.
Condiciones y límites
El búfer circular de recepción de ocho entradas admite siete bytes. Si está lleno, descarta el nuevo byte y retiene el error 3. Un byte recibido con valor cero es un dato válido.
No es una consulta pasiva: el byte SB completado se añade a la cola, lo que puede cambiar la disponibilidad y el estado de error.
Las pantallas proceden de KOKURA. Los ejemplos con varios extremos comprueban valores en instancias de emulador enlazadas y capturan sus estados finales guardados. Estas comprobaciones no demuestran el comportamiento de un cable físico ni de un adaptador para cuatro jugadores.
Ejecuta estos comandos PowerShell desde la carpeta que contiene kitaqgb, kokura y kitaq-docs. Compila todas las ROM participantes antes de iniciar la sesión enlazada. Para Link4, conserva los metadatos de símbolos generados junto a las ROM. Para ejecutar en DMG, cambia en todos los comandos --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
result[3]=Link_IsBusy();result[4]=Link_HasByte();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Conecta con BYTE SLAVE. Envía 42 y recibe 99; después intercambia cero en ambos sentidos. RECEIVED=1, PEER BYTE=99, ZERO READY=1 y ZERO BYTE=0 distinguen un cero válido de la ausencia de datos. Dos instancias CGB usan reloj rápido para el segundo intercambio.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_raw_master.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_raw_master.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_raw_slave.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_raw_slave.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology pair --run-frames 360 --link-session "name=raw_master|slot=0|rom=.\out\link_raw_master.gb|save_state=.\out\raw_master.kqs" --link-session "name=raw_slave|slot=1|rom=.\out\link_raw_slave.gb|save_state=.\out\raw_slave.kqs"
.\kokura\kokura-cli.exe .\out\link_raw_master.gb --hardware cgb --load-state .\out\raw_master.kqs --run-frames 2 --png .\out\raw_master.png
.\kokura\kokura-cli.exe .\out\link_raw_slave.gb --hardware cgb --load-state .\out\raw_slave.kqs --run-frames 2 --png .\out\raw_slave.pngImplementación y código fuente
kitaqgb/lib/link.h:56
Poll once before returning busy state, so this query may collect a completed byte.
kitaqgb/lib/link.c:340
u8 Link_IsBusy() {
Link_Poll();
return Link_Busy;
}Link_LastError
Lee el último error de enlace retenido sin borrarlo.
Sintaxis
u8 Link_LastError();Valor devuelto
Devuelve el código de error actual, de 0 a 5.
Condiciones y límites
Códigos de error: 0=ninguno, 1=ocupado, 2=tiempo agotado, 3=desbordamiento de recepción, 4=configuración/protocolo no válido y 5=tiempo de ACK agotado con respuesta similar a una desconexión. Las llamadas de inicio/configuración tienen éxito con 0; las de recepción/extracción, con 1. Una llamada correcta no borra un error retenido.
Las pantallas proceden de KOKURA. Los ejemplos con varios extremos comprueban valores en instancias de emulador enlazadas y capturan sus estados finales guardados. Estas comprobaciones no demuestran el comportamiento de un cable físico ni de un adaptador para cuatro jugadores.
Ejecuta estos comandos PowerShell desde la carpeta que contiene kitaqgb, kokura y kitaq-docs. Compila todas las ROM participantes antes de iniciar la sesión enlazada. Para Link4, conserva los metadatos de símbolos generados junto a las ROM. Para ejecutar en DMG, cambia en todos los comandos --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
result[2]=Link_LastError();Link_ClearError();result[3]=Link_LastError();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Envía la orden 49 con carga útil 7/42/255 y luego cambia el array de origen. QUEUED=0 acepta el envío; SECOND SEND=1 rechaza un segundo inicio. El error de ocupado permanece hasta ClearError. PAYLOAD 2=42 en el receptor demuestra que la carga en cola es una copia propia.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_packet_master.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_packet_master.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_packet_slave.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_packet_slave.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology pair --run-frames 360 --link-session "name=packet_master|slot=0|rom=.\out\link_packet_master.gb|save_state=.\out\packet_master.kqs" --link-session "name=packet_slave|slot=1|rom=.\out\link_packet_slave.gb|save_state=.\out\packet_slave.kqs"
.\kokura\kokura-cli.exe .\out\link_packet_master.gb --hardware cgb --load-state .\out\packet_master.kqs --run-frames 2 --png .\out\packet_master.png
.\kokura\kokura-cli.exe .\out\link_packet_slave.gb --hardware cgb --load-state .\out\packet_slave.kqs --run-frames 2 --png .\out\packet_slave.pngImplementación y código fuente
kitaqgb/lib/link.h:60
Return the latest latched error without clearing it.
kitaqgb/lib/link.c:351
u8 Link_LastError() {
return Link_LastErrorCode;
}Link_OnSerialIRQ
Recoge un byte completado desde un manejador que ha identificado una petición serie.
Sintaxis
void Link_OnSerialIRQ();Valor devuelto
No devuelve ningún valor.
Condiciones y límites
El búfer circular de recepción de ocho entradas admite siete bytes. Si está lleno, descarta el nuevo byte y retiene el error 3. Un byte recibido con valor cero es un dato válido.
Las secciones críticas internas controlan la profundidad de anidamiento por software. Salir de la más externa habilita las interrupciones de CPU; no supongas que se conserva un estado IME previamente deshabilitado.
La función no comprueba en SC si ha terminado. No la llames desde una interrupción de temporizador ajena mientras haya una transferencia serie activa. El ejemplo ejecuta explícitamente el cuerpo tras una petición IF.serial real, con la fuente IRQ serie de CPU enmascarada; prueba el cuerpo, no la instalación del vector.
Las pantallas proceden de KOKURA. Los ejemplos con varios extremos comprueban valores en instancias de emulador enlazadas y capturan sus estados finales guardados. Estas comprobaciones no demuestran el comportamiento de un cable físico ni de un adaptador para cuatro jugadores.
Ejecuta estos comandos PowerShell desde la carpeta que contiene kitaqgb, kokura y kitaq-docs. Compila todas las ROM participantes antes de iniciar la sesión enlazada. Para Link4, conserva los metadatos de símbolos generados junto a las ROM. Para ejecutar en DMG, cambia en todos los comandos --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
lesson_delay(2);result[14]=(IF_REG&8)!=0;Link_OnSerialIRQ();result[15]=Link_HasByte();result[16]=Link_ReadByte();result[17]=(IF_REG&8)!=0;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Comprueba inicialización, rechazo por ocupación, tiempo agotado con reloj externo y capacidad del búfer. Se esperan BUSY ERROR=1, TIMEOUT=2, OPEN RX=255, OVERFLOW=3 y QUEUE BYTES=7. Tras observar IRQ REQUEST=1, la lección ejecuta explícitamente el cuerpo del manejador mientras la fuente IRQ serie permanece enmascarada.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_control.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_control.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe .\out\link_control.gb --hardware cgb --run-frames 330 --png .\out\control.pngImplementación y código fuente
kitaqgb/lib/link.h:74
Acknowledge serial IRQ and finish a software-busy transfer. Call this from the actual serial interrupt handler, not an unrelated interrupt.
kitaqgb/lib/link.c:410
void Link_OnSerialIRQ() {
LinkHw_WriteIF((u8)(LinkHw_ReadIF() & (u8)~LINK_IF_SERIAL));
if (Link_Busy == 0) return;
Link_FinishTransfer();
}Link_Poll
Recoge una transferencia activa solo después de que SC borre su bit de inicio y añade el byte recibido a la cola.
Sintaxis
void Link_Poll();Valor devuelto
No devuelve ningún valor.
Condiciones y límites
El búfer circular de recepción de ocho entradas admite siete bytes. Si está lleno, descarta el nuevo byte y retiene el error 3. Un byte recibido con valor cero es un dato válido.
La llamada no bloquea. No hace nada si el estado por software está inactivo y no implementa tiempo de espera máximo.
Las pantallas proceden de KOKURA. Los ejemplos con varios extremos comprueban valores en instancias de emulador enlazadas y capturan sus estados finales guardados. Estas comprobaciones no demuestran el comportamiento de un cable físico ni de un adaptador para cuatro jugadores.
Ejecuta estos comandos PowerShell desde la carpeta que contiene kitaqgb, kokura y kitaq-docs. Compila todas las ROM participantes antes de iniciar la sesión enlazada. Para Link4, conserva los metadatos de símbolos generados junto a las ROM. Para ejecutar en DMG, cambia en todos los comandos --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
for(i=0;i<24;i++){Link_Poll();if(Link_HasByte())break;m_wait();}Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
BYTE MASTER aporta el reloj. Se esperan PEER BYTE=42, ZERO READY=1 y ZERO BYTE=0. Después EMPTY READ también es cero, por lo que hace falta el estado de disponibilidad o el valor devuelto por TryRead para distinguir una cola vacía.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_raw_master.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_raw_master.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_raw_slave.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_raw_slave.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology pair --run-frames 360 --link-session "name=raw_master|slot=0|rom=.\out\link_raw_master.gb|save_state=.\out\raw_master.kqs" --link-session "name=raw_slave|slot=1|rom=.\out\link_raw_slave.gb|save_state=.\out\raw_slave.kqs"
.\kokura\kokura-cli.exe .\out\link_raw_master.gb --hardware cgb --load-state .\out\raw_master.kqs --run-frames 2 --png .\out\raw_master.png
.\kokura\kokura-cli.exe .\out\link_raw_slave.gb --hardware cgb --load-state .\out\raw_slave.kqs --run-frames 2 --png .\out\raw_slave.pngImplementación y código fuente
kitaqgb/lib/link.h:68
Collect a pending transfer only after hardware clears the SC start bit.
kitaqgb/lib/link.c:388
void Link_Poll() {
if (Link_Busy == 0) return;
if ((LinkHw_ReadSC() & LINK_SC_START) != 0) return;
Link_FinishTransfer();
}Link_PollPacket
Analiza los bytes recibidos, inicia el siguiente byte saliente o ACK y avanza el estado de espera y reintentos.
Sintaxis
void Link_PollPacket();Valor devuelto
No devuelve ningún valor.
Condiciones y límites
Un paquete contiene 0xA5, orden, longitud, de 0 a 24 bytes de carga útil y una suma de comprobación XOR. La respuesta es 0x79 (ACK, aceptado) o 0x1F (NAK, rechazado). La suma aplica XOR a la orden, la longitud y la carga útil. Cada máquina tiene un buzón de paquetes compartido; Link4 añade uno por interlocutor.
Mantén el sondeo en ambos extremos. El tiempo de espera cuenta 90 llamadas sin progreso, no fotogramas de hardware. Enviar 0xFF solo para dar reloj a un ACK no amplía ese plazo; se permiten como máximo tres intentos. Los reintentos pueden entregar duplicados, así que añade identificadores de aplicación si una orden debe ejecutarse exactamente una vez.
Las lecturas sin procesar de tipo ReadByte consumen el mismo búfer general y pueden llevarse parte de un paquete. No mezcles lecturas sin procesar con recepción de paquetes.
Link4 copia cada byte recibido tanto al búfer general como a uno por interlocutor. Leer uno no vacía el otro. El sondeo de paquetes consume el búfer general; descarta también periódicamente los bytes sin procesar que no uses de cada interlocutor para evitar desbordamientos.
Las pantallas proceden de KOKURA. Los ejemplos con varios extremos comprueban valores en instancias de emulador enlazadas y capturan sus estados finales guardados. Estas comprobaciones no demuestran el comportamiento de un cable físico ni de un adaptador para cuatro jugadores.
Ejecuta estos comandos PowerShell desde la carpeta que contiene kitaqgb, kokura y kitaq-docs. Compila todas las ROM participantes antes de iniciar la sesión enlazada. Para Link4, conserva los metadatos de símbolos generados junto a las ROM. Para ejecutar en DMG, cambia en todos los comandos --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
Link_InitSlave();for(i=0;i<120;i++){Link_PollPacket();m_wait();}Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Conecta con PACKET MASTER y comprueba COMMAND=49, LENGTH=3 y carga útil 7/42/255. CONSUMED=0 tras ReadPacket significa que el buzón ya está vacío.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_packet_master.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_packet_master.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_packet_slave.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_packet_slave.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology pair --run-frames 360 --link-session "name=packet_master|slot=0|rom=.\out\link_packet_master.gb|save_state=.\out\packet_master.kqs" --link-session "name=packet_slave|slot=1|rom=.\out\link_packet_slave.gb|save_state=.\out\packet_slave.kqs"
.\kokura\kokura-cli.exe .\out\link_packet_master.gb --hardware cgb --load-state .\out\packet_master.kqs --run-frames 2 --png .\out\packet_master.png
.\kokura\kokura-cli.exe .\out\link_packet_slave.gb --hardware cgb --load-state .\out\packet_slave.kqs --run-frames 2 --png .\out\packet_slave.pngEjemplo de uso
Link_InitMaster();result[0]=Link_SendPacket(0,0,7);
// An absent peer cannot acknowledge the packet, despite completed FF exchanges.
for(ticks=0;ticks<300;ticks++){Link_PollPacket();m_wait();}
result[1]=Link_LastError();Link_Cancel();result[2]=Link_IsBusy();Link_ClearError();result[3]=Link_LastError();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Envía sin un interlocutor conectado. Las transferencias de bytes terminan con reloj interno, pero no llega ACK; tras los reintentos, NO ACK ERROR=5. Cancel deja CANCEL BUSY=0.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_deadline.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_deadline.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe .\out\link_deadline.gb --hardware cgb --run-frames 330 --png .\out\deadline.pngImplementación y código fuente
kitaqgb/lib/link.h:92
Drain received bytes, advance one outgoing exchange and update the retry timer. Timeout ticks count calls without progress, not hardware frames; call with a controlled cadence and avoid mixing raw reads with packet consumption.
kitaqgb/lib/link_packet.c:400
void Link_PollPacket() {
u8 progress = 0;
u8 previous_state;
u8 value = 0;
Link_Poll();
if (Link_PacketState == LINK_PKT_STATE_ERROR) {
Link_PacketGoIdle();
return;
}
while (Link_TryReadByte(&value) != 0) {
if (Link_PacketConsumeByte(value) != 0) progress = 1;
}
if (Link_PacketState == LINK_PKT_STATE_SEND_ACK) {
if (Link_PacketStartAckTransfer() != 0) progress = 1;
} else if (Link_PacketIsSendState() != 0) {
// Clocking an ACK is not protocol progress: a missing peer must time out.
previous_state = Link_PacketState;
if (Link_PacketStartNextTransfer() != 0 && previous_state != LINK_PKT_STATE_WAIT_ACK) progress = 1;
} else {
if (Link_PacketStartReceiveTransfer() != 0) progress = 1;
}
if (Link_PacketState == LINK_PKT_STATE_IDLE) {
Link_PacketTimer = 0;
return;
}
if (progress != 0) {
Link_PacketTimer = LINK_PKT_TIMEOUT_TICKS;
return;
}
if (Link_PacketTimer != 0) Link_PacketTimer--;
if (Link_PacketTimer == 0) Link_PacketHandleTimeout();
}Link_ReadByte
Devuelve un byte extraído del búfer general de recepción.
Sintaxis
u8 Link_ReadByte();Valor devuelto
Devuelve el byte recibido; una cola vacía también devuelve cero.
Condiciones y límites
El búfer circular de recepción de ocho entradas admite siete bytes. Si está lleno, descarta el nuevo byte y retiene el error 3. Un byte recibido con valor cero es un dato válido.
Las secciones críticas internas controlan la profundidad de anidamiento por software. Salir de la más externa habilita las interrupciones de CPU; no supongas que se conserva un estado IME previamente deshabilitado.
El valor devuelto por sí solo no distingue un cero recibido de una cola vacía. Usa la bandera de éxito de TryReadByte o consulta HasByte antes de leer.
Las pantallas proceden de KOKURA. Los ejemplos con varios extremos comprueban valores en instancias de emulador enlazadas y capturan sus estados finales guardados. Estas comprobaciones no demuestran el comportamiento de un cable físico ni de un adaptador para cuatro jugadores.
Ejecuta estos comandos PowerShell desde la carpeta que contiene kitaqgb, kokura y kitaq-docs. Compila todas las ROM participantes antes de iniciar la sesión enlazada. Para Link4, conserva los metadatos de símbolos generados junto a las ROM. Para ejecutar en DMG, cambia en todos los comandos --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
result[6]=Link_HasByte();result[7]=Link_ReadByte();result[8]=Link_ReadByte();result[9]=Link_LastError();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
BYTE MASTER aporta el reloj. Se esperan PEER BYTE=42, ZERO READY=1 y ZERO BYTE=0. Después EMPTY READ también es cero, por lo que hace falta el estado de disponibilidad o el valor devuelto por TryRead para distinguir una cola vacía.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_raw_master.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_raw_master.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_raw_slave.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_raw_slave.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology pair --run-frames 360 --link-session "name=raw_master|slot=0|rom=.\out\link_raw_master.gb|save_state=.\out\raw_master.kqs" --link-session "name=raw_slave|slot=1|rom=.\out\link_raw_slave.gb|save_state=.\out\raw_slave.kqs"
.\kokura\kokura-cli.exe .\out\link_raw_master.gb --hardware cgb --load-state .\out\raw_master.kqs --run-frames 2 --png .\out\raw_master.png
.\kokura\kokura-cli.exe .\out\link_raw_slave.gb --hardware cgb --load-state .\out\raw_slave.kqs --run-frames 2 --png .\out\raw_slave.pngImplementación y código fuente
kitaqgb/lib/link.h:80
Pop one byte, returning zero when empty. Use Link_TryReadByte when a received zero byte must be distinguished from an empty queue.
kitaqgb/lib/link.c:427
u8 Link_ReadByte() {
u8 value = 0;
if (Link_PopRxByte(&value) != 0) return value;
return 0;
}Link_ReadPacket
Copia un paquete completado y lo consume del buzón compartido.
Sintaxis
u8 __stackcall Link_ReadPacket(u8 *cmd, u8 *len, u8 *dst);Parámetros
cmdByte de orden escribible; null omite esta salida.
lenByte de longitud escribible, de 0 a 24; null omite esta salida.
dstBúfer de carga útil escribible con espacio para 24 bytes; null descarta la carga útil.
Valor devuelto
Devuelve 1 si consume un paquete y 0 si está vacío; una lectura vacía no modifica las salidas.
Condiciones y límites
No hay parámetro de capacidad del destino. Proporciona 24 bytes escribibles si usas dst. cmd, len y dst pueden ser null de forma independiente. Serializa la consulta y el consumo del buzón respecto al resto del código y las interrupciones.
En modo Link4 también vacía el buzón del interlocutor correspondiente a este paquete compartido. Los demás buzones siguen disponibles.
Las pantallas proceden de KOKURA. Los ejemplos con varios extremos comprueban valores en instancias de emulador enlazadas y capturan sus estados finales guardados. Estas comprobaciones no demuestran el comportamiento de un cable físico ni de un adaptador para cuatro jugadores.
Ejecuta estos comandos PowerShell desde la carpeta que contiene kitaqgb, kokura y kitaq-docs. Compila todas las ROM participantes antes de iniciar la sesión enlazada. Para Link4, conserva los metadatos de símbolos generados junto a las ROM. Para ejecutar en DMG, cambia en todos los comandos --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
result[0]=Link_HasPacket();cmd=0;len=0;result[1]=Link_ReadPacket(&cmd,&len,data);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Conecta con PACKET MASTER y comprueba COMMAND=49, LENGTH=3 y carga útil 7/42/255. CONSUMED=0 tras ReadPacket significa que el buzón ya está vacío.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_packet_master.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_packet_master.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_packet_slave.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_packet_slave.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology pair --run-frames 360 --link-session "name=packet_master|slot=0|rom=.\out\link_packet_master.gb|save_state=.\out\packet_master.kqs" --link-session "name=packet_slave|slot=1|rom=.\out\link_packet_slave.gb|save_state=.\out\packet_slave.kqs"
.\kokura\kokura-cli.exe .\out\link_packet_master.gb --hardware cgb --load-state .\out\packet_master.kqs --run-frames 2 --png .\out\packet_master.png
.\kokura\kokura-cli.exe .\out\link_packet_slave.gb --hardware cgb --load-state .\out\packet_slave.kqs --run-frames 2 --png .\out\packet_slave.pngImplementación y código fuente
kitaqgb/lib/link.h:98
Consume the shared packet mailbox and its matching peer flag. Any output may be null; a nonnull destination needs room for the received payload because there is no destination-capacity argument.
kitaqgb/lib/link_packet.c:448
u8 __stackcall Link_ReadPacket(u8 *cmd, u8 *len, u8 *dst) {
u8 i;
u8 peer_slot = Link4_LastPacketPeer;
if (Link_ReceivedPacketReady == 0) return 0;
if (cmd != 0) *cmd = Link_ReceivedPacketCmd;
if (len != 0) *len = Link_ReceivedPacketLen;
if (dst != 0) {
for (i = 0; i < Link_ReceivedPacketLen; ++i) {
dst[(__safe_index u8)i] = Link_ReceivedPacketBuf[(__safe_index u8)i];
}
}
Link_ReceivedPacketReady = 0;
if (Link4_IsValidRemoteSlotInternal(peer_slot) != 0) {
Link4_ReceivedPacketReady[(__safe_index u8)peer_slot] = 0;
}
Link4_LastPacketPeer = LINK4_INVALID_SLOT;
return 1;
}Link_SendPacket
Copia la carga útil a almacenamiento propio y programa la transmisión del paquete.
Sintaxis
u8 __stackcall Link_SendPacket(const u8 *data, u8 len, u8 cmd);Parámetros
dataOrigen legible de len bytes; solo puede ser null si len es cero.
lenLongitud de la carga útil en bytes, de 0 a 24.
cmdOrden de ocho bits definida por la aplicación.
Valor devuelto
Devuelve 0 si se acepta, 1 si el estado de paquetes está ocupado y 4 si la longitud o el puntero no son válidos.
Condiciones y límites
Códigos de error: 0=ninguno, 1=ocupado, 2=tiempo agotado, 3=desbordamiento de recepción, 4=configuración/protocolo no válido y 5=tiempo de ACK agotado con respuesta similar a una desconexión. Las llamadas de inicio/configuración tienen éxito con 0; las de recepción/extracción, con 1. Una llamada correcta no borra un error retenido.
Un paquete contiene 0xA5, orden, longitud, de 0 a 24 bytes de carga útil y una suma de comprobación XOR. La respuesta es 0x79 (ACK, aceptado) o 0x1F (NAK, rechazado). La suma aplica XOR a la orden, la longitud y la carga útil. Cada máquina tiene un buzón de paquetes compartido; Link4 añade uno por interlocutor.
Mantén el sondeo en ambos extremos. El tiempo de espera cuenta 90 llamadas sin progreso, no fotogramas de hardware. Enviar 0xFF solo para dar reloj a un ACK no amplía ese plazo; se permiten como máximo tres intentos. Los reintentos pueden entregar duplicados, así que añade identificadores de aplicación si una orden debe ejecutarse exactamente una vez.
Cero significa encolado, no recibido ni confirmado por el interlocutor. Puedes reutilizar el array de origen tras la aceptación.
Las pantallas proceden de KOKURA. Los ejemplos con varios extremos comprueban valores en instancias de emulador enlazadas y capturan sus estados finales guardados. Estas comprobaciones no demuestran el comportamiento de un cable físico ni de un adaptador para cuatro jugadores.
Ejecuta estos comandos PowerShell desde la carpeta que contiene kitaqgb, kokura y kitaq-docs. Compila todas las ROM participantes antes de iniciar la sesión enlazada. Para Link4, conserva los metadatos de símbolos generados junto a las ROM. Para ejecutar en DMG, cambia en todos los comandos --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
result[0]=Link_SendPacket(data,3,0x31);data[1]=0;result[1]=Link_SendPacket(data,3,0x32);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Envía la orden 49 con carga útil 7/42/255 y luego cambia el array de origen. QUEUED=0 acepta el envío; SECOND SEND=1 rechaza un segundo inicio. El error de ocupado permanece hasta ClearError. PAYLOAD 2=42 en el receptor demuestra que la carga en cola es una copia propia.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_packet_master.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_packet_master.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_packet_slave.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_packet_slave.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology pair --run-frames 360 --link-session "name=packet_master|slot=0|rom=.\out\link_packet_master.gb|save_state=.\out\packet_master.kqs" --link-session "name=packet_slave|slot=1|rom=.\out\link_packet_slave.gb|save_state=.\out\packet_slave.kqs"
.\kokura\kokura-cli.exe .\out\link_packet_master.gb --hardware cgb --load-state .\out\packet_master.kqs --run-frames 2 --png .\out\packet_master.png
.\kokura\kokura-cli.exe .\out\link_packet_slave.gb --hardware cgb --load-state .\out\packet_slave.kqs --run-frames 2 --png .\out\packet_slave.pngImplementación y código fuente
kitaqgb/lib/link.h:88
Validate payload size and idle packet state, copy payload bytes into owned storage and schedule transmission. Return success means queued, not acknowledged; keep polling to progress the exchange and inspect the error latch.
kitaqgb/lib/link_packet.c:361
u8 __stackcall Link_SendPacket(const u8 *data, u8 len, u8 cmd) {
u8 i;
u8 checksum = (u8)(cmd ^ len);
if (len > LINK_PKT_MAX_PAYLOAD) {
Link_SetErrorInternal(LINK_ERR_PROTOCOL);
return LINK_ERR_PROTOCOL;
}
if (len != 0 && data == 0) {
Link_SetErrorInternal(LINK_ERR_PROTOCOL);
return LINK_ERR_PROTOCOL;
}
if (Link_PacketState != LINK_PKT_STATE_IDLE || Link_PendingAck != 0) {
Link_SetErrorInternal(LINK_ERR_BUSY);
return LINK_ERR_BUSY;
}
Link_CurrentPacketCmd = cmd;
Link_CurrentPacketLen = len;
for (i = 0; i < len; ++i) {
Link_CurrentPacketBuf[(__safe_index u8)i] = data[(__safe_index u8)i];
checksum = (u8)(checksum ^ data[(__safe_index u8)i]);
}
Link_CurrentPacketChecksum = checksum;
Link_TxSeq = 0;
Link_RxSeq = 0;
Link_PacketRetryCount = 0;
Link_PacketTimer = LINK_PKT_TIMEOUT_TICKS;
Link_PacketState = LINK_PKT_STATE_SEND_SYNC;
return LINK_ERR_NONE;
}Link_SetFastClock
Elige si las próximas transferencias con reloj interno usan el bit de reloj rápido de CGB.
Sintaxis
void __stackcall Link_SetFastClock(u8 on);Parámetros
onCero solicita velocidad normal; un valor distinto de cero solicita velocidad rápida.
Valor devuelto
No devuelve ningún valor.
Condiciones y límites
Cada máquina tiene un estado de enlace compartido. Los intercambios de bytes son de dúplex completo: un lado aporta el reloj interno y el otro usa reloj externo. La velocidad normal requiere 512 ciclos por bit; la rápida de CGB, 16.
No cambia una transferencia en curso. Las transferencias con reloj externo ignoran este ajuste. No se comprueba la compatibilidad del hardware; ejecuta ambos extremos del ejemplo en modos de hardware compatibles.
Las pantallas proceden de KOKURA. Los ejemplos con varios extremos comprueban valores en instancias de emulador enlazadas y capturan sus estados finales guardados. Estas comprobaciones no demuestran el comportamiento de un cable físico ni de un adaptador para cuatro jugadores.
Ejecuta estos comandos PowerShell desde la carpeta que contiene kitaqgb, kokura y kitaq-docs. Compila todas las ROM participantes antes de iniciar la sesión enlazada. Para Link4, conserva los metadatos de símbolos generados junto a las ROM. Para ejecutar en DMG, cambia en todos los comandos --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
lesson_delay(12);Link_SetFastClock(__cgb_is_cgb());result[5]=Link_BeginTransfer(0);value=77;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Conecta con BYTE SLAVE. Envía 42 y recibe 99; después intercambia cero en ambos sentidos. RECEIVED=1, PEER BYTE=99, ZERO READY=1 y ZERO BYTE=0 distinguen un cero válido de la ausencia de datos. Dos instancias CGB usan reloj rápido para el segundo intercambio.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_raw_master.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_raw_master.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_raw_slave.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_raw_slave.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology pair --run-frames 360 --link-session "name=raw_master|slot=0|rom=.\out\link_raw_master.gb|save_state=.\out\raw_master.kqs" --link-session "name=raw_slave|slot=1|rom=.\out\link_raw_slave.gb|save_state=.\out\raw_slave.kqs"
.\kokura\kokura-cli.exe .\out\link_raw_master.gb --hardware cgb --load-state .\out\raw_master.kqs --run-frames 2 --png .\out\raw_master.png
.\kokura\kokura-cli.exe .\out\link_raw_slave.gb --hardware cgb --load-state .\out\raw_slave.kqs --run-frames 2 --png .\out\raw_slave.pngImplementación y código fuente
kitaqgb/lib/link.h:53
Select the fast-clock bit for future master transfers; this does not restart an active transfer or verify that the hardware supports CGB fast mode.
kitaqgb/lib/link.c:334
void __stackcall Link_SetFastClock(u8 on) {
if (on != 0) Link_FastClock = LINK_CLOCK_FAST;
else Link_FastClock = LINK_CLOCK_NORMAL;
}Link_SetUseInterrupt
Activa el bit de habilitación de interrupción serie y borra una petición serie pendiente.
Sintaxis
void __stackcall Link_SetUseInterrupt(u8 on);Parámetros
onCero deshabilita; cualquier valor distinto de cero habilita.
Valor devuelto
No devuelve ningún valor.
Condiciones y límites
Las secciones críticas internas controlan la profundidad de anidamiento por software. Salir de la más externa habilita las interrupciones de CPU; no supongas que se conserva un estado IME previamente deshabilitado.
Instala aparte un manejador en el vector 0058h; esta biblioteca no lo registra. El ejemplo vuelve a enmascarar la fuente antes de transferir y no prueba el código de entrada de interrupción de CPU.
Las pantallas proceden de KOKURA. Los ejemplos con varios extremos comprueban valores en instancias de emulador enlazadas y capturan sus estados finales guardados. Estas comprobaciones no demuestran el comportamiento de un cable físico ni de un adaptador para cuatro jugadores.
Ejecuta estos comandos PowerShell desde la carpeta que contiene kitaqgb, kokura y kitaq-docs. Compila todas las ROM participantes antes de iniciar la sesión enlazada. Para Link4, conserva los metadatos de símbolos generados junto a las ROM. Para ejecutar en DMG, cambia en todos los comandos --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
Link_SetUseInterrupt(1);result[3]=(IE_REG&8)!=0;Link_SetUseInterrupt(0);result[4]=(IE_REG&8)!=0;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Comprueba inicialización, rechazo por ocupación, tiempo agotado con reloj externo y capacidad del búfer. Se esperan BUSY ERROR=1, TIMEOUT=2, OPEN RX=255, OVERFLOW=3 y QUEUE BYTES=7. Tras observar IRQ REQUEST=1, la lección ejecuta explícitamente el cuerpo del manejador mientras la fuente IRQ serie permanece enmascarada.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_control.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_control.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe .\out\link_control.gb --hardware cgb --run-frames 330 --png .\out\control.pngImplementación y código fuente
kitaqgb/lib/link.h:50
Enable or disable serial IRQ delivery and clear its pending flag. Enabling does not install the handler. Leaving its outer critical section enables CPU interrupts.
kitaqgb/lib/link.c:322
void __stackcall Link_SetUseInterrupt(u8 on) {
if (on != 0) {
Link_UseInterrupt = 1;
Link_SetSerialInterruptEnabled(1);
} else {
Link_UseInterrupt = 0;
Link_SetSerialInterruptEnabled(0);
}
}Link_TryReadByte
Extrae un byte del búfer general de recepción sin esperar.
Sintaxis
u8 __stackcall Link_TryReadByte(u8 *out);Parámetros
outDestino escribible de un byte; null descarta el byte.
Valor devuelto
Devuelve 1 si extrae un byte y 0 si está vacío; una lectura vacía no modifica out.
Condiciones y límites
El búfer circular de recepción de ocho entradas admite siete bytes. Si está lleno, descarta el nuevo byte y retiene el error 3. Un byte recibido con valor cero es un dato válido.
Las secciones críticas internas controlan la profundidad de anidamiento por software. Salir de la más externa habilita las interrupciones de CPU; no supongas que se conserva un estado IME previamente deshabilitado.
Link4 copia cada byte recibido tanto al búfer general como a uno por interlocutor. Leer uno no vacía el otro. El sondeo de paquetes consume el búfer general; descarta también periódicamente los bytes sin procesar que no uses de cada interlocutor para evitar desbordamientos.
Las pantallas proceden de KOKURA. Los ejemplos con varios extremos comprueban valores en instancias de emulador enlazadas y capturan sus estados finales guardados. Estas comprobaciones no demuestran el comportamiento de un cable físico ni de un adaptador para cuatro jugadores.
Ejecuta estos comandos PowerShell desde la carpeta que contiene kitaqgb, kokura y kitaq-docs. Compila todas las ROM participantes antes de iniciar la sesión enlazada. Para Link4, conserva los metadatos de símbolos generados junto a las ROM. Para ejecutar en DMG, cambia en todos los comandos --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
result[1]=Link_HasByte();value=77;result[2]=Link_TryReadByte(&value);result[3]=value;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
BYTE MASTER aporta el reloj. Se esperan PEER BYTE=42, ZERO READY=1 y ZERO BYTE=0. Después EMPTY READ también es cero, por lo que hace falta el estado de disponibilidad o el valor devuelto por TryRead para distinguir una cola vacía.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_raw_master.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_raw_master.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_raw_slave.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_raw_slave.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology pair --run-frames 360 --link-session "name=raw_master|slot=0|rom=.\out\link_raw_master.gb|save_state=.\out\raw_master.kqs" --link-session "name=raw_slave|slot=1|rom=.\out\link_raw_slave.gb|save_state=.\out\raw_slave.kqs"
.\kokura\kokura-cli.exe .\out\link_raw_master.gb --hardware cgb --load-state .\out\raw_master.kqs --run-frames 2 --png .\out\raw_master.png
.\kokura\kokura-cli.exe .\out\link_raw_slave.gb --hardware cgb --load-state .\out\raw_slave.kqs --run-frames 2 --png .\out\raw_slave.pngImplementación y código fuente
kitaqgb/lib/link.h:77
Pop the ordinary receive queue without waiting or polling hardware; null discards a byte.
kitaqgb/lib/link.c:417
u8 __stackcall Link_TryReadByte(u8 *out) {
return Link_PopRxByte(out);
}Link_WaitByte
Consulta inmediatamente y espera un byte con un límite basado en VBlank.
Sintaxis
u8 __stackcall Link_WaitByte(u16 timeout_frames, u8 *out);Parámetros
timeout_framesNúmero máximo de esperas VBlank. Cero aun así realiza la consulta y lectura iniciales.
outByte escribible obligatorio. null devuelve cero de inmediato sin cambiar el error retenido.
Valor devuelto
Devuelve 1 al recibir y 0 si se agota el tiempo o la salida es null.
Condiciones y límites
El búfer circular de recepción de ocho entradas admite siete bytes. Si está lleno, descarta el nuevo byte y retiene el error 3. Un byte recibido con valor cero es un dato válido.
Úsalo con el LCD activo. El tiempo agotado retiene el error 2 y deja out intacto. La transferencia no se cancela; llama a Cancel si la abandonas.
Las pantallas proceden de KOKURA. Los ejemplos con varios extremos comprueban valores en instancias de emulador enlazadas y capturan sus estados finales guardados. Estas comprobaciones no demuestran el comportamiento de un cable físico ni de un adaptador para cuatro jugadores.
Ejecuta estos comandos PowerShell desde la carpeta que contiene kitaqgb, kokura y kitaq-docs. Compila todas las ROM participantes antes de iniciar la sesión enlazada. Para Link4, conserva los metadatos de símbolos generados junto a las ROM. Para ejecutar en DMG, cambia en todos los comandos --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
value=77;result[9]=Link_WaitByte(2,&value);result[10]=value;result[11]=Link_LastError();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Comprueba inicialización, rechazo por ocupación, tiempo agotado con reloj externo y capacidad del búfer. Se esperan BUSY ERROR=1, TIMEOUT=2, OPEN RX=255, OVERFLOW=3 y QUEUE BYTES=7. Tras observar IRQ REQUEST=1, la lección ejecuta explícitamente el cuerpo del manejador mientras la fuente IRQ serie permanece enmascarada.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_control.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_control.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe .\out\link_control.gb --hardware cgb --run-frames 330 --png .\out\control.pngImplementación y código fuente
kitaqgb/lib/link.h:83
Require an output pointer, poll immediately, then wait at most timeout_frames VBlanks for a byte. Zero timeout still performs the initial poll and read.
kitaqgb/lib/link.c:435
u8 __stackcall Link_WaitByte(u16 timeout_frames, u8 *out) {
u16 waited = 0;
if (out == 0) return 0;
Link_Poll();
if (Link_TryReadByte(out) != 0) return 1;
while (waited < timeout_frames) {
__wait_vblank();
waited++;
Link_Poll();
if (Link_TryReadByte(out) != 0) return 1;
}
Link_SetErrorInternal(LINK_ERR_TIMEOUT);
return 0;
}link_dmg07.h — Comunicación DMG-07 con reloj externo
DMG-07 difunde un byte de cada consola a los cuatro jugadores. La biblioteca gestiona descubrimiento, inicio por jugador 1, difusión retrasada y control de reinicio alineado. Aprende intercambio a cuatro con EXCHANGE, timeout con NO ADAPTER, datos sin leer con OVERFLOW y recuperación con RESTART.
La biblioteca numera jugadores 1..4; cero significa no descubierto. Los bits 0..3 de la máscara de conexión corresponden a jugadores 1..4. Los valores slot de KOKURA --link-session son 0..3, una numeración distinta de la API ROM.
Este controlador ocupa el puerto serie. No ejecutes Link normal ni Link4 a la vez; incluye link_hwregs_gb.c y link_dmg07.c una vez cada uno. El adaptador aporta el reloj externo; el controlador no selecciona el modo serie rápido de CGB.
Llama a Poll repetidamente durante todo el fotograma y a TickFrame exactamente una vez por fotograma. Un Poll por VBlank no rearma el puerto entre bytes del adaptador. d_poll de la cabecera compartida detecta la entrada en LY >= 144 para llamar una vez a TickFrame. Serializa ambas operaciones para evitar carreras entre ISR y bucle principal.
Con SIZE=1, cada consola envía un byte; la difusión de cuatro bytes sigue el orden de jugadores 1..4. Se descarta la primera difusión. Las siguientes contienen las aportaciones del paquete anterior. Una difusión de cuatro bytes 0xFF se reserva como señal de reinicio.
LinkDmg07_ClearError
Restablece el último código de error a cero.
Sintaxis
void LinkDmg07_ClearError();Valor devuelto
No devuelve ningún valor.
Condiciones y límites
SilenceFrames y los contadores de diagnóstico se saturan en 255. Init los restablece todos; los reinicios normales del protocolo conservan los de diagnóstico. ClearError solo borra el código de error.
Conserva datos recibidos, fase, conexión y marca de timeout. Esta llamada por sí sola no reconecta ni reanuda la recepción.
Las pantallas se capturan con el modelo DMG-07 de KOKURA. Cada consola se ejecuta de forma independiente y se comparan los valores enviados y recibidos. No se han verificado el comportamiento eléctrico ni la temporización del adaptador y cable físicos. En CGB los números aparecen en azul.
Coloca kitaqgb, kokura y kitaq-docs bajo un mismo directorio padre y abre PowerShell allí. Los ejemplos de cuatro consolas ejecutan la misma ROM en cuatro sesiones. Para comprobar DMG, sustituye en todas partes --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
LinkDmg07_ClearError();result[21]=LinkDmg07_LastError();result[22]=LinkDmg07_GetErrorCount();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Deja el primer paquete válido sin leer hasta que llegue otro. Se esperan SENT SEQ=3, PACKET SEQ=2 y ERROR=6; la lectura devuelve los últimos 33/34/35/36. ClearError pone CLEAR ERROR a cero, pero ErrorCount sigue en uno.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_overflow.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_overflow.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_overflow.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_overflow.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_overflow.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_overflow.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_overflow.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_overflow.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_overflow.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_overflow.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.pngImplementación y código fuente
kitaqgb/lib/link_dmg07.h:125
Clear only the latest error code, preserving counters and protocol state.
kitaqgb/lib/link_dmg07.c:541
void LinkDmg07_ClearError() {
LinkDmg07_LastErrorCode = LINK_DMG07_ERR_NONE;
}LinkDmg07_ConsumePingStatus
Consume y borra una notificación de descubrimiento completado.
Sintaxis
u8 LinkDmg07_ConsumePingStatus();Valor devuelto
Devuelve 1 si se consume y 0 si no.
Condiciones y límites
Borra solo la notificación y conserva slot, máscara y LastStatus. Las llamadas siguientes devuelven cero hasta que llegue otra notificación.
Las pantallas se capturan con el modelo DMG-07 de KOKURA. Cada consola se ejecuta de forma independiente y se comparan los valores enviados y recibidos. No se han verificado el comportamiento eléctrico ni la temporización del adaptador y cable físicos. En CGB los números aparecen en azul.
Coloca kitaqgb, kokura y kitaq-docs bajo un mismo directorio padre y abre PowerShell allí. Los ejemplos de cuatro consolas ejecutan la misma ROM en cuatro sesiones. Para comprobar DMG, sustituye en todas partes --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
result[3]=LinkDmg07_ConsumePingStatus();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Ejecuta la misma ROM en cuatro consolas, cada una enviando 32 más su número. Todas reciben PLAYER 1..4 = 33/34/35/36. La primera difusión válida registra SENT SEQ=2 y PACKET SEQ=1, mostrando el retraso de un paquete. La pantalla congela esa observación; un juego sigue consultando después.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.pngImplementación y código fuente
kitaqgb/lib/link_dmg07.h:71
Clear and report the completed-discovery flag; return zero if no new status exists.
kitaqgb/lib/link_dmg07.c:418
u8 LinkDmg07_ConsumePingStatus() {
if (LinkDmg07_PingStatusReady == 0) return 0;
LinkDmg07_PingStatusReady = 0;
return 1;
}LinkDmg07_GetConnectedMask
Lee el conjunto de jugadores de cuatro bits del último estado aceptado.
Sintaxis
u8 LinkDmg07_GetConnectedMask();Valor devuelto
Los bits 0..3 indican jugadores conectados. No descubierto es cero; cuatro jugadores conectados es 15.
Condiciones y límites
La biblioteca numera jugadores 1..4; cero significa no descubierto. Los bits 0..3 de la máscara de conexión corresponden a jugadores 1..4. Los valores slot de KOKURA --link-session son 0..3, una numeración distinta de la API ROM.
Devuelve el estado de descubrimiento guardado, sin sondear el cableado físico. Durante la transferencia refleja la última notificación aceptada.
Las pantallas se capturan con el modelo DMG-07 de KOKURA. Cada consola se ejecuta de forma independiente y se comparan los valores enviados y recibidos. No se han verificado el comportamiento eléctrico ni la temporización del adaptador y cable físicos. En CGB los números aparecen en azul.
Coloca kitaqgb, kokura y kitaq-docs bajo un mismo directorio padre y abre PowerShell allí. Los ejemplos de cuatro consolas ejecutan la misma ROM en cuatro sesiones. Para comprobar DMG, sustituye en todas partes --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
result[1]=LinkDmg07_GetConnectedMask();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Ejecuta la misma ROM en cuatro consolas, cada una enviando 32 más su número. Todas reciben PLAYER 1..4 = 33/34/35/36. La primera difusión válida registra SENT SEQ=2 y PACKET SEQ=1, mostrando el retraso de un paquete. La pantalla congela esa observación; un juego sigue consultando después.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.pngImplementación y código fuente
kitaqgb/lib/link_dmg07.h:65
Normalized mask: bit 0 is player 1, ..., bit 3 is player 4.
kitaqgb/lib/link_dmg07.c:403
u8 LinkDmg07_GetConnectedMask() {
return LinkDmg07_ConnectedMask;
}LinkDmg07_GetDisconnectCount
Lee las pérdidas registradas: silencio tras detectar adaptador o jugadores que desaparecen del estado de descubrimiento.
Sintaxis
u8 LinkDmg07_GetDisconnectCount();Valor devuelto
Devuelve 0..255 eventos, no el número de jugadores perdidos.
Condiciones y límites
SilenceFrames y los contadores de diagnóstico se saturan en 255. Init los restablece todos; los reinicios normales del protocolo conservan los de diagnóstico. ClearError solo borra el código de error.
Un plazo agotado antes de observar ningún adaptador no lo incrementa. Varios jugadores eliminados por un único cambio de estado cuentan como un evento.
Las pantallas se capturan con el modelo DMG-07 de KOKURA. Cada consola se ejecuta de forma independiente y se comparan los valores enviados y recibidos. No se han verificado el comportamiento eléctrico ni la temporización del adaptador y cable físicos. En CGB los números aparecen en azul.
Coloca kitaqgb, kokura y kitaq-docs bajo un mismo directorio padre y abre PowerShell allí. Los ejemplos de cuatro consolas ejecutan la misma ROM en cuatro sesiones. Para comprobar DMG, sustituye en todas partes --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
result[8]=LinkDmg07_GetDisconnectCount();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Ejecuta sin adaptador. Se espera PLAYER=0, START ERROR=2, SILENT FRAME=12, TIMEOUTS=1 y ERROR=4. DISCONNECTS sigue en cero porque nunca se detectó adaptador. Una lectura vacía conserva EMPTY BUFFER=77; ClearError produce CLEARED=0.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_absent.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_absent.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe .\out\dmg07_absent.gb --hardware cgb --run-frames 90 --png .\out\absent.pngImplementación y código fuente
kitaqgb/lib/link_dmg07.h:118
Return the saturating count of removed-player and previously-seen-adapter timeout events.
kitaqgb/lib/link_dmg07.c:525
u8 LinkDmg07_GetDisconnectCount() {
return LinkDmg07_DisconnectCount;
}LinkDmg07_GetErrorCount
Lee el número de errores de protocolo recibidos y sobrescrituras de paquetes sin leer.
Sintaxis
u8 LinkDmg07_GetErrorCount();Valor devuelto
Devuelve 0..255. No incluye errores de validación/estado de solicitudes ni tiempos agotados.
Condiciones y límites
SilenceFrames y los contadores de diagnóstico se saturan en 255. Init los restablece todos; los reinicios normales del protocolo conservan los de diagnóstico. ClearError solo borra el código de error.
El buzón de recepción solo conserva el último paquete. Completar otro sobrescribe los datos sin leer, registra el error 6 e incrementa ErrorCount. El adaptador no espera a que la aplicación consuma el buzón.
Las pantallas se capturan con el modelo DMG-07 de KOKURA. Cada consola se ejecuta de forma independiente y se comparan los valores enviados y recibidos. No se han verificado el comportamiento eléctrico ni la temporización del adaptador y cable físicos. En CGB los números aparecen en azul.
Coloca kitaqgb, kokura y kitaq-docs bajo un mismo directorio padre y abre PowerShell allí. Los ejemplos de cuatro consolas ejecutan la misma ROM en cuatro sesiones. Para comprobar DMG, sustituye en todas partes --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
result[19]=LinkDmg07_GetErrorCount();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Deja el primer paquete válido sin leer hasta que llegue otro. Se esperan SENT SEQ=3, PACKET SEQ=2 y ERROR=6; la lectura devuelve los últimos 33/34/35/36. ClearError pone CLEAR ERROR a cero, pero ErrorCount sigue en uno.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_overflow.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_overflow.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_overflow.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_overflow.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_overflow.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_overflow.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_overflow.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_overflow.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_overflow.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_overflow.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.pngImplementación y código fuente
kitaqgb/lib/link_dmg07.h:121
Return the saturating protocol/overflow error count. Timeout and request validation paths use separate counters or latches and do not increment this value.
kitaqgb/lib/link_dmg07.c:531
u8 LinkDmg07_GetErrorCount() {
return LinkDmg07_ErrorCount;
}LinkDmg07_GetLastStatus
Lee el último byte de estado bruto validado del adaptador.
Sintaxis
u8 LinkDmg07_GetLastStatus();Valor devuelto
El nibble alto es la máscara de conexión; los tres bits bajos contienen el número local. Inicialmente cero.
Condiciones y límites
La biblioteca numera jugadores 1..4; cero significa no descubierto. Los bits 0..3 de la máscara de conexión corresponden a jugadores 1..4. Los valores slot de KOKURA --link-session son 0..3, una numeración distinta de la API ROM.
Rechaza estados con bit 3 activado, jugador cero o mayor que cuatro, o número local cambiado después del descubrimiento. Registra el error 5 sin guardar ese valor en LastStatus.
Las pantallas se capturan con el modelo DMG-07 de KOKURA. Cada consola se ejecuta de forma independiente y se comparan los valores enviados y recibidos. No se han verificado el comportamiento eléctrico ni la temporización del adaptador y cable físicos. En CGB los números aparecen en azul.
Coloca kitaqgb, kokura y kitaq-docs bajo un mismo directorio padre y abre PowerShell allí. Los ejemplos de cuatro consolas ejecutan la misma ROM en cuatro sesiones. Para comprobar DMG, sustituye en todas partes --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
result[2]=LinkDmg07_GetLastStatus();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Ejecuta la misma ROM en cuatro consolas, cada una enviando 32 más su número. Todas reciben PLAYER 1..4 = 33/34/35/36. La primera difusión válida registra SENT SEQ=2 y PACKET SEQ=1, mostrando el retraso de un paquete. La pantalla congela esa observación; un juego sigue consultando después.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.pngImplementación y código fuente
kitaqgb/lib/link_dmg07.h:67
Return the last validated raw adapter status byte.
kitaqgb/lib/link_dmg07.c:408
u8 LinkDmg07_GetLastStatus() {
return LinkDmg07_LastStatus;
}LinkDmg07_GetLocalSlot
Lee el número de jugador de esta consola obtenido del estado del adaptador.
Sintaxis
u8 LinkDmg07_GetLocalSlot();Valor devuelto
Devuelve 1..4 tras descubrir; cero antes o justo después de reiniciar el descubrimiento.
Condiciones y límites
La biblioteca numera jugadores 1..4; cero significa no descubierto. Los bits 0..3 de la máscara de conexión corresponden a jugadores 1..4. Los valores slot de KOKURA --link-session son 0..3, una numeración distinta de la API ROM.
Las pantallas se capturan con el modelo DMG-07 de KOKURA. Cada consola se ejecuta de forma independiente y se comparan los valores enviados y recibidos. No se han verificado el comportamiento eléctrico ni la temporización del adaptador y cable físicos. En CGB los números aparecen en azul.
Coloca kitaqgb, kokura y kitaq-docs bajo un mismo directorio padre y abre PowerShell allí. Los ejemplos de cuatro consolas ejecutan la misma ROM en cuatro sesiones. Para comprobar DMG, sustituye en todas partes --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
slot=LinkDmg07_GetLocalSlot();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Ejecuta la misma ROM en cuatro consolas, cada una enviando 32 más su número. Todas reciben PLAYER 1..4 = 33/34/35/36. La primera difusión válida registra SENT SEQ=2 y PACKET SEQ=1, mostrando el retraso de un paquete. La pantalla congela esa observación; un juego sigue consultando después.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.pngImplementación y código fuente
kitaqgb/lib/link_dmg07.h:62
Return the one-based player slot, or LINK_DMG07_NO_SLOT before discovery.
kitaqgb/lib/link_dmg07.c:398
u8 LinkDmg07_GetLocalSlot() {
return LinkDmg07_LocalSlot;
}LinkDmg07_GetPacketSequence
Lee la secuencia asignada al último paquete publicado.
Sintaxis
u8 LinkDmg07_GetPacketSequence();Valor devuelto
Devuelve la secuencia de paquete de ocho bits sin cambiar la disponibilidad.
Condiciones y límites
Los números de secuencia pasan de 255 a cero. Al publicar el paquete, PacketSequence es SentSequence menos uno. Inicios de transmisión posteriores avanzan SentSequence, así que lecturas posteriores de ambos valores no tienen por qué diferir en uno.
El buzón de recepción solo conserva el último paquete. Completar otro sobrescribe los datos sin leer, registra el error 6 e incrementa ErrorCount. El adaptador no espera a que la aplicación consuma el buzón.
Las pantallas se capturan con el modelo DMG-07 de KOKURA. Cada consola se ejecuta de forma independiente y se comparan los valores enviados y recibidos. No se han verificado el comportamiento eléctrico ni la temporización del adaptador y cable físicos. En CGB los números aparecen en azul.
Coloca kitaqgb, kokura y kitaq-docs bajo un mismo directorio padre y abre PowerShell allí. Los ejemplos de cuatro consolas ejecutan la misma ROM en cuatro sesiones. Para comprobar DMG, sustituye en todas partes --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
result[7]=LinkDmg07_GetPacketSequence();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Ejecuta la misma ROM en cuatro consolas, cada una enviando 32 más su número. Todas reciben PLAYER 1..4 = 33/34/35/36. La primera difusión válida registra SENT SEQ=2 y PACKET SEQ=1, mostrando el retraso de un paquete. La pantalla congela esa observación; un juego sigue consultando después.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.pngImplementación y código fuente
kitaqgb/lib/link_dmg07.h:109
Return the modulo-256 sequence associated with the most recently published packet.
kitaqgb/lib/link_dmg07.c:510
u8 LinkDmg07_GetPacketSequence() {
return LinkDmg07_PacketSequence;
}LinkDmg07_GetPacketSlot
Lee el byte de un jugador del paquete guardado.
Sintaxis
u8 __stackcall LinkDmg07_GetPacketSlot(u8 player_slot);Parámetros
player_slotNúmero de jugador físico, 1..4.
Valor devuelto
Devuelve el byte guardado del jugador 1..4 o cero para un número no válido.
Condiciones y límites
La biblioteca numera jugadores 1..4; cero significa no descubierto. Los bits 0..3 de la máscara de conexión corresponden a jugadores 1..4. Los valores slot de KOKURA --link-session son 0..3, una numeración distinta de la API ROM.
No comprueba ni consume la disponibilidad. Devuelve cero justo después de inicializar y puede devolver bytes conservados tras consumir o reiniciar descubrimiento. No lo uses para detectar datos nuevos.
Las pantallas se capturan con el modelo DMG-07 de KOKURA. Cada consola se ejecuta de forma independiente y se comparan los valores enviados y recibidos. No se han verificado el comportamiento eléctrico ni la temporización del adaptador y cable físicos. En CGB los números aparecen en azul.
Coloca kitaqgb, kokura y kitaq-docs bajo un mismo directorio padre y abre PowerShell allí. Los ejemplos de cuatro consolas ejecutan la misma ROM en cuatro sesiones. Para comprobar DMG, sustituye en todas partes --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
result[16]=LinkDmg07_GetPacketSlot(4);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Ejecuta la misma ROM en cuatro consolas, cada una enviando 32 más su número. Todas reciben PLAYER 1..4 = 33/34/35/36. La primera difusión válida registra SENT SEQ=2 y PACKET SEQ=1, mostrando el retraso de un paquete. La pantalla congela esa observación; un juego sigue consultando después.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.pngImplementación y código fuente
kitaqgb/lib/link_dmg07.h:102
Read one cached player byte using a one-based slot. Invalid slots return zero; the function neither requires readiness nor consumes the packet.
kitaqgb/lib/link_dmg07.c:499
u8 __stackcall LinkDmg07_GetPacketSlot(u8 player_slot) {
if ((player_slot == 0) || (player_slot > LINK_DMG07_MAX_PLAYERS)) return 0;
return LinkDmg07_RxPacket[(__safe_index u8)(player_slot - 1)];
}LinkDmg07_GetPhase
Lee la fase actual: descubrimiento, solicitud de inicio, confirmación o transferencia.
Sintaxis
u8 LinkDmg07_GetPhase();Valor devuelto
0=PING, 1=REQUEST_AA, 2=WAIT_CC, 3=TRANSFER.
Condiciones y límites
No consulta ni espera. Aceptar una solicitud de inicio no basta para TRANSFER: se necesitan cuatro bytes 0xCC consecutivos.
Las pantallas se capturan con el modelo DMG-07 de KOKURA. Cada consola se ejecuta de forma independiente y se comparan los valores enviados y recibidos. No se han verificado el comportamiento eléctrico ni la temporización del adaptador y cable físicos. En CGB los números aparecen en azul.
Coloca kitaqgb, kokura y kitaq-docs bajo un mismo directorio padre y abre PowerShell allí. Los ejemplos de cuatro consolas ejecutan la misma ROM en cuatro sesiones. Para comprobar DMG, sustituye en todas partes --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
result[8]=LinkDmg07_GetPhase();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Ejecuta la misma ROM en cuatro consolas, cada una enviando 32 más su número. Todas reciben PLAYER 1..4 = 33/34/35/36. La primera difusión válida registra SENT SEQ=2 y PACKET SEQ=1, mostrando el retraso de un paquete. La pantalla congela esa observación; un juego sigue consultando después.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.pngImplementación y código fuente
kitaqgb/lib/link_dmg07.h:60
Return the discovery, start-handshake or transfer phase without polling.
kitaqgb/lib/link_dmg07.c:393
u8 LinkDmg07_GetPhase() {
return LinkDmg07_Phase;
}LinkDmg07_GetRestartState
Lee si el control de reinicio está ausente, pendiente o enviándose.
Sintaxis
u8 LinkDmg07_GetRestartState();Valor devuelto
0=ninguno, 1=esperando límite, 2=enviando control.
Condiciones y límites
Es independiente de la fase de comunicación. Cero por sí solo no implica una conexión establecida o utilizable.
Las pantallas se capturan con el modelo DMG-07 de KOKURA. Cada consola se ejecuta de forma independiente y se comparan los valores enviados y recibidos. No se han verificado el comportamiento eléctrico ni la temporización del adaptador y cable físicos. En CGB los números aparecen en azul.
Coloca kitaqgb, kokura y kitaq-docs bajo un mismo directorio padre y abre PowerShell allí. Los ejemplos de cuatro consolas ejecutan la misma ROM en cuatro sesiones. Para comprobar DMG, sustituye en todas partes --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
result[4]=LinkDmg07_GetRestartState();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El jugador 2 solicita reinicio; su consola registra PENDING=1 y SENT FF=1. Las cuatro muestran DATA VALID=1, RESET PHASE=0, SLOT AFTER=0 y RESET PRIME=0. El controlador conserva el intercambio activo hasta que la indicación del adaptador lo devuelve al descubrimiento.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_restart.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_restart.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_restart.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_restart.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_restart.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_restart.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_restart.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_restart.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_restart.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_restart.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.pngImplementación y código fuente
kitaqgb/lib/link_dmg07.h:85
Return whether aligned recovery is absent, pending or sending control traffic.
kitaqgb/lib/link_dmg07.c:457
u8 LinkDmg07_GetRestartState() {
return LinkDmg07_RestartState;
}LinkDmg07_GetSentSequence
Lee el número de bytes de aplicación realmente transmitidos con el reloj.
Sintaxis
u8 LinkDmg07_GetSentSequence();Valor devuelto
Devuelve la secuencia enviada de ocho bits. Cuenta el envío inicial pero excluye el control de reinicio.
Condiciones y límites
Los números de secuencia pasan de 255 a cero. Al publicar el paquete, PacketSequence es SentSequence menos uno. Inicios de transmisión posteriores avanzan SentSequence, así que lecturas posteriores de ambos valores no tienen por qué diferir en uno.
Con SIZE=1, cada consola envía un byte; la difusión de cuatro bytes sigue el orden de jugadores 1..4. Se descarta la primera difusión. Las siguientes contienen las aportaciones del paquete anterior. Una difusión de cuatro bytes 0xFF se reserva como señal de reinicio.
Las pantallas se capturan con el modelo DMG-07 de KOKURA. Cada consola se ejecuta de forma independiente y se comparan los valores enviados y recibidos. No se han verificado el comportamiento eléctrico ni la temporización del adaptador y cable físicos. En CGB los números aparecen en azul.
Coloca kitaqgb, kokura y kitaq-docs bajo un mismo directorio padre y abre PowerShell allí. Los ejemplos de cuatro consolas ejecutan la misma ROM en cuatro sesiones. Para comprobar DMG, sustituye en todas partes --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
result[6]=LinkDmg07_GetSentSequence();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Ejecuta la misma ROM en cuatro consolas, cada una enviando 32 más su número. Todas reciben PLAYER 1..4 = 33/34/35/36. La primera difusión válida registra SENT SEQ=2 y PACKET SEQ=1, mostrando el retraso de un paquete. La pantalla congela esa observación; un juego sigue consultando después.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.pngImplementación y código fuente
kitaqgb/lib/link_dmg07.h:107
SentSequence increments when this console's packet byte is clocked out. PacketSequence labels the returned four-byte packet. For a valid packet it is one less than SentSequence, making the DMG-07 one-packet delay explicit.
kitaqgb/lib/link_dmg07.c:505
u8 LinkDmg07_GetSentSequence() {
return LinkDmg07_SentSequence;
}LinkDmg07_GetSilenceFrames
Lee los fotogramas contados desde la última finalización serie procesada.
Sintaxis
u8 LinkDmg07_GetSilenceFrames();Valor devuelto
0..255; procesar una finalización lo restablece y cada TickFrame lo incrementa.
Condiciones y límites
Llama a Poll repetidamente durante todo el fotograma y a TickFrame exactamente una vez por fotograma. Un Poll por VBlank no rearma el puerto entre bytes del adaptador. d_poll de la cabecera compartida detecta la entrada en LY >= 144 para llamar una vez a TickFrame. Serializa ambas operaciones para evitar carreras entre ISR y bucle principal.
SilenceFrames y los contadores de diagnóstico se saturan en 255. Init los restablece todos; los reinicios normales del protocolo conservan los de diagnóstico. ClearError solo borra el código de error.
Las pantallas se capturan con el modelo DMG-07 de KOKURA. Cada consola se ejecuta de forma independiente y se comparan los valores enviados y recibidos. No se han verificado el comportamiento eléctrico ni la temporización del adaptador y cable físicos. En CGB los números aparecen en azul.
Coloca kitaqgb, kokura y kitaq-docs bajo un mismo directorio padre y abre PowerShell allí. Los ejemplos de cuatro consolas ejecutan la misma ROM en cuatro sesiones. Para comprobar DMG, sustituye en todas partes --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
result[6]=LinkDmg07_GetSilenceFrames();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Ejecuta sin adaptador. Se espera PLAYER=0, START ERROR=2, SILENT FRAME=12, TIMEOUTS=1 y ERROR=4. DISCONNECTS sigue en cero porque nunca se detectó adaptador. Una lectura vacía conserva EMPTY BUFFER=77; ClearError produce CLEARED=0.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_absent.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_absent.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe .\out\dmg07_absent.gb --hardware cgb --run-frames 90 --png .\out\absent.pngImplementación y código fuente
kitaqgb/lib/link_dmg07.h:114
SilenceFrames is reset by every completed serial byte. TimeoutCount counts distinct serial-silence or AA/CC/restart handshake timeouts. DisconnectCount counts adapter-silence outages and ping-status membership drops. All saturate.
kitaqgb/lib/link_dmg07.c:515
u8 LinkDmg07_GetSilenceFrames() {
return LinkDmg07_SilenceFrames;
}LinkDmg07_GetTimeoutCount
Lee el número de plazos agotados de silencio o negociación.
Sintaxis
u8 LinkDmg07_GetTimeoutCount();Valor devuelto
Devuelve un total acumulado de 0 a 255.
Condiciones y límites
SilenceFrames y los contadores de diagnóstico se saturan en 255. Init los restablece todos; los reinicios normales del protocolo conservan los de diagnóstico. ClearError solo borra el código de error.
No cuenta el mismo silencio en cada fotograma antes de reanudar la recepción. ClearError conserva esta marca de supresión y el total.
Las pantallas se capturan con el modelo DMG-07 de KOKURA. Cada consola se ejecuta de forma independiente y se comparan los valores enviados y recibidos. No se han verificado el comportamiento eléctrico ni la temporización del adaptador y cable físicos. En CGB los números aparecen en azul.
Coloca kitaqgb, kokura y kitaq-docs bajo un mismo directorio padre y abre PowerShell allí. Los ejemplos de cuatro consolas ejecutan la misma ROM en cuatro sesiones. Para comprobar DMG, sustituye en todas partes --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
result[7]=LinkDmg07_GetTimeoutCount();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Ejecuta sin adaptador. Se espera PLAYER=0, START ERROR=2, SILENT FRAME=12, TIMEOUTS=1 y ERROR=4. DISCONNECTS sigue en cero porque nunca se detectó adaptador. Una lectura vacía conserva EMPTY BUFFER=77; ClearError produce CLEARED=0.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_absent.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_absent.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe .\out\dmg07_absent.gb --hardware cgb --run-frames 90 --png .\out\absent.pngImplementación y código fuente
kitaqgb/lib/link_dmg07.h:116
Return the saturating lifetime timeout count, preserved across protocol restarts.
kitaqgb/lib/link_dmg07.c:520
u8 LinkDmg07_GetTimeoutCount() {
return LinkDmg07_TimeoutCount;
}LinkDmg07_HasPacket
Comprueba si hay un paquete completo de cuatro bytes sin leer.
Sintaxis
u8 LinkDmg07_HasPacket();Valor devuelto
Devuelve 1 si hay datos sin leer y 0 si no.
Condiciones y límites
Con SIZE=1, cada consola envía un byte; la difusión de cuatro bytes sigue el orden de jugadores 1..4. Se descarta la primera difusión. Las siguientes contienen las aportaciones del paquete anterior. Una difusión de cuatro bytes 0xFF se reserva como señal de reinicio.
El buzón de recepción solo conserva el último paquete. Completar otro sobrescribe los datos sin leer, registra el error 6 e incrementa ErrorCount. El adaptador no espera a que la aplicación consuma el buzón.
Las pantallas se capturan con el modelo DMG-07 de KOKURA. Cada consola se ejecuta de forma independiente y se comparan los valores enviados y recibidos. No se han verificado el comportamiento eléctrico ni la temporización del adaptador y cable físicos. En CGB los números aparecen en azul.
Coloca kitaqgb, kokura y kitaq-docs bajo un mismo directorio padre y abre PowerShell allí. Los ejemplos de cuatro consolas ejecutan la misma ROM en cuatro sesiones. Para comprobar DMG, sustituye en todas partes --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
result[15]=LinkDmg07_HasPacket();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Ejecuta la misma ROM en cuatro consolas, cada una enviando 32 más su número. Todas reciben PLAYER 1..4 = 33/34/35/36. La primera difusión válida registra SENT SEQ=2 y PACKET SEQ=1, mostrando el retraso de un paquete. La pantalla congela esa observación; un juego sigue consultando después.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.pngImplementación y código fuente
kitaqgb/lib/link_dmg07.h:96
Inspect the one-packet receive mailbox without consuming it.
kitaqgb/lib/link_dmg07.c:473
u8 LinkDmg07_HasPacket() {
return LinkDmg07_PacketReady;
}LinkDmg07_HasPingStatus
Comprueba si un intercambio de descubrimiento de cuatro bytes completado espera confirmación.
Sintaxis
u8 LinkDmg07_HasPingStatus();Valor devuelto
Devuelve 1 si hay una notificación sin consumir y 0 si no.
Condiciones y límites
Solo lee un indicador. El intercambio de descubrimiento puede avanzar aunque se rechace un estado; no deduzcas solo de él datos totalmente válidos o inicio completado. Comprueba también slot, máscara y LastError.
Las pantallas se capturan con el modelo DMG-07 de KOKURA. Cada consola se ejecuta de forma independiente y se comparan los valores enviados y recibidos. No se han verificado el comportamiento eléctrico ni la temporización del adaptador y cable físicos. En CGB los números aparecen en azul.
Coloca kitaqgb, kokura y kitaq-docs bajo un mismo directorio padre y abre PowerShell allí. Los ejemplos de cuatro consolas ejecutan la misma ROM en cuatro sesiones. Para comprobar DMG, sustituye en todas partes --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
result[4]=LinkDmg07_HasPingStatus();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Ejecuta la misma ROM en cuatro consolas, cada una enviando 32 más su número. Todas reciben PLAYER 1..4 = 33/34/35/36. La primera difusión válida registra SENT SEQ=2 y PACKET SEQ=1, mostrando el retraso de un paquete. La pantalla congela esa observación; un juego sigue consultando después.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.pngImplementación y código fuente
kitaqgb/lib/link_dmg07.h:69
Read the completed-discovery status flag without clearing it.
kitaqgb/lib/link_dmg07.c:413
u8 LinkDmg07_HasPingStatus() {
return LinkDmg07_PingStatusReady;
}LinkDmg07_Init
Restablece descubrimiento, almacenamiento de recepción y diagnósticos, y prepara la recepción con el reloj del adaptador.
Sintaxis
void __stackcall LinkDmg07_Init(u8 rate);Parámetros
rateRespuesta RATE de ocho bits al adaptador; cero elige el valor predeterminado 0x10.
Valor devuelto
No devuelve ningún valor.
Condiciones y límites
Este controlador ocupa el puerto serie. No ejecutes Link normal ni Link4 a la vez; incluye link_hwregs_gb.c y link_dmg07.c una vez cada uno. El adaptador aporta el reloj externo; el controlador no selecciona el modo serie rápido de CGB.
La biblioteca numera jugadores 1..4; cero significa no descubierto. Los bits 0..3 de la máscara de conexión corresponden a jugadores 1..4. Los valores slot de KOKURA --link-session son 0..3, una numeración distinta de la API ROM.
Pone SC en 0x80 y SB en 0x88; borra solo los bits serie de IE e IF. No modifica los demás bits de habilitación ni el IME de la CPU.
Las pantallas se capturan con el modelo DMG-07 de KOKURA. Cada consola se ejecuta de forma independiente y se comparan los valores enviados y recibidos. No se han verificado el comportamiento eléctrico ni la temporización del adaptador y cable físicos. En CGB los números aparecen en azul.
Coloca kitaqgb, kokura y kitaq-docs bajo un mismo directorio padre y abre PowerShell allí. Los ejemplos de cuatro consolas ejecutan la misma ROM en cuatro sesiones. Para comprobar DMG, sustituye en todas partes --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
LinkDmg07_Init(0);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Ejecuta la misma ROM en cuatro consolas, cada una enviando 32 más su número. Todas reciben PLAYER 1..4 = 33/34/35/36. La primera difusión válida registra SENT SEQ=2 y PACKET SEQ=1, mostrando el retraso de un paquete. La pantalla congela esa observación; un juego sigue consultando después.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.pngImplementación y código fuente
kitaqgb/lib/link_dmg07.h:50
Initializes polling-only external-clock operation. A zero RATE is replaced with LINK_DMG07_DEFAULT_RATE. This driver disables only the serial IRQ bit.
kitaqgb/lib/link_dmg07.c:282
void __stackcall LinkDmg07_Init(u8 rate) {
u8 i;
LinkDmg07_Rate = rate;
if (LinkDmg07_Rate == 0) LinkDmg07_Rate = LINK_DMG07_DEFAULT_RATE;
LinkDmg07_LocalByte = 0;
LinkDmg07_SentSequence = 0;
LinkDmg07_PacketSequence = 0;
LinkDmg07_RestartState = LINK_DMG07_RESTART_NONE;
LinkDmg07_SilenceFrames = 0;
LinkDmg07_TimeoutCount = 0;
LinkDmg07_DisconnectCount = 0;
LinkDmg07_ErrorCount = 0;
LinkDmg07_LastErrorCode = LINK_DMG07_ERR_NONE;
LinkDmg07_SeenAdapter = 0;
LinkDmg07_TimeoutLatched = 0;
for (i = 0; i < LINK_DMG07_PACKET_BYTES; ++i) {
LinkDmg07_RxBuild[(__safe_index u8)i] = 0;
LinkDmg07_RxPacket[(__safe_index u8)i] = 0;
}
LinkDmg07_ResetToPingInternal();
LinkHw_WriteIE((u8)(LinkHw_ReadIE() & LINK_DMG07_IRQ_SERIAL_CLEAR));
LinkHw_WriteIF((u8)(LinkHw_ReadIF() & LINK_DMG07_IRQ_SERIAL_CLEAR));
LinkDmg07_ArmInternal(LINK_DMG07_ACK);
}LinkDmg07_IsPipelinePrimed
Comprueba si se ha descartado la difusión inicial indefinida.
Sintaxis
u8 LinkDmg07_IsPipelinePrimed();Valor devuelto
Devuelve 1 tras la difusión inicial; lo borran la inicialización, el reinicio de descubrimiento y la confirmación de inicio.
Condiciones y límites
Con SIZE=1, cada consola envía un byte; la difusión de cuatro bytes sigue el orden de jugadores 1..4. Se descarta la primera difusión. Las siguientes contienen las aportaciones del paquete anterior. Una difusión de cuatro bytes 0xFF se reserva como señal de reinicio.
Una cadena preparada no tiene por qué contener un paquete completo. Usa HasPacket para saber si se puede leer.
Las pantallas se capturan con el modelo DMG-07 de KOKURA. Cada consola se ejecuta de forma independiente y se comparan los valores enviados y recibidos. No se han verificado el comportamiento eléctrico ni la temporización del adaptador y cable físicos. En CGB los números aparecen en azul.
Coloca kitaqgb, kokura y kitaq-docs bajo un mismo directorio padre y abre PowerShell allí. Los ejemplos de cuatro consolas ejecutan la misma ROM en cuatro sesiones. Para comprobar DMG, sustituye en todas partes --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
result[9]=LinkDmg07_IsPipelinePrimed();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Ejecuta la misma ROM en cuatro consolas, cada una enviando 32 más su número. Todas reciben PLAYER 1..4 = 33/34/35/36. La primera difusión válida registra SENT SEQ=2 y PACKET SEQ=1, mostrando el retraso de un paquete. La pantalla congela esa observación; un juego sigue consultando después.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.pngImplementación y código fuente
kitaqgb/lib/link_dmg07.h:94
The first incoming adapter data packet is discarded. Thereafter ReadPacket copies four bytes in physical slot order (players 1..4).
kitaqgb/lib/link_dmg07.c:468
u8 LinkDmg07_IsPipelinePrimed() {
return LinkDmg07_PipelinePrimed;
}LinkDmg07_LastError
Lee el último código de error registrado.
Sintaxis
u8 LinkDmg07_LastError();Valor devuelto
Devuelve un código de error de 0 a 6.
Condiciones y límites
Errores: 0=ninguno, 1=fase incorrecta, 2=no es jugador 1, 3=no preparado, 4=tiempo agotado, 5=error de protocolo, 6=paquete sin leer sobrescrito. Las solicitudes tienen éxito con cero; recibir/extraer, con uno. Una solicitud correcta no borra un error anterior.
Leer no lo borra. Guarda solo el último código, no un historial de errores.
Las pantallas se capturan con el modelo DMG-07 de KOKURA. Cada consola se ejecuta de forma independiente y se comparan los valores enviados y recibidos. No se han verificado el comportamiento eléctrico ni la temporización del adaptador y cable físicos. En CGB los números aparecen en azul.
Coloca kitaqgb, kokura y kitaq-docs bajo un mismo directorio padre y abre PowerShell allí. Los ejemplos de cuatro consolas ejecutan la misma ROM en cuatro sesiones. Para comprobar DMG, sustituye en todas partes --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
result[9]=LinkDmg07_LastError();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Ejecuta sin adaptador. Se espera PLAYER=0, START ERROR=2, SILENT FRAME=12, TIMEOUTS=1 y ERROR=4. DISCONNECTS sigue en cero porque nunca se detectó adaptador. Una lectura vacía conserva EMPTY BUFFER=77; ClearError produce CLEARED=0.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_absent.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_absent.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe .\out\dmg07_absent.gb --hardware cgb --run-frames 90 --png .\out\absent.pngImplementación y código fuente
kitaqgb/lib/link_dmg07.h:123
Return the latest error latch without clearing counters or restarting the protocol.
kitaqgb/lib/link_dmg07.c:536
u8 LinkDmg07_LastError() {
return LinkDmg07_LastErrorCode;
}LinkDmg07_Poll
Procesa un byte serie completado en la fase actual y prepara de inmediato la siguiente respuesta.
Sintaxis
void LinkDmg07_Poll();Valor devuelto
No devuelve ningún valor.
Condiciones y límites
Este controlador ocupa el puerto serie. No ejecutes Link normal ni Link4 a la vez; incluye link_hwregs_gb.c y link_dmg07.c una vez cada uno. El adaptador aporta el reloj externo; el controlador no selecciona el modo serie rápido de CGB.
Llama a Poll repetidamente durante todo el fotograma y a TickFrame exactamente una vez por fotograma. Un Poll por VBlank no rearma el puerto entre bytes del adaptador. d_poll de la cabecera compartida detecta la entrada en LY >= 144 para llamar una vez a TickFrame. Serializa ambas operaciones para evitar carreras entre ISR y bucle principal.
No hace nada mientras esté activo el bit de inicio de SC. Procesar una finalización restablece SilenceFrames y el indicador retenido de timeout. Inicializa antes de consultar.
Las pantallas se capturan con el modelo DMG-07 de KOKURA. Cada consola se ejecuta de forma independiente y se comparan los valores enviados y recibidos. No se han verificado el comportamiento eléctrico ni la temporización del adaptador y cable físicos. En CGB los números aparecen en azul.
Coloca kitaqgb, kokura y kitaq-docs bajo un mismo directorio padre y abre PowerShell allí. Los ejemplos de cuatro consolas ejecutan la misma ROM en cuatro sesiones. Para comprobar DMG, sustituye en todas partes --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
void d_poll(){LinkDmg07_Poll();if(D_LY>=144){if(d_vblank==0){d_vblank=1;LinkDmg07_TickFrame();}}else d_vblank=0;}Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Ejecuta la misma ROM en cuatro consolas, cada una enviando 32 más su número. Todas reciben PLAYER 1..4 = 33/34/35/36. La primera difusión válida registra SENT SEQ=2 y PACKET SEQ=1, mostrando el retraso de un paquete. La pantalla congela esa observación; un juego sigue consultando después.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.pngImplementación y código fuente
kitaqgb/lib/link_dmg07.h:54
Services at most one completed serial byte and immediately re-arms SC=$80. Call continuously from the main loop, including between VBlanks.
kitaqgb/lib/link_dmg07.c:311
void LinkDmg07_Poll() {
u8 value;
u8 next;
if ((LinkHw_ReadSC() & LINK_DMG07_SC_EXTERNAL_START) != 0) return;
value = LinkHw_ReadSB();
LinkDmg07_SilenceFrames = 0;
LinkDmg07_TimeoutLatched = 0;
LinkDmg07_SeenAdapter = 1;
next = 0;
if (LinkDmg07_Phase == LINK_DMG07_PHASE_PING) {
next = LinkDmg07_ProcessPingInternal(value);
} else if (LinkDmg07_Phase == LINK_DMG07_PHASE_REQUEST_AA) {
next = LinkDmg07_ProcessRequestInternal(value);
} else if (LinkDmg07_Phase == LINK_DMG07_PHASE_WAIT_CC) {
next = LinkDmg07_ProcessWaitCcInternal(value);
} else if (LinkDmg07_Phase == LINK_DMG07_PHASE_TRANSFER) {
next = LinkDmg07_ProcessTransferInternal(value);
} else {
LinkDmg07_SetRuntimeErrorInternal(LINK_DMG07_ERR_PROTOCOL);
LinkDmg07_ResetToPingInternal();
next = LINK_DMG07_ACK;
}
LinkDmg07_ArmInternal(next);
}LinkDmg07_ReadPacket
Copia el último paquete completo y borra su indicador de no leído.
Sintaxis
u8 __stackcall LinkDmg07_ReadPacket(u8 *dst);Parámetros
dstCuatro bytes escribibles; null descarta el paquete.
Valor devuelto
Devuelve 1 si se consume y 0 si está vacío. Una lectura vacía no cambia dst.
Condiciones y límites
Con SIZE=1, cada consola envía un byte; la difusión de cuatro bytes sigue el orden de jugadores 1..4. Se descarta la primera difusión. Las siguientes contienen las aportaciones del paquete anterior. Una difusión de cuatro bytes 0xFF se reserva como señal de reinicio.
El buzón de recepción solo conserva el último paquete. Completar otro sobrescribe los datos sin leer, registra el error 6 e incrementa ErrorCount. El adaptador no espera a que la aplicación consuma el buzón.
Los bytes guardados siguen disponibles mediante GetPacketSlot después de consumir. Un ReadPacket vacío no vuelve a copiarlos.
Las pantallas se capturan con el modelo DMG-07 de KOKURA. Cada consola se ejecuta de forma independiente y se comparan los valores enviados y recibidos. No se han verificado el comportamiento eléctrico ni la temporización del adaptador y cable físicos. En CGB los números aparecen en azul.
Coloca kitaqgb, kokura y kitaq-docs bajo un mismo directorio padre y abre PowerShell allí. Los ejemplos de cuatro consolas ejecutan la misma ROM en cuatro sesiones. Para comprobar DMG, sustituye en todas partes --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
result[10]=LinkDmg07_ReadPacket(packet);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Ejecuta la misma ROM en cuatro consolas, cada una enviando 32 más su número. Todas reciben PLAYER 1..4 = 33/34/35/36. La primera difusión válida registra SENT SEQ=2 y PACKET SEQ=1, mostrando el retraso de un paquete. La pantalla congela esa observación; un juego sigue consultando después.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.pngImplementación y código fuente
kitaqgb/lib/link_dmg07.h:99
Consume the latest four-byte packet. A nonnull destination must hold four bytes; null discards the packet. Packet storage remains after the flag clears.
kitaqgb/lib/link_dmg07.c:479
u8 __stackcall LinkDmg07_ReadPacket(u8 *dst) {
if (LinkDmg07_PacketReady == 0) return 0;
if (dst != 0) {
// Keep this as a sequential pointer copy. Besides being smaller for a
// fixed four-byte packet, it avoids making a serial hot-path copy
// depend on general variable-index pointer lowering.
*dst = LinkDmg07_RxPacket[0];
dst++;
*dst = LinkDmg07_RxPacket[1];
dst++;
*dst = LinkDmg07_RxPacket[2];
dst++;
*dst = LinkDmg07_RxPacket[3];
}
LinkDmg07_PacketReady = 0;
return 1;
}LinkDmg07_RequestRestart
Programa tráfico de control de reinicio a partir de un límite de paquete de transferencia.
Sintaxis
u8 LinkDmg07_RequestRestart();Valor devuelto
Devuelve 0 en TRANSFER y 1 fuera de esa fase. Las solicitudes repetidas mientras está pendiente/enviando también dan 0.
Condiciones y límites
Con SIZE=1, cada consola envía un byte; la difusión de cuatro bytes sigue el orden de jugadores 1..4. Se descarta la primera difusión. Las siguientes contienen las aportaciones del paquete anterior. Una difusión de cuatro bytes 0xFF se reserva como señal de reinicio.
Errores: 0=ninguno, 1=fase incorrecta, 2=no es jugador 1, 3=no preparado, 4=tiempo agotado, 5=error de protocolo, 6=paquete sin leer sobrescrito. Las solicitudes tienen éxito con cero; recibir/extraer, con uno. Una solicitud correcta no borra un error anterior.
Puede solicitarlo cualquier jugador. Conserva la posición de byte, envía tráfico 0xFF alineado y vuelve al descubrimiento tras la indicación de todos 0xFF del adaptador. Solicitarlo no borra el slot local ni la cadena de recepción.
Las pantallas se capturan con el modelo DMG-07 de KOKURA. Cada consola se ejecuta de forma independiente y se comparan los valores enviados y recibidos. No se han verificado el comportamiento eléctrico ni la temporización del adaptador y cable físicos. En CGB los números aparecen en azul.
Coloca kitaqgb, kokura y kitaq-docs bajo un mismo directorio padre y abre PowerShell allí. Los ejemplos de cuatro consolas ejecutan la misma ROM en cuatro sesiones. Para comprobar DMG, sustituye en todas partes --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
result[3]=LinkDmg07_RequestRestart();result[4]=LinkDmg07_GetRestartState();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El jugador 2 solicita reinicio; su consola registra PENDING=1 y SENT FF=1. Las cuatro muestran DATA VALID=1, RESET PHASE=0, SLOT AFTER=0 y RESET PRIME=0. El controlador conserva el intercambio activo hasta que la indicación del adaptador lo devuelve al descubrimiento.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_restart.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_restart.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_restart.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_restart.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_restart.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_restart.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_restart.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_restart.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_restart.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_restart.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.pngImplementación y código fuente
kitaqgb/lib/link_dmg07.h:83
Any physical slot may schedule FF FF FF FF at the next four-byte packet boundary while remaining in TRANSFER phase. The driver keeps sending aligned FF bytes until it sees the adapter's complete all-FF indicator packet, then returns to PING. A transfer-phase silence timeout schedules the same recovery automatically and preserves the current byte position for clocks that resume.
kitaqgb/lib/link_dmg07.c:445
u8 LinkDmg07_RequestRestart() {
if (LinkDmg07_Phase != LINK_DMG07_PHASE_TRANSFER) {
LinkDmg07_LastErrorCode = LINK_DMG07_ERR_STATE;
return LINK_DMG07_ERR_STATE;
}
if (LinkDmg07_RestartState == LINK_DMG07_RESTART_NONE) {
LinkDmg07_RestartState = LINK_DMG07_RESTART_PENDING;
}
return LINK_DMG07_ERR_NONE;
}LinkDmg07_RequestTransmission
Programa la solicitud de inicio del jugador físico 1 en el siguiente límite de paquete de descubrimiento.
Sintaxis
u8 LinkDmg07_RequestTransmission();Valor devuelto
Devuelve 0 si se programa, 1 por fase incorrecta, 2 si no es jugador 1 o 3 si falta el bit de conexión local.
Condiciones y límites
La biblioteca numera jugadores 1..4; cero significa no descubierto. Los bits 0..3 de la máscara de conexión corresponden a jugadores 1..4. Los valores slot de KOKURA --link-session son 0..3, una numeración distinta de la API ROM.
Errores: 0=ninguno, 1=fase incorrecta, 2=no es jugador 1, 3=no preparado, 4=tiempo agotado, 5=error de protocolo, 6=paquete sin leer sobrescrito. Las solicitudes tienen éxito con cero; recibir/extraer, con uno. Una solicitud correcta no borra un error anterior.
Solo se puede programar en PING. No espera por sí mismo a los cuatro jugadores; el ejemplo comprueba la máscara 15 en la aplicación. La programación es asíncrona: el tráfico 0xAA alineado precede a la confirmación 0xCC.
Las pantallas se capturan con el modelo DMG-07 de KOKURA. Cada consola se ejecuta de forma independiente y se comparan los valores enviados y recibidos. No se han verificado el comportamiento eléctrico ni la temporización del adaptador y cable físicos. En CGB los números aparecen en azul.
Coloca kitaqgb, kokura y kitaq-docs bajo un mismo directorio padre y abre PowerShell allí. Los ejemplos de cuatro consolas ejecutan la misma ROM en cuatro sesiones. Para comprobar DMG, sustituye en todas partes --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
result[5]=LinkDmg07_RequestTransmission();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Ejecuta la misma ROM en cuatro consolas, cada una enviando 32 más su número. Todas reciben PLAYER 1..4 = 33/34/35/36. La primera difusión válida registra SENT SEQ=2 y PACKET SEQ=1, mostrando el retraso de un paquete. La pantalla congela esa observación; un juego sigue consultando después.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.pngImplementación y código fuente
kitaqgb/lib/link_dmg07.h:76
Only physical player 1 may request AA AA AA AA. The bytes are aligned to the next FE/status/status/status ping packet. All consoles enter transfer mode only after receiving four consecutive CC bytes.
kitaqgb/lib/link_dmg07.c:426
u8 LinkDmg07_RequestTransmission() {
if (LinkDmg07_Phase != LINK_DMG07_PHASE_PING) {
LinkDmg07_LastErrorCode = LINK_DMG07_ERR_STATE;
return LINK_DMG07_ERR_STATE;
}
if (LinkDmg07_LocalSlot != 1) {
LinkDmg07_LastErrorCode = LINK_DMG07_ERR_NOT_PLAYER1;
return LINK_DMG07_ERR_NOT_PLAYER1;
}
if ((LinkDmg07_ConnectedMask & (u8)0x01) == 0) {
LinkDmg07_LastErrorCode = LINK_DMG07_ERR_NOT_READY;
return LINK_DMG07_ERR_NOT_READY;
}
LinkDmg07_StartRequested = 1;
return LINK_DMG07_ERR_NONE;
}LinkDmg07_SetLocalByte
Establece el valor de aplicación de un byte para un próximo paquete saliente.
Sintaxis
void __stackcall LinkDmg07_SetLocalByte(u8 value);Parámetros
valueValor de aplicación de ocho bits que se enviará.
Valor devuelto
No devuelve ningún valor.
Condiciones y límites
Con SIZE=1, cada consola envía un byte; la difusión de cuatro bytes sigue el orden de jugadores 1..4. Se descarta la primera difusión. Las siguientes contienen las aportaciones del paquete anterior. Una difusión de cuatro bytes 0xFF se reserva como señal de reinicio.
Se toma al preparar el byte cero del paquete. No modifica un byte SB ya preparado. Establece el primer valor antes de solicitar el inicio.
Las pantallas se capturan con el modelo DMG-07 de KOKURA. Cada consola se ejecuta de forma independiente y se comparan los valores enviados y recibidos. No se han verificado el comportamiento eléctrico ni la temporización del adaptador y cable físicos. En CGB los números aparecen en azul.
Coloca kitaqgb, kokura y kitaq-docs bajo un mismo directorio padre y abre PowerShell allí. Los ejemplos de cuatro consolas ejecutan la misma ROM en cuatro sesiones. Para comprobar DMG, sustituye en todas partes --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
LinkDmg07_SetLocalByte(32+slot);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Ejecuta la misma ROM en cuatro consolas, cada una enviando 32 más su número. Todas reciben PLAYER 1..4 = 33/34/35/36. La primera difusión válida registra SENT SEQ=2 y PACKET SEQ=1, mostrando el retraso de un paquete. La pantalla congela esa observación; un juego sigue consultando después.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.pngImplementación y código fuente
kitaqgb/lib/link_dmg07.h:90
Sets the byte sampled when byte 0 of the next adapter packet is armed. Set it before the current packet completes (and before requesting start for the first submission). During normal transfer, bytes 1..3 are sent as zero.
kitaqgb/lib/link_dmg07.c:463
void __stackcall LinkDmg07_SetLocalByte(u8 value) {
LinkDmg07_LocalByte = value;
}LinkDmg07_TickFrame
Avanza un fotograma las vigilancias de silencio e inicio/reinicio y solicita recuperación al alcanzar el plazo.
Sintaxis
void LinkDmg07_TickFrame();Valor devuelto
No devuelve ningún valor.
Condiciones y límites
Llama a Poll repetidamente durante todo el fotograma y a TickFrame exactamente una vez por fotograma. Un Poll por VBlank no rearma el puerto entre bytes del adaptador. d_poll de la cabecera compartida detecta la entrada en LY >= 144 para llamar una vez a TickFrame. Serializa ambas operaciones para evitar carreras entre ISR y bucle principal.
SilenceFrames y los contadores de diagnóstico se saturan en 255. Init los restablece todos; los reinicios normales del protocolo conservan los de diagnóstico. ClearError solo borra el código de error.
El plazo predeterminado es de 12 llamadas; define LINK_DMG07_TIMEOUT_FRAMES entre 1 y 255 antes de incluir para cambiarlo. Cada episodio de silencio se cuenta una vez hasta que otro byte borra su marca. Recuperar una transferencia conserva la alineación de bytes; recuperar descubrimiento/inicio vuelve al descubrimiento.
Las pantallas se capturan con el modelo DMG-07 de KOKURA. Cada consola se ejecuta de forma independiente y se comparan los valores enviados y recibidos. No se han verificado el comportamiento eléctrico ni la temporización del adaptador y cable físicos. En CGB los números aparecen en azul.
Coloca kitaqgb, kokura y kitaq-docs bajo un mismo directorio padre y abre PowerShell allí. Los ejemplos de cuatro consolas ejecutan la misma ROM en cuatro sesiones. Para comprobar DMG, sustituye en todas partes --cgb=cgb por --cgb=dmg y --hardware cgb por --hardware dmg.
Ejemplo de uso
void d_poll(){LinkDmg07_Poll();if(D_LY>=144){if(d_vblank==0){d_vblank=1;LinkDmg07_TickFrame();}}else d_vblank=0;}Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Ejecuta sin adaptador. Se espera PLAYER=0, START ERROR=2, SILENT FRAME=12, TIMEOUTS=1 y ERROR=4. DISCONNECTS sigue en cero porque nunca se detectó adaptador. Una lectura vacía conserva EMPTY BUFFER=77; ClearError produce CLEARED=0.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_absent.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_absent.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe .\out\dmg07_absent.gb --hardware cgb --run-frames 90 --png .\out\absent.pngImplementación y código fuente
kitaqgb/lib/link_dmg07.h:57
Advances saturating frame-based silence and handshake timeout counters.
kitaqgb/lib/link_dmg07.c:369
void LinkDmg07_TickFrame() {
LinkDmg07_SilenceFrames = LinkDmg07_IncrementSaturatingInternal(LinkDmg07_SilenceFrames);
if ((LinkDmg07_Phase == LINK_DMG07_PHASE_REQUEST_AA) ||
(LinkDmg07_Phase == LINK_DMG07_PHASE_WAIT_CC) ||
(LinkDmg07_RestartState == LINK_DMG07_RESTART_SENDING)) {
LinkDmg07_HandshakeFrames = LinkDmg07_IncrementSaturatingInternal(LinkDmg07_HandshakeFrames);
} else {
LinkDmg07_HandshakeFrames = 0;
}
if ((LinkDmg07_SilenceFrames >= LINK_DMG07_TIMEOUT_FRAMES) &&
(LinkDmg07_TimeoutLatched == 0)) {
LinkDmg07_TimeoutInternal(1);
return;
}
if ((LinkDmg07_HandshakeFrames >= LINK_DMG07_TIMEOUT_FRAMES) &&
(LinkDmg07_TimeoutLatched == 0)) {
LinkDmg07_TimeoutInternal(0);
}
}physics2d.h — Movimiento y colisiones en 2D
Proporciona integración de cajas, contactos AABB y un solucionador opcional de respuesta a superficies. Los cuerpos usan centros y semiextensiones; active=0 excluye una posición del array e inv_mass_q8<=0 la hace estática. KQRect usa la esquina superior izquierda y ancho/alto. Los contactos entre cajas no usan el campo restitution del cuerpo; las respuestas a superficies usan los coeficientes de KQSurface2D.
Usa unidades enteras coherentes para posiciones, radios, semiextensiones, velocidades y gravedad. Cada paso equivale a un tick de simulación. Los ejemplos usan una unidad por píxel. Estas rutinas no convierten automáticamente las posiciones a Q8.8 ni las dibujan.
El mundo utiliza un array prestado. El código que llama reserva y posee la memoria de los cuerpos y debe mantenerla válida. Inicializar el mundo no inicializa los elementos del array.
kq2d_body_apply_friction
Escala ambas componentes de velocidad por un coeficiente de un byte con signo dividido entre 256, sin comprobar la posición ni la actividad.
Sintaxis
void kq2d_body_apply_friction(KQBody2D* body, u8 friction_q8);Parámetros
bodyPuntero al cuerpo que se va a modificar. Los campos que no usa esta operación se conservan.
friction_q8Multiplicador de velocidad que utiliza esta función. Se convierte a s8, por lo que los valores 128..255 se vuelven coeficientes negativos.
Valor devuelto
Sin valor de retorno. Esta entrada describe qué campos se actualizan y cuándo surten efecto los cambios.
Condiciones y límites
Los valores 0..127 dan multiplicadores de 0 a 127/256. Los valores 128..255 se vuelven negativos al convertirlos a s8 e invierten la velocidad. Para aplicar amortiguamiento no negativo en todo el rango 0..255, usa kq2d_scale_q8 en cada componente. Los productos se truncan hacia cero. Ignora NULL.
Ejemplo de uso
kq2d_body_apply_friction(&temp,64);
result[11]=temp.vx; result[12]=temp.vy;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La izquierda muestra el estado inicial; la derecha, un tick después. Una caja roja de 16x16 con centro (24,24) y velocidad (4,16) llega a (28,36), con velocidad Y nula sobre el suelo azul. Los orígenes de los paneles están en las coordenadas de pantalla (8,48) y (88,48). En DMG, todas las marcas son negras. Las comprobaciones de RAM también cubren la inicialización, las funciones de ajuste, la integración, las consultas de rectángulos y puntos y el escalado con signo.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body2d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body2d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/physics2d.h:66
Scale both velocities through the signed 8-bit coefficient intrinsic. Despite the unsigned parameter, values 128..255 become negative coefficients; this is not a full-range unsigned Q8 damping helper. Null is ignored.
kitaqgb/lib/physics2d.c:654
void kq2d_body_apply_friction(KQBody2D* body, u8 friction_q8)
{
if (body == 0) return;
body->vx = (s16)__smul16x8(body->vx, (s8)friction_q8);
body->vy = (s16)__smul16x8(body->vy, (s8)friction_q8);
}kq2d_body_apply_gravity
Añade gravedad a un cuerpo dinámico activo y limita cada eje a +/-max_speed sin actualizar la posición.
Sintaxis
void kq2d_body_apply_gravity(KQBody2D* body, s16 gravity_x, s16 gravity_y, s16 max_speed);Parámetros
bodyPuntero al cuerpo que se va a modificar. Los campos que no usa esta operación se conservan.
gravity_xAceleración que esta llamada suma a la velocidad X.
gravity_yAceleración que esta llamada suma a la velocidad Y.
max_speedLímite de velocidad. La entrada indica si se aplica a cada eje o al vector conjunto.
Valor devuelto
Sin valor de retorno. Esta entrada describe qué campos se actualizan y cuándo surten efecto los cambios.
Condiciones y límites
Usa unidades enteras coherentes para posiciones, radios, semiextensiones, velocidades y gravedad. Cada paso equivale a un tick de simulación. Los ejemplos usan una unidad por píxel. Estas rutinas no convierten automáticamente las posiciones a Q8.8 ni las dibujan.
Mantén las sumas, diferencias, sumas de semiextensiones y productos de corrección de contactos dentro del rango de 16 bits con signo. Los límites de velocidad se aplican después de sumar y no pueden evitar un desbordamiento durante esa suma.
Las rutinas de integración y colisión de cajas comparten memoria temporal. No vuelvas a entrar en estas rutinas de física desde una interrupción.
Ignora NULL, los cuerpos inactivos y los de masa inversa no positiva. Proporciona un límite de velocidad no negativo.
Ejemplo de uso
kq2d_body_apply_gravity(&temp,5,-10,32);
result[9]=temp.vx; result[10]=temp.vy;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La izquierda muestra el estado inicial; la derecha, un tick después. Una caja roja de 16x16 con centro (24,24) y velocidad (4,16) llega a (28,36), con velocidad Y nula sobre el suelo azul. Los orígenes de los paneles están en las coordenadas de pantalla (8,48) y (88,48). En DMG, todas las marcas son negras. Las comprobaciones de RAM también cubren la inicialización, las funciones de ajuste, la integración, las consultas de rectángulos y puntos y el escalado con signo.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body2d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body2d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/physics2d.h:62
Add gravity and clamp each velocity axis separately for an active dynamic body. Null, inactive and static bodies are ignored. Supply a nonnegative limit and avoid overflow in the additions before clamping; position is unchanged.
kitaqgb/lib/physics2d.c:630
void kq2d_body_apply_gravity(KQBody2D* body, s16 gravity_x, s16 gravity_y, s16 max_speed)
{
if (body == 0) return;
if (body->active == 0) return;
if (body->inv_mass_q8 <= 0) return;
kq2d_asm_value = body->vx;
kq2d_asm_operand = gravity_x;
kq2d_add_s16_asm();
kq2d_asm_limit = max_speed;
kq2d_clamp_abs_s16_asm();
body->vx = kq2d_asm_value;
kq2d_asm_value = body->vy;
kq2d_asm_operand = gravity_y;
kq2d_add_s16_asm();
kq2d_asm_limit = max_speed;
kq2d_clamp_abs_s16_asm();
body->vy = kq2d_asm_value;
}kq2d_body_init
Inicializa una caja definida por su centro con las semiextensiones indicadas, velocidad cero, masa inversa 256 y estado activo.
Sintaxis
void kq2d_body_init(KQBody2D* body, s16 x, s16 y, s16 half_x, s16 half_y);Parámetros
bodyPuntero al cuerpo que se va a modificar. Los campos que no usa esta operación se conservan.
xCoordenada X del centro o del punto, en píxeles en el ejemplo.
yCoordenada Y del centro o del punto; en el ejemplo, el sentido positivo es hacia abajo.
half_xSemiextensión en X; el ancho total de la caja es el doble de este valor.
half_ySemiextensión en Y; la altura total de la caja es el doble de este valor.
Valor devuelto
Sin valor de retorno. Esta entrada describe qué campos se actualizan y cuándo surten efecto los cambios.
Condiciones y límites
Usa unidades enteras coherentes para posiciones, radios, semiextensiones, velocidades y gravedad. Cada paso equivale a un tick de simulación. Los ejemplos usan una unidad por píxel. Estas rutinas no convierten automáticamente las posiciones a Q8.8 ni las dibujan.
Establece restitution_q8 en cero. Ignora un cuerpo NULL. Proporciona semiextensiones positivas.
Ejemplo de uso
kq2d_body_init(&temp,10,20,8,8);
result[3]=temp.inv_mass_q8; result[4]=temp.active;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La izquierda muestra el estado inicial; la derecha, un tick después. Una caja roja de 16x16 con centro (24,24) y velocidad (4,16) llega a (28,36), con velocidad Y nula sobre el suelo azul. Los orígenes de los paneles están en las coordenadas de pantalla (8,48) y (88,48). En DMG, todas las marcas son negras. Las comprobaciones de RAM también cubren la inicialización, las funciones de ajuste, la integración, las consultas de rectángulos y puntos y el escalado con signo.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body2d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body2d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/physics2d.h:54
Initialize an active unit-inverse-mass body at the supplied center and half extents, with zero velocity and reserved restitution set to zero. Null is ignored.
kitaqgb/lib/physics2d.c:597
void kq2d_body_init(KQBody2D* body, s16 x, s16 y, s16 half_x, s16 half_y)
{
if (body == 0) return;
body->x = x;
body->y = y;
body->vx = 0;
body->vy = 0;
body->half_x = half_x;
body->half_y = half_y;
body->inv_mass_q8 = 256;
body->restitution_q8 = 0;
body->active = 1;
}kq2d_body_limit_speed
Consulte los cambios y la verificación del 2026-10-03 para las diferencias locales de esta API.
Estima de forma conservadora la longitud del vector y escala ambos ejes conjuntamente para limitar la rapidez total.
Sintaxis
void kq2d_body_limit_speed(KQBody2D* body, s16 max_speed);Parámetros
bodyPuntero al cuerpo que se va a modificar. Los campos que no usa esta operación se conservan.
max_speedLímite de velocidad. La entrada indica si se aplica a cada eje o al vector conjunto.
Valor devuelto
Sin valor de retorno. Esta entrada describe qué campos se actualizan y cuándo surten efecto los cambios.
Condiciones y límites
Mantén los valores absolutos de las componentes de velocidad y un max_speed positivo en 16383 como máximo. Un límite no positivo pone la velocidad a cero. Ignora NULL, pero la actividad y la masa no impiden la modificación. La cuantización entera puede dejar el resultado por debajo del límite y los factores muy pequeños pueden producir cero.
Ejemplo de uso
kq2d_body_limit_speed(&body,250);
result[2]=body.vx; result[3]=body.vy;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El cuerpo rojo permanece en su sitio. Su línea verde de velocidad cambia de (8,16) a la izquierda a (2,-8) a la derecha, mostrando el rebote y la fricción tangencial contra la superficie azul. Los orígenes de los paneles están en (8,48)/(88,48) de la pantalla; el centro del cuerpo está en (24,40) dentro del panel. La rapidez de entrada es 16 y el ejemplo del instante de cruce devuelve 192/256. El ejemplo del límite de rapidez reduce (300,400) a (147,196). En DMG, todas las marcas son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_surface.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_surface.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/physics2d.h:92
Conservative circular bound, with a shared Q8 scale for both components. Quantizes toward zero; very small limits relative to input may yield zero. Components and positive max_speed must be <= 16383 in magnitude.
kitaqgb/lib/physics2d.c:260
void kq2d_body_limit_speed(KQBody2D* body, s16 max_speed)
{
u16 x;
u16 y;
u16 swap;
u16 ratio;
u16 length;
if (body == 0) return;
if (max_speed <= 0) { body->vx = 0; body->vy = 0; return; }
x = (u16)body->vx;
y = (u16)body->vy;
if (body->vx < 0) x = (u16)(0 - body->vx);
if (body->vy < 0) y = (u16)(0 - body->vy);
if (x + y <= (u16)max_speed) return;
if (x < y) { swap = x; x = y; y = swap; }
// major + minor/2 bounds hypot from above for 0 <= minor <= major.
if (x + (y >> 1) + 1 <= (u16)max_speed) return;
// Round the minor/major ratio upward for the 65-entry upper-bound table.
// The extra unit covers truncation when converting the estimate back to speed.
ratio = (kq2d__fraction_q8(y, x) + 4) >> 2;
if (ratio > 64) ratio = 64;
length = x + (u16)kq2d_scale_q8((s16)x, (s16)kq2d_hypot_extra[(__safe_index u8)ratio]) + 1;
if (length <= (u16)max_speed) return;
ratio = kq2d__fraction_q8((u16)max_speed, length);
body->vx = kq2d_scale_q8(body->vx, (s16)ratio);
body->vy = kq2d_scale_q8(body->vy, (s16)ratio);
}kq2d_body_resolve_surface
Consulte los cambios y la verificación del 2026-10-03 para las diferencias locales de esta API.
Usa la velocidad relativa a una superficie móvil para aplicar rebote normal, rapidez mínima de rebote y fricción tangencial.
Sintaxis
s16 kq2d_body_resolve_surface(KQBody2D* body, const KQSurface2D* surface);Parámetros
bodyPuntero al cuerpo que se va a modificar. Los campos que no usa esta operación se conservan.
surfacePuntero a una KQSurface2D que contiene su normal, velocidad y ajustes de rebote y fricción.
Valor devuelto
Devuelve la rapidez normal de entrada como valor positivo, o 0 si hay entradas NULL o movimiento de separación.
Condiciones y límites
Usa una normal unitaria Q8 de longitud 256. Mantén las componentes relativas en +/-8191, threshold/kick no negativos y los coeficientes en 0..255. La restitución solo se aplica si se supera estrictamente el umbral; kick fija la rapidez mínima de rebote. Las entradas NULL o el movimiento de separación dejan la velocidad intacta. La detección del contacto y la corrección de penetración se hacen aparte; no se comprueban la actividad ni la masa.
Ejemplo de uso
result[6]=kq2d_body_resolve_surface(&body,&surface);
result[7]=body.vx; result[8]=body.vy; result[9]=body.y;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El cuerpo rojo permanece en su sitio. Su línea verde de velocidad cambia de (8,16) a la izquierda a (2,-8) a la derecha, mostrando el rebote y la fricción tangencial contra la superficie azul. Los orígenes de los paneles están en (8,48)/(88,48) de la pantalla; el centro del cuerpo está en (24,40) dentro del panel. La rapidez de entrada es 16 y el ejemplo del instante de cruce devuelve 192/256. El ejemplo del límite de rapidez reduce (300,400) a (147,196). En DMG, todas las marcas son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_surface.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_surface.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/physics2d.h:95
Kinematic surface response; returns incoming normal speed, or zero if separating. Caller resolves penetration separately. Relative components must fit +/-8191.
kitaqgb/lib/physics2d.c:314
s16 kq2d_body_resolve_surface(KQBody2D* body, const KQSurface2D* surface)
{
s16 vx;
s16 vy;
s16 speed;
s16 tangent;
s16 bounce = 0;
s16 impulse;
s16 friction;
if (body == 0 || surface == 0) return 0;
vx = (s16)(body->vx - surface->vx);
vy = (s16)(body->vy - surface->vy);
speed = (s16)(kq2d_scale_q8(vx,surface->nx_q8) + kq2d_scale_q8(vy,surface->ny_q8));
if (speed >= 0) return 0;
speed = (s16)(0 - speed);
if (speed > surface->bounce_threshold) bounce = kq2d_scale_q8(speed,(s16)surface->restitution_q8);
if (bounce < surface->kick) bounce = surface->kick;
impulse = (s16)(speed + bounce);
// A resting contact is a tangent constraint, not a tiny rounded bounce.
if (bounce == 0) {
tangent = (s16)(kq2d__rest_component(vy,surface->nx_q8) - kq2d__rest_component(vx,surface->ny_q8));
friction = kq2d_scale_q8(impulse,(s16)surface->friction_q8);
if (tangent > friction) tangent = (s16)(tangent - friction);
else if (tangent < (s16)(0 - friction)) tangent = (s16)(tangent + friction);
else tangent = 0;
body->vx = (s16)(surface->vx - kq2d__rest_component(tangent,surface->ny_q8));
body->vy = (s16)(surface->vy + kq2d__rest_component(tangent,surface->nx_q8));
return speed;
}
body->vx = (s16)(body->vx + kq2d_scale_q8(impulse,surface->nx_q8));
body->vy = (s16)(body->vy + kq2d_scale_q8(impulse,surface->ny_q8));
if (surface->friction_q8 != 0) {
tangent = (s16)(kq2d_scale_q8(vy,surface->nx_q8) - kq2d_scale_q8(vx,surface->ny_q8));
friction = kq2d_scale_q8(impulse,(s16)surface->friction_q8);
if (tangent > friction) tangent = friction;
if (tangent < (s16)(0 - friction)) tangent = (s16)(0 - friction);
body->vx = (s16)(body->vx + kq2d_scale_q8(tangent,surface->ny_q8));
body->vy = (s16)(body->vy - kq2d_scale_q8(tangent,surface->nx_q8));
}
return speed;
}kq2d_body_set_pos
Sustituye solo el centro del cuerpo y conserva la velocidad, las dimensiones y el estado de actividad.
Sintaxis
void kq2d_body_set_pos(KQBody2D* body, s16 x, s16 y);Parámetros
bodyPuntero al cuerpo que se va a modificar. Los campos que no usa esta operación se conservan.
xCoordenada X del centro o del punto, en píxeles en el ejemplo.
yCoordenada Y del centro o del punto; en el ejemplo, el sentido positivo es hacia abajo.
Valor devuelto
Sin valor de retorno. Esta entrada describe qué campos se actualizan y cuándo surten efecto los cambios.
Condiciones y límites
Usa unidades enteras coherentes para posiciones, radios, semiextensiones, velocidades y gravedad. Cada paso equivale a un tick de simulación. Los ejemplos usan una unidad por píxel. Estas rutinas no convierten automáticamente las posiciones a Q8.8 ni las dibujan.
Ignora NULL. Si el puntero es válido, también modifica los cuerpos inactivos y estáticos.
Ejemplo de uso
kq2d_body_set_pos(&temp,-12,20);
result[5]=temp.x; result[6]=temp.y;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La izquierda muestra el estado inicial; la derecha, un tick después. Una caja roja de 16x16 con centro (24,24) y velocidad (4,16) llega a (28,36), con velocidad Y nula sobre el suelo azul. Los orígenes de los paneles están en las coordenadas de pantalla (8,48) y (88,48). En DMG, todas las marcas son negras. Las comprobaciones de RAM también cubren la inicialización, las funciones de ajuste, la integración, las consultas de rectángulos y puntos y el escalado con signo.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body2d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body2d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/physics2d.h:56
Replace the center without altering velocity, extents or activity. Null is ignored.
kitaqgb/lib/physics2d.c:612
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
Establece directamente la velocidad sin limitarla ni actualizar la posición.
Sintaxis
void kq2d_body_set_velocity(KQBody2D* body, s16 vx, s16 vy);Parámetros
bodyPuntero al cuerpo que se va a modificar. Los campos que no usa esta operación se conservan.
vxDesplazamiento en X por tick de simulación, en las mismas unidades que la posición.
vyDesplazamiento en Y por tick de simulación, en las mismas unidades que la posición.
Valor devuelto
Sin valor de retorno. Esta entrada describe qué campos se actualizan y cuándo surten efecto los cambios.
Condiciones y límites
Usa unidades enteras coherentes para posiciones, radios, semiextensiones, velocidades y gravedad. Cada paso equivale a un tick de simulación. Los ejemplos usan una unidad por píxel. Estas rutinas no convierten automáticamente las posiciones a Q8.8 ni las dibujan.
Ignora NULL. Si el puntero es válido, también modifica los cuerpos inactivos y estáticos.
Ejemplo de uso
kq2d_body_set_velocity(&temp,40,-30);
result[7]=temp.vx; result[8]=temp.vy;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La izquierda muestra el estado inicial; la derecha, un tick después. Una caja roja de 16x16 con centro (24,24) y velocidad (4,16) llega a (28,36), con velocidad Y nula sobre el suelo azul. Los orígenes de los paneles están en las coordenadas de pantalla (8,48) y (88,48). En DMG, todas las marcas son negras. Las comprobaciones de RAM también cubren la inicialización, las funciones de ajuste, la integración, las consultas de rectángulos y puntos y el escalado con signo.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body2d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body2d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/physics2d.h:58
Replace velocity without clamping or checking activity/mass. Null is ignored.
kitaqgb/lib/physics2d.c:620
void kq2d_body_set_velocity(KQBody2D* body, s16 vx, s16 vy)
{
if (body == 0) return;
body->vx = vx;
body->vy = vy;
}kq2d_integrate_body
Aplica la gravedad del mundo y los límites de velocidad por eje a un cuerpo dinámico; después suma su velocidad a la posición.
Sintaxis
void kq2d_integrate_body(KQWorld2D* world, KQBody2D* body);Parámetros
worldPuntero al mundo que contiene el array de cuerpos y los ajustes de simulación.
bodyPuntero al cuerpo que se va a modificar. Los campos que no usa esta operación se conservan.
Valor devuelto
Sin valor de retorno. Esta entrada describe qué campos se actualizan y cuándo surten efecto los cambios.
Condiciones y límites
Usa unidades enteras coherentes para posiciones, radios, semiextensiones, velocidades y gravedad. Cada paso equivale a un tick de simulación. Los ejemplos usan una unidad por píxel. Estas rutinas no convierten automáticamente las posiciones a Q8.8 ni las dibujan.
Mantén las sumas, diferencias, sumas de semiextensiones y productos de corrección de contactos dentro del rango de 16 bits con signo. Los límites de velocidad se aplican después de sumar y no pueden evitar un desbordamiento durante esa suma.
Las rutinas de integración y colisión de cajas comparten memoria temporal. No vuelvas a entrar en estas rutinas de física desde una interrupción.
Ignora NULL, los cuerpos inactivos y los de masa inversa no positiva. Proporciona un límite de velocidad no negativo.
Esta llamada no resuelve contactos con otros cuerpos. También ignora un mundo NULL.
Ejemplo de uso
kq2d_integrate_body(&world,&temp);
result[18]=temp.x; result[19]=temp.y;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La izquierda muestra el estado inicial; la derecha, un tick después. Una caja roja de 16x16 con centro (24,24) y velocidad (4,16) llega a (28,36), con velocidad Y nula sobre el suelo azul. Los orígenes de los paneles están en las coordenadas de pantalla (8,48) y (88,48). En DMG, todas las marcas son negras. Las comprobaciones de RAM también cubren la inicialización, las funciones de ajuste, la integración, las consultas de rectángulos y puntos y el escalado con signo.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body2d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body2d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/physics2d.h:47
For one active dynamic body, add gravity, clamp each velocity axis and then add velocity to position. Null inputs are ignored; no contacts are solved. Use a nonnegative speed limit and keep additions in signed 16-bit range.
kitaqgb/lib/physics2d.c:664
void kq2d_integrate_body(KQWorld2D* world, KQBody2D* body)
{
if (world == 0) return;
if (body == 0) return;
if (body->active == 0) return;
if (body->inv_mass_q8 <= 0) return;
kq2d_asm_value = body->vx;
kq2d_asm_operand = world->gravity_x;
kq2d_add_s16_asm();
kq2d_asm_limit = world->max_speed;
kq2d_clamp_abs_s16_asm();
body->vx = kq2d_asm_value;
kq2d_asm_value = body->vy;
kq2d_asm_operand = world->gravity_y;
kq2d_add_s16_asm();
kq2d_asm_limit = world->max_speed;
kq2d_clamp_abs_s16_asm();
body->vy = kq2d_asm_value;
kq2d_asm_value = body->x;
kq2d_asm_operand = body->vx;
kq2d_add_s16_asm();
body->x = kq2d_asm_value;
kq2d_asm_value = body->y;
kq2d_asm_operand = body->vy;
kq2d_add_s16_asm();
body->y = kq2d_asm_value;
}kq2d_overlap_aabb
Comprueba el solapamiento estricto de dos cajas definidas por su centro en los ejes X e Y.
Sintaxis
u8 kq2d_overlap_aabb(const KQBody2D* a, const KQBody2D* b);Parámetros
aPuntero válido a un cuerpo. La consulta ignora la actividad, la masa y las banderas.
bPuntero válido a un cuerpo. La consulta ignora la actividad, la masa y las banderas.
Valor devuelto
Devuelve 1 si los interiores se solapan y 0 si las formas solo se tocan o están separadas.
Condiciones y límites
Usa unidades enteras coherentes para posiciones, radios, semiextensiones, velocidades y gravedad. Cada paso equivale a un tick de simulación. Los ejemplos usan una unidad por píxel. Estas rutinas no convierten automáticamente las posiciones a Q8.8 ni las dibujan.
Mantén las sumas, diferencias, sumas de semiextensiones y productos de corrección de contactos dentro del rango de 16 bits con signo. Los límites de velocidad se aplican después de sumar y no pueden evitar un desbordamiento durante esa suma.
Ejemplo de uso
result[20]=kq2d_overlap_aabb(&bodies[0],&bodies[1]);
bodies[1].x=40; result[21]=kq2d_overlap_aabb(&bodies[0],&bodies[1]);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La izquierda muestra el estado inicial; la derecha, un tick después. Una caja roja de 16x16 con centro (24,24) y velocidad (4,16) llega a (28,36), con velocidad Y nula sobre el suelo azul. Los orígenes de los paneles están en las coordenadas de pantalla (8,48) y (88,48). En DMG, todas las marcas son negras. Las comprobaciones de RAM también cubren la inicialización, las funciones de ajuste, la integración, las consultas de rectángulos y puntos y el escalado con signo.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body2d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body2d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/physics2d.h:51
Test strict overlap of two centered boxes; touching edges return false. Both pointers must be valid. Active/mass flags are ignored, and coordinate differences and extent sums must fit the signed 16-bit calculations.
kitaqgb/lib/physics2d.c:579
u8 kq2d_overlap_aabb(const KQBody2D* a, const KQBody2D* b)
{
s16 dx = (s16)(b->x - a->x);
s16 dy = (s16)(b->y - a->y);
s16 adx = kq2d__abs_s16(dx);
s16 ady = kq2d__abs_s16(dy);
s16 sx = (s16)(a->half_x + b->half_x);
s16 sy = (s16)(a->half_y + b->half_y);
if (adx >= sx) return 0;
if (ady >= sy) return 0;
return 1;
}kq2d_point_in_rect
Comprueba si un punto está dentro de un rectángulo, incluidos los bordes izquierdo y superior, pero excluidos el derecho y el inferior.
Sintaxis
u8 kq2d_point_in_rect(s16 x, s16 y, KQRect r);Parámetros
xCoordenada X del centro o del punto, en píxeles en el ejemplo.
yCoordenada Y del centro o del punto; en el ejemplo, el sentido positivo es hacia abajo.
rValor KQRect con la posición x/y de la esquina superior izquierda y el ancho/alto w/h.
Valor devuelto
Devuelve 1 si está dentro y 0 si está fuera.
Condiciones y límites
Mantén las sumas, diferencias, sumas de semiextensiones y productos de corrección de contactos dentro del rango de 16 bits con signo. Los límites de velocidad se aplican después de sumar y no pueden evitar un desbordamiento durante esa suma.
Ejemplo de uso
result[16]=kq2d_point_in_rect(0,0,r1);
result[17]=kq2d_point_in_rect(16,0,r1);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La izquierda muestra el estado inicial; la derecha, un tick después. Una caja roja de 16x16 con centro (24,24) y velocidad (4,16) llega a (28,36), con velocidad Y nula sobre el suelo azul. Los orígenes de los paneles están en las coordenadas de pantalla (8,48) y (88,48). En DMG, todas las marcas son negras. Las comprobaciones de RAM también cubren la inicialización, las funciones de ajuste, la integración, las consultas de rectángulos y puntos y el escalado con signo.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body2d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body2d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/physics2d.h:72
Delegate the half-open point test: include left/top and exclude right/bottom. Coordinate-plus-size sums must remain representable as s16.
kitaqgb/lib/physics2d.c:705
u8 kq2d_point_in_rect(s16 x, s16 y, KQRect r)
{
return kq_point_in_rect(x, y, r);
}kq2d_rect_intersect
Comprueba el solapamiento interior de dos rectángulos representados por la esquina superior izquierda y el tamaño.
Sintaxis
u8 kq2d_rect_intersect(KQRect a, KQRect b);Parámetros
aValor KQRect con coordenadas de la esquina superior izquierda y ancho y alto positivos.
bValor KQRect con coordenadas de la esquina superior izquierda y ancho y alto positivos.
Valor devuelto
Devuelve 1 si los interiores se solapan y 0 si las formas solo se tocan o están separadas.
Condiciones y límites
Mantén las sumas, diferencias, sumas de semiextensiones y productos de corrección de contactos dentro del rango de 16 bits con signo. Los límites de velocidad se aplican después de sumar y no pueden evitar un desbordamiento durante esa suma.
Las dimensiones no positivas no se rechazan explícitamente. No copies directamente el centro y las semiextensiones de un cuerpo en un KQRect.
Ejemplo de uso
result[14]=kq2d_rect_intersect(r1,r2);
r2.x=16; result[15]=kq2d_rect_intersect(r1,r2);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La izquierda muestra el estado inicial; la derecha, un tick después. Una caja roja de 16x16 con centro (24,24) y velocidad (4,16) llega a (28,36), con velocidad Y nula sobre el suelo azul. Los orígenes de los paneles están en las coordenadas de pantalla (8,48) y (88,48). En DMG, todas las marcas son negras. Las comprobaciones de RAM también cubren la inicialización, las funciones de ajuste, la integración, las consultas de rectángulos y puntos y el escalado con signo.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body2d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body2d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/physics2d.h:69
Delegate strict rectangle overlap to the fixed-point utility; edge-only contact is false. Coordinate-plus-size sums must remain representable as s16.
kitaqgb/lib/physics2d.c:698
u8 kq2d_rect_intersect(KQRect a, KQRect b)
{
return kq_rect_intersect(a, b);
}kq2d_scale_q8
Consulte los cambios y la verificación del 2026-10-03 para las diferencias locales de esta API.
Multiplica por un coeficiente con signo dividido entre 256 y trunca hacia cero para ambos signos.
Sintaxis
s16 kq2d_scale_q8(s16 value, s16 coefficient);Parámetros
valueValor de 16 bits con signo al que se aplica el factor de escala.
coefficientCoeficiente con signo entre -256 y 256; 256 representa 1,0.
Valor devuelto
Devuelve el resultado de 16 bits con signo truncado hacia cero.
Condiciones y límites
Usa solo coeficientes entre -256 y 256; +/-256 equivale a +/-1. Para value=-32768 y coefficient=-256, el resultado matemático es 32768 y no cabe en s16.
Ejemplo de uso
result[0]=kq2d_scale_q8(-257,128);
result[1]=kq2d_scale_q8(300,-256);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El cuerpo rojo permanece en su sitio. Su línea verde de velocidad cambia de (8,16) a la izquierda a (2,-8) a la derecha, mostrando el rebote y la fricción tangencial contra la superficie azul. Los orígenes de los paneles están en (8,48)/(88,48) de la pantalla; el centro del cuerpo está en (24,40) dentro del panel. La rapidez de entrada es 16 y el ejemplo del instante de cruce devuelve 192/256. El ejemplo del límite de rapidez reduce (300,400) a (147,196). En DMG, todas las marcas son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_surface.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_surface.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/physics2d.h:88
Truncates toward zero, including negative values; coefficient is -256..256.
kitaqgb/lib/physics2d.c:8
s16 kq2d_scale_q8(s16 value, s16 coefficient)
{
// Eight-bit shift/add product in HL:C, with sign applied after truncation.
__asm {
LD_HL_IMM value
LD_A_HL
LD_E_A
INC_HL
LD_A_HL
LD_D_A
OR_E
JP_Z kqscale_zero
LD_HL_IMM coefficient
LD_A_HL
LD_C_A
INC_HL
LD_A_HL
LD_B_A
LD_A_C
OR_A
JR_NZ kqscale_fraction
LD_A_B
OR_A
JP_Z kqscale_zero
LD_H_D
LD_L_E
AND_IMM 128
RET_Z
JP kqscale_negate
kqscale_fraction:
LD_A_D
XOR_B
AND_IMM 128
PUSH_AF
LD_A_D
AND_IMM 128
JR_Z kqscale_value_positive
XOR_A
SUB_E
LD_E_A
LD_A_IMM 0
SBC_D
LD_D_A
kqscale_value_positive:
LD_A_B
AND_IMM 128
JR_Z kqscale_coefficient_positive
XOR_A
SUB_C
LD_C_A
kqscale_coefficient_positive:
LD_HL_IMM 0
// Unroll eight bits: avoid a loop branch on every fixed-point product.
LD_A_C
AND_IMM 1
JR_Z kqscale_shift_0
ADD_HL_DE
kqscale_shift_0:
LD_A_H
RRA
LD_H_A
LD_A_L
RRA
LD_L_A
LD_A_C
RRA
LD_C_A
LD_A_C
AND_IMM 1
JR_Z kqscale_shift_1
ADD_HL_DE
kqscale_shift_1:
LD_A_H
RRA
LD_H_A
LD_A_L
RRA
LD_L_A
LD_A_C
RRA
LD_C_A
LD_A_C
AND_IMM 1
JR_Z kqscale_shift_2
ADD_HL_DE
kqscale_shift_2:
LD_A_H
RRA
LD_H_A
LD_A_L
RRA
LD_L_A
LD_A_C
RRA
LD_C_A
LD_A_C
AND_IMM 1
JR_Z kqscale_shift_3
ADD_HL_DE
kqscale_shift_3:
LD_A_H
RRA
LD_H_A
LD_A_L
RRA
LD_L_A
LD_A_C
RRA
LD_C_A
LD_A_C
AND_IMM 1
JR_Z kqscale_shift_4
ADD_HL_DE
kqscale_shift_4:
LD_A_H
RRA
LD_H_A
LD_A_L
RRA
LD_L_A
LD_A_C
RRA
LD_C_A
LD_A_C
AND_IMM 1
JR_Z kqscale_shift_5
ADD_HL_DE
kqscale_shift_5:
LD_A_H
RRA
LD_H_A
LD_A_L
RRA
LD_L_A
LD_A_C
RRA
LD_C_A
LD_A_C
AND_IMM 1
JR_Z kqscale_shift_6
ADD_HL_DE
kqscale_shift_6:
LD_A_H
RRA
LD_H_A
LD_A_L
RRA
LD_L_A
LD_A_C
RRA
LD_C_A
LD_A_C
AND_IMM 1
JR_Z kqscale_shift_7
ADD_HL_DE
kqscale_shift_7:
LD_A_H
RRA
LD_H_A
LD_A_L
RRA
LD_L_A
LD_A_C
RRA
LD_C_A
POP_AF
OR_A
RET_Z
kqscale_negate:
XOR_A
SUB_L
LD_L_A
LD_A_IMM 0
SBC_H
LD_H_A
RET
kqscale_zero:
LD_HL_IMM 0
RET
}
}kq2d_step
Integra los cuerpos dinámicos activos y después resuelve los contactos entre las entradas activas del array.
Sintaxis
void kq2d_step(KQWorld2D* world);Parámetros
worldPuntero al mundo que contiene el array de cuerpos y los ajustes de simulación.
Valor devuelto
Sin valor de retorno. Esta entrada describe qué campos se actualizan y cuándo surten efecto los cambios.
Condiciones y límites
Usa unidades enteras coherentes para posiciones, radios, semiextensiones, velocidades y gravedad. Cada paso equivale a un tick de simulación. Los ejemplos usan una unidad por píxel. Estas rutinas no convierten automáticamente las posiciones a Q8.8 ni las dibujan.
El mundo utiliza un array prestado. El código que llama reserva y posee la memoria de los cuerpos y debe mantenerla válida. Inicializar el mundo no inicializa los elementos del array.
Mantén las sumas, diferencias, sumas de semiextensiones y productos de corrección de contactos dentro del rango de 16 bits con signo. Los límites de velocidad se aplican después de sumar y no pueden evitar un desbordamiento durante esa suma.
Los contactos se resuelven por el eje de menor penetración, eligiendo Y en caso de empate. La corrección de posición usa las masas inversas, pero dos cuerpos dinámicos reciben la media simple de sus velocidades en ese eje; chocar con un cuerpo estático anula esa componente. Este solucionador no usa restitution_q8. La detección es discreta y puede pasar por alto cruces rápidos.
Las rutinas de integración y colisión de cajas comparten memoria temporal. No vuelvas a entrar en estas rutinas de física desde una interrupción.
Ignora un mundo o array NULL. Aunque solver_iterations valga cero, realiza una pasada de contactos.
Ejemplo de uso
kq2d_step(&world);
result[22]=bodies[0].x; result[23]=bodies[0].y;
result[24]=bodies[0].vx; result[25]=bodies[0].vy;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La izquierda muestra el estado inicial; la derecha, un tick después. Una caja roja de 16x16 con centro (24,24) y velocidad (4,16) llega a (28,36), con velocidad Y nula sobre el suelo azul. Los orígenes de los paneles están en las coordenadas de pantalla (8,48) y (88,48). En DMG, todas las marcas son negras. Las comprobaciones de RAM también cubren la inicialización, las funciones de ajuste, la integración, las consultas de rectángulos y puntos y el escalado con signo.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body2d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body2d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/physics2d.h:43
Advance active dynamic bodies, then visit each active unordered pair for the configured contact passes (zero means one). Static bodies still participate as obstacles. The world borrows its array and shares non-reentrant ASM scratch. This is discrete integration; fast bodies can pass through thin obstacles.
kitaqgb/lib/physics2d.c:794
void kq2d_step(KQWorld2D* world)
{
if (world == 0) return;
if (world->bodies == 0) return;
KQBody2D* bodies = world->bodies;
u8 count = world->body_count;
// Integrate dynamic bodies.
u8 i;
for (i = 0; i < count; i++)
{
KQBody2D* b = &bodies[(__safe_index u8)i];
if (b->active == 0) continue;
if (b->inv_mass_q8 <= 0) continue;
kq2d_asm_value = b->vx;
kq2d_asm_operand = world->gravity_x;
kq2d_add_s16_asm();
kq2d_asm_limit = world->max_speed;
kq2d_clamp_abs_s16_asm();
b->vx = kq2d_asm_value;
kq2d_asm_value = b->vy;
kq2d_asm_operand = world->gravity_y;
kq2d_add_s16_asm();
kq2d_asm_limit = world->max_speed;
kq2d_clamp_abs_s16_asm();
b->vy = kq2d_asm_value;
kq2d_asm_value = b->x;
kq2d_asm_operand = b->vx;
kq2d_add_s16_asm();
b->x = kq2d_asm_value;
kq2d_asm_value = b->y;
kq2d_asm_operand = b->vy;
kq2d_add_s16_asm();
b->y = kq2d_asm_value;
}
// Solve contacts with a small fixed iteration count.
u8 iterations = world->solver_iterations;
if (iterations == 0) iterations = 1;
u8 it;
for (it = 0; it < iterations; it++)
{
for (i = 0; i < count; i++)
{
KQBody2D* a = &bodies[(__safe_index u8)i];
if (a->active == 0) continue;
u8 j;
for (j = (u8)(i + 1); j < count; j++)
{
KQBody2D* b = &bodies[(__safe_index u8)j];
if (b->active == 0) continue;
kq2d__resolve_pair(a, b);
}
}
}
}kq2d_surface_toi_q8
Estima el instante de cruce dentro del tick a partir de las distancias inicial y final con signo, suponiendo un movimiento lineal.
Sintaxis
u16 kq2d_surface_toi_q8(s16 start_gap, s16 end_gap);Parámetros
start_gapDistancia con signo al inicio del tick; un valor positivo indica que está fuera de la superficie.
end_gapDistancia con signo al final del tick; un valor negativo indica que se ha atravesado la superficie.
Valor devuelto
Devuelve un tiempo Q8 de 0 a 256; 192 equivale al 75 % del tick.
Condiciones y límites
Mantén las distancias dentro de +/-8191. Un inicio no positivo devuelve 0; un final no negativo devuelve 256. El solapamiento inicial y el instante cero comparten valor de retorno, al igual que la ausencia de cruce y el contacto justo al final. No modifica ninguna posición.
Ejemplo de uso
result[4]=kq2d_surface_toi_q8(6,-2);
result[5]=kq2d_surface_toi_q8(6,0);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El cuerpo rojo permanece en su sitio. Su línea verde de velocidad cambia de (8,16) a la izquierda a (2,-8) a la derecha, mostrando el rebote y la fricción tangencial contra la superficie azul. Los orígenes de los paneles están en (8,48)/(88,48) de la pantalla; el centro del cuerpo está en (24,40) dentro del panel. La rapidez de entrada es 16 y el ejemplo del instante de cruce devuelve 192/256. El ejemplo del límite de rapidez reduce (300,400) a (147,196). En DMG, todas las marcas son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_surface.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_surface.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/physics2d.h:98
Linear crossing time in Q8 (0..256); positive separation is outside. Returns 0 for initial overlap, 256 for no crossing. Gaps must fit +/-8191.
kitaqgb/lib/physics2d.c:291
u16 kq2d_surface_toi_q8(s16 start_gap, s16 end_gap)
{
if (start_gap <= 0) return 0;
if (end_gap >= 0) return 256;
return kq2d__fraction_q8((u16)start_gap, (u16)(start_gap - end_gap));
}kq2d_world_init
Asocia un array a un mundo 2D y establece gravedad (0,32), cuatro iteraciones de contacto y un límite de velocidad por eje de 512.
Sintaxis
void kq2d_world_init(KQWorld2D* world, KQBody2D* bodies, u8 body_count);Parámetros
worldPuntero al mundo que contiene el array de cuerpos y los ajustes de simulación.
bodiesInicio de un array de cuerpos propiedad del código que llama, con body_count elementos.
body_countNúmero de posiciones del array, de 0 a 255, incluidas las entradas inactivas.
Valor devuelto
Sin valor de retorno. Esta entrada describe qué campos se actualizan y cuándo surten efecto los cambios.
Condiciones y límites
Usa unidades enteras coherentes para posiciones, radios, semiextensiones, velocidades y gravedad. Cada paso equivale a un tick de simulación. Los ejemplos usan una unidad por píxel. Estas rutinas no convierten automáticamente las posiciones a Q8.8 ni las dibujan.
El mundo utiliza un array prestado. El código que llama reserva y posee la memoria de los cuerpos y debe mantenerla válida. Inicializar el mundo no inicializa los elementos del array.
Ejemplo de uso
kq2d_world_init(&world,bodies,2);
result[0]=world.gravity_y; result[1]=world.solver_iterations; result[2]=world.max_speed;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La izquierda muestra el estado inicial; la derecha, un tick después. Una caja roja de 16x16 con centro (24,24) y velocidad (4,16) llega a (28,36), con velocidad Y nula sobre el suelo azul. Los orígenes de los paneles están en las coordenadas de pantalla (8,48) y (88,48). En DMG, todas las marcas son negras. Las comprobaciones de RAM también cubren la inicialización, las funciones de ajuste, la integración, las consultas de rectángulos y puntos y el escalado con signo.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body2d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body2d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/physics2d.h:38
Retain the caller-owned body array without initializing its elements. Set gravity to (0,32), four contact iterations and a per-axis speed limit of 512. A null world is ignored; the array must outlive subsequent world operations.
kitaqgb/lib/physics2d.c:564
void kq2d_world_init(KQWorld2D* world, KQBody2D* bodies, u8 body_count)
{
if (world == 0) return;
world->bodies = bodies;
world->body_count = body_count;
world->gravity_x = 0;
world->gravity_y = 32;
world->solver_iterations = 4;
world->max_speed = 512;
}physics2d_circle.h — Física de círculos
Admite radio de círculo, masa inversa, restitución, fricción tangencial, amortiguamiento del mundo y límites. El código que llama inicializa todos los campos del cuerpo. friction_q8 del cuerpo y wall_friction_q8 indican la proporción de movimiento tangencial eliminada; linear_damping_q8 indica la proporción de velocidad conservada. Los coeficientes de un byte se dividen entre 256, por lo que 255 no es exactamente 1,0.
Usa unidades enteras coherentes para posiciones, radios, semiextensiones, velocidades y gravedad. Cada paso equivale a un tick de simulación. Los ejemplos usan una unidad por píxel. Estas rutinas no convierten automáticamente las posiciones a Q8.8 ni las dibujan.
La distancia y las normales de los círculos son aproximaciones enteras. Reducir cada componente a un máximo de 255 no garantiza que la suma de cuadrados quepa en 65535. Mantén las diferencias entre centros y las sumas de radios y masas inversas dentro de su rango representable. En el cálculo de pesos, inv_mass_q8 * 255 no debe superar 32767; el ejemplo usa 64.
kq2dc_overlap_circle
Aproxima el solapamiento interior usando la distancia reducida entre centros y la suma de los radios.
Sintaxis
u8 kq2dc_overlap_circle(const KQCircleBody2D* a, const KQCircleBody2D* b);Parámetros
aPuntero válido al primer círculo.
bPuntero válido al segundo círculo.
Valor devuelto
Devuelve 1 si los interiores se solapan y 0 si las formas solo se tocan o están separadas.
Condiciones y límites
Usa unidades enteras coherentes para posiciones, radios, semiextensiones, velocidades y gravedad. Cada paso equivale a un tick de simulación. Los ejemplos usan una unidad por píxel. Estas rutinas no convierten automáticamente las posiciones a Q8.8 ni las dibujan.
La distancia y las normales de los círculos son aproximaciones enteras. Reducir cada componente a un máximo de 255 no garantiza que la suma de cuadrados quepa en 65535. Mantén las diferencias entre centros y las sumas de radios y masas inversas dentro de su rango representable. En el cálculo de pesos, inv_mass_q8 * 255 no debe superar 32767; el ejemplo usa 64.
Requiere dos punteros válidos y radios positivos. Ignora la actividad y la masa. La reducción y las raíces cuadradas enteras pueden dar un resultado distinto de una prueba exacta de distancia geométrica.
Ejemplo de uso
result[4]=kq2dc_overlap_circle(&balls[0],&balls[1]);
balls[1].x=18; result[5]=kq2dc_overlap_circle(&balls[0],&balls[1]);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Un círculo rojo de radio 6 pasa del centro (24,24) a la izquierda a (54,24) a la derecha. Los límites locales son (4,4)..(60,60). La pared derecha limita el centro a 54 y cambia la velocidad X de 32 a -15: primero se aplica una restitución de pared de 128/256 y después un amortiguamiento de 255/256. Los orígenes de los paneles están en (8,48)/(88,48) de la pantalla. En DMG, el círculo y el borde aparecen en negro.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_circle.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_circle.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/physics2d_circle.h:55
Compare a reduced integer center distance with the reduced radius sum. Valid pointers and positive radii are required; activity and mass are ignored. This approximate test requires representable differences, radius sums and squared-distance sum. Touching at the computed distance returns false.
kitaqgb/lib/physics2d_circle.c:397
u8 kq2dc_overlap_circle(const KQCircleBody2D* a, const KQCircleBody2D* b)
{
s16 dx;
s16 dy;
s16 sdx;
s16 sdy;
u8 shift;
u16 adx;
u16 ady;
u16 dist_sq;
u16 dist_scaled;
s16 radius_sum;
u16 radius_sum_scaled;
dx = (s16)(b->x - a->x);
dy = (s16)(b->y - a->y);
sdx = dx;
sdy = dy;
shift = kq2dc__reduce_vector(&sdx, &sdy);
adx = (u16)kq2dc__abs_s16(sdx);
ady = (u16)kq2dc__abs_s16(sdy);
dist_sq = (u16)((adx * adx) + (ady * ady));
dist_scaled = kq2dc__isqrt_u16(dist_sq);
radius_sum = (s16)(a->radius + b->radius);
radius_sum_scaled = kq2dc__scale_down_positive(radius_sum, shift);
if (dist_scaled >= radius_sum_scaled) return 0;
return 1;
}kq2dc_set_bounds
Guarda y activa los límites del mundo de círculos sin mover inmediatamente los cuerpos.
Sintaxis
void kq2dc_set_bounds(KQCircleWorld2D* world, s16 min_x, s16 min_y, s16 max_x, s16 max_y);Parámetros
worldPuntero al mundo que contiene el array de cuerpos y los ajustes de simulación.
min_xLímite izquierdo; el centro del círculo no puede ser menor que min_x + radius.
min_yLímite superior; el centro del círculo no puede ser menor que min_y + radius.
max_xLímite derecho; el centro del círculo no puede superar max_x - radius.
max_yLímite inferior; el centro del círculo no puede superar max_y - radius.
Valor devuelto
Sin valor de retorno. Esta entrada describe qué campos se actualizan y cuándo surten efecto los cambios.
Condiciones y límites
Usa unidades enteras coherentes para posiciones, radios, semiextensiones, velocidades y gravedad. Cada paso equivale a un tick de simulación. Los ejemplos usan una unidad por píxel. Estas rutinas no convierten automáticamente las posiciones a Q8.8 ni las dibujan.
Ignora NULL. No valida el orden de los límites ni el espacio disponible; proporciona un ancho y un alto al menos iguales al diámetro del círculo. La corrección real de posición se realiza durante un paso de simulación.
Ejemplo de uso
kq2dc_set_bounds(&world,4,4,60,60);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Un círculo rojo de radio 6 pasa del centro (24,24) a la izquierda a (54,24) a la derecha. Los límites locales son (4,4)..(60,60). La pared derecha limita el centro a 54 y cambia la velocidad X de 32 a -15: primero se aplica una restitución de pared de 128/256 y después un amortiguamiento de 255/256. Los orígenes de los paneles están en (8,48)/(88,48) de la pantalla. En DMG, el círculo y el borde aparecen en negro.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_circle.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_circle.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/physics2d_circle.h:45
Store and enable bounds without validating their order or fitting bodies immediately. Supply extents large enough for body diameters. Null is ignored.
kitaqgb/lib/physics2d_circle.c:382
void kq2dc_set_bounds(KQCircleWorld2D* world, s16 min_x, s16 min_y, s16 max_x, s16 max_y)
{
if (world == 0) return;
world->use_bounds = 1;
world->min_x = min_x;
world->min_y = min_y;
world->max_x = max_x;
world->max_y = max_y;
}kq2dc_step
Integra los círculos, resuelve los límites y los contactos entre círculos y después aplica amortiguamiento lineal.
Sintaxis
void kq2dc_step(KQCircleWorld2D* world);Parámetros
worldPuntero al mundo que contiene el array de cuerpos y los ajustes de simulación.
Valor devuelto
Sin valor de retorno. Esta entrada describe qué campos se actualizan y cuándo surten efecto los cambios.
Condiciones y límites
Usa unidades enteras coherentes para posiciones, radios, semiextensiones, velocidades y gravedad. Cada paso equivale a un tick de simulación. Los ejemplos usan una unidad por píxel. Estas rutinas no convierten automáticamente las posiciones a Q8.8 ni las dibujan.
El mundo utiliza un array prestado. El código que llama reserva y posee la memoria de los cuerpos y debe mantenerla válida. Inicializar el mundo no inicializa los elementos del array.
La distancia y las normales de los círculos son aproximaciones enteras. Reducir cada componente a un máximo de 255 no garantiza que la suma de cuadrados quepa en 65535. Mantén las diferencias entre centros y las sumas de radios y masas inversas dentro de su rango representable. En el cálculo de pesos, inv_mass_q8 * 255 no debe superar 32767; el ejemplo usa 64.
Al final pone a cero las componentes de velocidad entre -1 y 1. Incluso con amortiguamiento 255 se pierde algo de velocidad. Puede quedar solapamiento entre círculos en reposo. Los círculos estáticos también se mueven dentro de los límites activos. Cero iteraciones significa una pasada; ignora mundo o array NULL. Este solucionador discreto y cuantizado puede recorrer los contactos en distinto orden cuando cambian las velocidades.
Ejemplo de uso
kq2dc_step(&world);
result[6]=balls[0].x; result[7]=balls[0].y; result[8]=balls[0].vx;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Un círculo rojo de radio 6 pasa del centro (24,24) a la izquierda a (54,24) a la derecha. Los límites locales son (4,4)..(60,60). La pared derecha limita el centro a 54 y cambia la velocidad X de 32 a -15: primero se aplica una restitución de pared de 128/256 y después un amortiguamiento de 255/256. Los orígenes de los paneles están en (8,48)/(88,48) de la pantalla. En DMG, el círculo y el borde aparecen en negro.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_circle.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_circle.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/physics2d_circle.h:50
Integrate active dynamic bodies, apply bounds, solve contacts, then damp velocity and snap components in -1..1 to zero. Zero solver iterations means one. Pairs with both velocities zero are skipped, so resting overlaps can remain. Bounds can reposition static bodies; null world/array inputs are ignored.
kitaqgb/lib/physics2d_circle.c:433
void kq2dc_step(KQCircleWorld2D* world)
{
KQCircleBody2D* bodies;
u8 count;
u8 i;
u8 iterations;
u8 it;
if (world == 0) return;
if (world->bodies == 0) return;
bodies = world->bodies;
count = world->body_count;
for (i = 0; i < count; i++)
{
KQCircleBody2D* body = &bodies[(__safe_index u8)i];
if (body->active == 0) continue;
if (body->inv_mass_q8 <= 0)
{
if (world->use_bounds != 0) kq2dc__resolve_bounds(world, body);
continue;
}
body->vx = (s16)(body->vx + world->gravity_x);
body->vy = (s16)(body->vy + world->gravity_y);
body->vx = kq2dc__clamp_abs(body->vx, world->max_speed);
body->vy = kq2dc__clamp_abs(body->vy, world->max_speed);
body->x = (s16)(body->x + body->vx);
body->y = (s16)(body->y + body->vy);
if (world->use_bounds != 0) kq2dc__resolve_bounds(world, body);
}
iterations = world->solver_iterations;
if (iterations == 0) iterations = 1;
for (it = 0; it < iterations; it++)
{
for (i = 0; i < count; i++)
{
KQCircleBody2D* a = &bodies[(__safe_index u8)i];
if (a->active == 0) continue;
if (a->vx == 0 && a->vy == 0) continue;
if (world->use_bounds != 0) kq2dc__resolve_bounds(world, a);
{
u8 j;
for (j = 0; j < count; j++)
{
KQCircleBody2D* b = &bodies[(__safe_index u8)j];
s16 radius_sum;
if (j == i) continue;
if (b->active == 0) continue;
// Avoid revisiting an earlier moving body, but still allow a moving body
// to resolve against a stationary slot with a lower index. Velocities are live
// solver state, so contact ordering can change which later pairs are visited.
if (j < i && (b->vx != 0 || b->vy != 0)) continue;
radius_sum = (s16)(a->radius + b->radius);
if (kq2dc__abs_s16((s16)(b->x - a->x)) >= radius_sum) continue;
if (kq2dc__abs_s16((s16)(b->y - a->y)) >= radius_sum) continue;
kq2dc__resolve_pair(a, b);
}
}
}
}
for (i = 0; i < count; i++)
{
KQCircleBody2D* body = &bodies[(__safe_index u8)i];
if (body->active == 0) continue;
if (body->inv_mass_q8 <= 0) continue;
body->vx = kq2dc__mul_q8(body->vx, world->linear_damping_q8);
body->vy = kq2dc__mul_q8(body->vy, world->linear_damping_q8);
if (body->vx >= -1 && body->vx <= 1) body->vx = 0;
if (body->vy >= -1 && body->vy <= 1) body->vy = 0;
if (world->use_bounds != 0) kq2dc__resolve_bounds(world, body);
}
}kq2dc_world_init
Asocia un array de círculos y establece gravedad cero, cuatro pasadas, límite por eje 768 y amortiguamiento 252/256.
Sintaxis
void kq2dc_world_init(KQCircleWorld2D* world, KQCircleBody2D* bodies, u8 body_count);Parámetros
worldPuntero al mundo que contiene el array de cuerpos y los ajustes de simulación.
bodiesInicio de un array de cuerpos propiedad del código que llama, con body_count elementos.
body_countNúmero de posiciones del array, de 0 a 255, incluidas las entradas inactivas.
Valor devuelto
Sin valor de retorno. Esta entrada describe qué campos se actualizan y cuándo surten efecto los cambios.
Condiciones y límites
Usa unidades enteras coherentes para posiciones, radios, semiextensiones, velocidades y gravedad. Cada paso equivale a un tick de simulación. Los ejemplos usan una unidad por píxel. Estas rutinas no convierten automáticamente las posiciones a Q8.8 ni las dibujan.
El mundo utiliza un array prestado. El código que llama reserva y posee la memoria de los cuerpos y debe mantenerla válida. Inicializar el mundo no inicializa los elementos del array.
Los límites empiezan desactivados, con valores (0,0)..(159,143); la restitución de pared es 240 y la fricción de pared, 16. No hay inicializador de cuerpos circulares: el código que llama debe asignar todos los campos. Ignora un mundo NULL.
Ejemplo de uso
kq2dc_world_init(&world,balls,1);
result[0]=world.gravity_y; result[1]=world.solver_iterations;
result[2]=world.max_speed; result[3]=world.linear_damping_q8;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Un círculo rojo de radio 6 pasa del centro (24,24) a la izquierda a (54,24) a la derecha. Los límites locales son (4,4)..(60,60). La pared derecha limita el centro a 54 y cambia la velocidad X de 32 a -15: primero se aplica una restitución de pared de 128/256 y después un amortiguamiento de 255/256. Los orígenes de los paneles están en (8,48)/(88,48) de la pantalla. En DMG, el círculo y el borde aparecen en negro.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_circle.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_circle.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/physics2d_circle.h:42
Retain a caller-owned array without initializing bodies. Set zero gravity, four contact passes, per-axis limit 768 and damping 252/256; bounds start disabled. A null world is ignored. Keep the array alive for subsequent steps.
kitaqgb/lib/physics2d_circle.c:360
void kq2dc_world_init(KQCircleWorld2D* world, KQCircleBody2D* bodies, u8 body_count)
{
if (world == 0) return;
world->bodies = bodies;
world->body_count = body_count;
world->gravity_x = 0;
world->gravity_y = 0;
world->solver_iterations = 4;
world->max_speed = 768;
world->linear_damping_q8 = 252;
world->use_bounds = 0;
world->min_x = 0;
world->min_y = 0;
world->max_x = 159;
world->max_y = 143;
world->wall_restitution_q8 = 240;
world->wall_friction_q8 = 16;
}physics3d.h — Física de cajas AABB en 3D
Física para cajas 3D sin rotación, representadas por su centro y semiextensiones por eje. La masa y la masa inversa ponderan los contactos, restitution_q8 controla el rebote y ax/ay/az aportan aceleración persistente. El renderizado es independiente. El ejemplo dibuja vistas frontal y superior del mismo cuerpo para mostrar el movimiento en profundidad y el rebote contra una pared.
Usa unidades enteras coherentes para posiciones, radios, semiextensiones, velocidades y gravedad. Cada paso equivale a un tick de simulación. Los ejemplos usan una unidad por píxel. Estas rutinas no convierten automáticamente las posiciones a Q8.8 ni las dibujan.
physics3d.c reside en el banco ROM 2. El ejemplo usa una ROM MBC5 de 128 KB, incluye primero esta implementación y sitúa main en el banco 0. No cambies el mapeo de ROM desde fuera durante una llamada.
last_impact_speed registra la máxima velocidad de acercamiento en un eje de contacto. La integración la borra para los cuerpos dinámicos activos; los estáticos e inactivos la conservan. Ni break_speed ni KQ3D_BODY_BROKEN provocan una destrucción automática. El juego decide cuándo romper un cuerpo y modifica flags/active por su cuenta.
kq3d_body_init
Inicializa el centro 3D, las semiextensiones y la masa; pone a cero la velocidad, la aceleración, el impacto y las banderas, y activa el cuerpo.
Sintaxis
void kq3d_body_init(KQBody3D* body, s16 x, s16 y, s16 z, s16 half_x, s16 half_y, s16 half_z, s16 mass_q8);Parámetros
bodyPuntero al cuerpo que se va a modificar. Los campos que no usa esta operación se conservan.
xCoordenada X del centro o del punto, en píxeles en el ejemplo.
yCoordenada Y del centro o del punto; en el ejemplo, el sentido positivo es hacia abajo.
zCoordenada Z del centro, representada verticalmente en la vista superior del ejemplo.
half_xSemiextensión en X; el ancho total de la caja es el doble de este valor.
half_ySemiextensión en Y; la altura total de la caja es el doble de este valor.
half_zSemiextensión en Z; la profundidad total es el doble de este valor.
mass_q8Valor de masa, donde 256 representa 1,0; los valores no positivos crean un cuerpo estático.
Valor devuelto
Sin valor de retorno. Esta entrada describe qué campos se actualizan y cuándo surten efecto los cambios.
Condiciones y límites
Usa unidades enteras coherentes para posiciones, radios, semiextensiones, velocidades y gravedad. Cada paso equivale a un tick de simulación. Los ejemplos usan una unidad por píxel. Estas rutinas no convierten automáticamente las posiciones a Q8.8 ni las dibujan.
physics3d.c reside en el banco ROM 2. El ejemplo usa una ROM MBC5 de 128 KB, incluye primero esta implementación y sitúa main en el banco 0. No cambies el mapeo de ROM desde fuera durante una llamada.
La restitución es 224 y break_speed es cero. La masa sigue las reglas de kq3d_body_set_mass. Ignora NULL; el código que llama debe proporcionar semiextensiones válidas.
Ejemplo de uso
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;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
A la izquierda está la vista frontal X/Y y a la derecha, la vista superior X/Z. Los contornos verdes marcan la posición inicial (24,24,16); las cajas rojas muestran (36,24,24) tras un tick; las zonas azules son el obstáculo estático. La velocidad X rebota de 16 a -14, mientras que la velocidad Z se mantiene en 8. El impacto es 16, pero flags permanece en cero pese a break_speed=1. Los orígenes de los paneles están en (8,48)/(88,48) de la pantalla. En DMG, todas las marcas son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body3d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/physics3d.h:50
Initialize an active centered box with zero velocity/acceleration, restitution 224, cleared impact/flags and mass set through the weight helper. The caller supplies valid half extents. Null body is ignored.
kitaqgb/lib/physics3d.c:330
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
Guarda la masa solicitada y calcula un peso de masa inversa para la corrección y el rebote.
Sintaxis
void kq3d_body_set_mass(KQBody3D* body, s16 mass_q8);Parámetros
bodyPuntero al cuerpo que se va a modificar. Los campos que no usa esta operación se conservan.
mass_q8Valor de masa, donde 256 representa 1,0; los valores no positivos crean un cuerpo estático.
Valor devuelto
Sin valor de retorno. Esta entrada describe qué campos se actualizan y cuándo surten efecto los cambios.
Condiciones y límites
physics3d.c reside en el banco ROM 2. El ejemplo usa una ROM MBC5 de 128 KB, incluye primero esta implementación y sitúa main en el banco 0. No cambies el mapeo de ROM desde fuera durante una llamada.
Una masa no positiva da masa inversa cero, es decir, un cuerpo estático. Para una masa positiva se usa la división entera 32767/max(mass,64), con un mínimo de 1. La masa almacenada conserva el valor solicitado: el peso no es un recíproco Q8 exacto. La masa 256 da masa inversa 127. La velocidad y la actividad no cambian; ignora NULL.
Ejemplo de uso
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);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
A la izquierda está la vista frontal X/Y y a la derecha, la vista superior X/Z. Los contornos verdes marcan la posición inicial (24,24,16); las cajas rojas muestran (36,24,24) tras un tick; las zonas azules son el obstáculo estático. La velocidad X rebota de 16 a -14, mientras que la velocidad Z se mantiene en 8. El impacto es 16, pero flags permanece en cero pese a break_speed=1. Los orígenes de los paneles están en (8,48)/(88,48) de la pantalla. En DMG, todas las marcas son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body3d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/physics3d.h:55
Store the requested mass; nonpositive mass makes the body static. For positive mass compute inverse weight as max(1,32767/max(mass,64)). The stored mass retains the original input; this is a relative solver weight, not an exact Q8 reciprocal. Null body is ignored.
kitaqgb/lib/physics3d.c:311
void kq3d_body_set_mass(KQBody3D* body, s16 mass_q8)
{
if (body == 0) return;
body->mass_q8 = mass_q8;
if (mass_q8 <= 0)
{
body->inv_mass_q8 = 0;
return;
}
if (mass_q8 < 64) mass_q8 = 64;
body->inv_mass_q8 = (s16)(32767 / mass_q8);
if (body->inv_mass_q8 <= 0) body->inv_mass_q8 = 1;
}kq3d_dot_q8_8
Divide cada uno de los tres productos con signo entre 256, trunca cada término hacia cero y después los suma.
Sintaxis
s16 kq3d_dot_q8_8(s16 x, s16 y, s16 z, s8 ax, s8 ay, s8 az);Parámetros
xComponente de 16 bits con signo que se multiplica por el coeficiente correspondiente; puede representar posición o velocidad.
yComponente de 16 bits con signo que se multiplica por el coeficiente correspondiente; puede representar posición o velocidad.
zComponente de 16 bits con signo que se multiplica por el coeficiente correspondiente; puede representar posición o velocidad.
axCoeficiente de un byte con signo para este eje (-128..127), aplicado con escala 1/256.
ayCoeficiente de un byte con signo para este eje (-128..127), aplicado con escala 1/256.
azCoeficiente de un byte con signo para este eje (-128..127), aplicado con escala 1/256.
Valor devuelto
Devuelve la suma de tres términos cuantizados como s16.
Condiciones y límites
physics3d.c reside en el banco ROM 2. El ejemplo usa una ROM MBC5 de 128 KB, incluye primero esta implementación y sitúa main en el banco 0. No cambies el mapeo de ROM desde fuera durante una llamada.
Truncar primero cada término hacia cero puede dar un resultado distinto de desplazar una sola vez la suma completa. Un coeficiente no puede almacenar 1,0=256. La suma final no se satura.
Ejemplo de uso
result[13]=kq3d_dot_q8_8(256,128,0,64,-64,127);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
A la izquierda está la vista frontal X/Y y a la derecha, la vista superior X/Z. Los contornos verdes marcan la posición inicial (24,24,16); las cajas rojas muestran (36,24,24) tras un tick; las zonas azules son el obstáculo estático. La velocidad X rebota de 16 a -14, mientras que la velocidad Z se mantiene en 8. El impacto es 16, pero flags permanece en cero pese a break_speed=1. Los orígenes de los paneles están en (8,48)/(88,48) de la pantalla. En DMG, todas las marcas son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body3d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/physics3d.h:74
Sum three signed products, shifting each by eight bits before addition. Coefficients are signed bytes scaled by 1/256; the 16-bit sum is not saturated.
kitaqgb/lib/physics3d.c:576
s16 kq3d_dot_q8_8(s16 x, s16 y, s16 z, s8 ax, s8 ay, s8 az)
{
return __sdot3_q8_8(x, y, z, ax, ay, az);
}kq3d_integrate_body
Consulte los cambios y la verificación del 2026-10-03 para las diferencias locales de esta API.
Borra el impacto de un cuerpo dinámico activo, suma la gravedad del mundo y la aceleración del cuerpo, limita cada eje de velocidad y avanza la posición.
Sintaxis
void kq3d_integrate_body(KQWorld3D* world, KQBody3D* body);Parámetros
worldPuntero al mundo que contiene el array de cuerpos y los ajustes de simulación.
bodyPuntero al cuerpo que se va a modificar. Los campos que no usa esta operación se conservan.
Valor devuelto
Sin valor de retorno. Esta entrada describe qué campos se actualizan y cuándo surten efecto los cambios.
Condiciones y límites
Usa unidades enteras coherentes para posiciones, radios, semiextensiones, velocidades y gravedad. Cada paso equivale a un tick de simulación. Los ejemplos usan una unidad por píxel. Estas rutinas no convierten automáticamente las posiciones a Q8.8 ni las dibujan.
Mantén las sumas, diferencias, sumas de semiextensiones y productos de corrección de contactos dentro del rango de 16 bits con signo. Los límites de velocidad se aplican después de sumar y no pueden evitar un desbordamiento durante esa suma.
Las rutinas de integración y colisión de cajas comparten memoria temporal. No vuelvas a entrar en estas rutinas de física desde una interrupción.
physics3d.c reside en el banco ROM 2. El ejemplo usa una ROM MBC5 de 128 KB, incluye primero esta implementación y sitúa main en el banco 0. No cambies el mapeo de ROM desde fuera durante una llamada.
last_impact_speed registra la máxima velocidad de acercamiento en un eje de contacto. La integración la borra para los cuerpos dinámicos activos; los estáticos e inactivos la conservan. Ni break_speed ni KQ3D_BODY_BROKEN provocan una destrucción automática. El juego decide cuándo romper un cuerpo y modifica flags/active por su cuenta.
ax/ay/az se conservan y vuelven a aplicarse en la siguiente integración. Esta función por sí sola no resuelve contactos. No modifica NULL ni cuerpos inactivos o estáticos.
Ejemplo de uso
kq3d_integrate_body(&world,&temp);
result[9]=temp.x; result[10]=temp.y; result[11]=temp.z; result[12]=temp.last_impact_speed;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
A la izquierda está la vista frontal X/Y y a la derecha, la vista superior X/Z. Los contornos verdes marcan la posición inicial (24,24,16); las cajas rojas muestran (36,24,24) tras un tick; las zonas azules son el obstáculo estático. La velocidad X rebota de 16 a -14, mientras que la velocidad Z se mantiene en 8. El impacto es 16, pero flags permanece en cero pese a break_speed=1. Los orígenes de los paneles están en (8,48)/(88,48) de la pantalla. En DMG, todas las marcas son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body3d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/physics3d.h:66
Reset impact for one active dynamic body, add gravity and persistent body acceleration, clamp velocity per axis and advance position. Static/inactive bodies retain impact state. Null inputs are ignored; no contacts are solved. Use a nonnegative speed limit and avoid overflow before clamping.
kitaqgb/lib/physics3d.c:436
void kq3d_integrate_body(KQWorld3D* world, KQBody3D* body)
{
if (world == 0) return;
if (body == 0) return;
if (body->active == 0) return;
if (body->inv_mass_q8 <= 0) return;
body->last_impact_speed = 0;
kq3d_asm_value = body->vx;
kq3d_asm_operand = world->gravity_x;
kq3d_add_s16_asm();
kq3d_asm_operand = body->ax;
kq3d_add_s16_asm();
kq3d_asm_limit = world->max_speed;
kq3d_clamp_abs_s16_asm();
body->vx = kq3d_asm_value;
kq3d_asm_value = body->vy;
kq3d_asm_operand = world->gravity_y;
kq3d_add_s16_asm();
kq3d_asm_operand = body->ay;
kq3d_add_s16_asm();
kq3d_asm_limit = world->max_speed;
kq3d_clamp_abs_s16_asm();
body->vy = kq3d_asm_value;
kq3d_asm_value = body->vz;
kq3d_asm_operand = world->gravity_z;
kq3d_add_s16_asm();
kq3d_asm_operand = body->az;
kq3d_add_s16_asm();
kq3d_asm_limit = world->max_speed;
kq3d_clamp_abs_s16_asm();
body->vz = kq3d_asm_value;
kq3d_asm_value = body->x;
kq3d_asm_operand = body->vx;
kq3d_add_s16_asm();
body->x = kq3d_asm_value;
kq3d_asm_value = body->y;
kq3d_asm_operand = body->vy;
kq3d_add_s16_asm();
body->y = kq3d_asm_value;
kq3d_asm_value = body->z;
kq3d_asm_operand = body->vz;
kq3d_add_s16_asm();
body->z = kq3d_asm_value;
}kq3d_overlap_aabb
Comprueba el solapamiento estricto de dos cajas definidas por su centro en los tres ejes.
Sintaxis
u8 kq3d_overlap_aabb(const KQBody3D* a, const KQBody3D* b);Parámetros
aPuntero válido a un cuerpo. La consulta ignora la actividad, la masa y las banderas.
bPuntero válido a un cuerpo. La consulta ignora la actividad, la masa y las banderas.
Valor devuelto
Devuelve 1 si los interiores se solapan y 0 si las formas solo se tocan o están separadas.
Condiciones y límites
Usa unidades enteras coherentes para posiciones, radios, semiextensiones, velocidades y gravedad. Cada paso equivale a un tick de simulación. Los ejemplos usan una unidad por píxel. Estas rutinas no convierten automáticamente las posiciones a Q8.8 ni las dibujan.
Mantén las sumas, diferencias, sumas de semiextensiones y productos de corrección de contactos dentro del rango de 16 bits con signo. Los límites de velocidad se aplican después de sumar y no pueden evitar un desbordamiento durante esa suma.
physics3d.c reside en el banco ROM 2. El ejemplo usa una ROM MBC5 de 128 KB, incluye primero esta implementación y sitúa main en el banco 0. No cambies el mapeo de ROM desde fuera durante una llamada.
Ejemplo de uso
result[14]=kq3d_overlap_aabb(&bodies[0],&bodies[1]);
bodies[1].z=32; result[15]=kq3d_overlap_aabb(&bodies[0],&bodies[1]);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
A la izquierda está la vista frontal X/Y y a la derecha, la vista superior X/Z. Los contornos verdes marcan la posición inicial (24,24,16); las cajas rojas muestran (36,24,24) tras un tick; las zonas azules son el obstáculo estático. La velocidad X rebota de 16 a -14, mientras que la velocidad Z se mantiene en 8. El impacto es 16, pero flags permanece en cero pese a break_speed=1. Los orígenes de los paneles están en (8,48)/(88,48) de la pantalla. En DMG, todas las marcas son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body3d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/physics3d.h:70
Test strict overlap on all three axes; face-only contact returns false. Valid pointers are required and flags are ignored. Center differences and extent sums must fit the signed 16-bit magnitude calculations.
kitaqgb/lib/physics3d.c:357
u8 kq3d_overlap_aabb(const KQBody3D* a, const KQBody3D* b)
{
s16 dx = kq3d__abs_s16((s16)(b->x - a->x));
s16 dy = kq3d__abs_s16((s16)(b->y - a->y));
s16 dz = kq3d__abs_s16((s16)(b->z - a->z));
s16 sx = (s16)(a->half_x + b->half_x);
s16 sy = (s16)(a->half_y + b->half_y);
s16 sz = (s16)(a->half_z + b->half_z);
if (dx >= sx) return 0;
if (dy >= sy) return 0;
if (dz >= sz) return 0;
return 1;
}kq3d_step
Consulte los cambios y la verificación del 2026-10-03 para las diferencias locales de esta API.
Integra los cuerpos dinámicos activos y resuelve la corrección de contactos, el rebote y los registros de impacto entre las entradas activas del mundo.
Sintaxis
void kq3d_step(KQWorld3D* world);Parámetros
worldPuntero al mundo que contiene el array de cuerpos y los ajustes de simulación.
Valor devuelto
Sin valor de retorno. Esta entrada describe qué campos se actualizan y cuándo surten efecto los cambios.
Condiciones y límites
Usa unidades enteras coherentes para posiciones, radios, semiextensiones, velocidades y gravedad. Cada paso equivale a un tick de simulación. Los ejemplos usan una unidad por píxel. Estas rutinas no convierten automáticamente las posiciones a Q8.8 ni las dibujan.
El mundo utiliza un array prestado. El código que llama reserva y posee la memoria de los cuerpos y debe mantenerla válida. Inicializar el mundo no inicializa los elementos del array.
Mantén las sumas, diferencias, sumas de semiextensiones y productos de corrección de contactos dentro del rango de 16 bits con signo. Los límites de velocidad se aplican después de sumar y no pueden evitar un desbordamiento durante esa suma.
Las rutinas de integración y colisión de cajas comparten memoria temporal. No vuelvas a entrar en estas rutinas de física desde una interrupción.
physics3d.c reside en el banco ROM 2. El ejemplo usa una ROM MBC5 de 128 KB, incluye primero esta implementación y sitúa main en el banco 0. No cambies el mapeo de ROM desde fuera durante una llamada.
Los contactos usan el eje de menor penetración, con prioridad X, Y y Z en caso de empate. Solo hay rebote si los cuerpos se están acercando; se calcula con las masas inversas y la restitución media limitada a 0..256. No se gestionan el efecto túnel a alta velocidad, la rotación, el momento angular ni la fricción.
last_impact_speed registra la máxima velocidad de acercamiento en un eje de contacto. La integración la borra para los cuerpos dinámicos activos; los estáticos e inactivos la conservan. Ni break_speed ni KQ3D_BODY_BROKEN provocan una destrucción automática. El juego decide cuándo romper un cuerpo y modifica flags/active por su cuenta.
Ignora un mundo o array NULL. Aunque solver_iterations valga cero, realiza una pasada de contactos.
Los productos intermedios impact*(256+restitution) y correction*inverse-mass también son s16. Mantén los productos en 32767 como máximo; por ejemplo, con restitution 256, impact no debe superar 63.
Ejemplo de uso
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;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
A la izquierda está la vista frontal X/Y y a la derecha, la vista superior X/Z. Los contornos verdes marcan la posición inicial (24,24,16); las cajas rojas muestran (36,24,24) tras un tick; las zonas azules son el obstáculo estático. La velocidad X rebota de 16 a -14, mientras que la velocidad Z se mantiene en 8. El impacto es 16, pero flags permanece en cero pese a break_speed=1. Los orígenes de los paneles están en (8,48)/(88,48) de la pantalla. En DMG, todas las marcas son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body3d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/physics3d.h:61
Integrate active dynamic bodies and reset their impact values, then solve each active unordered pair for the configured passes (zero means one). Static bodies retain previous impact maxima until the game clears them. Acceleration persists; flags and break thresholds remain game-owned. This discrete solver shares non-reentrant ASM scratch and can miss fast crossings.
kitaqgb/lib/physics3d.c:492
void kq3d_step(KQWorld3D* world)
{
if (world == 0) return;
if (world->bodies == 0) return;
KQBody3D* bodies = world->bodies;
u8 count = world->body_count;
u8 i;
for (i = 0; i < count; i++)
{
KQBody3D* b = &bodies[(__safe_index u8)i];
if (b->active == 0) continue;
if (b->inv_mass_q8 <= 0) continue;
b->last_impact_speed = 0;
kq3d_asm_value = b->vx;
kq3d_asm_operand = world->gravity_x;
kq3d_add_s16_asm();
kq3d_asm_operand = b->ax;
kq3d_add_s16_asm();
kq3d_asm_limit = world->max_speed;
kq3d_clamp_abs_s16_asm();
b->vx = kq3d_asm_value;
kq3d_asm_value = b->vy;
kq3d_asm_operand = world->gravity_y;
kq3d_add_s16_asm();
kq3d_asm_operand = b->ay;
kq3d_add_s16_asm();
kq3d_asm_limit = world->max_speed;
kq3d_clamp_abs_s16_asm();
b->vy = kq3d_asm_value;
kq3d_asm_value = b->vz;
kq3d_asm_operand = world->gravity_z;
kq3d_add_s16_asm();
kq3d_asm_operand = b->az;
kq3d_add_s16_asm();
kq3d_asm_limit = world->max_speed;
kq3d_clamp_abs_s16_asm();
b->vz = kq3d_asm_value;
kq3d_asm_value = b->x;
kq3d_asm_operand = b->vx;
kq3d_add_s16_asm();
b->x = kq3d_asm_value;
kq3d_asm_value = b->y;
kq3d_asm_operand = b->vy;
kq3d_add_s16_asm();
b->y = kq3d_asm_value;
kq3d_asm_value = b->z;
kq3d_asm_operand = b->vz;
kq3d_add_s16_asm();
b->z = kq3d_asm_value;
}
u8 iterations = world->solver_iterations;
if (iterations == 0) iterations = 1;
u8 it;
for (it = 0; it < iterations; it++)
{
for (i = 0; i < count; i++)
{
KQBody3D* a = &bodies[(__safe_index u8)i];
if (a->active == 0) continue;
u8 j;
for (j = (u8)(i + 1); j < count; j++)
{
KQBody3D* b = &bodies[(__safe_index u8)j];
if (b->active == 0) continue;
kq3d__resolve_pair(a, b);
}
}
}
}kq3d_world_init
Asocia un array de cuerpos a un mundo 3D con gravedad (0,24,0), cuatro pasadas y límite de velocidad por eje 512.
Sintaxis
void kq3d_world_init(KQWorld3D* world, KQBody3D* bodies, u8 body_count);Parámetros
worldPuntero al mundo que contiene el array de cuerpos y los ajustes de simulación.
bodiesInicio de un array de cuerpos propiedad del código que llama, con body_count elementos.
body_countNúmero de posiciones del array, de 0 a 255, incluidas las entradas inactivas.
Valor devuelto
Sin valor de retorno. Esta entrada describe qué campos se actualizan y cuándo surten efecto los cambios.
Condiciones y límites
Usa unidades enteras coherentes para posiciones, radios, semiextensiones, velocidades y gravedad. Cada paso equivale a un tick de simulación. Los ejemplos usan una unidad por píxel. Estas rutinas no convierten automáticamente las posiciones a Q8.8 ni las dibujan.
El mundo utiliza un array prestado. El código que llama reserva y posee la memoria de los cuerpos y debe mantenerla válida. Inicializar el mundo no inicializa los elementos del array.
physics3d.c reside en el banco ROM 2. El ejemplo usa una ROM MBC5 de 128 KB, incluye primero esta implementación y sitúa main en el banco 0. No cambies el mapeo de ROM desde fuera durante una llamada.
Ejemplo de uso
kq3d_world_init(&world,bodies,2);
result[0]=world.gravity_y; result[1]=world.solver_iterations; result[2]=world.max_speed;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
A la izquierda está la vista frontal X/Y y a la derecha, la vista superior X/Z. Los contornos verdes marcan la posición inicial (24,24,16); las cajas rojas muestran (36,24,24) tras un tick; las zonas azules son el obstáculo estático. La velocidad X rebota de 16 a -14, mientras que la velocidad Z se mantiene en 8. El impacto es 16, pero flags permanece en cero pese a break_speed=1. Los orígenes de los paneles están en (8,48)/(88,48) de la pantalla. En DMG, todas las marcas son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body3d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/physics3d.h:46
Borrow the body array without initializing it. Set gravity (0,24,0), four contact passes and a per-axis speed limit of 512. Null world is ignored; the caller retains ownership and must keep the array alive.
kitaqgb/lib/physics3d.c:294
void kq3d_world_init(KQWorld3D* world, KQBody3D* bodies, u8 body_count)
{
if (world == 0) return;
world->bodies = bodies;
world->body_count = body_count;
world->gravity_x = 0;
world->gravity_y = 24;
world->gravity_z = 0;
world->solver_iterations = 4;
world->max_speed = 512;
}raster.h — Tablas de desplazamiento por franjas y líneas de barrido
La biblioteca Raster ofrece una tabla de ocho franjas y un renderizador LineX que cambia X en las 144 líneas visibles. Las franjas sirven para HUD fijos, paralaje, cambios de ventana y regiones de color CGB. LineX sirve para títulos ondulantes y efectos de pantalla. Elige un controlador; no ejecutes ambos a la vez.
Incluye raster.h y compila raster.c junto con scroll.c. Una tabla compartida admite hasta ocho franjas. Mientras la construyes con Raster_*, no intercales llamadas directas a Scroll_Split* ni a __scroll_split_*: no actualizan el recuento ni el registro de la última línea de la capa Raster.
Reconstruye durante VBlank o en otro intervalo en el que controles el efecto sobre la imagen: borra, añade entradas y confirma. Borrar también detiene las divisiones activas; no estás editando un búfer secundario independiente. LY programa una interrupción y las escrituras en registros requieren tiempo adicional. Para ondas por línea de barrido, usa la familia independiente Raster_LineX*; no ejecutes ambos controladores a la vez.
Onda por líneas de barrido y entrada animada del título
Cambiar la posición X del fondo en cada línea de pantalla hace ondular los pilares y las letras. Este efecto sirve para una teletransportación, la aparición de un jefe o un título. La vista previa inferior recorre ocho capturas; en la ROM, la fase de la onda avanza en cada fotograma.
Las operaciones Raster_Push programan hasta ocho franjas. Use Raster_LineXRunFrame para asignar un desplazamiento horizontal distinto a cada línea. Los sprites y la ventana no se deforman. El renderizador ocupa la CPU y enmascara las interrupciones durante las 144 líneas visibles; actualice la lógica y el audio del juego entre llamadas.

El título entra por la derecha con una onda grande, pasa a una ondulación pequeña y finalmente se estabiliza. Incluye raster_wave.c del mismo directorio, así que mantenga ambos archivos fuente juntos. Las entradas de API inferiores incluyen comandos de compilación y notas de uso individuales.
La biblioteca Raster ofrece una tabla de ocho franjas y un renderizador LineX que cambia X en las 144 líneas visibles. Las franjas sirven para HUD fijos, paralaje, cambios de ventana y regiones de color CGB. LineX sirve para títulos ondulantes y efectos de pantalla. Elige un controlador; no ejecutes ambos a la vez.
Incluye raster.h y compila raster.c junto con scroll.c. Una tabla compartida admite hasta ocho franjas. Mientras la construyes con Raster_*, no intercales llamadas directas a Scroll_Split* ni a __scroll_split_*: no actualizan el recuento ni el registro de la última línea de la capa Raster.
Reconstruye durante VBlank o en otro intervalo en el que controles el efecto sobre la imagen: borra, añade entradas y confirma. Borrar también detiene las divisiones activas; no estás editando un búfer secundario independiente. LY programa una interrupción y las escrituras en registros requieren tiempo adicional. Para ondas por línea de barrido, usa la familia independiente Raster_LineX*; no ejecutes ambos controladores a la vez.
Raster_BuildHudBottom
Construye una zona de juego superior desplazable y un HUD inferior fijo. LY=0 usa las coordenadas de cámara; hud_y cambia al fondo (0,0).
Sintaxis
u8 Raster_BuildHudBottom(u8 hud_y, u8 camera_x, u8 camera_y);Parámetros
hud_yLínea de división, de 1 a 143. Cero o valores de 144 en adelante devuelven BAD_RANGE.
camera_xByte de desplazamiento del fondo, de 0 a 255. SCX/SCY indican desde dónde leer el mapa de fondo, no una posición en pantalla. Las coordenadas se repiten en el fondo de 256 píxeles.
camera_yByte de desplazamiento del fondo, de 0 a 255. SCX/SCY indican desde dónde leer el mapa de fondo, no una posición en pantalla. Las coordenadas se repiten en el fondo de 256 píxeles.
Valor devuelto
Devuelve KQ_RASTER_OK (0) si tiene éxito o un estado de error de 1 a 4. Consulta las restricciones de la función y Raster_GetLastError.
Condiciones y límites
Incluye raster.h y compila raster.c junto con scroll.c. Una tabla compartida admite hasta ocho franjas. Mientras la construyes con Raster_*, no intercales llamadas directas a Scroll_Split* ni a __scroll_split_*: no actualizan el recuento ni el registro de la última línea de la capa Raster.
Reconstruye durante VBlank o en otro intervalo en el que controles el efecto sobre la imagen: borra, añade entradas y confirma. Borrar también detiene las divisiones activas; no estás editando un búfer secundario independiente. LY programa una interrupción y las escrituras en registros requieren tiempo adicional. Para ondas por línea de barrido, usa la familia independiente Raster_LineX*; no ejecutes ambos controladores a la vez.
Los códigos de estado son 0 OK, 1 FULL, 2 BAD_LY, 3 UNSORTED y 4 BAD_RANGE. Las inserciones comprueban, en este orden, el rango de LY, la capacidad y el orden de las líneas. Una entrada rechazada no aumenta la tabla. Una inserción posterior correcta o un borrado pone el error a cero; comprueba el retorno de cada llamada en ese momento.
Con parámetros válidos, detiene las divisiones existentes, vacía la tabla y añade las nuevas franjas. Con parámetros inválidos, conserva la tabla y el recuento y guarda BAD_RANGE. Aunque la construcción tenga éxito, sigue siendo necesario llamar a Raster_Commit.
Ejemplo de uso
Raster_BuildHudBottom(96,8,8);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Las filas desde la 96 hacia abajo permanecen fijas. La cámara (8,8) coloca los rectángulos superiores en (24,8) y (24,72), mientras el inferior sigue en (32,112). FIXED BOTTOM HUD permanece abajo.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_hud_bottom.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/raster.h:73
Build a scrolling upper playfield and fixed bottom HUD after validating the split.
kitaqgb/lib/raster.c:183
u8 Raster_BuildHudBottom(u8 hud_y, u8 camera_x, u8 camera_y)
{
u8 r;
if (hud_y == 0) return Raster_SetError(KQ_RASTER_BAD_RANGE);
if (hud_y >= 144) return Raster_SetError(KQ_RASTER_BAD_RANGE);
Raster_Clear();
r = Raster_Push(0, camera_x, camera_y);
if (r != KQ_RASTER_OK) return r;
return Raster_Push(hud_y, 0, 0);
}Raster_BuildHudTop
Construye dos franjas de fondo para un HUD superior fijo: (0,0) en LY=0 y después las coordenadas de cámara en hud_height. Divide el desplazamiento del fondo; no usa la ventana.
Sintaxis
u8 Raster_BuildHudTop(u8 hud_height, u8 camera_x, u8 camera_y);Parámetros
hud_heightLínea de división, de 1 a 143. Cero o valores de 144 en adelante devuelven BAD_RANGE.
camera_xByte de desplazamiento del fondo, de 0 a 255. SCX/SCY indican desde dónde leer el mapa de fondo, no una posición en pantalla. Las coordenadas se repiten en el fondo de 256 píxeles.
camera_yByte de desplazamiento del fondo, de 0 a 255. SCX/SCY indican desde dónde leer el mapa de fondo, no una posición en pantalla. Las coordenadas se repiten en el fondo de 256 píxeles.
Valor devuelto
Devuelve KQ_RASTER_OK (0) si tiene éxito o un estado de error de 1 a 4. Consulta las restricciones de la función y Raster_GetLastError.
Condiciones y límites
Incluye raster.h y compila raster.c junto con scroll.c. Una tabla compartida admite hasta ocho franjas. Mientras la construyes con Raster_*, no intercales llamadas directas a Scroll_Split* ni a __scroll_split_*: no actualizan el recuento ni el registro de la última línea de la capa Raster.
Reconstruye durante VBlank o en otro intervalo en el que controles el efecto sobre la imagen: borra, añade entradas y confirma. Borrar también detiene las divisiones activas; no estás editando un búfer secundario independiente. LY programa una interrupción y las escrituras en registros requieren tiempo adicional. Para ondas por línea de barrido, usa la familia independiente Raster_LineX*; no ejecutes ambos controladores a la vez.
Los códigos de estado son 0 OK, 1 FULL, 2 BAD_LY, 3 UNSORTED y 4 BAD_RANGE. Las inserciones comprueban, en este orden, el rango de LY, la capacidad y el orden de las líneas. Una entrada rechazada no aumenta la tabla. Una inserción posterior correcta o un borrado pone el error a cero; comprueba el retorno de cada llamada en ese momento.
Con parámetros válidos, detiene las divisiones existentes, vacía la tabla y añade las nuevas franjas. Con parámetros inválidos, conserva la tabla y el recuento y guarda BAD_RANGE. Aunque la construcción tenga éxito, sigue siendo necesario llamar a Raster_Commit.
Ejemplo de uso
Raster_BuildHudTop(32,8,8);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Las 32 primeras filas permanecen fijas. El rectángulo superior sigue en (32,16); la cámara (8,8) mueve los otros dos a (24,72) y (24,104). FIXED TOP HUD permanece arriba.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_hud_top.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/raster.h:71
Validate the HUD height, then replace pending splits with a fixed top band and scrolling playfield. The new table still requires an explicit commit.
kitaqgb/lib/raster.c:169
u8 Raster_BuildHudTop(u8 hud_height, u8 camera_x, u8 camera_y)
{
u8 r;
if (hud_height == 0) return Raster_SetError(KQ_RASTER_BAD_RANGE);
if (hud_height >= 144) return Raster_SetError(KQ_RASTER_BAD_RANGE);
Raster_Clear();
r = Raster_Push(0, 0, 0);
if (r != KQ_RASTER_OK) return r;
return Raster_Push(hud_height, camera_x, camera_y);
}Raster_BuildParallax2
Construye dos franjas de fondo con desplazamientos horizontales distintos: far_scx en LY=0 y near_scx desde split_y, compartiendo el desplazamiento Y.
Sintaxis
u8 Raster_BuildParallax2(u8 split_y, u8 far_scx, u8 near_scx, u8 scy);Parámetros
split_yLínea de división, de 1 a 143. Cero o valores de 144 en adelante devuelven BAD_RANGE.
far_scxByte de desplazamiento del fondo, de 0 a 255. SCX/SCY indican desde dónde leer el mapa de fondo, no una posición en pantalla. Las coordenadas se repiten en el fondo de 256 píxeles.
near_scxByte de desplazamiento del fondo, de 0 a 255. SCX/SCY indican desde dónde leer el mapa de fondo, no una posición en pantalla. Las coordenadas se repiten en el fondo de 256 píxeles.
scyByte de desplazamiento del fondo, de 0 a 255. SCX/SCY indican desde dónde leer el mapa de fondo, no una posición en pantalla. Las coordenadas se repiten en el fondo de 256 píxeles.
Valor devuelto
Devuelve KQ_RASTER_OK (0) si tiene éxito o un estado de error de 1 a 4. Consulta las restricciones de la función y Raster_GetLastError.
Condiciones y límites
Incluye raster.h y compila raster.c junto con scroll.c. Una tabla compartida admite hasta ocho franjas. Mientras la construyes con Raster_*, no intercales llamadas directas a Scroll_Split* ni a __scroll_split_*: no actualizan el recuento ni el registro de la última línea de la capa Raster.
Reconstruye durante VBlank o en otro intervalo en el que controles el efecto sobre la imagen: borra, añade entradas y confirma. Borrar también detiene las divisiones activas; no estás editando un búfer secundario independiente. LY programa una interrupción y las escrituras en registros requieren tiempo adicional. Para ondas por línea de barrido, usa la familia independiente Raster_LineX*; no ejecutes ambos controladores a la vez.
Los códigos de estado son 0 OK, 1 FULL, 2 BAD_LY, 3 UNSORTED y 4 BAD_RANGE. Las inserciones comprueban, en este orden, el rango de LY, la capacidad y el orden de las líneas. Una entrada rechazada no aumenta la tabla. Una inserción posterior correcta o un borrado pone el error a cero; comprueba el retorno de cada llamada en ese momento.
Con parámetros válidos, detiene las divisiones existentes, vacía la tabla y añade las nuevas franjas. Con parámetros inválidos, conserva la tabla y el recuento y guarda BAD_RANGE. Aunque la construcción tenga éxito, sigue siendo necesario llamar a Raster_Commit.
Ejemplo de uso
Raster_BuildParallax2(64,0,16,0);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
X cambia de 0 a 16 en la línea programada 64. Los rectángulos aparecen en (32,16), (16,80) y (16,112); solo la zona inferior se desplaza dieciséis píxeles a la izquierda.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_parallax2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/raster.h:76
Build two horizontal-scroll bands sharing one vertical scroll value.
kitaqgb/lib/raster.c:197
u8 Raster_BuildParallax2(u8 split_y, u8 far_scx, u8 near_scx, u8 scy)
{
u8 r;
if (split_y == 0) return Raster_SetError(KQ_RASTER_BAD_RANGE);
if (split_y >= 144) return Raster_SetError(KQ_RASTER_BAD_RANGE);
Raster_Clear();
r = Raster_Push(0, far_scx, scy);
if (r != KQ_RASTER_OK) return r;
return Raster_Push(split_y, near_scx, scy);
}Raster_BuildParallax3
Registra scx0, scx1 y scx2 para franjas que empiezan en LY=0, y1 e y2. Asigna distintos desplazamientos horizontales a las capas lejana, intermedia y cercana, con desplazamiento Y compartido.
Sintaxis
u8 Raster_BuildParallax3(u8 y1, u8 y2, u8 scx0, u8 scx1, u8 scx2, u8 scy);Parámetros
y1Líneas de división; deben cumplir 1 <= y1 < y2 <= 143.
y2Líneas de división; deben cumplir 1 <= y1 < y2 <= 143.
scx0Byte de desplazamiento del fondo, de 0 a 255. SCX/SCY indican desde dónde leer el mapa de fondo, no una posición en pantalla. Las coordenadas se repiten en el fondo de 256 píxeles.
scx1Byte de desplazamiento del fondo, de 0 a 255. SCX/SCY indican desde dónde leer el mapa de fondo, no una posición en pantalla. Las coordenadas se repiten en el fondo de 256 píxeles.
scx2Byte de desplazamiento del fondo, de 0 a 255. SCX/SCY indican desde dónde leer el mapa de fondo, no una posición en pantalla. Las coordenadas se repiten en el fondo de 256 píxeles.
scyByte de desplazamiento del fondo, de 0 a 255. SCX/SCY indican desde dónde leer el mapa de fondo, no una posición en pantalla. Las coordenadas se repiten en el fondo de 256 píxeles.
Valor devuelto
Devuelve KQ_RASTER_OK (0) si tiene éxito o un estado de error de 1 a 4. Consulta las restricciones de la función y Raster_GetLastError.
Condiciones y límites
Incluye raster.h y compila raster.c junto con scroll.c. Una tabla compartida admite hasta ocho franjas. Mientras la construyes con Raster_*, no intercales llamadas directas a Scroll_Split* ni a __scroll_split_*: no actualizan el recuento ni el registro de la última línea de la capa Raster.
Reconstruye durante VBlank o en otro intervalo en el que controles el efecto sobre la imagen: borra, añade entradas y confirma. Borrar también detiene las divisiones activas; no estás editando un búfer secundario independiente. LY programa una interrupción y las escrituras en registros requieren tiempo adicional. Para ondas por línea de barrido, usa la familia independiente Raster_LineX*; no ejecutes ambos controladores a la vez.
Los códigos de estado son 0 OK, 1 FULL, 2 BAD_LY, 3 UNSORTED y 4 BAD_RANGE. Las inserciones comprueban, en este orden, el rango de LY, la capacidad y el orden de las líneas. Una entrada rechazada no aumenta la tabla. Una inserción posterior correcta o un borrado pone el error a cero; comprueba el retorno de cada llamada en ese momento.
Con parámetros válidos, detiene las divisiones existentes, vacía la tabla y añade las nuevas franjas. Con parámetros inválidos, conserva la tabla y el recuento y guarda BAD_RANGE. Aunque la construcción tenga éxito, sigue siendo necesario llamar a Raster_Commit.
Ejemplo de uso
Raster_BuildParallax3(64,104,0,8,16,0);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Las líneas programadas 64 y 104 delimitan los desplazamientos X de 0, 8 y 16. Los rectángulos en (32,16), (24,80) y (16,112) muestran el desplazamiento creciente de las tres franjas.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_parallax3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/raster.h:79
Build three horizontal-scroll bands at ordered visible split lines. Invalid parameters leave the previous pending table intact and set the error status.
kitaqgb/lib/raster.c:212
u8 Raster_BuildParallax3(u8 y1, u8 y2, u8 scx0, u8 scx1, u8 scx2, u8 scy)
{
u8 r;
if (y1 == 0) return Raster_SetError(KQ_RASTER_BAD_RANGE);
if (y2 >= 144) return Raster_SetError(KQ_RASTER_BAD_RANGE);
if (y2 <= y1) return Raster_SetError(KQ_RASTER_BAD_RANGE);
Raster_Clear();
r = Raster_Push(0, scx0, scy);
if (r != KQ_RASTER_OK) return r;
r = Raster_Push(y1, scx1, scy);
if (r != KQ_RASTER_OK) return r;
return Raster_Push(y2, scx2, scy);
}Raster_Clear
Detiene inmediatamente la programación de divisiones y reinicia el recuento, el orden y el estado de error antes de reconstruir la tabla en la misma escena. No pone a cero todos los bytes de la memoria de la tabla.
Sintaxis
void Raster_Clear();Valor devuelto
No devuelve ningún valor.
Condiciones y límites
Incluye raster.h y compila raster.c junto con scroll.c. Una tabla compartida admite hasta ocho franjas. Mientras la construyes con Raster_*, no intercales llamadas directas a Scroll_Split* ni a __scroll_split_*: no actualizan el recuento ni el registro de la última línea de la capa Raster.
Reconstruye durante VBlank o en otro intervalo en el que controles el efecto sobre la imagen: borra, añade entradas y confirma. Borrar también detiene las divisiones activas; no estás editando un búfer secundario independiente. LY programa una interrupción y las escrituras en registros requieren tiempo adicional. Para ondas por línea de barrido, usa la familia independiente Raster_LineX*; no ejecutes ambos controladores a la vez.
Los códigos de estado son 0 OK, 1 FULL, 2 BAD_LY, 3 UNSORTED y 4 BAD_RANGE. Las inserciones comprueban, en este orden, el rango de LY, la capacidad y el orden de las líneas. Una entrada rechazada no aumenta la tabla. Una inserción posterior correcta o un borrado pone el error a cero; comprueba el retorno de cada llamada en ese momento.
Detener las divisiones no pone SCX, SCY, WX ni WY a cero. Usa funciones normales como Scroll_SetBg para establecer el estado base deseado. Estas funciones tampoco restauran los bits IE de VBlank/STAT ni IME anteriores.
Ejemplo de uso
Raster_Clear();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Aparecen rectángulos rojos de 24x16 píxeles, negros en DMG, en (32,16), (24,80) y (16,112). Las franjas inferiores se desplazan más hacia la izquierda. Los resultados internos registran un recuento de 3, error 0 y resultado de confirmación 0.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_bands.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/raster.h:39
Stop splits immediately and clear bookkeeping. Build and commit a new table to restart.
kitaqgb/lib/raster.c:65
void Raster_Clear()
{
Scroll_SplitReset();
Raster_CountValue = 0;
Raster_LastLyValue = 0;
Raster_HasLastLy = 0;
Raster_LastErrorValue = KQ_RASTER_OK;
}Raster_Commit
Activa la tabla compartida construida. Aunque una inserción anterior haya fallado, se activan las entradas añadidas correctamente antes de ella; el código que llama debe comprobar cada registro.
Sintaxis
u8 Raster_Commit();Valor devuelto
Devuelve el último error guardado. Cero no demuestra que todos los registros anteriores hayan tenido éxito.
Condiciones y límites
Incluye raster.h y compila raster.c junto con scroll.c. Una tabla compartida admite hasta ocho franjas. Mientras la construyes con Raster_*, no intercales llamadas directas a Scroll_Split* ni a __scroll_split_*: no actualizan el recuento ni el registro de la última línea de la capa Raster.
Reconstruye durante VBlank o en otro intervalo en el que controles el efecto sobre la imagen: borra, añade entradas y confirma. Borrar también detiene las divisiones activas; no estás editando un búfer secundario independiente. LY programa una interrupción y las escrituras en registros requieren tiempo adicional. Para ondas por línea de barrido, usa la familia independiente Raster_LineX*; no ejecutes ambos controladores a la vez.
Los códigos de estado son 0 OK, 1 FULL, 2 BAD_LY, 3 UNSORTED y 4 BAD_RANGE. Las inserciones comprueban, en este orden, el rango de LY, la capacidad y el orden de las líneas. Una entrada rechazada no aumenta la tabla. Una inserción posterior correcta o un borrado pone el error a cero; comprueba el retorno de cada llamada en ese momento.
Una tabla no vacía activa los bits IE de VBlank/STAT y ejecuta EI para habilitar las interrupciones; conserva los demás bits IE. Una tabla vacía desactiva la programación de divisiones sin restaurar la configuración global de interrupciones.
Ejemplo de uso
result[2]=Raster_Commit();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Aparecen rectángulos rojos de 24x16 píxeles, negros en DMG, en (32,16), (24,80) y (16,112). Las franjas inferiores se desplazan más hacia la izquierda. Los resultados internos registran un recuento de 3, error 0 y resultado de confirmación 0.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_bands.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/raster.h:67
Publish pending splits and return the stored status. This commits even if an earlier append failed; callers should inspect errors while building the table.
kitaqgb/lib/raster.c:161
u8 Raster_Commit()
{
Scroll_SplitCommit();
return Raster_LastErrorValue;
}Raster_Disable
Borra y confirma una tabla vacía para desactivar las franjas ráster. Úsalo como parada explícita al entrar en una escena sin desplazamiento dividido.
Sintaxis
void Raster_Disable();Valor devuelto
No devuelve ningún valor.
Condiciones y límites
Incluye raster.h y compila raster.c junto con scroll.c. Una tabla compartida admite hasta ocho franjas. Mientras la construyes con Raster_*, no intercales llamadas directas a Scroll_Split* ni a __scroll_split_*: no actualizan el recuento ni el registro de la última línea de la capa Raster.
Reconstruye durante VBlank o en otro intervalo en el que controles el efecto sobre la imagen: borra, añade entradas y confirma. Borrar también detiene las divisiones activas; no estás editando un búfer secundario independiente. LY programa una interrupción y las escrituras en registros requieren tiempo adicional. Para ondas por línea de barrido, usa la familia independiente Raster_LineX*; no ejecutes ambos controladores a la vez.
Los códigos de estado son 0 OK, 1 FULL, 2 BAD_LY, 3 UNSORTED y 4 BAD_RANGE. Las inserciones comprueban, en este orden, el rango de LY, la capacidad y el orden de las líneas. Una entrada rechazada no aumenta la tabla. Una inserción posterior correcta o un borrado pone el error a cero; comprueba el retorno de cada llamada en ese momento.
Detener las divisiones no pone SCX, SCY, WX ni WY a cero. Usa funciones normales como Scroll_SetBg para establecer el estado base deseado. Estas funciones tampoco restauran los bits IE de VBlank/STAT ni IME anteriores.
Ejemplo de uso
Raster_Disable();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Aparecen rectángulos rojos de 24x16 píxeles, negros en DMG, en (32,16), (24,80) y (16,112). Las franjas inferiores se desplazan más hacia la izquierda. Los resultados internos registran un recuento de 3, error 0 y resultado de confirmación 0.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_bands.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/raster.h:41
Commit an empty split table so no raster bands remain active.
kitaqgb/lib/raster.c:75
void Raster_Disable()
{
Raster_Clear();
Scroll_SplitCommit();
}Raster_GetCount
Lee el número de franjas registradas mediante la capa Raster. Clear/Disable lo pone a cero; confirmar por sí solo lo conserva.
Sintaxis
u8 Raster_GetCount();Valor devuelto
Devuelve el número de entradas, de 0 a 8. Réstalo de ocho para obtener la capacidad restante. La lectura no altera el estado.
Condiciones y límites
Incluye raster.h y compila raster.c junto con scroll.c. Una tabla compartida admite hasta ocho franjas. Mientras la construyes con Raster_*, no intercales llamadas directas a Scroll_Split* ni a __scroll_split_*: no actualizan el recuento ni el registro de la última línea de la capa Raster.
Reconstruye durante VBlank o en otro intervalo en el que controles el efecto sobre la imagen: borra, añade entradas y confirma. Borrar también detiene las divisiones activas; no estás editando un búfer secundario independiente. LY programa una interrupción y las escrituras en registros requieren tiempo adicional. Para ondas por línea de barrido, usa la familia independiente Raster_LineX*; no ejecutes ambos controladores a la vez.
Los códigos de estado son 0 OK, 1 FULL, 2 BAD_LY, 3 UNSORTED y 4 BAD_RANGE. Las inserciones comprueban, en este orden, el rango de LY, la capacidad y el orden de las líneas. Una entrada rechazada no aumenta la tabla. Una inserción posterior correcta o un borrado pone el error a cero; comprueba el retorno de cada llamada en ese momento.
Ejemplo de uso
result[0]=Raster_GetCount();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Aparecen rectángulos rojos de 24x16 píxeles, negros en DMG, en (32,16), (24,80) y (16,112). Las franjas inferiores se desplazan más hacia la izquierda. Los resultados internos registran un recuento de 3, error 0 y resultado de confirmación 0.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_bands.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/raster.h:44
Read the number of bands currently recorded by this wrapper.
kitaqgb/lib/raster.c:82
u8 Raster_GetCount()
{
return Raster_CountValue;
}Raster_GetLastError
Lee el último estado Raster guardado sin borrarlo. No es un registro acumulado de todos los fallos anteriores.
Sintaxis
u8 Raster_GetLastError();Valor devuelto
Devuelve el estado guardado, de 0 a 4. La confirmación devuelve este valor, pero no deshace automáticamente un fallo ni descarta la tabla.
Condiciones y límites
Incluye raster.h y compila raster.c junto con scroll.c. Una tabla compartida admite hasta ocho franjas. Mientras la construyes con Raster_*, no intercales llamadas directas a Scroll_Split* ni a __scroll_split_*: no actualizan el recuento ni el registro de la última línea de la capa Raster.
Reconstruye durante VBlank o en otro intervalo en el que controles el efecto sobre la imagen: borra, añade entradas y confirma. Borrar también detiene las divisiones activas; no estás editando un búfer secundario independiente. LY programa una interrupción y las escrituras en registros requieren tiempo adicional. Para ondas por línea de barrido, usa la familia independiente Raster_LineX*; no ejecutes ambos controladores a la vez.
Los códigos de estado son 0 OK, 1 FULL, 2 BAD_LY, 3 UNSORTED y 4 BAD_RANGE. Las inserciones comprueban, en este orden, el rango de LY, la capacidad y el orden de las líneas. Una entrada rechazada no aumenta la tabla. Una inserción posterior correcta o un borrado pone el error a cero; comprueba el retorno de cada llamada en ese momento.
Ejemplo de uso
result[1]=Raster_GetLastError();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Aparecen rectángulos rojos de 24x16 píxeles, negros en DMG, en (32,16), (24,80) y (16,112). Las franjas inferiores se desplazan más hacia la izquierda. Los resultados internos registran un recuento de 3, error 0 y resultado de confirmación 0.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_bands.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/raster.h:46
Read the last stored status without clearing it.
kitaqgb/lib/raster.c:88
u8 Raster_GetLastError()
{
return Raster_LastErrorValue;
}Raster_Init
Vacía la tabla compartida de franjas, detiene las divisiones e inicializa el recuento, la validez del último LY y el estado de error. A diferencia de Scroll_Init, no inicializa las coordenadas del fondo ni de la ventana.
Sintaxis
void Raster_Init();Valor devuelto
No devuelve ningún valor.
Condiciones y límites
Incluye raster.h y compila raster.c junto con scroll.c. Una tabla compartida admite hasta ocho franjas. Mientras la construyes con Raster_*, no intercales llamadas directas a Scroll_Split* ni a __scroll_split_*: no actualizan el recuento ni el registro de la última línea de la capa Raster.
Reconstruye durante VBlank o en otro intervalo en el que controles el efecto sobre la imagen: borra, añade entradas y confirma. Borrar también detiene las divisiones activas; no estás editando un búfer secundario independiente. LY programa una interrupción y las escrituras en registros requieren tiempo adicional. Para ondas por línea de barrido, usa la familia independiente Raster_LineX*; no ejecutes ambos controladores a la vez.
Los códigos de estado son 0 OK, 1 FULL, 2 BAD_LY, 3 UNSORTED y 4 BAD_RANGE. Las inserciones comprueban, en este orden, el rango de LY, la capacidad y el orden de las líneas. Una entrada rechazada no aumenta la tabla. Una inserción posterior correcta o un borrado pone el error a cero; comprueba el retorno de cada llamada en ese momento.
Detener las divisiones no pone SCX, SCY, WX ni WY a cero. Usa funciones normales como Scroll_SetBg para establecer el estado base deseado. Estas funciones tampoco restauran los bits IE de VBlank/STAT ni IME anteriores.
Ejemplo de uso
Raster_Init();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Aparecen rectángulos rojos de 24x16 píxeles, negros en DMG, en (32,16), (24,80) y (16,112). Las franjas inferiores se desplazan más hacia la izquierda. Los resultados internos registran un recuento de 3, error 0 y resultado de confirmación 0.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_bands.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/raster.h:37
Stop split scheduling, empty the shared table and clear error/count state.
kitaqgb/lib/raster.c:59
void Raster_Init()
{
Raster_Clear();
}Raster_LineXGetOffset
Calcula SCX para la línea solicitada sin cambiar el estado, la imagen ni la fase.
Sintaxis
u8 Raster_LineXGetOffset(const RasterLineX* effect, u8 ly);Parámetros
effectPuntero a un RasterLineX inicializado que siga siendo válido durante toda la llamada.
lyCoordenada de línea a consultar (0..255); las líneas visibles son 0..143. La consulta se repite según el período de la onda en lugar de devolver un error de rango.
Valor devuelto
SCX de ocho bits igual a la X base más el desplazamiento de esa fila. La consulta del ejemplo en fase 8, línea 0 devuelve 17.
Condiciones y límites
SCX es un valor de ocho bits y el fondo se repite cada 256 píxeles. Los desplazamientos negativos usan valores de byte módulo 256. Rellena también el mapa más allá del área visible.
El efecto modifica el desplazamiento horizontal del fondo; los sprites y la ventana no se deforman. RunFrame ocupa la CPU y bloquea las interrupciones durante las 144 líneas visibles. Actualiza la lógica del juego y el audio entre llamadas y no combines este renderizador con un controlador ráster basado en interrupciones STAT.
Las imágenes proceden de ejecuciones DMG y CGB en KOKURA. Cada píxel de la escena de 160×144, incluidos pilares y texto, se compara con las coordenadas esperadas por línea. No se han probado los tiempos en hardware real.
Coloca kitaqgb, kokura y kitaq-docs bajo un mismo directorio padre y abre PowerShell allí. La ROM admite DMG y CGB; selecciona dmg o cgb con KOKURA --hardware.
Ejemplo de uso
wave_lookup = Raster_LineXGetOffset(&wave, 0);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Los pilares y las letras se curvan horizontalmente hasta 24 píxeles. Una onda abarca 64 líneas de barrido y su fase avanza una línea por fotograma. En CGB, pilares y letras son azules. Fíjate en que cada fila tenga un desplazamiento horizontal distinto, en lugar de moverse toda la pantalla por igual.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_wave.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_wave.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
.\kokura\kokura-cli.exe .\out\raster_wave.gb --hardware cgb --run-frames 120 --png .\out\raster_wave.pngImplementación y código fuente
kitaqgb/lib/raster.h:91
Look up the selected periodic profile at LY + phase and add base X modulo 256. An unknown profile returns the unmodified base X.
kitaqgb/lib/raster.c:264
u8 Raster_LineXGetOffset(const RasterLineX* effect, u8 ly)
{
u8 index;
if (effect->profile == KQ_RASTER_LINE_X_TITLE) {
index = (u8)((ly + effect->phase) & 15);
return (u8)(effect->base_x + Raster_LineXXTitle[(__safe_index u8)index]);
}
if (effect->profile == KQ_RASTER_LINE_TRAVEL_GATE) {
index = (u8)((ly + effect->phase) & 63);
return (u8)(effect->base_x + Raster_LineXTravelGate[(__safe_index u8)index]);
}
return effect->base_x;
}Raster_LineXInit
Inicializa el perfil y la X base, con fase cero y un paso de fase por fotograma. Esta llamada no dibuja ni escribe registros de desplazamiento.
Sintaxis
void Raster_LineXInit(RasterLineX* effect, u8 profile, u8 base_x);Parámetros
effectPuntero a memoria RasterLineX escribible; no requiere inicialización previa.
profile0 (FLAT) no aplica desplazamiento; 1 (X_TITLE) repite offsets de −4 a +3 píxeles cada 16 líneas; 2 (TRAVEL_GATE) repite una onda de ±24 píxeles cada 64 líneas. Los demás valores no aplican desplazamiento.
base_xX del fondo que se suma al desplazamiento de la onda, en píxeles (0..255).
Valor devuelto
No devuelve ningún valor.
Condiciones y límites
SCX es un valor de ocho bits y el fondo se repite cada 256 píxeles. Los desplazamientos negativos usan valores de byte módulo 256. Rellena también el mapa más allá del área visible.
El efecto modifica el desplazamiento horizontal del fondo; los sprites y la ventana no se deforman. RunFrame ocupa la CPU y bloquea las interrupciones durante las 144 líneas visibles. Actualiza la lógica del juego y el audio entre llamadas y no combines este renderizador con un controlador ráster basado en interrupciones STAT.
Las imágenes proceden de ejecuciones DMG y CGB en KOKURA. Cada píxel de la escena de 160×144, incluidos pilares y texto, se compara con las coordenadas esperadas por línea. No se han probado los tiempos en hardware real.
Coloca kitaqgb, kokura y kitaq-docs bajo un mismo directorio padre y abre PowerShell allí. La ROM admite DMG y CGB; selecciona dmg o cgb con KOKURA --hardware.
Ejemplo de uso
Raster_LineXInit(&wave, KQ_RASTER_LINE_TRAVEL_GATE, 0);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Los pilares y las letras se curvan horizontalmente hasta 24 píxeles. Una onda abarca 64 líneas de barrido y su fase avanza una línea por fotograma. En CGB, pilares y letras son azules. Fíjate en que cada fila tenga un desplazamiento horizontal distinto, en lugar de moverse toda la pantalla por igual.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_wave.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_wave.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
.\kokura\kokura-cli.exe .\out\raster_wave.gb --hardware cgb --run-frames 120 --png .\out\raster_wave.pngImplementación y código fuente
kitaqgb/lib/raster.h:82
Initialize a scanline-wave state with phase zero and one phase step per frame.
kitaqgb/lib/raster.c:229
void Raster_LineXInit(RasterLineX* effect, u8 profile, u8 base_x)
{
effect->profile = profile;
effect->base_x = base_x;
effect->phase = 0;
effect->phase_step = 1;
effect->frame_divider = 1;
effect->frame_counter = 0;
}Raster_LineXRunFrame
Espera a VBlank y renderiza las 144 líneas visibles siguientes con una X de fondo por línea. Después avanza el contador divisor y actualiza la fase al intervalo elegido.
Sintaxis
void Raster_LineXRunFrame(RasterLineX* effect);Parámetros
effectPuntero a un RasterLineX inicializado que siga siendo válido durante toda la llamada.
Valor devuelto
No devuelve ningún valor.
Condiciones y límites
Si el LCD está apagado, retorna inmediatamente sin modificar el efecto. En caso contrario, bloquea hasta actualizar SCX en las 144 filas, restaura el estado de habilitación de interrupciones y sincroniza las funciones Scroll con el SCX final. El retorno no garantiza estar en VBlank. Antes de escribir directamente en VRAM, espera a VBlank o usa una rutina de transferencia que gestione los tiempos de acceso seguros.
SCX es un valor de ocho bits y el fondo se repite cada 256 píxeles. Los desplazamientos negativos usan valores de byte módulo 256. Rellena también el mapa más allá del área visible.
El efecto modifica el desplazamiento horizontal del fondo; los sprites y la ventana no se deforman. RunFrame ocupa la CPU y bloquea las interrupciones durante las 144 líneas visibles. Actualiza la lógica del juego y el audio entre llamadas y no combines este renderizador con un controlador ráster basado en interrupciones STAT.
Las imágenes proceden de ejecuciones DMG y CGB en KOKURA. Cada píxel de la escena de 160×144, incluidos pilares y texto, se compara con las coordenadas esperadas por línea. No se han probado los tiempos en hardware real.
Coloca kitaqgb, kokura y kitaq-docs bajo un mismo directorio padre y abre PowerShell allí. La ROM admite DMG y CGB; selecciona dmg o cgb con KOKURA --hardware.
Ejemplo de uso
Raster_LineXRunFrame(&wave);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Los pilares y las letras se curvan horizontalmente hasta 24 píxeles. Una onda abarca 64 líneas de barrido y su fase avanza una línea por fotograma. En CGB, pilares y letras son azules. Fíjate en que cada fila tenga un desplazamiento horizontal distinto, en lugar de moverse toda la pantalla por igual.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_wave.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_wave.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
.\kokura\kokura-cli.exe .\out\raster_wave.gb --hardware cgb --run-frames 120 --png .\out\raster_wave.pngImplementación y código fuente
kitaqgb/lib/raster.h:96
Render all 144 visible lines with one SCX write per line, then advance phase. This foreground renderer masks interrupts during the visible frame. Do game and audio work between calls; do not combine it with a STAT raster driver. Returns without changing the effect when the LCD is off.
kitaqgb/lib/raster.c:298
void Raster_LineXRunFrame(RasterLineX* effect)
{
u8 interrupt_state;
if ((Raster_LineXLcdc & 0x80) == 0) return;
Raster_LineXTable = Raster_LineXFlat;
Raster_LineXMask = 15;
if (effect->profile == KQ_RASTER_LINE_X_TITLE) {
Raster_LineXTable = Raster_LineXXTitle;
}
if (effect->profile == KQ_RASTER_LINE_TRAVEL_GATE) {
Raster_LineXTable = Raster_LineXTravelGate;
Raster_LineXMask = 63;
}
Raster_LineXPhase = effect->phase;
Raster_LineXBase = effect->base_x;
interrupt_state = __critical_enter();
__asm {
PUSH_AF
PUSH_BC
PUSH_DE
PUSH_HL
// Use the current VBlank when the preceding frame ended there.
// Waiting for another VBlank edge would leave every second frame flat.
raster_linex_vblank:
LDH_A_MEM 0x44
CP_IMM 144
JR_C raster_linex_vblank
LD_B_IMM 0
LD_A_MEM Raster_LineXPhase
LD_C_A
LD_A_MEM Raster_LineXMask
LD_D_A
LD_A_MEM Raster_LineXBase
LD_E_A
raster_linex_line:
LD_A_B
ADD_C
AND_D
LD_L_A
LD_H_IMM 0
PUSH_DE
LD_A_MEM Raster_LineXTable
LD_E_A
LD_A_MEM Raster_LineXTable+1
LD_D_A
ADD_HL_DE
POP_DE
LD_A_HL
ADD_E
PUSH_AF
raster_linex_wait:
LDH_A_MEM 0x44
CP_B
JR_NZ raster_linex_wait
POP_AF
LDH_MEM_A 0x43
INC_B
LD_A_B
CP_IMM 144
JR_NZ raster_linex_line
POP_HL
POP_DE
POP_BC
POP_AF
}
// Synchronize the scroll helper's tracked state with the last hardware write.
__scroll_bg_x_set(Raster_LineXScx);
__critical_leave(interrupt_state);
effect->frame_counter++;
if (effect->frame_counter >= effect->frame_divider) {
effect->frame_counter = 0;
effect->phase = (u8)(effect->phase + effect->phase_step);
}
}Raster_LineXSetPhase
Establece directamente la posición de la onda, conservando la X base, la velocidad y el contador divisor.
Sintaxis
void Raster_LineXSetPhase(RasterLineX* effect, u8 phase);Parámetros
effectPuntero a un RasterLineX inicializado que siga siendo válido durante toda la llamada.
phaseValor de fase de ocho bits; la onda elegida se repite cada 16 o 64 pasos.
Valor devuelto
No devuelve ningún valor.
Condiciones y límites
SCX es un valor de ocho bits y el fondo se repite cada 256 píxeles. Los desplazamientos negativos usan valores de byte módulo 256. Rellena también el mapa más allá del área visible.
El efecto modifica el desplazamiento horizontal del fondo; los sprites y la ventana no se deforman. RunFrame ocupa la CPU y bloquea las interrupciones durante las 144 líneas visibles. Actualiza la lógica del juego y el audio entre llamadas y no combines este renderizador con un controlador ráster basado en interrupciones STAT.
Las imágenes proceden de ejecuciones DMG y CGB en KOKURA. Cada píxel de la escena de 160×144, incluidos pilares y texto, se compara con las coordenadas esperadas por línea. No se han probado los tiempos en hardware real.
Coloca kitaqgb, kokura y kitaq-docs bajo un mismo directorio padre y abre PowerShell allí. La ROM admite DMG y CGB; selecciona dmg o cgb con KOKURA --hardware.
Ejemplo de uso
Raster_LineXSetPhase(&wave, 8);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Los pilares y las letras se curvan horizontalmente hasta 24 píxeles. Una onda abarca 64 líneas de barrido y su fase avanza una línea por fotograma. En CGB, pilares y letras son azules. Fíjate en que cada fila tenga un desplazamiento horizontal distinto, en lugar de moverse toda la pantalla por igual.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_wave.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_wave.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
.\kokura\kokura-cli.exe .\out\raster_wave.gb --hardware cgb --run-frames 120 --png .\out\raster_wave.pngImplementación y código fuente
kitaqgb/lib/raster.h:88
Set the byte phase directly without resetting the frame-divider counter.
kitaqgb/lib/raster.c:257
void Raster_LineXSetPhase(RasterLineX* effect, u8 phase)
{
effect->phase = phase;
}Raster_LineXSetProfile
Selecciona un perfil y pone a cero la fase y el contador divisor de fotogramas. Conserva la X base y la velocidad.
Sintaxis
void Raster_LineXSetProfile(RasterLineX* effect, u8 profile);Parámetros
effectPuntero a un RasterLineX inicializado que siga siendo válido durante toda la llamada.
profile0 (FLAT) no aplica desplazamiento; 1 (X_TITLE) repite offsets de −4 a +3 píxeles cada 16 líneas; 2 (TRAVEL_GATE) repite una onda de ±24 píxeles cada 64 líneas. Los demás valores no aplican desplazamiento.
Valor devuelto
No devuelve ningún valor.
Condiciones y límites
SCX es un valor de ocho bits y el fondo se repite cada 256 píxeles. Los desplazamientos negativos usan valores de byte módulo 256. Rellena también el mapa más allá del área visible.
El efecto modifica el desplazamiento horizontal del fondo; los sprites y la ventana no se deforman. RunFrame ocupa la CPU y bloquea las interrupciones durante las 144 líneas visibles. Actualiza la lógica del juego y el audio entre llamadas y no combines este renderizador con un controlador ráster basado en interrupciones STAT.
Las imágenes proceden de ejecuciones DMG y CGB en KOKURA. Cada píxel de la escena de 160×144, incluidos pilares y texto, se compara con las coordenadas esperadas por línea. No se han probado los tiempos en hardware real.
Coloca kitaqgb, kokura y kitaq-docs bajo un mismo directorio padre y abre PowerShell allí. La ROM admite DMG y CGB; selecciona dmg o cgb con KOKURA --hardware.
Ejemplo de uso
Raster_LineXSetProfile(&wave, KQ_RASTER_LINE_X_TITLE);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El título original ORBIT GUARD entra desde la derecha con una onda amplia. Tras 48 fotogramas renderizados pasa a una ondulación pequeña; desde el fotograma 96 queda inmóvil. La entrada se repite tras 160 fotogramas. Las imágenes muestran, en ese orden, la llegada, la ondulación pequeña y el título asentado.






Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_title_entry.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_title_entry.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
.\kokura\kokura-cli.exe .\out\raster_title_entry.gb --hardware cgb --run-frames 120 --png .\out\raster_title_entry.pngImplementación y código fuente
kitaqgb/lib/raster.h:84
Change the wave profile and restart its phase/divider counter.
kitaqgb/lib/raster.c:240
void Raster_LineXSetProfile(RasterLineX* effect, u8 profile)
{
effect->profile = profile;
effect->phase = 0;
effect->frame_counter = 0;
}Raster_LineXSetSpeed
Establece el incremento de fase y el intervalo de actualización. Reinicia el contador divisor conservando la fase actual.
Sintaxis
void Raster_LineXSetSpeed(RasterLineX* effect, u8 phase_step, u8 frame_divider);Parámetros
effectPuntero a un RasterLineX inicializado que siga siendo válido durante toda la llamada.
phase_stepIncremento de fase por actualización (0..255). Cero congela la onda. El valor 255 retrocede un paso mediante el desbordamiento circular de ocho bits.
frame_dividerNúmero de llamadas RunFrame que renderizan entre actualizaciones de fase (1..255). Cero selecciona uno. No cuentan las llamadas que retornan porque el LCD está apagado.
Valor devuelto
No devuelve ningún valor.
Condiciones y límites
SCX es un valor de ocho bits y el fondo se repite cada 256 píxeles. Los desplazamientos negativos usan valores de byte módulo 256. Rellena también el mapa más allá del área visible.
El efecto modifica el desplazamiento horizontal del fondo; los sprites y la ventana no se deforman. RunFrame ocupa la CPU y bloquea las interrupciones durante las 144 líneas visibles. Actualiza la lógica del juego y el audio entre llamadas y no combines este renderizador con un controlador ráster basado en interrupciones STAT.
Las imágenes proceden de ejecuciones DMG y CGB en KOKURA. Cada píxel de la escena de 160×144, incluidos pilares y texto, se compara con las coordenadas esperadas por línea. No se han probado los tiempos en hardware real.
Coloca kitaqgb, kokura y kitaq-docs bajo un mismo directorio padre y abre PowerShell allí. La ROM admite DMG y CGB; selecciona dmg o cgb con KOKURA --hardware.
Ejemplo de uso
Raster_LineXSetSpeed(&wave, 1, 1);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Los pilares y las letras se curvan horizontalmente hasta 24 píxeles. Una onda abarca 64 líneas de barrido y su fase avanza una línea por fotograma. En CGB, pilares y letras son azules. Fíjate en que cada fila tenga un desplazamiento horizontal distinto, en lugar de moverse toda la pantalla por igual.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_wave.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_wave.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
.\kokura\kokura-cli.exe .\out\raster_wave.gb --hardware cgb --run-frames 120 --png .\out\raster_wave.pngImplementación y código fuente
kitaqgb/lib/raster.h:86
Configure the phase increment and frame interval; clamp a zero interval to one.
kitaqgb/lib/raster.c:248
void Raster_LineXSetSpeed(RasterLineX* effect, u8 phase_step, u8 frame_divider)
{
effect->phase_step = phase_step;
if (frame_divider == 0) frame_divider = 1;
effect->frame_divider = frame_divider;
effect->frame_counter = 0;
}Raster_Push
Añade una franja que cambia SCX/SCY del fondo en el LY programado. Esta operación exclusiva del fondo no modifica la ventana ni los colores.
Sintaxis
u8 Raster_Push(u8 ly, u8 scx, u8 scy);Parámetros
lyLínea visible programada, de 0 a 143, estrictamente mayor que la entrada anterior. Una primera entrada en LY=0 se aplica durante el tratamiento de VBlank para establecer el estado inicial del fotograma.
scxByte de desplazamiento del fondo, de 0 a 255. SCX/SCY indican desde dónde leer el mapa de fondo, no una posición en pantalla. Las coordenadas se repiten en el fondo de 256 píxeles.
scyByte de desplazamiento del fondo, de 0 a 255. SCX/SCY indican desde dónde leer el mapa de fondo, no una posición en pantalla. Las coordenadas se repiten en el fondo de 256 píxeles.
Valor devuelto
Devuelve KQ_RASTER_OK (0) si tiene éxito o un estado de error de 1 a 4. Consulta las restricciones de la función y Raster_GetLastError.
Condiciones y límites
Incluye raster.h y compila raster.c junto con scroll.c. Una tabla compartida admite hasta ocho franjas. Mientras la construyes con Raster_*, no intercales llamadas directas a Scroll_Split* ni a __scroll_split_*: no actualizan el recuento ni el registro de la última línea de la capa Raster.
Reconstruye durante VBlank o en otro intervalo en el que controles el efecto sobre la imagen: borra, añade entradas y confirma. Borrar también detiene las divisiones activas; no estás editando un búfer secundario independiente. LY programa una interrupción y las escrituras en registros requieren tiempo adicional. Para ondas por línea de barrido, usa la familia independiente Raster_LineX*; no ejecutes ambos controladores a la vez.
Los códigos de estado son 0 OK, 1 FULL, 2 BAD_LY, 3 UNSORTED y 4 BAD_RANGE. Las inserciones comprueban, en este orden, el rango de LY, la capacidad y el orden de las líneas. Una entrada rechazada no aumenta la tabla. Una inserción posterior correcta o un borrado pone el error a cero; comprueba el retorno de cada llamada en ese momento.
Ejemplo de uso
Raster_Push(0,0,0);Raster_Push(64,8,0);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Aparecen rectángulos rojos de 24x16 píxeles, negros en DMG, en (32,16), (24,80) y (16,112). Las franjas inferiores se desplazan más hacia la izquierda. Los resultados internos registran un recuento de 3, error 0 y resultado de confirmación 0.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_bands.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/raster.h:50
Append a validated background-scroll band and advance the monotonic-LY bookkeeping. A successful append clears the previous error.
kitaqgb/lib/raster.c:95
u8 Raster_Push(u8 ly, u8 scx, u8 scy)
{
u8 r;
r = Raster_CheckPush(ly);
if (r != KQ_RASTER_OK) return r;
Scroll_SplitPush(ly, scx, scy);
Raster_LastLyValue = ly;
Raster_HasLastLy = 1;
Raster_CountValue++;
Raster_LastErrorValue = KQ_RASTER_OK;
return KQ_RASTER_OK;
}Raster_PushBgColor0
Añade una franja que cambia el color cero de la paleta de fondo CGB cero durante el fotograma. No selecciona otra paleta ni modifica sus otros tres colores. Registrarla en DMG no produce un efecto de color.
Sintaxis
u8 Raster_PushBgColor0(u8 ly, u16 rgb15);Parámetros
lyLínea visible programada, de 0 a 143, estrictamente mayor que la entrada anterior. Una primera entrada en LY=0 se aplica durante el tratamiento de VBlank para establecer el estado inicial del fotograma.
rgb15RGB15: rojo en los bits 0..4, verde en 5..9 y azul en 10..14. 0x001F es rojo, 0x03E0 verde y 0x7C00 azul. No se comprueba el rango de entrada.
Valor devuelto
Devuelve KQ_RASTER_OK (0) si tiene éxito o un estado de error de 1 a 4. Consulta las restricciones de la función y Raster_GetLastError.
Condiciones y límites
Incluye raster.h y compila raster.c junto con scroll.c. Una tabla compartida admite hasta ocho franjas. Mientras la construyes con Raster_*, no intercales llamadas directas a Scroll_Split* ni a __scroll_split_*: no actualizan el recuento ni el registro de la última línea de la capa Raster.
Reconstruye durante VBlank o en otro intervalo en el que controles el efecto sobre la imagen: borra, añade entradas y confirma. Borrar también detiene las divisiones activas; no estás editando un búfer secundario independiente. LY programa una interrupción y las escrituras en registros requieren tiempo adicional. Para ondas por línea de barrido, usa la familia independiente Raster_LineX*; no ejecutes ambos controladores a la vez.
Los códigos de estado son 0 OK, 1 FULL, 2 BAD_LY, 3 UNSORTED y 4 BAD_RANGE. Las inserciones comprueban, en este orden, el rango de LY, la capacidad y el orden de las líneas. Una entrada rechazada no aumenta la tabla. Una inserción posterior correcta o un borrado pone el error a cero; comprueba el retorno de cada llamada en ese momento.
Los cambios de color usan BCPS/BCPD y no conservan el índice BCPS anterior. Si el código principal también escribe paletas, establece el índice explícitamente. El manejador espera un modo LCD accesible, por lo que el cambio de color visible puede aparecer después del LY programado.
Ejemplo de uso
Raster_PushBgColor0(0,0x7C00);Raster_PushBgColor0(64,0x001F);Raster_PushBgColor0(112,0x03E0);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
En la captura CGB verificada a velocidad normal, las filas 0..65 son azules, 66..113 rojas y 114..143 verdes. Los LY programados son 0, 64 y 112; la latencia de interrupción y de acceso a paleta influye en los límites visibles. No hay versión de color para DMG.

Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_color.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/raster.h:63
Pack a 15-bit color into the extended band's two scroll-byte fields and select the color-zero operation, which interprets those fields as color data.
kitaqgb/lib/raster.c:154
u8 Raster_PushBgColor0(u8 ly, u16 rgb15)
{
return Raster_PushEx(ly, (u8)rgb15, (u8)(rgb15 >> 8), 0, 0, KQ_RASTER_BG_COLOR0);
}Raster_PushBgWindowScreen
Actualiza el desplazamiento del fondo y las coordenadas de ventana en una sola franja. La función añade BG y WIN y convierte la X de pantalla de la ventana a WX.
Sintaxis
u8 Raster_PushBgWindowScreen(u8 ly, u8 scx, u8 scy, u8 screen_x, u8 screen_y, u8 flags);Parámetros
lyLínea visible programada, de 0 a 143, estrictamente mayor que la entrada anterior. Una primera entrada en LY=0 se aplica durante el tratamiento de VBlank para establecer el estado inicial del fotograma.
scxByte de desplazamiento del fondo, de 0 a 255. SCX/SCY indican desde dónde leer el mapa de fondo, no una posición en pantalla. Las coordenadas se repiten en el fondo de 256 píxeles.
scyByte de desplazamiento del fondo, de 0 a 255. SCX/SCY indican desde dónde leer el mapa de fondo, no una posición en pantalla. Las coordenadas se repiten en el fondo de 256 píxeles.
screen_xCoordenada X de pantalla del borde izquierdo de la ventana. La función suma siete para obtener WX. Normalmente usa 0..159. Los valores de 249 o más se desbordan al sumar en un byte; no los uses para ocultar la ventana.
screen_yWY de la ventana, en píxeles desde el borde superior. A diferencia de X, Y no necesita sumar siete. Los valores WY de 144 o más no tienen línea inicial en la zona visible.
flagsNormalmente pasa WIN_SHOW o WIN_HIDE. La función añade WIN, por lo que basta cero para actualizar las coordenadas sin cambiar la visibilidad. Los demás bits admitidos se transmiten tal cual; evita operaciones BG o de color no deseadas.
Valor devuelto
Devuelve KQ_RASTER_OK (0) si tiene éxito o un estado de error de 1 a 4. Consulta las restricciones de la función y Raster_GetLastError.
Condiciones y límites
Incluye raster.h y compila raster.c junto con scroll.c. Una tabla compartida admite hasta ocho franjas. Mientras la construyes con Raster_*, no intercales llamadas directas a Scroll_Split* ni a __scroll_split_*: no actualizan el recuento ni el registro de la última línea de la capa Raster.
Reconstruye durante VBlank o en otro intervalo en el que controles el efecto sobre la imagen: borra, añade entradas y confirma. Borrar también detiene las divisiones activas; no estás editando un búfer secundario independiente. LY programa una interrupción y las escrituras en registros requieren tiempo adicional. Para ondas por línea de barrido, usa la familia independiente Raster_LineX*; no ejecutes ambos controladores a la vez.
Los códigos de estado son 0 OK, 1 FULL, 2 BAD_LY, 3 UNSORTED y 4 BAD_RANGE. Las inserciones comprueban, en este orden, el rango de LY, la capacidad y el orden de las líneas. Una entrada rechazada no aumenta la tabla. Una inserción posterior correcta o un borrado pone el error a cero; comprueba el retorno de cada llamada en ese momento.
Ejemplo de uso
Raster_PushBgWindowScreen(0,8,0,24,48,KQ_RASTER_WIN_SHOW);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
X=8 en el fondo mueve el rectángulo rojo a (24,16). El origen de la ventana sigue en (24,48), manteniendo su rectángulo azul en (32,56). Así se muestra que los sistemas de coordenadas son independientes.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_bg_window.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/raster.h:60
Queue both background and window updates, converting window screen X to WX.
kitaqgb/lib/raster.c:145
u8 Raster_PushBgWindowScreen(u8 ly, u8 scx, u8 scy, u8 screen_x, u8 screen_y, u8 flags)
{
flags = (u8)(flags | KQ_RASTER_BG | KQ_RASTER_WIN);
return Raster_PushEx(ly, scx, scy, (u8)(screen_x + 7), screen_y, flags);
}Raster_PushEx
Añade una franja ampliada que ejecuta las operaciones de fondo, ventana, visibilidad o color elegidas por las banderas. Para cambios normales solo del fondo, usa Raster_Push, que requiere menos argumentos.
Sintaxis
u8 Raster_PushEx(u8 ly, u8 scx, u8 scy, u8 wx, u8 wy, u8 flags);Parámetros
lyLínea visible programada, de 0 a 143, estrictamente mayor que la entrada anterior. Una primera entrada en LY=0 se aplica durante el tratamiento de VBlank para establecer el estado inicial del fotograma.
scxByte de desplazamiento del fondo, de 0 a 255. SCX/SCY indican desde dónde leer el mapa de fondo, no una posición en pantalla. Las coordenadas se repiten en el fondo de 256 píxeles.
scyByte de desplazamiento del fondo, de 0 a 255. SCX/SCY indican desde dónde leer el mapa de fondo, no una posición en pantalla. Las coordenadas se repiten en el fondo de 256 píxeles.
wxValor bruto de WX del hardware. Suma siete a la coordenada X normal de pantalla; WX=7 coloca la ventana en el borde izquierdo. La función no limita ni valida WX.
wyWY de la ventana, en píxeles desde el borde superior. A diferencia de X, Y no necesita sumar siete. Los valores WY de 144 o más no tienen línea inicial en la zona visible.
flagsBanderas: BG=1 actualiza el desplazamiento del fondo, WIN=2 actualiza WX/WY, WIN_SHOW=4 muestra la ventana, WIN_HIDE=8 la oculta y BG_COLOR0=16 actualiza el color cero del fondo CGB. Se descartan los bits superiores desconocidos. Si están SHOW y HIDE, SHOW se aplica al final. Los cambios de color reutilizan los campos SCX/SCY; no los combines con desplazamiento normal del fondo.
Valor devuelto
Devuelve KQ_RASTER_OK (0) si tiene éxito o un estado de error de 1 a 4. Consulta las restricciones de la función y Raster_GetLastError.
Condiciones y límites
Incluye raster.h y compila raster.c junto con scroll.c. Una tabla compartida admite hasta ocho franjas. Mientras la construyes con Raster_*, no intercales llamadas directas a Scroll_Split* ni a __scroll_split_*: no actualizan el recuento ni el registro de la última línea de la capa Raster.
Reconstruye durante VBlank o en otro intervalo en el que controles el efecto sobre la imagen: borra, añade entradas y confirma. Borrar también detiene las divisiones activas; no estás editando un búfer secundario independiente. LY programa una interrupción y las escrituras en registros requieren tiempo adicional. Para ondas por línea de barrido, usa la familia independiente Raster_LineX*; no ejecutes ambos controladores a la vez.
Los códigos de estado son 0 OK, 1 FULL, 2 BAD_LY, 3 UNSORTED y 4 BAD_RANGE. Las inserciones comprueban, en este orden, el rango de LY, la capacidad y el orden de las líneas. Una entrada rechazada no aumenta la tabla. Una inserción posterior correcta o un borrado pone el error a cero; comprueba el retorno de cada llamada en ese momento.
Ejemplo de uso
Raster_PushEx(104,16,0,7,0,KQ_RASTER_BG|KQ_RASTER_WIN_HIDE);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Aparecen rectángulos rojos de 24x16 píxeles, negros en DMG, en (32,16), (24,80) y (16,112). Las franjas inferiores se desplazan más hacia la izquierda. Los resultados internos registran un recuento de 3, error 0 y resultado de confirmación 0.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_bands.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/raster.h:52
Append a validated extended band after masking flags to supported operations.
kitaqgb/lib/raster.c:112
u8 Raster_PushEx(u8 ly, u8 scx, u8 scy, u8 wx, u8 wy, u8 flags)
{
u8 r;
r = Raster_CheckPush(ly);
if (r != KQ_RASTER_OK) return r;
// Masking removes unknown bits but does not reject conflicting supported operations.
flags = (u8)(flags & KQ_RASTER_FLAG_MASK);
Scroll_SplitPushEx(ly, scx, scy, wx, wy, flags);
Raster_LastLyValue = ly;
Raster_HasLastLy = 1;
Raster_CountValue++;
Raster_LastErrorValue = KQ_RASTER_OK;
return KQ_RASTER_OK;
}Raster_PushWindowRaw
Añade una franja de ventana con los valores brutos WX/WY del hardware. Añade WIN automáticamente y pasa cero en los dos bytes de datos del fondo.
Sintaxis
u8 Raster_PushWindowRaw(u8 ly, u8 wx, u8 wy, u8 flags);Parámetros
lyLínea visible programada, de 0 a 143, estrictamente mayor que la entrada anterior. Una primera entrada en LY=0 se aplica durante el tratamiento de VBlank para establecer el estado inicial del fotograma.
wxValor bruto de WX del hardware. Suma siete a la coordenada X normal de pantalla; WX=7 coloca la ventana en el borde izquierdo. La función no limita ni valida WX.
wyWY de la ventana, en píxeles desde el borde superior. A diferencia de X, Y no necesita sumar siete. Los valores WY de 144 o más no tienen línea inicial en la zona visible.
flagsNormalmente pasa WIN_SHOW o WIN_HIDE. La función añade WIN, por lo que basta cero para actualizar las coordenadas sin cambiar la visibilidad. Los demás bits admitidos se transmiten tal cual; evita operaciones BG o de color no deseadas.
Valor devuelto
Devuelve KQ_RASTER_OK (0) si tiene éxito o un estado de error de 1 a 4. Consulta las restricciones de la función y Raster_GetLastError.
Condiciones y límites
Incluye raster.h y compila raster.c junto con scroll.c. Una tabla compartida admite hasta ocho franjas. Mientras la construyes con Raster_*, no intercales llamadas directas a Scroll_Split* ni a __scroll_split_*: no actualizan el recuento ni el registro de la última línea de la capa Raster.
Reconstruye durante VBlank o en otro intervalo en el que controles el efecto sobre la imagen: borra, añade entradas y confirma. Borrar también detiene las divisiones activas; no estás editando un búfer secundario independiente. LY programa una interrupción y las escrituras en registros requieren tiempo adicional. Para ondas por línea de barrido, usa la familia independiente Raster_LineX*; no ejecutes ambos controladores a la vez.
Los códigos de estado son 0 OK, 1 FULL, 2 BAD_LY, 3 UNSORTED y 4 BAD_RANGE. Las inserciones comprueban, en este orden, el rango de LY, la capacidad y el orden de las líneas. Una entrada rechazada no aumenta la tabla. Una inserción posterior correcta o un borrado pone el error a cero; comprueba el retorno de cada llamada en ese momento.
Ejemplo de uso
Raster_PushWindowRaw(0,31,48,KQ_RASTER_WIN_SHOW);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
WX=31 y WY=48 colocan el origen de la ventana en (24,48) de la pantalla. Su rectángulo azul de 16x16 en la posición local (8,8) aparece en (32,56). El rectángulo rojo del fondo superior permanece en (32,16). Ambos son negros en DMG.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_window_raw.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/raster.h:55
Enable window updates and pass hardware WX/WY values without coordinate conversion.
kitaqgb/lib/raster.c:131
u8 Raster_PushWindowRaw(u8 ly, u8 wx, u8 wy, u8 flags)
{
flags = (u8)(flags | KQ_RASTER_WIN);
return Raster_PushEx(ly, 0, 0, wx, wy, flags);
}Raster_PushWindowScreen
Añade una franja de ventana en coordenadas de pantalla. Suma siete a X antes de llamar a la variante bruta, para colocar la ventana sin confundir la X de pantalla con WX.
Sintaxis
u8 Raster_PushWindowScreen(u8 ly, u8 screen_x, u8 screen_y, u8 flags);Parámetros
lyLínea visible programada, de 0 a 143, estrictamente mayor que la entrada anterior. Una primera entrada en LY=0 se aplica durante el tratamiento de VBlank para establecer el estado inicial del fotograma.
screen_xCoordenada X de pantalla del borde izquierdo de la ventana. La función suma siete para obtener WX. Normalmente usa 0..159. Los valores de 249 o más se desbordan al sumar en un byte; no los uses para ocultar la ventana.
screen_yWY de la ventana, en píxeles desde el borde superior. A diferencia de X, Y no necesita sumar siete. Los valores WY de 144 o más no tienen línea inicial en la zona visible.
flagsNormalmente pasa WIN_SHOW o WIN_HIDE. La función añade WIN, por lo que basta cero para actualizar las coordenadas sin cambiar la visibilidad. Los demás bits admitidos se transmiten tal cual; evita operaciones BG o de color no deseadas.
Valor devuelto
Devuelve KQ_RASTER_OK (0) si tiene éxito o un estado de error de 1 a 4. Consulta las restricciones de la función y Raster_GetLastError.
Condiciones y límites
Incluye raster.h y compila raster.c junto con scroll.c. Una tabla compartida admite hasta ocho franjas. Mientras la construyes con Raster_*, no intercales llamadas directas a Scroll_Split* ni a __scroll_split_*: no actualizan el recuento ni el registro de la última línea de la capa Raster.
Reconstruye durante VBlank o en otro intervalo en el que controles el efecto sobre la imagen: borra, añade entradas y confirma. Borrar también detiene las divisiones activas; no estás editando un búfer secundario independiente. LY programa una interrupción y las escrituras en registros requieren tiempo adicional. Para ondas por línea de barrido, usa la familia independiente Raster_LineX*; no ejecutes ambos controladores a la vez.
Los códigos de estado son 0 OK, 1 FULL, 2 BAD_LY, 3 UNSORTED y 4 BAD_RANGE. Las inserciones comprueban, en este orden, el rango de LY, la capacidad y el orden de las líneas. Una entrada rechazada no aumenta la tabla. Una inserción posterior correcta o un borrado pone el error a cero; comprueba el retorno de cada llamada en ese momento.
Ejemplo de uso
Raster_PushWindowScreen(0,24,48,KQ_RASTER_WIN_SHOW);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Pasar directamente las coordenadas de pantalla (24,48) produce el mismo rectángulo azul de ventana en (32,56) que el ejemplo con valores brutos. La biblioteca suma siete a X. El rectángulo rojo del fondo superior está en (32,16).


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_window_screen.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/raster.h:58
Convert screen X to hardware WX by adding seven, then queue a window band. The byte addition wraps if callers supply an excessive X coordinate.
kitaqgb/lib/raster.c:139
u8 Raster_PushWindowScreen(u8 ly, u8 screen_x, u8 screen_y, u8 flags)
{
return Raster_PushWindowRaw(ly, (u8)(screen_x + 7), screen_y, flags);
}rpg.h — Números aleatorios, texto, mapas, guardado y servicios RPG/ADV/SLG
Las funciones auxiliares de texto absoluto dibujan directamente en el mapa del fondo. text_window abre un área con marco, text_clear_rect rellena una región y text_print_xy escribe bytes de tiles sin interpretar códigos de control. text_print_u8, text_print_u16 y text_print_s16 convierten números a decimal usando solo las celdas necesarias. Reserva y borra un campo completo al sustituir valores de distinta longitud.
Las funciones RNG declaradas en rpg.h se implementan en lib/rng.c. Comparten el generador GB del compilador: rng_seed lo reinicia, rng8/rng_next8 consumen un byte, rng16/rng_next16 consumen dos, y rand_range/rng_range, rng_chance y weighted_choice adaptan las extracciones a decisiones del juego. Compila rng.c con el programa al usar estas funciones. Para pruebas reproducibles, fija la semilla y el orden de llamadas; las selecciones basadas en módulo no garantizan probabilidades exactas.
La decodificación RLE usa pares de bytes count/value y un contador cero como terminador. rle_decode lee un puntero normal y escribe en RAM; rle_decode_far lee un puntero con banco ROM y escribe en RAM; __rle_decode_vram descomprime la entrada de un banco directamente en VRAM con escrituras adaptadas al LCD. Las funciones RAM están en lib/rle.c; la operación VRAM directa la genera el compilador. Las tres devuelven bytes de salida y requieren un flujo válido y espacio suficiente en destino.
El almacenamiento de estado declarado en rpg.h se implementa en lib/flags.c. Las tres funciones de banderas operan sobre 2048 bits booleanos independientes; quest_state y quest_set_state operan sobre 64 bytes independientes para etapas definidas por el juego. Compila flags.c, respeta los límites de ID y usa un sistema de guardado separado si el progreso debe conservarse al apagar.
El diálogo en ventana comparte un rectángulo activo, un cursor y una velocidad de caracteres. text_open inicializa el área, text_close la borra y text_set_speed fija esperas VBlank por carácter. text_print y text_print_far interpretan flujos; text_choice ejecuta un selector vertical bloqueante. Carga los tiles, ajusta el área y planifica cómo manejar esas llamadas en el juego.
Ofrece dibujo de mapas y metatiles, scripts, guardados SRAM y búsqueda de rutas. Las celdas normales miden 8×8 píxeles; los metatiles, 16×16. Cargar/dibujar, generar máscaras de movimiento y generar máscaras de ataque son operaciones separadas; el juego coordina la carga gráfica y la ejecución de eventos.
La búsqueda usa unos 4 KiB de espacio de trabajo compartido y no reentrante. Limita los mapas a 1024 celdas y las distancias exploradas a 254. La distancia 0xFF significa «no alcanzado», así que no se puede representar una ruta de 255 pasos. Las salidas de coste y máscara necesitan width*height bytes escribibles.
Por defecto hay cuatro ranuras de 512 bytes, cada una con una cabecera de seis bytes y hasta 506 bytes de datos. El ejemplo usa MBC5 con 8 KiB de SRAM. Las llamadas terminan con la RAM desactivada y no restauran el banco ni el estado de activación anterior.
Los menús permiten tanto una selección bloqueante como llamadas separadas de entrada y dibujo desde el bucle del juego. El menú del inventario muestra los nombres y las cantidades de los objetos.
camera_center
Centra una celda de mapa normal en un área visible de 20×18 tiles, limitada a los bordes del mapa.
Sintaxis
void camera_center(u8 x, u8 y);Parámetros
xCoordenada X de la celda.
yCoordenada Y de la celda.
Valor devuelto
No devuelve ningún valor.
Condiciones y límites
El origen parte de max(x−10,0), max(y−9,0), se limita a los bordes del mapa y después escribe los bytes bajos de origen*8 en SCX/SCY. No se aplica en modo metatile. No carga nuevas filas ni columnas en VRAM.
Ejemplo de uso
camera_center(5,4);result[9]=*((u8*)0xFF43);result[10]=*((u8*)0xFF42);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La cuadrícula izquierda muestra los costes de movimiento en tres pasos; la derecha, una ruta más corta de S a G. Los asteriscos verdes trazan nueve pasos alrededor de una pared roja de tres celdas; los dígitos azules muestran los costes. DMG usa la misma disposición en negro. Las comprobaciones de RAM también muestran que la máscara de ataque ignora las paredes.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_map_path.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_map_path.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=noneImplementación y código fuente
kitaqgb/lib/rpg.h:297
Center an ordinary-map tile coordinate within a 20-by-18 viewport and clamp the scroll origin to its edges. This adjusts scroll registers only; it does not stream newly exposed map rows into VRAM.
kitaqgb/lib/map.c:105
void camera_center(u8 x, u8 y)
{
u8 tile_x = 0;
u8 tile_y = 0;
u8 max_x = 0;
u8 max_y = 0;
map_camera_x = x;
map_camera_y = y;
if (map_loaded == 0) return;
if (map_current.width > 20) max_x = (u8)(map_current.width - 20);
if (map_current.height > 18) max_y = (u8)(map_current.height - 18);
if (x > 10) tile_x = (u8)(x - 10);
if (y > 9) tile_y = (u8)(y - 9);
if (tile_x > max_x) tile_x = max_x;
if (tile_y > max_y) tile_y = max_y;
__scroll_bg_set((u8)(tile_x << 3), (u8)(tile_y << 3));
}far_read16
Lee una palabra little-endian mediante un puntero con información de banco.
Sintaxis
#define far_read16(p) __farpeek16((p).bank, (p).ptr)Parámetros
pfar_ptr_t con bank y ptr, donde ptr es una dirección visible para la CPU.
Valor devuelto
La palabra como u16.
Condiciones y límites
La macro lee p.bank y p.ptr por separado; no pases una expresión con efectos secundarios. La función intrínseca selecciona temporalmente el banco ROM y lo restaura. Evita cambios de banco simultáneos desde las interrupciones.
Ejemplo de uso
result[1]=far_read16(far);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Lee los valores hexadecimales 34 12 AB de otro banco ROM: primer byte 52, palabra little-endian 4660 y último byte copiado 171.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_far.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_far.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=noneImplementación y código fuente
kitaqgb/lib/rpg.h:172
far_read8
Lee un byte mediante un puntero con información de banco.
Sintaxis
#define far_read8(p) __farpeek8((p).bank, (p).ptr)Parámetros
pfar_ptr_t con bank y ptr, donde ptr es una dirección visible para la CPU.
Valor devuelto
El byte como u8.
Condiciones y límites
La macro lee p.bank y p.ptr por separado; no pases una expresión con efectos secundarios. La función intrínseca selecciona temporalmente el banco ROM y lo restaura. Evita cambios de banco simultáneos desde las interrupciones.
Ejemplo de uso
far.bank=1;far.ptr=bank_bytes;result[0]=far_read8(far);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Lee los valores hexadecimales 34 12 AB de otro banco ROM: primer byte 52, palabra little-endian 4660 y último byte copiado 171.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_far.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_far.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=noneImplementación y código fuente
kitaqgb/lib/rpg.h:171
far_read_block
Copia bytes consecutivos a RAM desde un puntero con información de banco.
Sintaxis
#define far_read_block(dst, p, len) __farmemcpy((dst), (p).bank, (p).ptr, (len))Parámetros
dstInicio de len bytes escribibles de RAM.
pfar_ptr_t con bank y ptr, donde ptr es una dirección visible para la CPU.
lenNúmero de bytes; mantén toda la extensión de origen dentro de su banco.
Valor devuelto
No devuelve ningún valor.
Condiciones y límites
Macro que llama a __farmemcpy. No cruza automáticamente límites de banco ROM ni realiza un movimiento de memoria con zonas solapadas.
Ejemplo de uso
far_read_block(copy,far,3);result[2]=copy[2];Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Lee los valores hexadecimales 34 12 AB de otro banco ROM: primer byte 52, palabra little-endian 4660 y último byte copiado 171.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_far.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_far.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=noneImplementación y código fuente
kitaqgb/lib/rpg.h:173
flag_clear
Pone una bandera de juego a 0 sin borrar las vecinas. Úsalo cuando se deshaga una condición de evento o al inicializar explícitamente una bandera. Si ya estaba a cero, permanece a cero.
Sintaxis
void flag_clear(u16 id);Parámetros
idNúmero de bandera, de 0 a 2047, pasado como u16. El desplazamiento de byte es id / 8 y el bit dentro de él es id % 8, empezando por el menos significativo. El tipo de parámetro más amplio no aumenta el almacenamiento fijo de 2048 banderas.
Valor devuelto
Ninguno (void).
Condiciones y límites
La función no valida el ID. Mantén los ID de banderas por debajo de 2048 y los de misiones por debajo de 64; un acceso fuera de rango puede leer o sobrescribir otra RAM. Los ejemplos inicializan explícitamente en lugar de depender del contenido al arrancar.
flags.c dispone de 256 bytes de RAM para banderas y otros 64 para misiones. Estas funciones no acceden a la RAM de guardado del cartucho ni conservan datos al apagar. Para mantener el progreso, el juego debe serializar los valores de banderas y misiones mediante su sistema de guardado y restaurarlos al cargar.
Incluye rpg.h y compila lib/flags.c con el juego. Los arrays son privados de ese archivo; accede mediante las API de banderas y misiones. Todos los llamadores comparten el almacenamiento, así que coordina las escrituras del bucle principal y los manejadores de interrupciones.
Ejemplo de uso
flag_clear(9);flag_clear(9); // Mark it closed; clearing twice still leaves 0.
cleared=flag_get(9);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo borra la bandera de puerta 9 después de activarla. DOOR CLOSED muestra 000 aunque se llame dos veces al borrado. La observación anterior DOOR OPEN sigue visible como 001 para comparar los dos valores guardados.
El programa completo muestra resultados decimales sobre blanco: texto negro en DMG y azul en CGB. FAILED debe ser 000. Las capturas solo muestran el comportamiento del estado en RAM; no demuestran el guardado de una partida.
La verificación en el emulador DMG cubrió todos los ID de banderas de 0 a 2047, activaciones y borrados repetidos, entradas vecinas y los 256 valores de estado de cada una de las 64 misiones. Se compararon un patrón final de 256 bytes de banderas y 64 bytes de misiones con los datos esperados. Ambas pantallas didácticas se comprobaron tras 240 fotogramas. No se probaron hardware físico ni persistencia del guardado.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\flags_quests.c .\kitaqgb\lib\flags.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\flags_quests.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/rpg.h:372
Clear a flag bit; id must be below 2048.
kitaqgb/lib/flags.c:21
void flag_clear(u16 id)
{
__bit_clear(flags_bits, id);
}flag_get
Lee una bandera de juego de activado/desactivado del array de bits en RAM de la biblioteca. Úsala para saber si una puerta está abierta, si se ha recogido un objeto o si ha ocurrido otro evento definido por el juego. Leerla no la modifica.
Sintaxis
u8 flag_get(u16 id);Parámetros
idNúmero de bandera, de 0 a 2047, pasado como u16. El desplazamiento de byte es id / 8 y el bit dentro de él es id % 8, empezando por el menos significativo. El tipo de parámetro más amplio no aumenta el almacenamiento fijo de 2048 banderas.
Valor devuelto
Booleano u8 normalizado: 0 si la bandera está desactivada y 1 si está activada. Esta biblioteca GB llama a la función intrínseca GB __bit_test, que normaliza el resultado.
Condiciones y límites
La función no valida el ID. Mantén los ID de banderas por debajo de 2048 y los de misiones por debajo de 64; un acceso fuera de rango puede leer o sobrescribir otra RAM. Los ejemplos inicializan explícitamente en lugar de depender del contenido al arrancar.
flags.c dispone de 256 bytes de RAM para banderas y otros 64 para misiones. Estas funciones no acceden a la RAM de guardado del cartucho ni conservan datos al apagar. Para mantener el progreso, el juego debe serializar los valores de banderas y misiones mediante su sistema de guardado y restaurarlos al cargar.
Incluye rpg.h y compila lib/flags.c con el juego. Los arrays son privados de ese archivo; accede mediante las API de banderas y misiones. Todos los llamadores comparten el almacenamiento, así que coordina las escrituras del bucle principal y los manejadores de interrupciones.
Ejemplo de uso
before=flag_get(9); // Door-open flag: 0 after explicit initialization.Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo asigna la bandera 9 a una puerta. Tras borrarla explícitamente, BEFORE muestra 000. Activarla y borrarla después produce DOOR OPEN 001 y DOOR CLOSED 000, mostrando que las lecturas reflejan la condición almacenada.
El programa completo muestra resultados decimales sobre blanco: texto negro en DMG y azul en CGB. FAILED debe ser 000. Las capturas solo muestran el comportamiento del estado en RAM; no demuestran el guardado de una partida.
La verificación en el emulador DMG cubrió todos los ID de banderas de 0 a 2047, activaciones y borrados repetidos, entradas vecinas y los 256 valores de estado de cada una de las 64 misiones. Se compararon un patrón final de 256 bytes de banderas y 64 bytes de misiones con los datos esperados. Ambas pantallas didácticas se comprobaron tras 240 fotogramas. No se probaron hardware físico ni persistencia del guardado.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\flags_quests.c .\kitaqgb\lib\flags.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\flags_quests.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/rpg.h:368
Read a bit from the flag array. Callers must keep id below 2048.
kitaqgb/lib/flags.c:9
u8 flag_get(u16 id)
{
return __bit_test(flags_bits, id);
}flag_set
Pone una bandera de juego a 1 conservando las otras siete de su byte. Si ya estaba activada, sigue así; úsalo para registrar un evento único, como abrir una puerta.
Sintaxis
void flag_set(u16 id);Parámetros
idNúmero de bandera, de 0 a 2047, pasado como u16. El desplazamiento de byte es id / 8 y el bit dentro de él es id % 8, empezando por el menos significativo. El tipo de parámetro más amplio no aumenta el almacenamiento fijo de 2048 banderas.
Valor devuelto
Ninguno (void).
Condiciones y límites
La función no valida el ID. Mantén los ID de banderas por debajo de 2048 y los de misiones por debajo de 64; un acceso fuera de rango puede leer o sobrescribir otra RAM. Los ejemplos inicializan explícitamente en lugar de depender del contenido al arrancar.
flags.c dispone de 256 bytes de RAM para banderas y otros 64 para misiones. Estas funciones no acceden a la RAM de guardado del cartucho ni conservan datos al apagar. Para mantener el progreso, el juego debe serializar los valores de banderas y misiones mediante su sistema de guardado y restaurarlos al cargar.
Incluye rpg.h y compila lib/flags.c con el juego. Los arrays son privados de ese archivo; accede mediante las API de banderas y misiones. Todos los llamadores comparten el almacenamiento, así que coordina las escrituras del bucle principal y los manejadores de interrupciones.
Ejemplo de uso
flag_set(9); // Mark the door as open; setting an already set flag is harmless.
flag_set(9);
opened=flag_get(9);neighbor=flag_get(8); // 1 and 0: adjacent flag is unchanged.Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo activa dos veces la bandera de puerta 9. DOOR OPEN muestra 001 y la bandera vecina 8 permanece en NEIGHBOR 000. Ambas ocupan el mismo byte, así que el valor vecino demuestra que activar una bandera conserva la otra.
El programa completo muestra resultados decimales sobre blanco: texto negro en DMG y azul en CGB. FAILED debe ser 000. Las capturas solo muestran el comportamiento del estado en RAM; no demuestran el guardado de una partida.
La verificación en el emulador DMG cubrió todos los ID de banderas de 0 a 2047, activaciones y borrados repetidos, entradas vecinas y los 256 valores de estado de cada una de las 64 misiones. Se compararon un patrón final de 256 bytes de banderas y 64 bytes de misiones con los datos esperados. Ambas pantallas didácticas se comprobaron tras 240 fotogramas. No se probaron hardware físico ni persistencia del guardado.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\flags_quests.c .\kitaqgb\lib\flags.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\flags_quests.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/rpg.h:370
Set a flag bit without disturbing adjacent flags; id must be below 2048.
kitaqgb/lib/flags.c:15
void flag_set(u16 id)
{
__bit_set(flags_bits, id);
}map_current_height
Lee el alto del mapa activo.
Sintaxis
u8 map_current_height();Valor devuelto
Devuelve el alto en celdas, o cero si no hay ningún mapa cargado.
Condiciones y límites
Las coordenadas indican celdas del mapa activo: 8×8 píxeles para tiles normales y 16×16 para metatiles.
Ejemplo de uso
result[1]=map_current_height();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La cuadrícula izquierda muestra los costes de movimiento en tres pasos; la derecha, una ruta más corta de S a G. Los asteriscos verdes trazan nueve pasos alrededor de una pared roja de tres celdas; los dígitos azules muestran los costes. DMG usa la misma disposición en negro. Las comprobaciones de RAM también muestran que la máscara de ataque ignora las paredes.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_map_path.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_map_path.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=noneImplementación y código fuente
kitaqgb/lib/rpg.h:391
Return the active map height in its own cell units, or zero when no map is loaded.
kitaqgb/lib/map.c:25
u8 map_current_height()
{
if (map_meta_loaded != 0) return map_meta_current.height;
if (map_loaded == 0) return 0;
return map_current.height;
}map_current_width
Lee el ancho del mapa activo.
Sintaxis
u8 map_current_width();Valor devuelto
Devuelve el ancho en celdas, o cero si no hay ningún mapa cargado.
Condiciones y límites
Las coordenadas indican celdas del mapa activo: 8×8 píxeles para tiles normales y 16×16 para metatiles.
Ejemplo de uso
result[0]=map_current_width();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La cuadrícula izquierda muestra los costes de movimiento en tres pasos; la derecha, una ruta más corta de S a G. Los asteriscos verdes trazan nueve pasos alrededor de una pared roja de tres celdas; los dígitos azules muestran los costes. DMG usa la misma disposición en negro. Las comprobaciones de RAM también muestran que la máscara de ataque ignora las paredes.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_map_path.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_map_path.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=noneImplementación y código fuente
kitaqgb/lib/rpg.h:389
Return the active map width in its own cell units, or zero when no map is loaded.
kitaqgb/lib/map.c:17
u8 map_current_width()
{
if (map_meta_loaded != 0) return map_meta_current.width;
if (map_loaded == 0) return 0;
return map_current.width;
}map_draw_visible
Dibuja 10×9 metatiles desde el origen indicado y guarda esa posición de cámara para redibujar cuando haya cambios pendientes.
Sintaxis
void map_draw_visible(u8 camera_tx, u8 camera_ty);Parámetros
camera_txX de la celda más a la izquierda; mantenla como máximo en 246 para evitar el desbordamiento de byte durante el recorrido.
camera_tyY de la celda superior; mantenla como máximo en 247.
Valor devuelto
No devuelve ningún valor.
Condiciones y límites
Las celdas exteriores dibujan el metatile de ID cero, así que proporciona siempre la definición cero. La llamada no modifica las celdas fuera del área de 20×18 tiles ni los atributos de CGB.
Ejemplo de uso
map_draw_visible(1,0);result[9]=*((u8*)0x9800);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Edita un ID de metatile en RAM, márcalo como modificado y aplícalo. La cámara (1,0) muestra un cuadrado verde de 16×16 arriba a la izquierda. El ejemplo aplica expresamente los metadatos de paleta a los atributos CGB. DMG muestra un cuadrado negro.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_metatile.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_metatile.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=noneImplementación y código fuente
kitaqgb/lib/rpg.h:304
Draw a 10-by-9 metatile viewport as 20-by-18 individual background tiles. Out-of-range cells use definition zero; palette attributes are not written. Remember the camera and clear the dirty flag after the full redraw.
kitaqgb/lib/map.c:212
void map_draw_visible(u8 camera_tx, u8 camera_ty)
{
u8 my;
if (map_meta_loaded == 0) return;
map_camera_x = camera_tx;
map_camera_y = camera_ty;
my = 0;
while (my < 9) {
u8 mx = 0;
while (mx < 10) {
u8 tx = (u8)(camera_tx + mx);
u8 ty = (u8)(camera_ty + my);
u8 sx = (u8)(mx << 1);
u8 sy = (u8)(my << 1);
metatile_t meta;
u8 id = map_get_metatile(tx, ty);
map_read_metatile(id, &meta);
__settile_xy(sx, sy, meta.tile_tl);
__settile_xy((u8)(sx + 1), sy, meta.tile_tr);
__settile_xy(sx, (u8)(sy + 1), meta.tile_bl);
__settile_xy((u8)(sx + 1), (u8)(sy + 1), meta.tile_br);
mx++;
}
my++;
}
map_dirty = 0;
}map_flush_dirty
Si hay cambios pendientes, redibuja el área visible desde el origen de cámara guardado y borra el indicador de cambio.
Sintaxis
void map_flush_dirty();Valor devuelto
No devuelve ningún valor.
Condiciones y límites
No hace nada si no hay cambios pendientes. El redibujado abarca los 10×9 metatiles, no solo la celda modificada.
Ejemplo de uso
map_flush_dirty();result[11]=*((u8*)0x9800);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Edita un ID de metatile en RAM, márcalo como modificado y aplícalo. La cámara (1,0) muestra un cuadrado verde de 16×16 arriba a la izquierda. El ejemplo aplica expresamente los metadatos de paleta a los atributos CGB. DMG muestra un cuadrado negro.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_metatile.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_metatile.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=noneImplementación y código fuente
kitaqgb/lib/rpg.h:321
Redraw the remembered metatile viewport only when the shared dirty flag is set.
kitaqgb/lib/map.c:254
void map_flush_dirty()
{
if (map_dirty == 0) return;
map_draw_visible(map_camera_x, map_camera_y);
}map_get_attr
Lee los metadatos de paleta de la definición de metatile de la celda.
Sintaxis
u8 map_get_attr(u8 tx, u8 ty);Parámetros
txCoordenada X del metatile.
tyCoordenada Y del metatile.
Valor devuelto
Devuelve el byte de paleta. Las celdas exteriores usan la definición cero; fuera del modo metatile, devuelve cero.
Condiciones y límites
Las coordenadas indican celdas del mapa activo: 8×8 píxeles para tiles normales y 16×16 para metatiles.
Ejemplo de uso
result[3]=map_get_attr(0,0);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Edita un ID de metatile en RAM, márcalo como modificado y aplícalo. La cámara (1,0) muestra un cuadrado verde de 16×16 arriba a la izquierda. El ejemplo aplica expresamente los metadatos de paleta a los atributos CGB. DMG muestra un cuadrado negro.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_metatile.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_metatile.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=noneImplementación y código fuente
kitaqgb/lib/rpg.h:310
Return the selected definition's palette byte. An out-of-range coordinate uses the metatile-zero fallback; this function does not write CGB attributes.
kitaqgb/lib/map.c:172
u8 map_get_attr(u8 tx, u8 ty)
{
metatile_t meta;
u8 id;
if (map_meta_loaded == 0) return 0;
id = map_get_metatile(tx, ty);
map_read_metatile(id, &meta);
return meta.palette;
}map_get_event
Lee un ID de evento de metatile; los mapas normales indican si hay un evento.
Sintaxis
u8 map_get_event(u8 tx, u8 ty);Parámetros
txCoordenada X del metatile.
tyCoordenada Y del metatile.
Valor devuelto
Devuelve el byte de evento de metatile o el booleano del mapa normal; si no hay mapa o la celda está fuera, devuelve cero.
Condiciones y límites
Las coordenadas indican celdas del mapa activo: 8×8 píxeles para tiles normales y 16×16 para metatiles.
Ejemplo de uso
result[7]=map_get_event(0,0);result[8]=map_get_event(3,0);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Edita un ID de metatile en RAM, márcalo como modificado y aplícalo. La cámara (1,0) muestra un cuadrado verde de 16×16 arriba a la izquierda. El ejemplo aplica expresamente los metadatos de paleta a los atributos CGB. DMG muestra un cuadrado negro.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_metatile.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_metatile.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=noneImplementación y código fuente
kitaqgb/lib/rpg.h:316
Return a metatile event ID, or the ordinary-map Boolean trigger result. Missing/out-of-range metatile cells have no event.
kitaqgb/lib/map.c:197
u8 map_get_event(u8 tx, u8 ty)
{
metatile_t meta;
u8 id;
if (map_meta_loaded == 0) return map_trigger_at(tx, ty);
if (tx >= map_meta_current.width || ty >= map_meta_current.height) return 0;
id = map_get_metatile(tx, ty);
map_read_metatile(id, &meta);
return meta.event;
}map_get_metatile
Lee el ID de metatile de una celda.
Sintaxis
u8 map_get_metatile(u8 tx, u8 ty);Parámetros
txCoordenada X del metatile.
tyCoordenada Y del metatile.
Valor devuelto
Devuelve el ID, o cero fuera del mapa o si no está activo el modo metatile.
Condiciones y límites
Las coordenadas indican celdas del mapa activo: 8×8 píxeles para tiles normales y 16×16 para metatiles.
Ejemplo de uso
result[1]=map_get_metatile(0,0);result[2]=map_get_metatile(3,0);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Edita un ID de metatile en RAM, márcalo como modificado y aplícalo. La cámara (1,0) muestra un cuadrado verde de 16×16 arriba a la izquierda. El ejemplo aplica expresamente los metadatos de paleta a los atributos CGB. DMG muestra un cuadrado negro.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_metatile.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_metatile.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=noneImplementación y código fuente
kitaqgb/lib/rpg.h:307
Read a row-major metatile ID, returning ID zero for inactive or out-of-range lookups. Callers must provide a usable definition for metatile zero.
kitaqgb/lib/map.c:159
u8 map_get_metatile(u8 tx, u8 ty)
{
u16 index;
if (map_meta_loaded == 0) return 0;
if (tx >= map_meta_current.width || ty >= map_meta_current.height) return 0;
index = __map_index(tx, ty, map_meta_current.width);
return __farpeek8(map_meta_data_bank(), map_meta_current.metatile_ids + index);
}map_is_blocked
Comprueba si la celda de destino bloquea el movimiento; el modo metatile usa el campo collision de su definición.
Sintaxis
u8 map_is_blocked(u8 x, u8 y);Parámetros
xCoordenada X de la celda.
yCoordenada Y de la celda.
Valor devuelto
Devuelve 1 si es una pared, una coordenada exterior o no hay mapa, y 0 si la celda es transitable. En un mapa normal, un array de colisión NULL hace transitables todas las celdas dentro del mapa.
Condiciones y límites
Las coordenadas indican celdas del mapa activo: 8×8 píxeles para tiles normales y 16×16 para metatiles.
Ejemplo de uso
result[4]=map_is_blocked(2,2);result[5]=map_is_blocked(6,2);result[6]=map_is_blocked(1,2);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La cuadrícula izquierda muestra los costes de movimiento en tres pasos; la derecha, una ruta más corta de S a G. Los asteriscos verdes trazan nueve pasos alrededor de una pared roja de tres celdas; los dígitos azules muestran los costes. DMG usa la misma disposición en negro. Las comprobaciones de RAM también muestran que la máscara de ataque ignora las paredes.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_map_path.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_map_path.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=noneImplementación y código fuente
kitaqgb/lib/rpg.h:290
Use metatile collision when that mode is active; otherwise read one packed collision bit. Missing maps/out-of-range cells block movement, but a valid ordinary map without a collision array is entirely passable.
kitaqgb/lib/map.c:68
u8 map_is_blocked(u8 x, u8 y)
{
u16 index;
u8 value;
if (map_meta_loaded != 0) return map_is_solid(x, y);
if (map_loaded == 0) return 1;
if (x >= map_current.width || y >= map_current.height) return 1;
if (map_current.collision_bits == 0) return 0;
index = __map_index(x, y, map_current.width);
// Collision uses least-significant bit first within each row-major group of eight cells.
value = __farpeek8(map_bank, map_current.collision_bits + (index >> 3));
if ((value & (u8)(1 << (index & 7))) != 0) return 1;
return 0;
}map_is_solid
Comprueba la solidez; en modo de mapa normal delega en los bits de colisión.
Sintaxis
u8 map_is_solid(u8 tx, u8 ty);Parámetros
txCoordenada X del metatile.
tyCoordenada Y del metatile.
Valor devuelto
Devuelve 1 si collision no es cero o la celda está fuera del mapa; en caso contrario, 0.
Condiciones y límites
Las coordenadas indican celdas del mapa activo: 8×8 píxeles para tiles normales y 16×16 para metatiles.
Ejemplo de uso
result[4]=map_is_solid(0,0);result[5]=map_is_solid(1,0);result[6]=map_is_solid(3,0);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Edita un ID de metatile en RAM, márcalo como modificado y aplícalo. La cámara (1,0) muestra un cuadrado verde de 16×16 arriba a la izquierda. El ejemplo aplica expresamente los metadatos de paleta a los atributos CGB. DMG muestra un cuadrado negro.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_metatile.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_metatile.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=noneImplementación y código fuente
kitaqgb/lib/rpg.h:313
Treat out-of-range metatile cells as solid; otherwise inspect the definition collision flag. In ordinary-map mode, delegate to its packed collision bits.
kitaqgb/lib/map.c:184
u8 map_is_solid(u8 tx, u8 ty)
{
metatile_t meta;
u8 id;
if (map_meta_loaded == 0) return map_is_blocked(tx, ty);
if (tx >= map_meta_current.width || ty >= map_meta_current.height) return 1;
id = map_get_metatile(tx, ty);
map_read_metatile(id, &meta);
return (u8)(meta.collision != 0);
}map_load
Carga un descriptor de mapa normal y dibuja hasta 20×18 tiles desde su esquina superior izquierda en el mapa de fondo seleccionado.
Sintaxis
void map_load(u8 bank, const map_t* map);Parámetros
bankBanco ROM del descriptor, los bits de colisión y los eventos.
mapmap_t empaquetado de nueve bytes. tiles contiene width*height ID de tile; collision_bits empaqueta las celdas empezando por el bit menos significativo; events guarda un byte por celda. La lectura de tiles usa bank_tiles.
Valor devuelto
No devuelve ningún valor.
Condiciones y límites
Se comparte un único mapa activo. Se copia el descriptor, pero sus arrays deben seguir siendo legibles mientras se necesiten. Carga los gráficos de tiles en VRAM por separado.
Las coordenadas indican celdas del mapa activo: 8×8 píxeles para tiles normales y 16×16 para metatiles.
No borra las celdas fuera de un mapa pequeño. En los mapas normales, bank_tiles=0 significa banco cero; no hereda el banco del descriptor.
Ejemplo de uso
map_load(0,maps);result[2]=map_current_width();result[3]=map_current_height();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La cuadrícula izquierda muestra los costes de movimiento en tres pasos; la derecha, una ruta más corta de S a G. Los asteriscos verdes trazan nueve pasos alrededor de una pared roja de tres celdas; los dígitos azules muestran los costes. DMG usa la misma disposición en negro. Las comprobaciones de RAM también muestran que la máscara de ataque ignora las paredes.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_map_path.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_map_path.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=noneImplementación y código fuente
kitaqgb/lib/rpg.h:286
Load the nine-byte ordinary-map descriptor and draw up to 20 by 18 tiles from its top-left corner. Drawing does not upload tile graphics or clear background cells beyond smaller map dimensions.
kitaqgb/lib/map.c:35
void map_load(u8 bank, const map_t* map)
{
u8 row;
u8 h;
u8 w;
// The literal copy size depends on the packed map_t layout; changing that layout requires updating this copy.
__farmemcpy(&map_current, bank, map, 9);
map_bank = bank;
map_loaded = 1;
map_meta_loaded = 0;
w = map_current.width;
h = map_current.height;
if (w > 20) w = 20;
if (h > 18) h = 18;
row = 0;
while (row < h) {
u8 x = 0;
u16 base_index = __map_index(0, row, map_current.width);
while (x < w) {
map_row[x] = __farpeek8(map_current.bank_tiles, map_current.tiles + base_index + x);
x++;
}
__settile_row(0, row, map_row, w);
row++;
}
}map_load_metatile
Selecciona un mapa de metatiles y expande un área visible de 10×9 celdas con cámara en (0,0) a 20×18 tiles.
Sintaxis
void map_load_metatile(u8 bank, const metatile_map_t* map);Parámetros
bankBanco ROM que contiene el descriptor.
mapPuntero a metatile_map_t. Las dimensiones cuentan celdas de 16×16 píxeles. Hace referencia a un array de ID y una tabla de definiciones metatile_t de siete bytes.
Valor devuelto
No devuelve ningún valor.
Condiciones y límites
Se comparte un único mapa activo. Se copia el descriptor, pero sus arrays deben seguir siendo legibles mientras se necesiten. Carga los gráficos de tiles en VRAM por separado.
bank_tiles=0 hereda el banco del descriptor; un valor distinto de cero elige el banco tanto de los ID como de las definiciones. Una definición guarda los tiles superior izquierdo, superior derecho, inferior izquierdo e inferior derecho, además de colisión, paleta y evento. El dibujo no aplica automáticamente los metadatos de paleta.
Ejemplo de uso
map_load_metatile(0,&level);result[0]=*((u8*)0x9800);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Edita un ID de metatile en RAM, márcalo como modificado y aplícalo. La cámara (1,0) muestra un cuadrado verde de 16×16 arriba a la izquierda. El ejemplo aplica expresamente los metadatos de paleta a los atributos CGB. DMG muestra un cuadrado negro.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_metatile.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_metatile.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=noneImplementación y código fuente
kitaqgb/lib/rpg.h:300
Select metatile mode, copy its descriptor and draw the initial viewport with the camera at cell (0,0).
kitaqgb/lib/map.c:145
void map_load_metatile(u8 bank, const metatile_map_t* map)
{
map_meta_bank = bank;
__farmemcpy(&map_meta_current, bank, map, sizeof(metatile_map_t));
map_meta_loaded = 1;
map_loaded = 0;
map_dirty = 0;
map_camera_x = 0;
map_camera_y = 0;
map_draw_visible(0, 0);
}map_mark_dirty
Marca el área visible para redibujar cuando recibe una coordenada de metatile válida.
Sintaxis
void map_mark_dirty(u8 tx, u8 ty);Parámetros
txCoordenada X del metatile.
tyCoordenada Y del metatile.
Valor devuelto
No devuelve ningún valor.
Condiciones y límites
Activa un único indicador compartido de cambio en lugar de encolar una actualización por celda. Se ignoran las coordenadas exteriores. El código que llama cambia los ID o las definiciones por separado antes de marcar la modificación.
Ejemplo de uso
ids[1]=1;map_mark_dirty(1,0);result[10]=*((u8*)0x9800);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Edita un ID de metatile en RAM, márcalo como modificado y aplícalo. La cámara (1,0) muestra un cuadrado verde de 16×16 arriba a la izquierda. El ejemplo aplica expresamente los metadatos de paleta a los atributos CGB. DMG muestra un cuadrado negro.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_metatile.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_metatile.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=noneImplementación y código fuente
kitaqgb/lib/rpg.h:319
Mark the viewport for a full redraw when a valid metatile cell changes. The coordinate is validated but no per-cell dirty list is retained.
kitaqgb/lib/map.c:246
void map_mark_dirty(u8 tx, u8 ty)
{
if (map_meta_loaded == 0) return;
if (tx >= map_meta_current.width || ty >= map_meta_current.height) return;
map_dirty = 1;
}map_trigger_at
Comprueba si una celda tiene un evento, sin ejecutarlo.
Sintaxis
u8 map_trigger_at(u8 x, u8 y);Parámetros
xCoordenada X de la celda.
yCoordenada Y de la celda.
Valor devuelto
Devuelve 1 si hay un evento y 0 si no; no devuelve el byte de evento guardado ni el ID de evento del metatile.
Condiciones y límites
Las coordenadas indican celdas del mapa activo: 8×8 píxeles para tiles normales y 16×16 para metatiles.
Ejemplo de uso
result[7]=map_trigger_at(5,4);result[8]=map_trigger_at(6,4);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La cuadrícula izquierda muestra los costes de movimiento en tres pasos; la derecha, una ruta más corta de S a G. Los asteriscos verdes trazan nueve pasos alrededor de una pared roja de tres celdas; los dígitos azules muestran los costes. DMG usa la misma disposición en negro. Las comprobaciones de RAM también muestran que la máscara de ataque ignora las paredes.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_map_path.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_map_path.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=noneImplementación y código fuente
kitaqgb/lib/rpg.h:293
Report whether an event exists at the cell. Ordinary maps expose a Boolean byte-presence test; metatile maps reduce their event ID to a Boolean here.
kitaqgb/lib/map.c:87
u8 map_trigger_at(u8 x, u8 y)
{
u16 index;
u8 value;
if (map_meta_loaded != 0) return (u8)(map_get_event(x, y) != 0);
if (map_loaded == 0) return 0;
if (x >= map_current.width || y >= map_current.height) return 0;
if (map_current.events == 0) return 0;
index = __map_index(x, y, map_current.width);
value = __farpeek8(map_bank, ((const u8*)map_current.events) + index);
return (u8)((value != 0) ? 1 : 0);
}path_find_bfs
Encuentra una ruta ortogonal más corta y escribe sus direcciones en orden desde el inicio hasta el destino.
Sintaxis
u8 path_find_bfs(u8 sx, u8 sy, u8 gx, u8 gy, u8* out_path, u8 max_len);Parámetros
sxX de la celda inicial, dentro del mapa.
syY de la celda inicial.
gxX de la celda de destino; se rechaza un destino bloqueado distinto del origen.
gyY de la celda de destino.
out_pathArray escribible de al menos max_len bytes; 0=arriba, 1=derecha, 2=abajo, 3=izquierda.
max_lenCapacidad de salida; una ruta demasiado larga falla en lugar de truncarse.
Valor devuelto
Devuelve la longitud de la ruta; cero significa destino inalcanzable, coordenadas no válidas, max_len insuficiente o destino ya alcanzado.
Condiciones y límites
Las coordenadas indican celdas del mapa activo: 8×8 píxeles para tiles normales y 16×16 para metatiles.
La búsqueda usa unos 4 KiB de espacio de trabajo compartido y no reentrante. Limita los mapas a 1024 celdas y las distancias exploradas a 254. La distancia 0xFF significa «no alcanzado», así que no se puede representar una ruta de 255 pasos. Las salidas de coste y máscara necesitan width*height bytes escribibles.
max_len limita la salida, no el radio de búsqueda. No uses la salida como una ruta nueva después de un fallo.
Ejemplo de uso
result[49]=path_find_bfs(0,2,5,2,route,30);x=0;y=2;for(i=0;i<result[49];i++){if(route[i]==0)y--;if(route[i]==1)x++;if(route[i]==2)y++;if(route[i]==3)x--;}result[50]=x;result[51]=y;result[52]=path_find_bfs(0,2,5,2,route,2);result[53]=path_find_bfs(0,2,2,2,route,30);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La cuadrícula izquierda muestra los costes de movimiento en tres pasos; la derecha, una ruta más corta de S a G. Los asteriscos verdes trazan nueve pasos alrededor de una pared roja de tres celdas; los dígitos azules muestran los costes. DMG usa la misma disposición en negro. Las comprobaciones de RAM también muestran que la máscara de ataque ignora las paredes.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_map_path.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_map_path.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=noneImplementación y código fuente
kitaqgb/lib/rpg.h:361
Find a shortest cardinal path with BFS and write direction codes 0=up, 1=right, 2=down, 3=left. Return its byte length, or zero for failure or an already-reached goal. The caller supplies max_len output bytes and respects the shared workspace/distance limits; excessive paths are not truncated.
kitaqgb/lib/slg_path.c:78
u8 path_find_bfs(u8 sx, u8 sy, u8 gx, u8 gy, u8* out_path, u8 max_len)
{
u8 w = map_current_width();
u8 h = map_current_height();
u16 total;
u16 head = 0;
u16 tail = 0;
u16 start;
u16 goal;
u8 found = 0;
if (w == 0 || h == 0) return 0;
if (sx >= w || sy >= h || gx >= w || gy >= h) return 0;
if ((sx != gx || sy != gy) && map_is_blocked(gx, gy) != 0) return 0;
total = (u16)((u16)w * (u16)h);
__memset(path_dist, 0xFF, total);
start = __map_index(sx, sy, w);
goal = __map_index(gx, gy, w);
path_dist[start] = 0;
path_queue[tail++] = start;
while (head < tail) {
u16 cur = path_queue[head++];
u8 cost = path_dist[cur];
u8 y = (u8)(cur / w);
u8 x = (u8)(cur - ((u16)y * (u16)w));
if (cur == goal) {
found = 1;
break;
}
if (y > 0) {
u16 next = (u16)(cur - w);
if (path_dist[next] == 0xFF && map_is_blocked(x, (u8)(y - 1)) == 0) {
path_dist[next] = (u8)(cost + 1);
path_queue[tail++] = next;
}
}
if ((u8)(x + 1) < w) {
u16 next = (u16)(cur + 1);
if (path_dist[next] == 0xFF && map_is_blocked((u8)(x + 1), y) == 0) {
path_dist[next] = (u8)(cost + 1);
path_queue[tail++] = next;
}
}
if ((u8)(y + 1) < h) {
u16 next = (u16)(cur + w);
if (path_dist[next] == 0xFF && map_is_blocked(x, (u8)(y + 1)) == 0) {
path_dist[next] = (u8)(cost + 1);
path_queue[tail++] = next;
}
}
if (x > 0) {
u16 next = (u16)(cur - 1);
if (path_dist[next] == 0xFF && map_is_blocked((u8)(x - 1), y) == 0) {
path_dist[next] = (u8)(cost + 1);
path_queue[tail++] = next;
}
}
}
// Reject unreachable or oversized paths before reconstructing output.
if (found == 0) return 0;
if (path_dist[goal] > max_len) return 0;
{
// Walk backward through decreasing costs, recording forward directions in
// reverse order. The fixed neighbor order makes tied routes deterministic.
u8 len = 0;
u16 cur = goal;
while (cur != start) {
u8 cur_cost = path_dist[cur];
u8 y = (u8)(cur / w);
u8 x = (u8)(cur - ((u16)y * (u16)w));
if (y > 0 && path_dist[(u16)(cur - w)] == (u8)(cur_cost - 1)) {
path_rev[len++] = 2;
cur = (u16)(cur - w);
continue;
}
if ((u8)(x + 1) < w && path_dist[(u16)(cur + 1)] == (u8)(cur_cost - 1)) {
path_rev[len++] = 3;
cur = (u16)(cur + 1);
continue;
}
if ((u8)(y + 1) < h && path_dist[(u16)(cur + w)] == (u8)(cur_cost - 1)) {
path_rev[len++] = 0;
cur = (u16)(cur + w);
continue;
}
if (x > 0 && path_dist[(u16)(cur - 1)] == (u8)(cur_cost - 1)) {
path_rev[len++] = 1;
cur = (u16)(cur - 1);
continue;
}
return 0;
}
// Reverse the recovered directions so the first output step starts at the origin.
while (len != 0) {
len--;
out_path[path_dist[goal] - 1 - len] = path_rev[len];
}
return path_dist[goal];
}
}quest_set_state
Sustituye todo el byte de estado de una misión. El significado de cada valor lo define el juego; por ejemplo, 1 para aceptada y 3 para completada. La función no comprueba si la transición está permitida ni activa recompensas o retrollamadas.
Sintaxis
void quest_set_state(u8 quest_id, u8 state);Parámetros
quest_idNúmero de misión, de 0 a 63, pasado como u8. Indexa directamente uno de los 64 bytes de estado; es un ID definido por el juego, no un puntero ni un recuento de misiones completadas.
stateNuevo estado u8, de 0 a 255. Los ocho bits sustituyen el valor anterior. La biblioteca no asigna significados predefinidos a los valores ni reserva 0 o 255.
Valor devuelto
Ninguno (void).
Condiciones y límites
La función no valida el ID. Mantén los ID de banderas por debajo de 2048 y los de misiones por debajo de 64; un acceso fuera de rango puede leer o sobrescribir otra RAM. Los ejemplos inicializan explícitamente en lugar de depender del contenido al arrancar.
flags.c dispone de 256 bytes de RAM para banderas y otros 64 para misiones. Estas funciones no acceden a la RAM de guardado del cartucho ni conservan datos al apagar. Para mantener el progreso, el juego debe serializar los valores de banderas y misiones mediante su sistema de guardado y restaurarlos al cargar.
Incluye rpg.h y compila lib/flags.c con el juego. Los arrays son privados de ese archivo; accede mediante las API de banderas y misiones. Todos los llamadores comparten el almacenamiento, así que coordina las escrituras del bucle principal y los manejadores de interrupciones.
Ejemplo de uso
quest_set_state(2,1); // In this game, 1 means accepted.
started=quest_state(2);
quest_set_state(2,3); // In this game, 3 means completed; replace the whole byte.Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo almacena 1 y luego lo sustituye por 3 para la misión 2. ACCEPTED muestra la primera observación, 001, y COMPLETED el valor sustituto, 003. LAST QUEST es 255 tras guardar 255 en el ID de misión 63, la última entrada válida.
El programa completo muestra resultados decimales sobre blanco: texto negro en DMG y azul en CGB. FAILED debe ser 000. Las capturas solo muestran el comportamiento del estado en RAM; no demuestran el guardado de una partida.
La verificación en el emulador DMG cubrió todos los ID de banderas de 0 a 2047, activaciones y borrados repetidos, entradas vecinas y los 256 valores de estado de cada una de las 64 misiones. Se compararon un patrón final de 256 bytes de banderas y 64 bytes de misiones con los datos esperados. Ambas pantallas didácticas se comprobaron tras 240 fotogramas. No se probaron hardware físico ni persistencia del guardado.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\flags_quests.c .\kitaqgb\lib\flags.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\flags_quests.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/rpg.h:377
Replace a quest-state byte without validating its game-specific meaning. The caller must keep quest_id below 64.
kitaqgb/lib/flags.c:34
void quest_set_state(u8 quest_id, u8 state)
{
quest_states[quest_id] = state;
}quest_state
Lee el byte almacenado para una misión. A diferencia de una bandera de un bit, este byte distingue varias etapas, como no iniciada, aceptada y completada. La función solo lee el almacenamiento; no ejecuta lógica de misión ni avanza de etapa.
Sintaxis
u8 quest_state(u8 quest_id);Parámetros
quest_idNúmero de misión, de 0 a 63, pasado como u8. Indexa directamente uno de los 64 bytes de estado; es un ID definido por el juego, no un puntero ni un recuento de misiones completadas.
Valor devuelto
Valor u8 almacenado, de 0 a 255. Es un byte de estado completo, no un booleano normalizado; compáralo con los valores de etapa definidos por tu juego.
Condiciones y límites
La función no valida el ID. Mantén los ID de banderas por debajo de 2048 y los de misiones por debajo de 64; un acceso fuera de rango puede leer o sobrescribir otra RAM. Los ejemplos inicializan explícitamente en lugar de depender del contenido al arrancar.
flags.c dispone de 256 bytes de RAM para banderas y otros 64 para misiones. Estas funciones no acceden a la RAM de guardado del cartucho ni conservan datos al apagar. Para mantener el progreso, el juego debe serializar los valores de banderas y misiones mediante su sistema de guardado y restaurarlos al cargar.
Incluye rpg.h y compila lib/flags.c con el juego. Los arrays son privados de ese archivo; accede mediante las API de banderas y misiones. Todos los llamadores comparten el almacenamiento, así que coordina las escrituras del bucle principal y los manejadores de interrupciones.
Ejemplo de uso
finished=quest_state(2); // Read back 3 without advancing any quest logic.Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo lee la misión 2 después de que el juego cambie explícitamente su estado de 1 a 3. ACCEPTED muestra 001 y COMPLETED, 003. Los nombres y significados de las etapas los elige el ejemplo; no los impone la biblioteca.
El programa completo muestra resultados decimales sobre blanco: texto negro en DMG y azul en CGB. FAILED debe ser 000. Las capturas solo muestran el comportamiento del estado en RAM; no demuestran el guardado de una partida.
La verificación en el emulador DMG cubrió todos los ID de banderas de 0 a 2047, activaciones y borrados repetidos, entradas vecinas y los 256 valores de estado de cada una de las 64 misiones. Se compararon un patrón final de 256 bytes de banderas y 64 bytes de misiones con los datos esperados. Ambas pantallas didácticas se comprobaron tras 240 fotogramas. No se probaron hardware físico ni persistencia del guardado.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\flags_quests.c .\kitaqgb\lib\flags.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\flags_quests.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/rpg.h:374
Read a quest-state byte; quest_id must be below 64.
kitaqgb/lib/flags.c:27
u8 quest_state(u8 quest_id)
{
return quest_states[quest_id];
}rand_range
Elige un valor desde cero e inferior a max mediante rng8() % max. Por ejemplo, un límite de 10 da un índice de 0 a 9. Un límite cero devuelve cero inmediatamente sin extraer.
Sintaxis
u8 rand_range(u8 max);Parámetros
maxLímite superior excluido como u8 (0–255). Si max > 0, el resultado es menor que max. Este parámetro no puede expresar 256; usa rng8 para obtener el byte completo sin reducción módulo.
Valor devuelto
Si max > 0, un u8 de 0 a max−1 tras una extracción. Si max == 0, cero sin extracción. Incluso max == 1 consume una extracción aunque el resultado sea siempre cero.
Condiciones y límites
La reducción por módulo puede favorecer algunos resultados si el rango de entrada no es divisible por el límite. El generador subyacente tampoco tiene por qué ser uniforme. Trata los resultados acotados y los umbrales de probabilidad como aproximaciones para el juego, no como probabilidades exactas.
Estas llamadas comparten estado persistente. Para reproducir la secuencia hacen falta el mismo destino, semilla y orden de llamadas, incluidas las de otras funciones auxiliares. Mantén la semilla y las extracciones en un único contexto de ejecución; estas comprobaciones no demuestran que sea seguro usarlas simultáneamente desde una interrupción.
GB y FC usan algoritmos distintos y no prometen la misma secuencia con la misma semilla. Son generadores deterministas para juegos, no fuentes de aleatoriedad criptográfica; las pruebas comprueban el comportamiento de la implementación, no su calidad estadística ni su período.
Incluye rpg.h y compila lib/rng.c junto al juego cuando uses las funciones de biblioteca. Las intrínsecas __rng_seed y __rng8 las genera el compilador; un programa que solo use esas dos no necesita el objeto rng.c.
Ejemplo de uso
rng_seed(0x1234);
bounded=rand_range(10); // An index from 0 through 9; this seed yields 2.Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Este ejemplo elige un índice menor que 10. RANGE 10 muestra 00002 porque el primer byte de la semilla 0x1234 es 2. ZERO BOUND es 00000 y el siguiente NEXT BYTE sigue en 00002, confirmando que la llamada con límite cero no extrajo nada.
El programa completo muestra resultados decimales sobre blanco: texto negro en DMG y azul en CGB. FAILED debe indicar 00000. Las imágenes muestran la salida real del ejemplo en el emulador.
La verificación comparó por caso 32 salidas y ocho extracciones de byte posteriores con un modelo independiente en el equipo anfitrión: 93 casos GB y 18 FC, incluidos semillas constantes o en tiempo de ejecución y límites GB de rango, probabilidad y pesos. Las pantallas didácticas se comprobaron tras 240 fotogramas del emulador. No se probaron hardware físico ni calidad estadística.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\rng_choices.c .\kitaqgb\lib\rng.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\rng_choices.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/rpg.h:199
Reduce a random byte modulo max; zero returns zero without consuming randomness. Modulo reduction is biased unless max divides the generator range.
kitaqgb/lib/rng.c:37
u8 rand_range(u8 max)
{
if (max == 0) return 0;
return (u8)(rng8() % max);
}range_fill_move
Recorre los vecinos ortogonales con coste unitario mediante búsqueda en anchura para calcular los costes de movimiento.
Sintaxis
void range_fill_move(u8 sx, u8 sy, u8 move, u8* out_costmap);Parámetros
sxX de la celda inicial, dentro del mapa.
syY de la celda inicial.
moveLímite de movimiento de 0 a 254; cero alcanza solo el origen.
out_costmapArray de costes escribible de width*height: 255 para no alcanzado y cero en el origen.
Valor devuelto
No devuelve ningún valor.
Condiciones y límites
Las coordenadas indican celdas del mapa activo: 8×8 píxeles para tiles normales y 16×16 para metatiles.
La búsqueda usa unos 4 KiB de espacio de trabajo compartido y no reentrante. Limita los mapas a 1024 celdas y las distancias exploradas a 254. La distancia 0xFF significa «no alcanzado», así que no se puede representar una ruta de 255 pasos. Las salidas de coste y máscara necesitan width*height bytes escribibles.
Si no hay mapa o el origen no es válido, la salida no cambia. No se entra en celdas de destino bloqueadas.
Ejemplo de uso
range_fill_move(0,2,3,costs);for(i=0;i<30;i++)result[13+i]=costs[i];Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La cuadrícula izquierda muestra los costes de movimiento en tres pasos; la derecha, una ruta más corta de S a G. Los asteriscos verdes trazan nueve pasos alrededor de una pared roja de tres celdas; los dígitos azules muestran los costes. DMG usa la misma disposición en negro. Las comprobaciones de RAM también muestran que la máscara de ataque ignora las paredes.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_map_path.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_map_path.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=noneImplementación y código fuente
kitaqgb/lib/rpg.h:365
Flood cardinal neighbors at unit cost, stopping expansion at the movement limit and rejecting blocked destinations. Initialize output to 0xFF only after validating the map and origin; invalid input leaves output unchanged.
kitaqgb/lib/slg_path.c:14
void range_fill_move(u8 sx, u8 sy, u8 move, u8* out_costmap)
{
u8 w = map_current_width();
u8 h = map_current_height();
u16 total;
u16 head = 0;
u16 tail = 0;
u16 start;
if (w == 0 || h == 0) return;
if (sx >= w || sy >= h) return;
total = (u16)((u16)w * (u16)h);
__memset(out_costmap, 0xFF, total);
start = __map_index(sx, sy, w);
out_costmap[start] = 0;
path_queue[tail++] = start;
while (head < tail) {
u16 cur = path_queue[head++];
u8 cost = out_costmap[cur];
u8 y = (u8)(cur / w);
u8 x = (u8)(cur - ((u16)y * (u16)w));
if (cost >= move) continue;
if (y > 0) {
u16 next = (u16)(cur - w);
if (out_costmap[next] == 0xFF && map_is_blocked(x, (u8)(y - 1)) == 0) {
out_costmap[next] = (u8)(cost + 1);
path_queue[tail++] = next;
}
}
if ((u8)(x + 1) < w) {
u16 next = (u16)(cur + 1);
if (out_costmap[next] == 0xFF && map_is_blocked((u8)(x + 1), y) == 0) {
out_costmap[next] = (u8)(cost + 1);
path_queue[tail++] = next;
}
}
if ((u8)(y + 1) < h) {
u16 next = (u16)(cur + w);
if (out_costmap[next] == 0xFF && map_is_blocked(x, (u8)(y + 1)) == 0) {
out_costmap[next] = (u8)(cost + 1);
path_queue[tail++] = next;
}
}
if (x > 0) {
u16 next = (u16)(cur - 1);
if (out_costmap[next] == 0xFF && map_is_blocked((u8)(x - 1), y) == 0) {
out_costmap[next] = (u8)(cost + 1);
path_queue[tail++] = next;
}
}
}
}rle_decode
Descomprime un flujo de bytes RLE en RAM normal escribible. Cada par count/value repite un byte count veces; un contador cero termina el flujo. Usa esta variante si los datos codificados ya se pueden leer mediante un puntero normal y quieres inspeccionar o modificar los bytes descomprimidos antes de transferirlos.
Sintaxis
u16 rle_decode(void* dst, const void* src);Parámetros
dstPuntero a RAM escribible con espacio para todo el flujo descomprimido. No se pasa una capacidad a la función. Mantén la salida separada del origen codificado para no sobrescribir pares aún no leídos.
srcPuntero legible a pares de bytes count/value terminados por un contador cero. Una repetición normal tiene count entre 1 y 255; el valor puede ser cualquier byte, incluido cero. El cero final no lleva un byte value detrás. El puntero debe seguir siendo legible en el mapeo actual durante toda la llamada.
Valor devuelto
Número de bytes escritos como u16. Un contador cero inmediato no produce bytes y devuelve 0. El terminador no se copia. La longitud descomprimida debe caber en u16; el retorno no incluye un código de error separado ni representa una cantidad de tiles.
Condiciones y límites
La codificación trabaja con bytes, no con texto. Por ejemplo, {3, 0x12, 2, 0xA5, 0} se expande a cinco bytes: 12 12 12 A5 A5. Esa lista de salida está en hexadecimal. Un valor cero en un par con count distinto de cero es un dato normal, no una marca de fin.
No hay argumentos para el tamaño codificado, la capacidad de salida o el tratamiento de datos malformados. Valida los recursos al crearlos o cargarlos, añade el cero final y calcula el tamaño descomprimido antes de decodificar. Un flujo inválido o sin terminador puede leer fuera del origen y escribir fuera del destino.
Los decodificadores RAM usan escrituras normales y no se sincronizan con los períodos de acceso del LCD. Mantén sus destinos en RAM. Para mostrar el resultado, transfiérelo aparte con una API de copia VRAM adecuada, como hace el ejemplo con el LCD detenido.
Durante una lectura con banco indicado, evita que una interrupción cambie el mapeo ROM o reutilice la rutina de copia lejana: estas funciones comparten el estado de gestión de bancos. Sitúa el decodificador de puntero normal y su origen en mapeos compatibles; cambiar al banco de la función no debe ocultar el puntero normal de origen.
rle_decode y rle_decode_far se declaran en rpg.h y se implementan en lib/rle.c. Compila esa implementación una sola vez con el juego. El ejemplo completo incluye rle.c después de #pragma bank 0 para mantener el código que llama y los decodificadores en el banco común; no pases además rle.c como entrada separada en este ejemplo. La función intrínseca __rle_decode_vram no necesita un archivo de implementación de biblioteca.
Ejemplo de uso
near_count=rle_decode(near_buffer+1,local_rle); // 48 bytes in writable RAM.
__vram_copy(0x8800,near_buffer+1,near_count); // Upload those bytes while the LCD is off.Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Este ejemplo descomprime nueve bytes codificados en un búfer RAM con zonas de guarda y copia el resultado de 48 bytes a la dirección de tiles 0x8800. RLE TO RAM muestra 048. La fila superior es roja en CGB y presenta los tres tiles decodificados mediante el puntero normal.
Cada fila contiene, de izquierda a derecha, un cuadrado relleno de 8×8, un contorno de 8×8 de un píxel de grosor y un rectángulo relleno de 4×8 que ocupa la mitad izquierda de un tile de 8×8. Están en las columnas de tiles 2, 5 y 8 (x = 16, 40 y 64 píxeles). Las tres filas empiezan en y = 32, 72 y 112 píxeles. DMG usa formas negras; CGB usa rojo, verde y azul por fila. FAILED debe ser 000. Los números son bytes: tres tiles GB de 16 bytes requieren 48 bytes descomprimidos.
La matriz de verificación comprueba 42 casos: flujo vacío, repetición de un byte, datos de valor cero, repetición de 255 bytes, salida de 510 bytes que cruza una página de destino y datos codificados que cruzan una página de origen. Compara los 528 bytes observados de destino y guarda, la longitud de salida y el mapeo ROM restaurado. Los casos de VRAM directa incluyen LCD encendido/apagado en DMG y CGB, además de VBK 1 en CGB. Las dos pantallas didácticas se comprueban tras 240 fotogramas del emulador. No cubre recursos inválidos, uso simultáneo por interrupciones ni hardware físico.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\rle_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\rle_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/rpg.h:382
Expand count/value byte pairs until a zero count terminates the stream. The caller must provide a valid terminator and sufficient destination storage; there are no source or destination bounds parameters. Return the 16-bit byte count.
kitaqgb/lib/rle.c:8
u16 rle_decode(void* dst, const void* src)
{
const u8* in = (const u8*)src;
u8* out = (u8*)dst;
u16 total = 0;
while (1) {
u8 count = *in++;
u8 value;
if (count == 0) break;
value = *in++;
while (count != 0) {
*out++ = value;
total++;
count--;
}
}
return total;
}rle_decode_far
Descomprime el mismo formato count/value en RAM, leyendo cada byte codificado mediante __farpeek8 en el banco ROM indicado. Úsalo para recursos comprimidos en un banco ROM conmutable. El destino sigue siendo un puntero RAM normal; el argumento de banco describe el origen.
Sintaxis
u16 rle_decode_far(void* dst, u8 bank, const void* src);Parámetros
dstPuntero a RAM escribible con espacio para todo el flujo descomprimido. No se pasa una capacidad a la función. Mantén la salida separada del origen codificado para no sobrescribir pares aún no leídos.
bankNúmero de banco ROM de origen como u8. El banco y la dirección CPU deben corresponder al mapper del cartucho y a la ubicación del recurso. La selección de banco se restaura tras leer cada byte codificado. No selecciona el banco VRAM de destino ni puede representar un número de banco MBC5 de nueve bits.
srcPuntero CPU al flujo codificado en el banco indicado. La función incrementa la dirección, pero mantiene fijo el banco. Conserva todo el flujo, incluido el cero final, dentro de un mapeo legible; cruzar 0x7FFF no continúa automáticamente en el banco ROM siguiente.
Valor devuelto
Número de bytes escritos como u16. Un contador cero inmediato no produce bytes y devuelve 0. El terminador no se copia. La longitud descomprimida debe caber en u16; el retorno no incluye un código de error separado ni representa una cantidad de tiles.
Condiciones y límites
La codificación trabaja con bytes, no con texto. Por ejemplo, {3, 0x12, 2, 0xA5, 0} se expande a cinco bytes: 12 12 12 A5 A5. Esa lista de salida está en hexadecimal. Un valor cero en un par con count distinto de cero es un dato normal, no una marca de fin.
No hay argumentos para el tamaño codificado, la capacidad de salida o el tratamiento de datos malformados. Valida los recursos al crearlos o cargarlos, añade el cero final y calcula el tamaño descomprimido antes de decodificar. Un flujo inválido o sin terminador puede leer fuera del origen y escribir fuera del destino.
Los decodificadores RAM usan escrituras normales y no se sincronizan con los períodos de acceso del LCD. Mantén sus destinos en RAM. Para mostrar el resultado, transfiérelo aparte con una API de copia VRAM adecuada, como hace el ejemplo con el LCD detenido.
Durante una lectura con banco indicado, evita que una interrupción cambie el mapeo ROM o reutilice la rutina de copia lejana: estas funciones comparten el estado de gestión de bancos. Sitúa el decodificador de puntero normal y su origen en mapeos compatibles; cambiar al banco de la función no debe ocultar el puntero normal de origen.
rle_decode y rle_decode_far se declaran en rpg.h y se implementan en lib/rle.c. Compila esa implementación una sola vez con el juego. El ejemplo completo incluye rle.c después de #pragma bank 0 para mantener el código que llama y los decodificadores en el banco común; no pases además rle.c como entrada separada en este ejemplo. La función intrínseca __rle_decode_vram no necesita un archivo de implementación de biblioteca.
Ejemplo de uso
far_count=rle_decode_far(far_buffer+1,2,banked_rle); // Read encoded pairs from ROM bank 2.
if(*rle_bank_marker!=0xA1)failures++; // ROM bank 1 must be visible again.
__vram_copy(0x8830,far_buffer+1,far_count);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Este ejemplo lee el flujo codificado del banco ROM 2, descomprime 48 bytes en RAM y los transfiere a 0x8830. BANKED RAM muestra 048. La fila central es verde en CGB. También comprueba un marcador del banco ROM 1 para verificar que se restaura el mapeo del código que llama.
Cada fila contiene, de izquierda a derecha, un cuadrado relleno de 8×8, un contorno de 8×8 de un píxel de grosor y un rectángulo relleno de 4×8 que ocupa la mitad izquierda de un tile de 8×8. Están en las columnas de tiles 2, 5 y 8 (x = 16, 40 y 64 píxeles). Las tres filas empiezan en y = 32, 72 y 112 píxeles. DMG usa formas negras; CGB usa rojo, verde y azul por fila. FAILED debe ser 000. Los números son bytes: tres tiles GB de 16 bytes requieren 48 bytes descomprimidos.
La matriz de verificación comprueba 42 casos: flujo vacío, repetición de un byte, datos de valor cero, repetición de 255 bytes, salida de 510 bytes que cruza una página de destino y datos codificados que cruzan una página de origen. Compara los 528 bytes observados de destino y guarda, la longitud de salida y el mapeo ROM restaurado. Los casos de VRAM directa incluyen LCD encendido/apagado en DMG y CGB, además de VBK 1 en CGB. Las dos pantallas didácticas se comprueban tras 240 fotogramas del emulador. No cubre recursos inválidos, uso simultáneo por interrupciones ni hardware físico.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\rle_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\rle_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/rpg.h:386
Decode the same count/value format using bank-qualified reads for every source byte. Keep the encoded stream within the supplied bank/address mapping and provide enough destination space; a zero count ends the stream.
kitaqgb/lib/rle.c:34
u16 rle_decode_far(void* dst, u8 bank, const void* src)
{
const u8* p = (const u8*)src;
u8* out = (u8*)dst;
u16 total = 0;
while (1) {
u8 count = __farpeek8(bank, p);
u8 value;
p++;
if (count == 0) break;
value = __farpeek8(bank, p);
p++;
while (count != 0) {
*out++ = value;
total++;
count--;
}
}
return total;
}rng16
Construye un valor de 16 bits sin signo con dos extracciones consecutivas de rng8. El primer byte ocupa los bits 15–8 y el segundo los bits 7–0. Úsalo cuando un byte no alcance para el rango que necesitas.
Sintaxis
u16 rng16();Valor devuelto
Un resultado u16 (0–65535), formado como (first_byte << 8) | second_byte. Consume exactamente dos extracciones de byte; esto no demuestra una distribución uniforme de los 65536 valores.
Condiciones y límites
Estas llamadas comparten estado persistente. Para reproducir la secuencia hacen falta el mismo destino, semilla y orden de llamadas, incluidas las de otras funciones auxiliares. Mantén la semilla y las extracciones en un único contexto de ejecución; estas comprobaciones no demuestran que sea seguro usarlas simultáneamente desde una interrupción.
GB y FC usan algoritmos distintos y no prometen la misma secuencia con la misma semilla. Son generadores deterministas para juegos, no fuentes de aleatoriedad criptográfica; las pruebas comprueban el comportamiento de la implementación, no su calidad estadística ni su período.
Incluye rpg.h y compila lib/rng.c junto al juego cuando uses las funciones de biblioteca. Las intrínsecas __rng_seed y __rng8 las genera el compilador; un programa que solo use esas dos no necesita el objeto rng.c.
Ejemplo de uso
rng_seed(0x1234);
word=rng16(); // First draw 2 is high, second draw 34 is low: 0x0222 = 546.Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Este ejemplo muestra cómo se forma una palabra. Tras volver a sembrar con 0x1234, los bytes 2 y 34 forman 0x0222, por lo que RNG16 muestra 00546. FIRST y SECOND muestran los valores de byte por separado.
El programa completo muestra resultados decimales sobre blanco: texto negro en DMG y azul en CGB. FAILED debe indicar 00000. Las imágenes muestran la salida real del ejemplo en el emulador.
La verificación comparó por caso 32 salidas y ocho extracciones de byte posteriores con un modelo independiente en el equipo anfitrión: 93 casos GB y 18 FC, incluidos semillas constantes o en tiempo de ejecución y límites GB de rango, probabilidad y pesos. Las pantallas didácticas se comprobaron tras 240 fotogramas del emulador. No se probaron hardware físico ni calidad estadística.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\rng_values.c .\kitaqgb\lib\rng.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\rng_values.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/rpg.h:196
Consume two generator bytes in high-byte/low-byte order to form a 16-bit value.
kitaqgb/lib/rng.c:22
u16 rng16()
{
u16 hi = (u16)rng8();
u16 lo = (u16)rng8();
return (u16)((hi << 8) | lo);
}rng8
Obtiene un byte pseudoaleatorio mediante la biblioteca GB. rng8 llama a __rng8 exactamente una vez y constituye la extracción básica que usan las demás funciones de rng.c.
Sintaxis
u8 rng8();Valor devuelto
Un resultado u8 (0–255) tras avanzar una vez el generador compartido. Esto describe el tipo y los límites del valor, no que todos los bytes tengan la misma probabilidad.
Condiciones y límites
Estas llamadas comparten estado persistente. Para reproducir la secuencia hacen falta el mismo destino, semilla y orden de llamadas, incluidas las de otras funciones auxiliares. Mantén la semilla y las extracciones en un único contexto de ejecución; estas comprobaciones no demuestran que sea seguro usarlas simultáneamente desde una interrupción.
GB y FC usan algoritmos distintos y no prometen la misma secuencia con la misma semilla. Son generadores deterministas para juegos, no fuentes de aleatoriedad criptográfica; las pruebas comprueban el comportamiento de la implementación, no su calidad estadística ni su período.
Incluye rpg.h y compila lib/rng.c junto al juego cuando uses las funciones de biblioteca. Las intrínsecas __rng_seed y __rng8 las genera el compilador; un programa que solo use esas dos no necesita el objeto rng.c.
Ejemplo de uso
rng_seed(0x1234); // Reset the same generator used by the intrinsics.
wrapped=rng8(); // One byte draw: 2 after the preceding seed.Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Este ejemplo compara la extracción de byte de biblioteca con la intrínseca. Tras rng_seed(0x1234), RNG8 muestra 00002, igual que FIRST. Establecer la semilla no consume la primera extracción.
El programa completo muestra resultados decimales sobre blanco: texto negro en DMG y azul en CGB. FAILED debe indicar 00000. Las imágenes muestran la salida real del ejemplo en el emulador.
La verificación comparó por caso 32 salidas y ocho extracciones de byte posteriores con un modelo independiente en el equipo anfitrión: 93 casos GB y 18 FC, incluidos semillas constantes o en tiempo de ejecución y límites GB de rango, probabilidad y pesos. Las pantallas didácticas se comprobaron tras 240 fotogramas del emulador. No se probaron hardware físico ni calidad estadística.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\rng_values.c .\kitaqgb\lib\rng.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\rng_values.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/rpg.h:194
Advance the compiler-provided pseudorandom generator and return one byte.
kitaqgb/lib/rng.c:4
u8 rng8()
{
return __rng8();
}rng_chance
Toma una decisión de sí/no mediante rng_range(100) < percent. Sirve para probabilidades aproximadas de juego, como decidir si un enemigo deja un objeto. Cero siempre devuelve falso; 100 o más siempre devuelve verdadero. Ninguno de esos casos extremos consume una extracción.
Sintaxis
u8 rng_chance(u8 percent);Parámetros
percentProbabilidad solicitada como u8. Los valores 1–99 usan un byte reducido por módulo; 0 devuelve falso y 100–255 devuelven verdadero. Los valores intermedios son umbrales aproximados, no una garantía de porcentajes exactos.
Valor devuelto
Booleano normalizado: 0 para falso y 1 para verdadero. Un umbral de 1 a 99 consume una extracción de byte.
Condiciones y límites
La reducción por módulo puede favorecer algunos resultados si el rango de entrada no es divisible por el límite. El generador subyacente tampoco tiene por qué ser uniforme. Trata los resultados acotados y los umbrales de probabilidad como aproximaciones para el juego, no como probabilidades exactas.
Estas llamadas comparten estado persistente. Para reproducir la secuencia hacen falta el mismo destino, semilla y orden de llamadas, incluidas las de otras funciones auxiliares. Mantén la semilla y las extracciones en un único contexto de ejecución; estas comprobaciones no demuestran que sea seguro usarlas simultáneamente desde una interrupción.
GB y FC usan algoritmos distintos y no prometen la misma secuencia con la misma semilla. Son generadores deterministas para juegos, no fuentes de aleatoriedad criptográfica; las pruebas comprueban el comportamiento de la implementación, no su calidad estadística ni su período.
Incluye rpg.h y compila lib/rng.c junto al juego cuando uses las funciones de biblioteca. Las intrínsecas __rng_seed y __rng8 las genera el compilador; un programa que solo use esas dos no necesita el objeto rng.c.
Ejemplo de uso
rng_seed(0x1234);
chance=rng_chance(50); // Here 2 % 100 < 50, so the result is 1 (true).Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Este ejemplo toma una decisión aproximada del 50 %. El byte generado es 2 y 2 % 100 < 50 es verdadero, así que CHANCE 50 muestra 00001. Un único éxito no demuestra una tasa de éxito del 50 % a largo plazo.
El programa completo muestra resultados decimales sobre blanco: texto negro en DMG y azul en CGB. FAILED debe indicar 00000. Las imágenes muestran la salida real del ejemplo en el emulador.
La verificación comparó por caso 32 salidas y ocho extracciones de byte posteriores con un modelo independiente en el equipo anfitrión: 93 casos GB y 18 FC, incluidos semillas constantes o en tiempo de ejecución y límites GB de rango, probabilidad y pesos. Las pantallas didácticas se comprobaron tras 240 fotogramas del emulador. No se probaron hardware físico ni calidad estadística.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\rng_choices.c .\kitaqgb\lib\rng.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\rng_choices.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/rpg.h:214
Return false for zero and true for values at least 100. Intermediate values use the modulo-based range generator, so percentages are approximate.
kitaqgb/lib/rng.c:51
u8 rng_chance(u8 percent)
{
if (percent == 0) return 0;
if (percent >= 100) return 1;
return (u8)(rng_range(100) < percent);
}rng_next16
Devuelve la misma palabra de dos extracciones que rng16. Es un alias de biblioteca, con la primera extracción en el byte alto y la segunda en el bajo; no salta un valor adicional antes de extraer.
Sintaxis
u16 rng_next16();Valor devuelto
Un resultado u16 (0–65535), formado como (first_byte << 8) | second_byte. Consume exactamente dos extracciones de byte; esto no demuestra una distribución uniforme de los 65536 valores.
Condiciones y límites
Estas llamadas comparten estado persistente. Para reproducir la secuencia hacen falta el mismo destino, semilla y orden de llamadas, incluidas las de otras funciones auxiliares. Mantén la semilla y las extracciones en un único contexto de ejecución; estas comprobaciones no demuestran que sea seguro usarlas simultáneamente desde una interrupción.
GB y FC usan algoritmos distintos y no prometen la misma secuencia con la misma semilla. Son generadores deterministas para juegos, no fuentes de aleatoriedad criptográfica; las pruebas comprueban el comportamiento de la implementación, no su calidad estadística ni su período.
Incluye rpg.h y compila lib/rng.c junto al juego cuando uses las funciones de biblioteca. Las intrínsecas __rng_seed y __rng8 las genera el compilador; un programa que solo use esas dos no necesita el objeto rng.c.
Ejemplo de uso
rng_seed(0x1234);
nextword=rng_next16(); // The same two-draw word: 546.Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Este ejemplo compara el alias de palabra con rng16 tras semillas iguales. NEXT16 y RNG16 muestran 00546, formado por dos extracciones de byte en orden alto/bajo.
El programa completo muestra resultados decimales sobre blanco: texto negro en DMG y azul en CGB. FAILED debe indicar 00000. Las imágenes muestran la salida real del ejemplo en el emulador.
La verificación comparó por caso 32 salidas y ocho extracciones de byte posteriores con un modelo independiente en el equipo anfitrión: 93 casos GB y 18 FC, incluidos semillas constantes o en tiempo de ejecución y límites GB de rango, probabilidad y pesos. Las pantallas didácticas se comprobaron tras 240 fotogramas del emulador. No se probaron hardware físico ni calidad estadística.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\rng_values.c .\kitaqgb\lib\rng.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\rng_values.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/rpg.h:209
Alias the two-step 16-bit generator.
kitaqgb/lib/rng.c:30
u16 rng_next16()
{
return rng16();
}rng_next8
Extrae el siguiente byte con la misma operación que rng8. El nombre destaca el avance de la secuencia; llamar a ambos nombres sucesivamente consume dos extracciones consecutivas del mismo generador compartido.
Sintaxis
u8 rng_next8();Valor devuelto
Un resultado u8 (0–255) tras avanzar una vez el generador compartido. Esto describe el tipo y los límites del valor, no que todos los bytes tengan la misma probabilidad.
Condiciones y límites
Estas llamadas comparten estado persistente. Para reproducir la secuencia hacen falta el mismo destino, semilla y orden de llamadas, incluidas las de otras funciones auxiliares. Mantén la semilla y las extracciones en un único contexto de ejecución; estas comprobaciones no demuestran que sea seguro usarlas simultáneamente desde una interrupción.
GB y FC usan algoritmos distintos y no prometen la misma secuencia con la misma semilla. Son generadores deterministas para juegos, no fuentes de aleatoriedad criptográfica; las pruebas comprueban el comportamiento de la implementación, no su calidad estadística ni su período.
Incluye rpg.h y compila lib/rng.c junto al juego cuando uses las funciones de biblioteca. Las intrínsecas __rng_seed y __rng8 las genera el compilador; un programa que solo use esas dos no necesita el objeto rng.c.
Ejemplo de uso
rng_seed(0x1234);
nextbyte=rng_next8(); // One draw, just like rng8(): 2.Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Este ejemplo comprueba el alias de byte con la misma semilla. NEXT8 y RNG8 muestran 00002 porque el programa vuelve a establecer la semilla antes de cada comparación; sin esos reinicios consumirían valores consecutivos.
El programa completo muestra resultados decimales sobre blanco: texto negro en DMG y azul en CGB. FAILED debe indicar 00000. Las imágenes muestran la salida real del ejemplo en el emulador.
La verificación comparó por caso 32 salidas y ocho extracciones de byte posteriores con un modelo independiente en el equipo anfitrión: 93 casos GB y 18 FC, incluidos semillas constantes o en tiempo de ejecución y límites GB de rango, probabilidad y pesos. Las pantallas didácticas se comprobaron tras 240 fotogramas del emulador. No se probaron hardware físico ni calidad estadística.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\rng_values.c .\kitaqgb\lib\rng.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\rng_values.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/rpg.h:207
Alias the byte generator; this consumes one generator step.
kitaqgb/lib/rng.c:16
u8 rng_next8()
{
return rng8();
}rng_range
Llama a rand_range con el mismo límite superior excluido. Este nombre agrupa la selección acotada con las otras funciones rng_. Usa la misma extracción de byte y el mismo módulo, incluido el retorno sin extracción para límite cero.
Sintaxis
u8 rng_range(u8 max);Parámetros
maxLímite superior excluido como u8 (0–255). Si max > 0, el resultado es menor que max. Este parámetro no puede expresar 256; usa rng8 para obtener el byte completo sin reducción módulo.
Valor devuelto
Si max > 0, un u8 de 0 a max−1 tras una extracción. Si max == 0, cero sin extracción. Incluso max == 1 consume una extracción aunque el resultado sea siempre cero.
Condiciones y límites
La reducción por módulo puede favorecer algunos resultados si el rango de entrada no es divisible por el límite. El generador subyacente tampoco tiene por qué ser uniforme. Trata los resultados acotados y los umbrales de probabilidad como aproximaciones para el juego, no como probabilidades exactas.
Estas llamadas comparten estado persistente. Para reproducir la secuencia hacen falta el mismo destino, semilla y orden de llamadas, incluidas las de otras funciones auxiliares. Mantén la semilla y las extracciones en un único contexto de ejecución; estas comprobaciones no demuestran que sea seguro usarlas simultáneamente desde una interrupción.
GB y FC usan algoritmos distintos y no prometen la misma secuencia con la misma semilla. Son generadores deterministas para juegos, no fuentes de aleatoriedad criptográfica; las pruebas comprueban el comportamiento de la implementación, no su calidad estadística ni su período.
Incluye rpg.h y compila lib/rng.c junto al juego cuando uses las funciones de biblioteca. Las intrínsecas __rng_seed y __rng8 las genera el compilador; un programa que solo use esas dos no necesita el objeto rng.c.
Ejemplo de uso
rng_seed(0x1234);
alias=rng_range(10); // The same exclusive upper bound and result, 2.Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Este ejemplo compara los dos nombres de selección acotada. Restablecer la semilla antes de cada llamada hace que ALIAS 10 y RANGE 10 muestren 00002. El propio límite 10 queda excluido.
El programa completo muestra resultados decimales sobre blanco: texto negro en DMG y azul en CGB. FAILED debe indicar 00000. Las imágenes muestran la salida real del ejemplo en el emulador.
La verificación comparó por caso 32 salidas y ocho extracciones de byte posteriores con un modelo independiente en el equipo anfitrión: 93 casos GB y 18 FC, incluidos semillas constantes o en tiempo de ejecución y límites GB de rango, probabilidad y pesos. Las pantallas didácticas se comprobaron tras 240 fotogramas del emulador. No se probaron hardware físico ni calidad estadística.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\rng_choices.c .\kitaqgb\lib\rng.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\rng_choices.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/rpg.h:211
Alias rand_range and return a value in [0,max), or zero when max is zero.
kitaqgb/lib/rng.c:44
u8 rng_range(u8 max)
{
return rand_range(max);
}rng_seed
Establece la semilla mediante la interfaz de biblioteca GB. Es un envoltorio de __rng_seed y reinicia el mismo estado compartido que usan rng8, rng16 y las funciones de selección; no crea otro generador.
Sintaxis
void rng_seed(u16 seed);Parámetros
seedSemilla de 16 bits sin signo, de 0 a 65535. Los dos bytes se almacenan tal como se reciben. Elige y registra la semilla antes de la secuencia de extracciones del juego que quieras reproducir.
Valor devuelto
Ninguno (void).
Condiciones y límites
Se acepta el estado cero. En la siguiente extracción de byte, el generador GB lo sustituye por 0x5AA5 antes de avanzar; por eso __rng_seed(0) seguido de __rng8() devuelve 122. Volver a sembrar repetidamente reinicia la secuencia en lugar de añadir aleatoriedad.
Estas llamadas comparten estado persistente. Para reproducir la secuencia hacen falta el mismo destino, semilla y orden de llamadas, incluidas las de otras funciones auxiliares. Mantén la semilla y las extracciones en un único contexto de ejecución; estas comprobaciones no demuestran que sea seguro usarlas simultáneamente desde una interrupción.
GB y FC usan algoritmos distintos y no prometen la misma secuencia con la misma semilla. Son generadores deterministas para juegos, no fuentes de aleatoriedad criptográfica; las pruebas comprueban el comportamiento de la implementación, no su calidad estadística ni su período.
Incluye rpg.h y compila lib/rng.c junto al juego cuando uses las funciones de biblioteca. Las intrínsecas __rng_seed y __rng8 las genera el compilador; un programa que solo use esas dos no necesita el objeto rng.c.
Ejemplo de uso
rng_seed(0x1234); // Reset the same generator used by the intrinsics.
wrapped=rng8(); // One byte draw: 2 after the preceding seed.Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Este ejemplo compara la extracción de byte de biblioteca con la intrínseca. Tras rng_seed(0x1234), RNG8 muestra 00002, igual que FIRST. Establecer la semilla no consume la primera extracción.
El programa completo muestra resultados decimales sobre blanco: texto negro en DMG y azul en CGB. FAILED debe indicar 00000. Las imágenes muestran la salida real del ejemplo en el emulador.
La verificación comparó por caso 32 salidas y ocho extracciones de byte posteriores con un modelo independiente en el equipo anfitrión: 93 casos GB y 18 FC, incluidos semillas constantes o en tiempo de ejecución y límites GB de rango, probabilidad y pesos. Las pantallas didácticas se comprobaron tras 240 fotogramas del emulador. No se probaron hardware físico ni calidad estadística.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\rng_values.c .\kitaqgb\lib\rng.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\rng_values.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/rpg.h:205
Replace the generator seed so subsequent calls can reproduce a sequence.
kitaqgb/lib/rng.c:10
void rng_seed(u16 seed)
{
__rng_seed(seed);
}save_check
Realiza la misma comprobación de integridad que save_exists sin extraer los datos.
Sintaxis
u8 save_check(u8 slot);Parámetros
slotNúmero de ranura de 0 a 3.
Valor devuelto
Devuelve 1 si es válido y 0 si no. Un guardado de longitud cero puede ser válido.
Condiciones y límites
Por defecto hay cuatro ranuras de 512 bytes, cada una con una cabecera de seis bytes y hasta 506 bytes de datos. El ejemplo usa MBC5 con 8 KiB de SRAM. Las llamadas terminan con la RAM desactivada y no restauran el banco ni el estado de activación anterior.
Ejemplo de uso
result[4]=save_check(0);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Guarda tres bytes, 7/42/255, y prueba una longitud distinta, una ranura no válida y una suma de comprobación dañada. Una carga correcta da 42 en el byte central; una lectura fallida conserva 77 en el destino; validar después de borrar devuelve 0.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_save.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_save.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=8kImplementación y código fuente
kitaqgb/lib/rpg.h:341
Alias save_exists, including its header and checksum validation.
kitaqgb/lib/save.c:175
u8 save_check(u8 slot)
{
return save_exists(slot);
}save_clear
Pone a cero los 512 bytes de una ranura para invalidar su guardado.
Sintaxis
void save_clear(u8 slot);Parámetros
slotNúmero de ranura de 0 a 3.
Valor devuelto
No devuelve ningún valor.
Condiciones y límites
Por defecto hay cuatro ranuras de 512 bytes, cada una con una cabecera de seis bytes y hasta 506 bytes de datos. El ejemplo usa MBC5 con 8 KiB de SRAM. Las llamadas terminan con la RAM desactivada y no restauran el banco ni el estado de activación anterior.
Ignora las ranuras fuera de 0..3 y deja las demás intactas.
Ejemplo de uso
save_clear(0);result[16]=save_check(0);result[17]=save_write(3,payload,0);result[18]=save_exists(3);save_clear(3);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Guarda tres bytes, 7/42/255, y prueba una longitud distinta, una ranura no válida y una suma de comprobación dañada. Una carga correcta da 42 en el byte central; una lectura fallida conserva 77 en el destino; validar después de borrar devuelve 0.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_save.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_save.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=8kImplementación y código fuente
kitaqgb/lib/rpg.h:344
Zero the complete selected slot, including header and payload; invalid slot IDs are ignored. Cartridge RAM is disabled when clearing finishes.
kitaqgb/lib/save.c:225
void save_clear(u8 slot)
{
u16 base;
u16 i;
if (slot >= SAVE_SLOT_COUNT) return;
base = save_slot_base(slot);
save_enable();
i = 0;
while (i < SAVE_SLOT_SIZE) {
save_write_abs((u16)(base + i), 0);
i++;
}
save_disable();
}save_exists
Valida la cabecera, la longitud y la suma de comprobación de una ranura para comprobar si contiene un guardado utilizable.
Sintaxis
u8 save_exists(u8 slot);Parámetros
slotNúmero de ranura de 0 a 3.
Valor devuelto
Devuelve 1 si es válido y 0 si no. Un guardado de longitud cero puede ser válido.
Condiciones y límites
Por defecto hay cuatro ranuras de 512 bytes, cada una con una cabecera de seis bytes y hasta 506 bytes de datos. El ejemplo usa MBC5 con 8 KiB de SRAM. Las llamadas terminan con la RAM desactivada y no restauran el banco ni el estado de activación anterior.
Ejemplo de uso
result[0]=save_exists(0);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Guarda tres bytes, 7/42/255, y prueba una longitud distinta, una ranura no válida y una suma de comprobación dañada. Una carga correcta da 42 en el byte central; una lectura fallida conserva 77 en el destino; validar después de borrar devuelve 0.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_save.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_save.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=8kImplementación y código fuente
kitaqgb/lib/rpg.h:334
Validate a slot's header, payload bounds and checksum without copying the payload out. A nonzero result means the stored record passes these checks.
kitaqgb/lib/save.c:182
u8 save_exists(u8 slot)
{
u16 base;
u16 stored_len;
u8 stored_sum;
if (slot >= SAVE_SLOT_COUNT) return 0;
base = save_slot_base(slot);
save_enable();
if (save_read_abs(base + 0) != SAVE_MAGIC0) {
save_disable();
return 0;
}
if (save_read_abs(base + 1) != SAVE_MAGIC1) {
save_disable();
return 0;
}
if (save_read_abs(base + 2) != SAVE_VERSION) {
save_disable();
return 0;
}
stored_len = (u16)save_read_abs(base + 3);
stored_len |= (u16)((u16)save_read_abs(base + 4) << 8);
stored_sum = save_read_abs(base + 5);
if (stored_len > (u16)(SAVE_SLOT_SIZE - SAVE_HEADER_SIZE)) {
save_disable();
return 0;
}
if (save_checksum_ram((u16)(base + SAVE_HEADER_SIZE), stored_len) != stored_sum) {
save_disable();
return 0;
}
save_disable();
return 1;
}save_init
Selecciona el banco RAM cero, lo activa brevemente y después lo desactiva.
Sintaxis
void save_init();Valor devuelto
No devuelve ningún valor.
Condiciones y límites
Por defecto hay cuatro ranuras de 512 bytes, cada una con una cabecera de seis bytes y hasta 506 bytes de datos. El ejemplo usa MBC5 con 8 KiB de SRAM. Las llamadas terminan con la RAM desactivada y no restauran el banco ni el estado de activación anterior.
No borra datos guardados, no detecta el hardware del cartucho ni formatea ranuras.
Ejemplo de uso
save_init();save_clear(0);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Guarda tres bytes, 7/42/255, y prueba una longitud distinta, una ranura no válida y una suma de comprobación dañada. Una carga correcta da 42 en el byte central; una lectura fallida conserva 77 en el destino; validar después de borrar devuelve 0.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_save.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_save.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=8kImplementación y código fuente
kitaqgb/lib/rpg.h:337
Initialize the expected RAM access state and leave cartridge RAM disabled. Existing slot contents are preserved.
kitaqgb/lib/save.c:70
void save_init()
{
save_enable();
save_disable();
}save_load
Carga los datos guardados con la misma validación que save_read.
Sintaxis
u8 save_load(u8 slot, void* data, u16 len);Parámetros
slotNúmero de ranura de 0 a 3.
dataDestino escribible de len bytes.
lenLongitud de datos de 0 a 506 bytes. La lectura exige que coincida exactamente con la longitud guardada.
Valor devuelto
Devuelve 1 si la carga tiene éxito y 0 en caso contrario; la longitud solicitada debe coincidir con la guardada.
Condiciones y límites
Por defecto hay cuatro ranuras de 512 bytes, cada una con una cabecera de seis bytes y hasta 506 bytes de datos. El ejemplo usa MBC5 con 8 KiB de SRAM. Las llamadas terminan con la RAM desactivada y no restauran el banco ni el estado de activación anterior.
La suma de comprobación aditiva de ocho bits no detecta todas las alteraciones. Las escrituras no son atómicas ante una pérdida de alimentación; un resultado correcto por sí solo no garantiza la persistencia física.
Ejemplo de uso
readback[1]=0;result[10]=save_load(0,readback,3);result[11]=readback[1];Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Guarda tres bytes, 7/42/255, y prueba una longitud distinta, una ranura no válida y una suma de comprobación dañada. Una carga correcta da 42 en el byte central; una lectura fallida conserva 77 en el destino; validar después de borrar devuelve 0.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_save.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_save.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=8kImplementación y código fuente
kitaqgb/lib/rpg.h:339
Alias the checked save_read operation.
kitaqgb/lib/save.c:114
u8 save_load(u8 slot, void* data, u16 len)
{
return save_read(slot, data, len);
}save_read
Valida la cabecera, la longitud exacta y la suma de comprobación, y copia los datos solo si la validación es correcta.
Sintaxis
u8 save_read(u8 slot, void* data, u16 len);Parámetros
slotNúmero de ranura de 0 a 3.
dataDestino escribible de len bytes.
lenLongitud de datos de 0 a 506 bytes. La lectura exige que coincida exactamente con la longitud guardada.
Valor devuelto
Devuelve 1 si tiene éxito y 0 si falla la validación; el fallo deja el destino intacto.
Condiciones y límites
Por defecto hay cuatro ranuras de 512 bytes, cada una con una cabecera de seis bytes y hasta 506 bytes de datos. El ejemplo usa MBC5 con 8 KiB de SRAM. Las llamadas terminan con la RAM desactivada y no restauran el banco ni el estado de activación anterior.
La suma de comprobación aditiva de ocho bits no detecta todas las alteraciones. Las escrituras no son atómicas ante una pérdida de alimentación; un resultado correcto por sí solo no garantiza la persistencia física.
Ejemplo de uso
readback[0]=99;result[5]=save_read(0,readback,2);result[6]=readback[0];result[7]=save_read(0,readback,3);result[8]=readback[0];result[9]=readback[2];Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Guarda tres bytes, 7/42/255, y prueba una longitud distinta, una ranura no válida y una suma de comprobación dañada. Una carga correcta da 42 en el byte central; una lectura fallida conserva 77 en el destino; validar después de borrar devuelve 0.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_save.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_save.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=8kImplementación y código fuente
kitaqgb/lib/rpg.h:331
Require matching magic/version, exact requested length and a valid checksum before copying data into the destination. Validation failure leaves the destination unchanged. An invalid slot returns before touching RAM control; validation failures after enabling RAM disable it before returning zero.
kitaqgb/lib/save.c:125
u8 save_read(u8 slot, void* data, u16 len)
{
u8* dst = (u8*)data;
u16 base;
u16 stored_len;
u8 stored_sum;
u16 i;
if (slot >= SAVE_SLOT_COUNT) return 0;
base = save_slot_base(slot);
save_enable();
if (save_read_abs(base + 0) != SAVE_MAGIC0) {
save_disable();
return 0;
}
if (save_read_abs(base + 1) != SAVE_MAGIC1) {
save_disable();
return 0;
}
if (save_read_abs(base + 2) != SAVE_VERSION) {
save_disable();
return 0;
}
stored_len = (u16)save_read_abs(base + 3);
stored_len |= (u16)((u16)save_read_abs(base + 4) << 8);
stored_sum = save_read_abs(base + 5);
if (stored_len != len || stored_len > (u16)(SAVE_SLOT_SIZE - SAVE_HEADER_SIZE)) {
save_disable();
return 0;
}
if (save_checksum_ram((u16)(base + SAVE_HEADER_SIZE), stored_len) != stored_sum) {
save_disable();
return 0;
}
i = 0;
while (i < stored_len) {
dst[i] = save_read_abs((u16)(base + SAVE_HEADER_SIZE + i));
i++;
}
save_disable();
return 1;
}save_write
Escribe los datos, la longitud y la suma de comprobación en una ranura.
Sintaxis
u8 save_write(u8 slot, const void* data, u16 len);Parámetros
slotNúmero de ranura de 0 a 3.
dataFuente legible de len bytes.
lenLongitud de datos de 0 a 506 bytes. La lectura exige que coincida exactamente con la longitud guardada.
Valor devuelto
Devuelve 1 si los argumentos son válidos y 0 si la ranura o la longitud no lo son; no verifica mediante lectura posterior.
Condiciones y límites
Por defecto hay cuatro ranuras de 512 bytes, cada una con una cabecera de seis bytes y hasta 506 bytes de datos. El ejemplo usa MBC5 con 8 KiB de SRAM. Las llamadas terminan con la RAM desactivada y no restauran el banco ni el estado de activación anterior.
La suma de comprobación aditiva de ocho bits no detecta todas las alteraciones. Las escrituras no son atómicas ante una pérdida de alimentación; un resultado correcto por sí solo no garantiza la persistencia física.
Ejemplo de uso
payload[0]=7;payload[1]=42;payload[2]=255;result[1]=save_write(0,payload,3);result[2]=save_write(4,payload,3);result[3]=save_write(0,payload,507);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Guarda tres bytes, 7/42/255, y prueba una longitud distinta, una ranura no válida y una suma de comprobación dañada. Una carga correcta da 42 en el byte central; una lectura fallida conserva 77 en el destino; validar después de borrar devuelve 0.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_save.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_save.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=8kImplementación y código fuente
kitaqgb/lib/rpg.h:326
Validate slot and payload length, write payload bytes, then write the header and checksum. Return one after completing the writes; interruption can leave a partially replaced slot, so this is not transactional save storage.
kitaqgb/lib/save.c:81
u8 save_write(u8 slot, const void* data, u16 len)
{
const u8* src = (const u8*)data;
u16 base;
u16 i;
u8 sum = 0;
if (slot >= SAVE_SLOT_COUNT) return 0;
if (len > (u16)(SAVE_SLOT_SIZE - SAVE_HEADER_SIZE)) return 0;
base = save_slot_base(slot);
save_enable();
i = 0;
while (i < len) {
u8 v = src[i];
save_write_abs((u16)(base + SAVE_HEADER_SIZE + i), v);
sum = (u8)(sum + v);
i++;
}
save_write_abs(base + 0, SAVE_MAGIC0);
save_write_abs(base + 1, SAVE_MAGIC1);
save_write_abs(base + 2, SAVE_VERSION);
save_write_abs(base + 3, (u8)(len & 0xFF));
save_write_abs(base + 4, (u8)(len >> 8));
save_write_abs(base + 5, sum);
save_disable();
return 1;
}script_run
Selecciona un script y restablece su contador de espera, el resultado de elección y la posición de retorno guardada.
Sintaxis
void script_run(u8 bank, const u8* script);Parámetros
bankBanco ROM del flujo de instrucciones.
scriptInicio de un flujo válido con terminación; esta llamada lo prepara sin ejecutar comandos.
Valor devuelto
No devuelve ningún valor.
Condiciones y límites
Códigos de operación: 00 END; 01 TEXT(bank,ptr16); 02 SET_FLAG(id16); 03 CLEAR_FLAG(id16); 04 JUMP(bank,ptr16); 05 IF_FLAG(id16,bank,ptr16); 06 CHOICE(count,table16); 07 WAIT(n); 08 CALL_EVENT(bank,ptr16). Las palabras usan little-endian. Mantén legibles las cadenas, tablas de punteros e instrucciones, y dentro de sus bancos mapeados.
Ejemplo de uso
flag_clear(19);script_run(1,(const u8*)&entry);result[0]=flag_get(19);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Salta del banco 1 al 2, activa el indicador 19 y espera. Las dos primeras llamadas de espera devuelven 1; el indicador de destino pasa a 1; la finalización después de WAIT devuelve 2. El indicador prueba que el control llegó al otro banco.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_script.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_script.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=noneImplementación y código fuente
kitaqgb/lib/rpg.h:250
Replace the active script and clear wait, choice and saved-return state.
kitaqgb/lib/script.c:105
void script_run(u8 bank, const u8* script)
{
script_active = 1;
script_bank = bank;
script_pc = script;
script_wait = 0;
script_last_choice = 0xFF;
script_return_active = 0;
}script_step
Avanza por los comandos hasta que una salida, elección, espera o finalización devuelve el control.
Sintaxis
u8 script_step();Valor devuelto
0=TEXT/CHOICE cede el control; 1=espera; 2=terminado o inactivo. Los códigos de operación desconocidos también terminan con 2.
Condiciones y límites
Códigos de operación: 00 END; 01 TEXT(bank,ptr16); 02 SET_FLAG(id16); 03 CLEAR_FLAG(id16); 04 JUMP(bank,ptr16); 05 IF_FLAG(id16,bank,ptr16); 06 CHOICE(count,table16); 07 WAIT(n); 08 CALL_EVENT(bank,ptr16). Las palabras usan little-endian. Mantén legibles las cadenas, tablas de punteros e instrucciones, y dentro de sus bancos mapeados.
WAIT n devuelve 1 al decodificarse y después espera n llamadas más. CALL_EVENT solo tiene una posición de retorno guardada. CHOICE requiere un número distinto de cero y bloquea internamente hasta elegir. Un bucle de saltos que no ceda el control bloquea el bucle del juego; asegúrate de alcanzar una orden de terminación o que ceda el control.
Ejemplo de uso
result[3]=script_step();result[4]=flag_get(19);result[5]=script_step();result[6]=script_step();result[7]=script_step();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Salta del banco 1 al 2, activa el indicador 19 y espera. Las dos primeras llamadas de espera devuelven 1; el indicador de destino pasa a 1; la finalización después de WAIT devuelve 2. El indicador prueba que el control llegó al otro banco.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_script.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_script.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=noneImplementación y código fuente
kitaqgb/lib/rpg.h:254
Execute commands until an output/choice yields (0), a wait yields (1), or execution ends (2). Control/flag commands continue within the same call, so a script loop without a yielding command can block the game loop indefinitely.
kitaqgb/lib/script.c:125
u8 script_step()
{
if (script_active == 0) return 2;
if (script_wait != 0) {
script_wait--;
return 1;
}
while (script_active != 0) {
u8 op = script_read8();
// An END returns to the one saved caller when present; otherwise it ends the script.
if (op == SCRIPT_OP_END) {
if (script_return_active != 0) {
script_bank = script_return_bank;
script_pc = script_return_pc;
script_return_active = 0;
continue;
}
script_active = 0;
return 2;
}
if (op == SCRIPT_OP_TEXT) {
u8 bank = script_read8();
u16 ptr = script_read16();
text_print_far(bank, (const u8*)ptr);
return 0;
}
if (op == SCRIPT_OP_SET_FLAG) {
u16 id = script_read16();
flag_set(id);
continue;
}
if (op == SCRIPT_OP_CLEAR_FLAG) {
u16 id = script_read16();
flag_clear(id);
continue;
}
if (op == SCRIPT_OP_JUMP) {
// Read all operands in the source bank before installing the destination.
u8 bank = script_read8();
u16 ptr = script_read16();
script_bank = bank;
script_pc = (const u8*)ptr;
continue;
}
// Read all branch operands before switching bank/address so an untaken branch
// still consumes the full instruction.
if (op == SCRIPT_OP_IF_FLAG) {
u16 id = script_read16();
u8 bank = script_read8();
u16 ptr = script_read16();
if (flag_get(id) != 0) {
script_bank = bank;
script_pc = (const u8*)ptr;
}
continue;
}
if (op == SCRIPT_OP_CHOICE) {
u8 count = script_read8();
u16 table = script_read16();
script_last_choice = script_choice(script_bank, (const u8*)table, count);
return 0;
}
if (op == SCRIPT_OP_WAIT) {
script_wait = script_read8();
return 1;
}
// Save the continuation only when the single return slot is empty. Nested
// calls replace the current script but do not push another return address.
if (op == SCRIPT_OP_CALL_EVENT) {
u8 bank = script_read8();
u16 ptr = script_read16();
if (script_return_active == 0) {
script_return_active = 1;
script_return_bank = script_bank;
script_return_pc = script_pc;
}
script_bank = bank;
script_pc = (const u8*)ptr;
continue;
}
// Unknown opcodes terminate with the same return code as END; there is no distinct malformed-stream error.
script_active = 0;
return 2;
}
return 2;
}script_wait_frames
Hace que las siguientes llamadas a script_step esperen el número indicado de veces.
Sintaxis
void script_wait_frames(u8 n);Parámetros
nNúmero de llamadas de espera, de 0 a 255; cero cancela la espera.
Valor devuelto
No devuelve ningún valor.
Condiciones y límites
Solo equivale a un número de fotogramas si se llama a script_step una vez por fotograma; la función no espera a VBlank por sí misma.
Ejemplo de uso
script_wait_frames(2);result[1]=script_step();result[2]=script_step();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Salta del banco 1 al 2, activa el indicador 19 y espera. Las dos primeras llamadas de espera devuelven 1; el indicador de destino pasa a 1; la finalización después de WAIT devuelve 2. El indicador prueba que el control llegó al otro banco.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_script.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_script.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=noneImplementación y código fuente
kitaqgb/lib/rpg.h:257
Set the number of subsequent script_step calls to spend waiting. Frame-based timing requires the application to call script_step once per frame.
kitaqgb/lib/script.c:117
void script_wait_frames(u8 n)
{
script_wait = n;
}text_choice
Dibuja una lista vertical en el área activa y espera una selección. UP/DOWN mueven el cursor de forma circular; A confirma y B cancela. El bucle redibuja las opciones y consulta la entrada una vez tras esperar a VBlank. Devuelve un índice desde cero o 255 si se cancela o la lista está vacía.
Sintaxis
u8 text_choice(const u8* const* choices, u8 count);Parámetros
choicesPuntero a un array de count punteros a cadenas legibles. Cada cadena termina en cero y contiene ID de tile sin procesar; las etiquetas no interpretan controles de diálogo. Mantén mapeadas la tabla y las cadenas hasta terminar la selección.
countNúmero de opciones. Cero devuelve 255 de inmediato sin leer la tabla de punteros. Si la lista no está vacía, proporciona al menos count filas interiores y ancho para una celda de cursor más la etiqueta más larga. No hay recorte ni desplazamiento.
Valor devuelto
Índice de 0 a count−1 al confirmar con A. 255 significa cancelación con B o count igual a cero; distingue estos casos en el código que llama si hace falta. No cierra el área ni borra la lista.
Condiciones y límites
Usa un rectángulo BG válido y carga primero los tiles de fuente y marco. El área de texto por software usa el mapa BG elegido por el bit 3 de LCDC; no activa la capa Window de hardware. En CGB, usa VBK 0 para números de tile y configura los atributos de color por separado. Los ejemplos incluyen fuente mapeada a ASCII y tiles de marco, cursor e indicador de página. Los diálogos y etiquetas usan ID de tile de un byte, sin decodificar UTF-8. Para otros caracteres, proporciona sus glifos y codifica el texto con esos ID, dejando reservados los bytes de control del diálogo.
Abre y dimensiona el área antes de llamar. La selección usa la posición guardada sin comprobar si el área está abierta. Las etiquetas empiezan dos columnas dentro del borde izquierdo y una fila bajo el superior; el cursor ocupa la celda inmediata a su izquierda. La lista no usa la velocidad de caracteres del diálogo.
El bucle reacciona a pulsaciones nuevas, procesando UP antes de DOWN y A antes de B. Mantener una dirección no repite el movimiento; suelta y vuelve a pulsar. La máscara anterior empieza en cero, así que un botón mantenido puede actuar al entrar. Mover y pulsar A a la vez devuelve el índice tras moverse, aunque el último cursor dibujado aún muestre la posición anterior.
Son funciones bloqueantes: mientras esperan no llaman a la actualización del juego, al servicio de música ni al bucle de renderizado. Con el LCD apagado, __wait_vblank vuelve de inmediato, así que la velocidad de caracteres y WAIT no generan retrasos en fotogramas. Mantén el LCD activo para diálogo temporizado y entrada por fotogramas. Usa una máquina de estados del juego si otras tareas deben avanzar durante la conversación.
Las escrituras seguras de tiles esperan modos LCD escribibles con el LCD activo y usan DI/EI alrededor de la escritura. Pueden activar interrupciones en vez de conservar un estado inicialmente desactivado. No llames a estas funciones bloqueantes desde un manejador de interrupción ni dependas de que conserven ese estado.
Cada ejemplo completo incluye text.c una vez. Compila con los directorios de inclusión de la biblioteca y los ejemplos del manual; no añadas lib/text.c como otra fuente. El ejemplo de flujo lejano usa MBC5 y una ROM de 64 KiB para incluir los datos del banco 2.
Ejemplo de uso
selected=text_choice(dialogue_choices,3);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Pulsa DOWN una vez y después A. En la captura, el cursor hacia la derecha está junto a SHIELD en el tile (2,4) y SELECTED muestra 1. Las etiquetas empiezan en (3,3), (3,4) y (3,5). Marco, cursor y etiquetas son verdes en CGB y negros en DMG; resultado e instrucciones permanecen negros.
Las pruebas del emulador comparan todo el mapa BG y las cuatro imágenes de ejemplo. Otras ejecuciones cubren apertura/cierre, flujos normales y entre bancos, esperas temporizadas, páginas explícitas y automáticas, avance A/B/START, botones mantenidos, selección circular, listas vacías y prioridad simultánea. Los puntos antes y después de la entrada programada verifican que la espera de página bloquea realmente. No se prueban hardware físico ni concurrencia de interrupciones.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dialogue_choice.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dialogue_choice.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/rpg.h:231
Redraw choices and block for edge-triggered navigation: UP/DOWN wrap, A accepts, and B returns 0xFF. Zero choices also returns 0xFF. Choice strings use raw tile bytes, and the caller must fit them inside the available rows.
kitaqgb/lib/text.c:316
u8 text_choice(const u8* const* choices, u8 count)
{
u8 cursor;
u8 prev;
if (count == 0) return 0xFF;
cursor = 0;
prev = 0;
while (1) {
u8 i;
for (i = 0; i < count; i++) {
u8 py = (u8)(text_y + 1 + i);
__settile_xy((u8)(text_x + 1), py, (i == cursor) ? TEXT_TILE_CURSOR : TEXT_TILE_FILL);
text_draw_string_at((u8)(text_x + 2), py, choices[i]);
}
__wait_vblank();
{
u16 kt = __readpadex(prev);
u8 trigger;
prev = (u8)kt;
trigger = (u8)(kt >> 8);
if ((trigger & PAD_KEY_UP) != 0) {
if (cursor == 0) cursor = (u8)(count - 1);
else cursor--;
}
if ((trigger & PAD_KEY_DOWN) != 0) {
cursor++;
if (cursor >= count) cursor = 0;
}
if ((trigger & PAD_KEY_A) != 0) return cursor;
if ((trigger & PAD_KEY_B) != 0) return 0xFF;
}
}
}text_clear_rect
Rellena un rectángulo del mapa de tiles del fondo con TEXT_TILE_FILL. Úsalo para borrar una etiqueta, un campo numérico o parte de un panel. No mueve el cursor activo, no cierra el área de texto ni cambia sus dimensiones.
Sintaxis
void text_clear_rect(u8 x, u8 y, u8 w, u8 h);Parámetros
xColumna inicial, en celdas de 8×8 del mapa del fondo. Toda la salida debe quedar entre las columnas 0 y 31. Sin desplazamiento del fondo, se ven las columnas 0–19.
yFila inicial, de 0 a 31, en celdas de 8×8 del mapa del fondo. Sin desplazamiento, se ven las filas 0–17. Un rectángulo también debe caber verticalmente en el mapa.
wAnchura en celdas de tile. En text_window incluye las dos columnas del marco y deja max(w−2, 0) columnas interiores. En text_clear_rect es la cantidad de celdas que se rellenan en cada fila.
hAltura en celdas de tile. En text_window incluye los bordes superior e inferior y deja max(h−2, 0) filas interiores. En text_clear_rect es la cantidad de filas que se rellenan.
Valor devuelto
No devuelve ningún valor. Escribe las celdas del mapa antes de terminar; no devuelve una cantidad de caracteres ni un código de estado.
Condiciones y límites
Estas funciones dibujan en el mapa BG seleccionado por el bit 3 de LCDC. La ventana de texto es un área gestionada por software en ese mapa, no la capa Window del hardware. Mantén VBK en 0 en CGB para escribir números de tile; estas llamadas no configuran atributos de color, paletas ni desplazamiento.
Carga la fuente y los gráficos del marco antes de dibujar. Los ID predeterminados del marco son 1–6, el tile de relleno es 0 y los dígitos decimales empiezan en ASCII 0 (tile 48). El signo menos usa ASCII - (tile 45). El ejemplo incluye seis tiles de marco y la fuente del manual, cuyos ID de glifo coinciden con ASCII.
Mantén los rectángulos y el texto dentro del mapa de 32×32. El relleno rectangular no recorta la anchura ni la altura en los límites del mapa. Si cualquiera de ellas es cero, no rellena nada; aun así, text_window registra el área como abierta, sin interior utilizable.
Las funciones numéricas públicas usan exactamente el ancho que necesita el nuevo valor. No borran las celdas sobrantes a su derecha. Escribir 7 sobre 12345 en la misma posición muestra 72345. Para obtener solo 7, borra primero el campo reservado de cinco celdas con text_clear_rect. Reserva seis celdas para un valor de 16 bits con signo.
Las funciones intrínsecas de escritura comprueban el LCD: si está apagado, escriben al instante; si está encendido, esperan un modo que permita escribir y rodean la escritura con DI/EI. Este camino puede dejar las interrupciones habilitadas al terminar; no supongas que conserva su estado deshabilitado. Los ejemplos y las pruebas a nivel de byte de esta sección escriben con el LCD apagado.
El ejemplo completo incluye text.c una vez para compilar la implementación de la biblioteca junto con el programa. No pases además lib/text.c como entrada independiente. Para personalizar las constantes de tiles TEXT_*, defínelas antes de incluir rpg.h y la implementación; aplica las mismas definiciones allí donde se compile la biblioteca.
Ejemplo de uso
text_clear_rect(7,5,5,1);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Al principio, el marco contiene KEEP ERASE KEEP en la fila 5. Borrar cinco celdas desde (7,5) elimina ERASE, pero conserva ambos KEEP y el marco. La fila CLEAN también borra un campo numérico de cinco celdas antes de escribir 7.
La verificación compara cada píxel visible y los 1024 bytes del mapa BG en ambas pantallas de ejemplo. Unas ROM DMG/CGB independientes comprueban los 256 valores de byte sin signo, los cambios de cantidad de dígitos decimales y los extremos con signo, conservando puntos junto a cada número como centinelas. Las comprobaciones de disposición incluyen rectángulos vacíos y estrechos, posiciones en el borde del mapa, bytes de tile con valores de códigos de control sin interpretar y el cursor de ventana tras escrituras absolutas. Son pruebas en emulador, no en hardware físico.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\text_layout.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\text_layout.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/rpg.h:237
Fill the supplied tile rectangle without changing the active text window or cursor.
kitaqgb/lib/text.c:220
void text_clear_rect(u8 x, u8 y, u8 w, u8 h)
{
__settile_rect(x, y, w, h, TEXT_TILE_FILL);
}text_close
Borra el área activa, incluido su marco, con TEXT_TILE_FILL y la marca como cerrada. Volver a llamar mientras está cerrada no hace nada. No restaura los tiles de fondo anteriores a la apertura.
Sintaxis
void text_close();Valor devuelto
No devuelve ningún valor. El dibujo y las esperas bloqueantes se realizan antes de volver.
Condiciones y límites
Usa un rectángulo BG válido y carga primero los tiles de fuente y marco. El área de texto por software usa el mapa BG elegido por el bit 3 de LCDC; no activa la capa Window de hardware. En CGB, usa VBK 0 para números de tile y configura los atributos de color por separado. Los ejemplos incluyen fuente mapeada a ASCII y tiles de marco, cursor e indicador de página. Los diálogos y etiquetas usan ID de tile de un byte, sin decodificar UTF-8. Para otros caracteres, proporciona sus glifos y codifica el texto con esos ID, dejando reservados los bytes de control del diálogo.
Se ignoran los caracteres normales si el área está cerrada o no tiene interior utilizable. Los controles siguen interpretándose: WAIT puede bloquear y los controles de página pueden esperar o borrar el área guardada. Por tanto, text_print sobre un área cerrada no es siempre una operación vacía.
Son funciones bloqueantes: mientras esperan no llaman a la actualización del juego, al servicio de música ni al bucle de renderizado. Con el LCD apagado, __wait_vblank vuelve de inmediato, así que la velocidad de caracteres y WAIT no generan retrasos en fotogramas. Mantén el LCD activo para diálogo temporizado y entrada por fotogramas. Usa una máquina de estados del juego si otras tareas deben avanzar durante la conversación.
Las escrituras seguras de tiles esperan modos LCD escribibles con el LCD activo y usan DI/EI alrededor de la escritura. Pueden activar interrupciones en vez de conservar un estado inicialmente desactivado. No llames a estas funciones bloqueantes desde un manejador de interrupción ni dependas de que conserven ese estado.
Cada ejemplo completo incluye text.c una vez. Compila con los directorios de inclusión de la biblioteca y los ejemplos del manual; no añadas lib/text.c como otra fuente. El ejemplo de flujo lejano usa MBC5 y una ROM de 64 KiB para incluir los datos del banco 2.
Ejemplo de uso
text_close();
text_print("HIDDEN"); // With the area closed, ordinary characters are not drawn.Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo abre un área de 18×3 celdas en (1,9), escribe ERASE ME, la cierra e intenta escribir HIDDEN. Bajo CLOSED AREA, las celdas x=1–18 e y=9–11 deben quedar vacías, sin texto ni marco. El diálogo azul superior sigue visible.
Las pruebas del emulador comparan todo el mapa BG y las cuatro imágenes de ejemplo. Otras ejecuciones cubren apertura/cierre, flujos normales y entre bancos, esperas temporizadas, páginas explícitas y automáticas, avance A/B/START, botones mantenidos, selección circular, listas vacías y prioridad simultánea. Los puntos antes y después de la entrada programada verifican que la espera de página bloquea realmente. No se prueban hardware físico ni concurrencia de interrupciones.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dialogue_flow.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dialogue_flow.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/rpg.h:220
Erase the open window with the fill tile and disable windowed character output.
kitaqgb/lib/text.c:200
void text_close()
{
if (text_opened == 0) return;
__settile_rect(text_x, text_y, text_w, text_h, TEXT_TILE_FILL);
text_opened = 0;
}text_open
Abre un área de texto por software en el mapa de fondo. Guarda su posición y tamaño, sitúa el cursor en la primera celda interior, dibuja el marco y vacía el interior. Abrir otra área cambia el área y el cursor activos; no borra otra área ya dibujada en el mapa.
Sintaxis
void text_open(u8 x, u8 y, u8 w, u8 h);Parámetros
xColumna izquierda del área en celdas BG de 8×8. Mantén todo el ancho dentro de las columnas 0–31.
yFila superior del área en celdas BG de 8×8. Mantén todo el alto dentro de las filas 0–31.
wAncho total en celdas, incluidos los bordes izquierdo y derecho. Se necesitan al menos tres celdas para una columna interior de caracteres.
hAlto total en celdas, incluidos los bordes superior e inferior. Se necesitan al menos tres celdas para una fila interior de caracteres.
Valor devuelto
No devuelve ningún valor. El dibujo y las esperas bloqueantes se realizan antes de volver.
Condiciones y límites
Usa un rectángulo BG válido y carga primero los tiles de fuente y marco. El área de texto por software usa el mapa BG elegido por el bit 3 de LCDC; no activa la capa Window de hardware. En CGB, usa VBK 0 para números de tile y configura los atributos de color por separado. Los ejemplos incluyen fuente mapeada a ASCII y tiles de marco, cursor e indicador de página. Los diálogos y etiquetas usan ID de tile de un byte, sin decodificar UTF-8. Para otros caracteres, proporciona sus glifos y codifica el texto con esos ID, dejando reservados los bytes de control del diálogo.
Son funciones bloqueantes: mientras esperan no llaman a la actualización del juego, al servicio de música ni al bucle de renderizado. Con el LCD apagado, __wait_vblank vuelve de inmediato, así que la velocidad de caracteres y WAIT no generan retrasos en fotogramas. Mantén el LCD activo para diálogo temporizado y entrada por fotogramas. Usa una máquina de estados del juego si otras tareas deben avanzar durante la conversación.
Las escrituras seguras de tiles esperan modos LCD escribibles con el LCD activo y usan DI/EI alrededor de la escritura. Pueden activar interrupciones en vez de conservar un estado inicialmente desactivado. No llames a estas funciones bloqueantes desde un manejador de interrupción ni dependas de que conserven ese estado.
Cada ejemplo completo incluye text.c una vez. Compila con los directorios de inclusión de la biblioteca y los ejemplos del manual; no añadas lib/text.c como otra fuente. El ejemplo de flujo lejano usa MBC5 y una ROM de 64 KiB para incluir los datos del banco 2.
Ejemplo de uso
text_open(1,2,18,5);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
DIALOGUE FLOW abre un marco de 18×5 celdas en (1,2), con interior de 16×3. NEAR, READY y BANK 2 ocupan sus tres filas. Las líneas visibles abarcan x=11–147 e y=19–51 píxeles. Marco y texto son azules en CGB y negros en DMG. Abrir después el área de prueba de borrado deja este marco visible.
Las pruebas del emulador comparan todo el mapa BG y las cuatro imágenes de ejemplo. Otras ejecuciones cubren apertura/cierre, flujos normales y entre bancos, esperas temporizadas, páginas explícitas y automáticas, avance A/B/START, botones mantenidos, selección circular, listas vacías y prioridad simultánea. Los puntos antes y después de la entrada programada verifican que la espera de página bloquea realmente. No se prueban hardware físico ni concurrencia de interrupciones.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dialogue_flow.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dialogue_flow.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/rpg.h:218
Set the tile-space window, reset its cursor and redraw it immediately. Opening does not reset the existing character speed or load font tiles.
kitaqgb/lib/text.c:187
void text_open(u8 x, u8 y, u8 w, u8 h)
{
text_x = x;
text_y = y;
text_w = w;
text_h = h;
text_opened = 1;
text_reset_cursor();
text_draw_frame();
text_clear_inside();
}text_print
Lee un flujo de control mediante un puntero normal y escribe sus tiles de caracteres en el cursor de la ventana activa. Interpreta saltos de línea, esperas temporizadas y de página, y ajusta las líneas al ancho interior. Solo vuelve al llegar a END, así que una espera de página puede bloquear hasta pulsar un botón.
Sintaxis
void text_print(const u8* str);Parámetros
strPuntero legible a un flujo terminado en TEXT_CTRL_END (0). Mantén todo el flujo mapeado durante las esperas, incluido el operando de WAIT. No hay comprobación de longitud ni validez del búfer.
Valor devuelto
No devuelve ningún valor. El dibujo y las esperas bloqueantes se realizan antes de volver.
Condiciones y límites
Usa un rectángulo BG válido y carga primero los tiles de fuente y marco. El área de texto por software usa el mapa BG elegido por el bit 3 de LCDC; no activa la capa Window de hardware. En CGB, usa VBK 0 para números de tile y configura los atributos de color por separado. Los ejemplos incluyen fuente mapeada a ASCII y tiles de marco, cursor e indicador de página. Los diálogos y etiquetas usan ID de tile de un byte, sin decodificar UTF-8. Para otros caracteres, proporciona sus glifos y codifica el texto con esos ID, dejando reservados los bytes de control del diálogo.
Bytes de control: 0x00 termina el flujo; 0x0A pasa a otra fila interior; 0x01 consume el siguiente byte como número de esperas VBlank, incluido cero; 0x02 espera el cambio de página, vacía el interior y restablece el cursor. Los demás bytes son ID de tile. Un operando WAIT de cero no es un marcador END.
Al superar la última fila interior mediante salto o ajuste automático, muestra el marcador de espera, espera A, B o START, vacía el interior y continúa en la primera celda. Sustituye la página en vez de desplazar filas. Un 0x02 explícito espera sin añadir marcador. La consulta empieza sin botones recordados, por lo que uno ya pulsado al comenzar puede avanzar la página.
Se ignoran los caracteres normales si el área está cerrada o no tiene interior utilizable. Los controles siguen interpretándose: WAIT puede bloquear y los controles de página pueden esperar o borrar el área guardada. Por tanto, text_print sobre un área cerrada no es siempre una operación vacía.
Son funciones bloqueantes: mientras esperan no llaman a la actualización del juego, al servicio de música ni al bucle de renderizado. Con el LCD apagado, __wait_vblank vuelve de inmediato, así que la velocidad de caracteres y WAIT no generan retrasos en fotogramas. Mantén el LCD activo para diálogo temporizado y entrada por fotogramas. Usa una máquina de estados del juego si otras tareas deben avanzar durante la conversación.
Las escrituras seguras de tiles esperan modos LCD escribibles con el LCD activo y usan DI/EI alrededor de la escritura. Pueden activar interrupciones en vez de conservar un estado inicialmente desactivado. No llames a estas funciones bloqueantes desde un manejador de interrupción ni dependas de que conserven ese estado.
Cada ejemplo completo incluye text.c una vez. Compila con los directorios de inclusión de la biblioteca y los ejemplos del manual; no añadas lib/text.c como otra fuente. El ejemplo de flujo lejano usa MBC5 y una ROM de 64 KiB para incluir los datos del banco 2.
Ejemplo de uso
text_print(dialogue_near);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El flujo normal escribe NEAR, un salto de línea, READY y una orden de doce esperas antes de END. NEAR empieza en el tile (2,3) y READY en (2,4). El flujo posterior entre bancos continúa desde el mismo cursor, así que su salto inicial coloca BANK 2 en la tercera fila interior.
Las pruebas del emulador comparan todo el mapa BG y las cuatro imágenes de ejemplo. Otras ejecuciones cubren apertura/cierre, flujos normales y entre bancos, esperas temporizadas, páginas explícitas y automáticas, avance A/B/START, botones mantenidos, selección circular, listas vacías y prioridad simultánea. Los puntos antes y después de la entrada programada verifican que la espera de página bloquea realmente. No se prueban hardware físico ni concurrencia de interrupciones.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dialogue_flow.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dialogue_flow.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/rpg.h:224
Decode an END-terminated stream of tile bytes and newline/wait/page controls. WAIT consumes a following frame-count byte. The source must remain readable through blocking waits; the routine does not validate stream length.
kitaqgb/lib/text.c:261
void text_print(const u8* str)
{
while (*str != TEXT_CTRL_END) {
u8 c = *str++;
if (c == TEXT_CTRL_NEWLINE) {
text_newline();
continue;
}
if (c == TEXT_CTRL_WAIT) {
u8 frames = *str++;
text_delay_frames(frames);
continue;
}
if (c == TEXT_CTRL_PAGE_WAIT) {
text_wait_advance();
text_clear_inside();
text_reset_cursor();
continue;
}
text_put_tile(c);
}
}text_print_far
Interpreta el mismo flujo de diálogo leyendo cada byte del banco ROM indicado con __farpeek8. Úsalo para diálogos fuera del banco de origen actualmente mapeado. Posición, velocidad, ajuste de línea y control de páginas son iguales que en text_print.
Sintaxis
void text_print_far(u8 bank, const u8* str);Parámetros
bankNúmero de banco ROM de origen de ocho bits sin signo. El ejemplo guarda el flujo en el banco 2 y comprueba que después de imprimir aún se pueda leer un marcador en el banco 1.
strDirección de CPU del flujo en el banco indicado. La dirección avanza pero el banco permanece fijo; cruzar la ventana ROM conmutable no continúa automáticamente en el siguiente banco.
Valor devuelto
No devuelve ningún valor. El dibujo y las esperas bloqueantes se realizan antes de volver.
Condiciones y límites
Usa un rectángulo BG válido y carga primero los tiles de fuente y marco. El área de texto por software usa el mapa BG elegido por el bit 3 de LCDC; no activa la capa Window de hardware. En CGB, usa VBK 0 para números de tile y configura los atributos de color por separado. Los ejemplos incluyen fuente mapeada a ASCII y tiles de marco, cursor e indicador de página. Los diálogos y etiquetas usan ID de tile de un byte, sin decodificar UTF-8. Para otros caracteres, proporciona sus glifos y codifica el texto con esos ID, dejando reservados los bytes de control del diálogo.
Bytes de control: 0x00 termina el flujo; 0x0A pasa a otra fila interior; 0x01 consume el siguiente byte como número de esperas VBlank, incluido cero; 0x02 espera el cambio de página, vacía el interior y restablece el cursor. Los demás bytes son ID de tile. Un operando WAIT de cero no es un marcador END.
Al superar la última fila interior mediante salto o ajuste automático, muestra el marcador de espera, espera A, B o START, vacía el interior y continúa en la primera celda. Sustituye la página en vez de desplazar filas. Un 0x02 explícito espera sin añadir marcador. La consulta empieza sin botones recordados, por lo que uno ya pulsado al comenzar puede avanzar la página.
Se ignoran los caracteres normales si el área está cerrada o no tiene interior utilizable. Los controles siguen interpretándose: WAIT puede bloquear y los controles de página pueden esperar o borrar el área guardada. Por tanto, text_print sobre un área cerrada no es siempre una operación vacía.
Son funciones bloqueantes: mientras esperan no llaman a la actualización del juego, al servicio de música ni al bucle de renderizado. Con el LCD apagado, __wait_vblank vuelve de inmediato, así que la velocidad de caracteres y WAIT no generan retrasos en fotogramas. Mantén el LCD activo para diálogo temporizado y entrada por fotogramas. Usa una máquina de estados del juego si otras tareas deben avanzar durante la conversación.
Las escrituras seguras de tiles esperan modos LCD escribibles con el LCD activo y usan DI/EI alrededor de la escritura. Pueden activar interrupciones en vez de conservar un estado inicialmente desactivado. No llames a estas funciones bloqueantes desde un manejador de interrupción ni dependas de que conserven ese estado.
Cada ejemplo completo incluye text.c una vez. Compila con los directorios de inclusión de la biblioteca y los ejemplos del manual; no añadas lib/text.c como otra fuente. El ejemplo de flujo lejano usa MBC5 y una ROM de 64 KiB para incluir los datos del banco 2.
Ejemplo de uso
text_print_far(2,dialogue_far);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo lee el salto de línea y BANK 2 del banco ROM 2. BANK RESTORED muestra 161 al leer después el marcador del banco 1 del código que llama. BANK 2 empieza en el tile (2,5); el número de restauración aparece en (16,14).
Las pruebas del emulador comparan todo el mapa BG y las cuatro imágenes de ejemplo. Otras ejecuciones cubren apertura/cierre, flujos normales y entre bancos, esperas temporizadas, páginas explícitas y automáticas, avance A/B/START, botones mantenidos, selección circular, listas vacías y prioridad simultánea. Los puntos antes y después de la entrada programada verifican que la espera de página bloquea realmente. No se prueban hardware físico ni concurrencia de interrupciones.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dialogue_flow.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dialogue_flow.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/rpg.h:227
Decode the same text controls while fetching each byte from the specified ROM bank. The pointer advances within that bank; it does not roll into the next bank.
kitaqgb/lib/text.c:286
void text_print_far(u8 bank, const u8* str)
{
const u8* p = str;
while (1) {
u8 c = __farpeek8(bank, p);
p++;
if (c == TEXT_CTRL_END) return;
if (c == TEXT_CTRL_NEWLINE) {
text_newline();
continue;
}
if (c == TEXT_CTRL_WAIT) {
u8 frames = __farpeek8(bank, p);
p++;
text_delay_frames(frames);
continue;
}
if (c == TEXT_CTRL_PAGE_WAIT) {
text_wait_advance();
text_clear_inside();
text_reset_cursor();
continue;
}
text_put_tile(c);
}
}text_print_s16
Dibuja un valor de 16 bits con signo en decimal. Los negativos empiezan con el tile del signo menos, seguido de su magnitud; el cero y los positivos no llevan signo. La salida más larga es -32768 y ocupa seis celdas.
Sintaxis
void text_print_s16(u8 x, u8 y, s16 value);Parámetros
xColumna inicial, en celdas de 8×8 del mapa del fondo. Toda la salida debe quedar entre las columnas 0 y 31. Sin desplazamiento del fondo, se ven las columnas 0–19.
yFila inicial, de 0 a 31, en celdas de 8×8 del mapa del fondo. Sin desplazamiento, se ven las filas 0–17. Un rectángulo también debe caber verticalmente en el mapa.
valueValor con signo entre −32768 y 32767. El ejemplo convierte explícitamente el patrón de 16 bits 32768 (0x8000) a s16 para mostrar −32768.
Valor devuelto
No devuelve ningún valor. Escribe las celdas del mapa antes de terminar; no devuelve una cantidad de caracteres ni un código de estado.
Condiciones y límites
Estas funciones dibujan en el mapa BG seleccionado por el bit 3 de LCDC. La ventana de texto es un área gestionada por software en ese mapa, no la capa Window del hardware. Mantén VBK en 0 en CGB para escribir números de tile; estas llamadas no configuran atributos de color, paletas ni desplazamiento.
Carga la fuente y los gráficos del marco antes de dibujar. Los ID predeterminados del marco son 1–6, el tile de relleno es 0 y los dígitos decimales empiezan en ASCII 0 (tile 48). El signo menos usa ASCII - (tile 45). El ejemplo incluye seis tiles de marco y la fuente del manual, cuyos ID de glifo coinciden con ASCII.
Mantén los rectángulos y el texto dentro del mapa de 32×32. El relleno rectangular no recorta la anchura ni la altura en los límites del mapa. Si cualquiera de ellas es cero, no rellena nada; aun así, text_window registra el área como abierta, sin interior utilizable.
Las funciones numéricas públicas usan exactamente el ancho que necesita el nuevo valor. No borran las celdas sobrantes a su derecha. Escribir 7 sobre 12345 en la misma posición muestra 72345. Para obtener solo 7, borra primero el campo reservado de cinco celdas con text_clear_rect. Reserva seis celdas para un valor de 16 bits con signo.
Las funciones intrínsecas de escritura comprueban el LCD: si está apagado, escriben al instante; si está encendido, esperan un modo que permita escribir y rodean la escritura con DI/EI. Este camino puede dejar las interrupciones habilitadas al terminar; no supongas que conserva su estado deshabilitado. Los ejemplos y las pruebas a nivel de byte de esta sección escriben con el LCD apagado.
El ejemplo completo incluye text.c una vez para compilar la implementación de la biblioteca junto con el programa. No pases además lib/text.c como entrada independiente. Para personalizar las constantes de tiles TEXT_*, defínelas antes de incluir rpg.h y la implementación; aplica las mismas definiciones allí donde se compile la biblioteca.
Ejemplo de uso
text_print_s16(11,12,(s16)32768);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La fila S16 muestra -32768 desde (11,12), en seis celdas incluido el signo menos y en verde en CGB. Prueba el mínimo de 16 bits con signo, cuya magnitud positiva no cabe en s16.
La verificación compara cada píxel visible y los 1024 bytes del mapa BG en ambas pantallas de ejemplo. Unas ROM DMG/CGB independientes comprueban los 256 valores de byte sin signo, los cambios de cantidad de dígitos decimales y los extremos con signo, conservando puntos junto a cada número como centinelas. Las comprobaciones de disposición incluyen rectángulos vacíos y estrechos, posiciones en el borde del mapa, bytes de tile con valores de códigos de control sin interpretar y el cursor de ventana tras escrituras absolutas. Son pruebas en emulador, no en hardware físico.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\text_layout.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\text_layout.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/rpg.h:247
Print a minus tile for negative values, followed by the unsigned magnitude. Positive values use the unsigned decimal path; no plus sign is emitted.
kitaqgb/lib/text.c:246
void text_print_s16(u8 x, u8 y, s16 value)
{
u16 magnitude;
if (value < 0) {
__settile_xy(x, y, (u8)'-');
magnitude = (u16)((s16)0 - value);
text_print_u16_width((u8)(x + 1), y, magnitude, text_dec_digits_u16(magnitude));
return;
}
text_print_u16(x, y, (u16)value);
}text_print_u16
Dibuja un valor de 16 bits sin signo en decimal desde la posición de tile indicada. Ocupa de una a cinco celdas, sin ceros iniciales. Úsalo para puntuaciones o cantidades de objetos que puedan superar 255.
Sintaxis
void text_print_u16(u8 x, u8 y, u16 value);Parámetros
xColumna inicial, en celdas de 8×8 del mapa del fondo. Toda la salida debe quedar entre las columnas 0 y 31. Sin desplazamiento del fondo, se ven las columnas 0–19.
yFila inicial, de 0 a 31, en celdas de 8×8 del mapa del fondo. Sin desplazamiento, se ven las filas 0–17. Un rectángulo también debe caber verticalmente en el mapa.
valueValor sin signo entre 0 y 65535.
Valor devuelto
No devuelve ningún valor. Escribe las celdas del mapa antes de terminar; no devuelve una cantidad de caracteres ni un código de estado.
Condiciones y límites
Estas funciones dibujan en el mapa BG seleccionado por el bit 3 de LCDC. La ventana de texto es un área gestionada por software en ese mapa, no la capa Window del hardware. Mantén VBK en 0 en CGB para escribir números de tile; estas llamadas no configuran atributos de color, paletas ni desplazamiento.
Carga la fuente y los gráficos del marco antes de dibujar. Los ID predeterminados del marco son 1–6, el tile de relleno es 0 y los dígitos decimales empiezan en ASCII 0 (tile 48). El signo menos usa ASCII - (tile 45). El ejemplo incluye seis tiles de marco y la fuente del manual, cuyos ID de glifo coinciden con ASCII.
Mantén los rectángulos y el texto dentro del mapa de 32×32. El relleno rectangular no recorta la anchura ni la altura en los límites del mapa. Si cualquiera de ellas es cero, no rellena nada; aun así, text_window registra el área como abierta, sin interior utilizable.
Las funciones numéricas públicas usan exactamente el ancho que necesita el nuevo valor. No borran las celdas sobrantes a su derecha. Escribir 7 sobre 12345 en la misma posición muestra 72345. Para obtener solo 7, borra primero el campo reservado de cinco celdas con text_clear_rect. Reserva seis celdas para un valor de 16 bits con signo.
Las funciones intrínsecas de escritura comprueban el LCD: si está apagado, escriben al instante; si está encendido, esperan un modo que permita escribir y rodean la escritura con DI/EI. Este camino puede dejar las interrupciones habilitadas al terminar; no supongas que conserva su estado deshabilitado. Los ejemplos y las pruebas a nivel de byte de esta sección escriben con el LCD apagado.
El ejemplo completo incluye text.c una vez para compilar la implementación de la biblioteca junto con el programa. No pases además lib/text.c como entrada independiente. Para personalizar las constantes de tiles TEXT_*, defínelas antes de incluir rpg.h y la implementación; aplica las mismas definiciones allí donde se compile la biblioteca.
Ejemplo de uso
text_print_u16(11,10,65535);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La fila U16 muestra 65535 en (11,10), en cinco celdas y en azul en CGB. OVERWRITE muestra 72345 después de escribir 7 sobre 12345 sin borrar antes el campo de cinco celdas.
La verificación compara cada píxel visible y los 1024 bytes del mapa BG en ambas pantallas de ejemplo. Unas ROM DMG/CGB independientes comprueban los 256 valores de byte sin signo, los cambios de cantidad de dígitos decimales y los extremos con signo, conservando puntos junto a cada número como centinelas. Las comprobaciones de disposición incluyen rectángulos vacíos y estrechos, posiciones en el borde del mapa, bytes de tile con valores de códigos de control sin interpretar y el cursor de ventana tras escrituras absolutas. Son pruebas en emulador, no en hardware físico.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\text_layout.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\text_layout.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/rpg.h:244
Print an unsigned word in decimal using only the required number of cells.
kitaqgb/lib/text.c:239
void text_print_u16(u8 x, u8 y, u16 value)
{
text_print_u16_width(x, y, value, text_dec_digits_u16(value));
}text_print_u8
Dibuja un valor de 8 bits sin signo en decimal desde la posición de tile indicada. Ocupa de una a tres celdas, sin ceros iniciales; el cero ocupa una. Resulta útil para contadores pequeños, como vidas o munición.
Sintaxis
void text_print_u8(u8 x, u8 y, u8 value);Parámetros
xColumna inicial, en celdas de 8×8 del mapa del fondo. Toda la salida debe quedar entre las columnas 0 y 31. Sin desplazamiento del fondo, se ven las columnas 0–19.
yFila inicial, de 0 a 31, en celdas de 8×8 del mapa del fondo. Sin desplazamiento, se ven las filas 0–17. Un rectángulo también debe caber verticalmente en el mapa.
valueValor sin signo entre 0 y 255. El parámetro de la función convierte las expresiones de tipos más anchos a u8.
Valor devuelto
No devuelve ningún valor. Escribe las celdas del mapa antes de terminar; no devuelve una cantidad de caracteres ni un código de estado.
Condiciones y límites
Estas funciones dibujan en el mapa BG seleccionado por el bit 3 de LCDC. La ventana de texto es un área gestionada por software en ese mapa, no la capa Window del hardware. Mantén VBK en 0 en CGB para escribir números de tile; estas llamadas no configuran atributos de color, paletas ni desplazamiento.
Carga la fuente y los gráficos del marco antes de dibujar. Los ID predeterminados del marco son 1–6, el tile de relleno es 0 y los dígitos decimales empiezan en ASCII 0 (tile 48). El signo menos usa ASCII - (tile 45). El ejemplo incluye seis tiles de marco y la fuente del manual, cuyos ID de glifo coinciden con ASCII.
Mantén los rectángulos y el texto dentro del mapa de 32×32. El relleno rectangular no recorta la anchura ni la altura en los límites del mapa. Si cualquiera de ellas es cero, no rellena nada; aun así, text_window registra el área como abierta, sin interior utilizable.
Las funciones numéricas públicas usan exactamente el ancho que necesita el nuevo valor. No borran las celdas sobrantes a su derecha. Escribir 7 sobre 12345 en la misma posición muestra 72345. Para obtener solo 7, borra primero el campo reservado de cinco celdas con text_clear_rect. Reserva seis celdas para un valor de 16 bits con signo.
Las funciones intrínsecas de escritura comprueban el LCD: si está apagado, escriben al instante; si está encendido, esperan un modo que permita escribir y rodean la escritura con DI/EI. Este camino puede dejar las interrupciones habilitadas al terminar; no supongas que conserva su estado deshabilitado. Los ejemplos y las pruebas a nivel de byte de esta sección escriben con el LCD apagado.
El ejemplo completo incluye text.c una vez para compilar la implementación de la biblioteca junto con el programa. No pases además lib/text.c como entrada independiente. Para personalizar las constantes de tiles TEXT_*, defínelas antes de incluir rpg.h y la implementación; aplica las mismas definiciones allí donde se compile la biblioteca.
Ejemplo de uso
text_print_u8(11,8,255);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La fila U8 muestra 255 desde (11,8), en exactamente tres celdas y en azul en CGB. Las filas OVERWRITE y CLEAN muestran por qué hay que borrar explícitamente el campo al sustituir un valor por otro más corto.
La verificación compara cada píxel visible y los 1024 bytes del mapa BG en ambas pantallas de ejemplo. Unas ROM DMG/CGB independientes comprueban los 256 valores de byte sin signo, los cambios de cantidad de dígitos decimales y los extremos con signo, conservando puntos junto a cada número como centinelas. Las comprobaciones de disposición incluyen rectángulos vacíos y estrechos, posiciones en el borde del mapa, bytes de tile con valores de códigos de control sin interpretar y el cursor de ventana tras escrituras absolutas. Son pruebas en emulador, no en hardware físico.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\text_layout.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\text_layout.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/rpg.h:242
Print an unsigned byte in decimal using only the required number of cells.
kitaqgb/lib/text.c:233
void text_print_u8(u8 x, u8 y, u8 value)
{
text_print_u16_width(x, y, (u16)value, text_dec_digits_u16((u16)value));
}text_print_xy
Dibuja horizontalmente una secuencia de números de tile terminada en cero desde una posición absoluta del mapa del fondo. No aplica recorte de ventana, salto de línea automático, interpretación de códigos de control ni retardo entre caracteres. No mueve el cursor de text_print.
Sintaxis
void text_print_xy(u8 x, u8 y, const u8* str);Parámetros
xColumna inicial, en celdas de 8×8 del mapa del fondo. Toda la salida debe quedar entre las columnas 0 y 31. Sin desplazamiento del fondo, se ven las columnas 0–19.
yFila inicial, de 0 a 31, en celdas de 8×8 del mapa del fondo. Sin desplazamiento, se ven las filas 0–17. Un rectángulo también debe caber verticalmente en el mapa.
strPuntero legible a una secuencia de bytes de tiles terminada en 0. Cada byte se usa directamente como número de tile. Una cadena ASCII solo se verá como texto si los glifos correspondientes ocupan los ID de tile adecuados. La fuente debe seguir mapeada y accesible hasta que termine la llamada. Estas funciones no decodifican UTF-8 ni cargan glifos. Para mostrar texto multibyte, primero hay que preparar una codificación definida por el juego y los datos de tiles correspondientes.
Valor devuelto
No devuelve ningún valor. Escribe las celdas del mapa antes de terminar; no devuelve una cantidad de caracteres ni un código de estado.
Condiciones y límites
Estas funciones dibujan en el mapa BG seleccionado por el bit 3 de LCDC. La ventana de texto es un área gestionada por software en ese mapa, no la capa Window del hardware. Mantén VBK en 0 en CGB para escribir números de tile; estas llamadas no configuran atributos de color, paletas ni desplazamiento.
Carga la fuente y los gráficos del marco antes de dibujar. Los ID predeterminados del marco son 1–6, el tile de relleno es 0 y los dígitos decimales empiezan en ASCII 0 (tile 48). El signo menos usa ASCII - (tile 45). El ejemplo incluye seis tiles de marco y la fuente del manual, cuyos ID de glifo coinciden con ASCII.
Mantén los rectángulos y el texto dentro del mapa de 32×32. El relleno rectangular no recorta la anchura ni la altura en los límites del mapa. Si cualquiera de ellas es cero, no rellena nada; aun así, text_window registra el área como abierta, sin interior utilizable.
Las funciones intrínsecas de escritura comprueban el LCD: si está apagado, escriben al instante; si está encendido, esperan un modo que permita escribir y rodean la escritura con DI/EI. Este camino puede dejar las interrupciones habilitadas al terminar; no supongas que conserva su estado deshabilitado. Los ejemplos y las pruebas a nivel de byte de esta sección escriben con el LCD apagado.
El ejemplo completo incluye text.c una vez para compilar la implementación de la biblioteca junto con el programa. No pases además lib/text.c como entrada independiente. Para personalizar las constantes de tiles TEXT_*, defínelas antes de incluir rpg.h y la implementación; aplica las mismas definiciones allí donde se compile la biblioteca.
Ejemplo de uso
text_print_xy(2,3,"HELLO!");Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
HELLO! empieza en el tile (2,3), píxel (16,24), dentro del marco rojo en CGB. Es una posición absoluta del mapa BG: abrir el área de texto no añade ningún desplazamiento a x ni a y.
La verificación compara cada píxel visible y los 1024 bytes del mapa BG en ambas pantallas de ejemplo. Unas ROM DMG/CGB independientes comprueban los 256 valores de byte sin signo, los cambios de cantidad de dígitos decimales y los extremos con signo, conservando puntos junto a cada número como centinelas. Las comprobaciones de disposición incluyen rectángulos vacíos y estrechos, posiciones en el borde del mapa, bytes de tile con valores de códigos de control sin interpretar y el cursor de ventana tras escrituras absolutas. Son pruebas en emulador, no en hardware físico.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\text_layout.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\text_layout.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/rpg.h:240
Draw a zero-terminated tile string at absolute tile coordinates, without window clipping, control codes or the windowed printing delay.
kitaqgb/lib/text.c:227
void text_print_xy(u8 x, u8 y, const u8* str)
{
text_draw_string_at(x, y, str);
}text_set_speed
Establece cuántas esperas VBlank se hacen después de cada carácter normal escrito por text_print o text_print_far. Cero elimina esas esperas. Abrir o cerrar un área no restablece este ajuste. Las órdenes WAIT explícitas siguen esperando aunque la velocidad de caracteres sea cero.
Sintaxis
void text_set_speed(u8 speed);Parámetros
speedEsperas VBlank después de cada carácter, de 0 a 255. Es un número de esperas, no milisegundos. No afecta a text_print_xy, las funciones numéricas ni la lista de opciones.
Valor devuelto
No devuelve ningún valor. El dibujo y las esperas bloqueantes se realizan antes de volver.
Condiciones y límites
Usa un rectángulo BG válido y carga primero los tiles de fuente y marco. El área de texto por software usa el mapa BG elegido por el bit 3 de LCDC; no activa la capa Window de hardware. En CGB, usa VBK 0 para números de tile y configura los atributos de color por separado. Los ejemplos incluyen fuente mapeada a ASCII y tiles de marco, cursor e indicador de página. Los diálogos y etiquetas usan ID de tile de un byte, sin decodificar UTF-8. Para otros caracteres, proporciona sus glifos y codifica el texto con esos ID, dejando reservados los bytes de control del diálogo.
Son funciones bloqueantes: mientras esperan no llaman a la actualización del juego, al servicio de música ni al bucle de renderizado. Con el LCD apagado, __wait_vblank vuelve de inmediato, así que la velocidad de caracteres y WAIT no generan retrasos en fotogramas. Mantén el LCD activo para diálogo temporizado y entrada por fotogramas. Usa una máquina de estados del juego si otras tareas deben avanzar durante la conversación.
Las escrituras seguras de tiles esperan modos LCD escribibles con el LCD activo y usan DI/EI alrededor de la escritura. Pueden activar interrupciones en vez de conservar un estado inicialmente desactivado. No llames a estas funciones bloqueantes desde un manejador de interrupción ni dependas de que conserven ese estado.
Cada ejemplo completo incluye text.c una vez. Compila con los directorios de inclusión de la biblioteca y los ejemplos del manual; no añadas lib/text.c como otra fuente. El ejemplo de flujo lejano usa MBC5 y una ROM de 64 KiB para incluir los datos del banco 2.
Ejemplo de uso
text_set_speed(2);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo de flujo usa velocidad 2 para diálogo normal y entre bancos, e incluye un operando WAIT de 12. La imagen final muestra el texto tras esperar; una traza de fotogramas aparte comprueba velocidad 3, una orden de cinco esperas y otra de cuatro con el área cerrada. La temporización no se valida solo con la captura final.
Las pruebas del emulador comparan todo el mapa BG y las cuatro imágenes de ejemplo. Otras ejecuciones cubren apertura/cierre, flujos normales y entre bancos, esperas temporizadas, páginas explícitas y automáticas, avance A/B/START, botones mantenidos, selección circular, listas vacías y prioridad simultánea. Los puntos antes y después de la entrada programada verifican que la espera de página bloquea realmente. No se prueban hardware físico ni concurrencia de interrupciones.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dialogue_flow.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dialogue_flow.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/rpg.h:233
Set VBlank waits per windowed character; zero prints without character delays.
kitaqgb/lib/text.c:208
void text_set_speed(u8 speed)
{
text_speed = speed;
}text_window
Dibuja un área de texto con marco en el mapa de tiles del fondo y la activa para la escritura en ventana. Es un alias de text_open: devuelve el cursor a la primera celda interior, redibuja el marco y borra el interior. Conserva el retardo actual entre caracteres.
Sintaxis
void text_window(u8 x, u8 y, u8 w, u8 h);Parámetros
xColumna inicial, en celdas de 8×8 del mapa del fondo. Toda la salida debe quedar entre las columnas 0 y 31. Sin desplazamiento del fondo, se ven las columnas 0–19.
yFila inicial, de 0 a 31, en celdas de 8×8 del mapa del fondo. Sin desplazamiento, se ven las filas 0–17. Un rectángulo también debe caber verticalmente en el mapa.
wAnchura en celdas de tile. En text_window incluye las dos columnas del marco y deja max(w−2, 0) columnas interiores. En text_clear_rect es la cantidad de celdas que se rellenan en cada fila.
hAltura en celdas de tile. En text_window incluye los bordes superior e inferior y deja max(h−2, 0) filas interiores. En text_clear_rect es la cantidad de filas que se rellenan.
Valor devuelto
No devuelve ningún valor. Escribe las celdas del mapa antes de terminar; no devuelve una cantidad de caracteres ni un código de estado.
Condiciones y límites
Estas funciones dibujan en el mapa BG seleccionado por el bit 3 de LCDC. La ventana de texto es un área gestionada por software en ese mapa, no la capa Window del hardware. Mantén VBK en 0 en CGB para escribir números de tile; estas llamadas no configuran atributos de color, paletas ni desplazamiento.
Carga la fuente y los gráficos del marco antes de dibujar. Los ID predeterminados del marco son 1–6, el tile de relleno es 0 y los dígitos decimales empiezan en ASCII 0 (tile 48). El signo menos usa ASCII - (tile 45). El ejemplo incluye seis tiles de marco y la fuente del manual, cuyos ID de glifo coinciden con ASCII.
Mantén los rectángulos y el texto dentro del mapa de 32×32. El relleno rectangular no recorta la anchura ni la altura en los límites del mapa. Si cualquiera de ellas es cero, no rellena nada; aun así, text_window registra el área como abierta, sin interior utilizable.
Las funciones intrínsecas de escritura comprueban el LCD: si está apagado, escriben al instante; si está encendido, esperan un modo que permita escribir y rodean la escritura con DI/EI. Este camino puede dejar las interrupciones habilitadas al terminar; no supongas que conserva su estado deshabilitado. Los ejemplos y las pruebas a nivel de byte de esta sección escriben con el LCD apagado.
El ejemplo completo incluye text.c una vez para compilar la implementación de la biblioteca junto con el programa. No pases además lib/text.c como entrada independiente. Para personalizar las constantes de tiles TEXT_*, defínelas antes de incluir rpg.h y la implementación; aplica las mismas definiciones allí donde se compile la biblioteca.
Ejemplo de uso
text_window(1,2,18,5);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo abre un área de 18×5 celdas en (1,2), con un interior de 16×3. El marco incluido tiene trazos de un píxel; sus líneas exteriores visibles van de x=11 a 147 y de y=19 a 51 píxeles. Es rojo en CGB y negro en DMG.
La verificación compara cada píxel visible y los 1024 bytes del mapa BG en ambas pantallas de ejemplo. Unas ROM DMG/CGB independientes comprueban los 256 valores de byte sin signo, los cambios de cantidad de dígitos decimales y los extremos con signo, conservando puntos junto a cada número como centinelas. Las comprobaciones de disposición incluyen rectángulos vacíos y estrechos, posiciones en el borde del mapa, bytes de tile con valores de códigos de control sin interpretar y el cursor de ventana tras escrituras absolutas. Son pruebas en emulador, no en hardware físico.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\text_layout.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\text_layout.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/rpg.h:235
Open and redraw a window using the same tile-space arguments as text_open.
kitaqgb/lib/text.c:214
void text_window(u8 x, u8 y, u8 w, u8 h)
{
text_open(x, y, w, h);
}unit_attack_range
Marca las celdas cuya distancia Manhattan está entre atk_min y atk_max, ambos incluidos.
Sintaxis
u8 unit_attack_range(unit_t* u, u8* out_mask);Parámetros
uunit_t válido: posición en celdas, move en pasos, rango atk_min/atk_max inclusivo, y hp y acted para decidir si puede actuar.
out_maskwidth*height bytes escribibles; recibe cero o uno por celda.
Valor devuelto
Devuelve 1 si el mapa está disponible y 0 si sus dimensiones son cero.
Condiciones y límites
Las coordenadas indican celdas del mapa activo: 8×8 píxeles para tiles normales y 16×16 para metatiles.
Ignora obstáculos, línea de visión y unidades aliadas. Mantén las distancias evaluadas como máximo en 255. Si el alcance mínimo supera al máximo, todas las celdas valen cero.
Ejemplo de uso
result[46]=unit_attack_range(&hero,mask);result[47]=mask[12];result[48]=mask[14];Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La cuadrícula izquierda muestra los costes de movimiento en tres pasos; la derecha, una ruta más corta de S a G. Los asteriscos verdes trazan nueve pasos alrededor de una pared roja de tres celdas; los dígitos azules muestran los costes. DMG usa la misma disposición en negro. Las comprobaciones de RAM también muestran que la máscara de ataque ignora las paredes.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_map_path.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_map_path.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=noneImplementación y código fuente
kitaqgb/lib/rpg.h:352
Mark cells whose Manhattan distance falls within the inclusive attack range. This geometric mask does not test obstacles, line of sight or other units.
kitaqgb/lib/slg_unit.c:38
u8 unit_attack_range(unit_t* u, u8* out_mask)
{
u8 w = map_current_width();
u8 h = map_current_height();
u8 y;
if (w == 0 || h == 0) return 0;
__memset(out_mask, 0, (u16)((u16)w * (u16)h));
y = 0;
while (y < h) {
u8 x = 0;
while (x < w) {
u8 dist = __manhattan(u->x, u->y, x, y);
if (dist >= u->atk_min && dist <= u->atk_max) {
out_mask[__map_index(x, y, w)] = 1;
}
x++;
}
y++;
}
return 1;
}unit_can_act
Comprueba que una unidad tenga PV y aún no haya actuado.
Sintaxis
u8 unit_can_act(const unit_t* u);Parámetros
uunit_t válido: posición en celdas, move en pasos, rango atk_min/atk_max inclusivo, y hp y acted para decidir si puede actuar.
Valor devuelto
Devuelve 1 si hp no es cero y acted es cero; en caso contrario, 0. No modifica la unidad.
Ejemplo de uso
result[11]=unit_can_act(&hero);hero.acted=1;result[12]=unit_can_act(&hero);hero.acted=0;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La cuadrícula izquierda muestra los costes de movimiento en tres pasos; la derecha, una ruta más corta de S a G. Los asteriscos verdes trazan nueve pasos alrededor de una pared roja de tres celdas; los dígitos azules muestran los costes. DMG usa la misma disposición en negro. Las comprobaciones de RAM también muestran que la máscara de ataque ignora las paredes.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_map_path.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_map_path.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=noneImplementación y código fuente
kitaqgb/lib/rpg.h:355
A unit can act only while HP is nonzero and its acted flag is clear. The unit pointer must refer to a valid record.
kitaqgb/lib/slg_unit.c:5
u8 unit_can_act(const unit_t* u)
{
if (u->hp == 0) return 0;
if (u->acted != 0) return 0;
return 1;
}unit_move_range
Construye una máscara de las celdas alcanzables dentro del movimiento permitido de la unidad.
Sintaxis
u8 unit_move_range(unit_t* u, u8* out_mask);Parámetros
uunit_t válido: posición en celdas, move en pasos, rango atk_min/atk_max inclusivo, y hp y acted para decidir si puede actuar.
out_maskwidth*height bytes escribibles; recibe cero o uno por celda.
Valor devuelto
Devuelve 1 si el mapa está disponible y 0 si sus dimensiones son cero. El origen de la unidad debe estar dentro del mapa.
Condiciones y límites
Las coordenadas indican celdas del mapa activo: 8×8 píxeles para tiles normales y 16×16 para metatiles.
La búsqueda usa unos 4 KiB de espacio de trabajo compartido y no reentrante. Limita los mapas a 1024 celdas y las distancias exploradas a 254. La distancia 0xFF significa «no alcanzado», así que no se puede representar una ruta de 255 pasos. Las salidas de coste y máscara necesitan width*height bytes escribibles.
El origen se marca como alcanzable aunque esté bloqueado. Los PV, acted y otras unidades no afectan a la máscara de movimiento.
Ejemplo de uso
result[43]=unit_move_range(&hero,mask);result[44]=mask[12];result[45]=mask[14];Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La cuadrícula izquierda muestra los costes de movimiento en tres pasos; la derecha, una ruta más corta de S a G. Los asteriscos verdes trazan nueve pasos alrededor de una pared roja de tres celdas; los dígitos azules muestran los costes. DMG usa la misma disposición en negro. Las comprobaciones de RAM también muestran que la máscara de ataque ignora las paredes.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_map_path.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_map_path.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=noneImplementación y código fuente
kitaqgb/lib/rpg.h:349
Build movement costs, then convert reachable cells to one and unreachable 0xFF cells to zero. The caller provides one output byte per current-map cell and a valid unit origin; path-search workspace limits also apply.
kitaqgb/lib/slg_unit.c:15
u8 unit_move_range(unit_t* u, u8* out_mask)
{
u8 w = map_current_width();
u8 h = map_current_height();
u16 total;
u16 i;
if (w == 0 || h == 0) return 0;
// A valid origin is required: the fill leaves storage unchanged on invalid origins, but this loop still converts it.
range_fill_move(u->x, u->y, u->move, out_mask);
total = (u16)((u16)w * (u16)h);
i = 0;
while (i < total) {
out_mask[i] = (u8)((out_mask[i] == 0xFF) ? 0 : 1);
i++;
}
return 1;
}weighted_choice
Selecciona un índice de una lista de pesos relativos de un byte. Suma los pesos, reduce una extracción rng16 módulo ese total y busca el primer intervalo acumulado que contiene el resultado. Con pesos [1, 3, 6], los índices 0, 1 y 2 ocupan los intervalos 0, 1–3 y 4–9.
Sintaxis
u8 weighted_choice(const u8* weights, u8 count);Parámetros
weightsPuntero a count pesos u8 legibles. El array no se modifica. Se omiten los elementos de peso cero si el total es positivo. Con count == 0 no se lee el puntero y puede ser nulo; en otro caso, proporciona un array válido.
countNúmero de pesos, de 0 a 255. Como máximo, 255 pesos de 255 suman 65025, que cabe en el acumulador u16. La función recorre la lista para sumar los pesos y después vuelve a recorrerla hasta encontrar el intervalo elegido.
Valor devuelto
Con total positivo, un índice de 0 a count−1 tras dos extracciones de byte. Si count es cero o todos los pesos son cero, devuelve cero sin extraer. Ese valor alternativo no se distingue de una selección válida del índice 0; comprueba tú mismo las listas vacías o de pesos nulos si necesitas distinguirlos.
Condiciones y límites
Los pesos definen tamaños relativos de intervalos, no porcentajes observados garantizados. Tanto la distribución de rng16 como la reducción módulo el total afectan a las frecuencias reales. Un total positivo siempre consume dos extracciones de byte, aunque solo un elemento tenga peso distinto de cero.
Estas llamadas comparten estado persistente. Para reproducir la secuencia hacen falta el mismo destino, semilla y orden de llamadas, incluidas las de otras funciones auxiliares. Mantén la semilla y las extracciones en un único contexto de ejecución; estas comprobaciones no demuestran que sea seguro usarlas simultáneamente desde una interrupción.
GB y FC usan algoritmos distintos y no prometen la misma secuencia con la misma semilla. Son generadores deterministas para juegos, no fuentes de aleatoriedad criptográfica; las pruebas comprueban el comportamiento de la implementación, no su calidad estadística ni su período.
Incluye rpg.h y compila lib/rng.c junto al juego cuando uses las funciones de biblioteca. Las intrínsecas __rng_seed y __rng8 las genera el compilador; un programa que solo use esas dos no necesita el objeto rng.c.
Ejemplo de uso
weights[0]=1;weights[1]=3;weights[2]=6;
rng_seed(0x1234);
chosen=weighted_choice(weights,3); // 546 % 10 = 6 selects index 2.
empty=weighted_choice((const u8*)0,0); // No items: 0 is a fallback, not a chosen item.Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Este ejemplo asigna pesos 1, 3 y 6 a tres elementos. La palabra generada, 546, da resto 6, dentro del intervalo 4–9 del índice 2; WEIGHT INDEX muestra 00002. EMPTY LIST muestra 00000 como valor alternativo de lista vacía, no como selección correcta del elemento 0.
El programa completo muestra resultados decimales sobre blanco: texto negro en DMG y azul en CGB. FAILED debe indicar 00000. Las imágenes muestran la salida real del ejemplo en el emulador.
La verificación comparó por caso 32 salidas y ocho extracciones de byte posteriores con un modelo independiente en el equipo anfitrión: 93 casos GB y 18 FC, incluidos semillas constantes o en tiempo de ejecución y límites GB de rango, probabilidad y pesos. Las pantallas didácticas se comprobaron tras 240 fotogramas del emulador. No se probaron hardware físico ni calidad estadística.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\rng_choices.c .\kitaqgb\lib\rng.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\rng_choices.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/rpg.h:203
Select an index from cumulative byte weights using a 16-bit random draw. A zero total, including an empty list, returns zero; callers must distinguish that case from a valid index. Modulo reduction can introduce a small bias.
kitaqgb/lib/rng.c:61
u8 weighted_choice(const u8* weights, u8 count)
{
u8 i;
u16 total;
u16 pick;
u16 acc;
// At most 255 byte weights sum to 65025, so this accumulator fits u16.
// A nonempty list requires count readable weight bytes.
total = 0;
i = 0;
while (i < count) {
total = (u16)(total + (u16)weights[i]);
i++;
}
if (total == 0) return 0;
pick = (u16)(rng16() % total);
acc = 0;
i = 0;
while (i < count) {
acc = (u16)(acc + (u16)weights[i]);
if (pick < acc) return i;
i++;
}
return (u8)(count - 1);
}scene.h — Registro, cambio y actualización de escenas
Invoca los manejadores enter, update, draw y exit de una tabla de escenas para cambiar entre pantallas como el título y la partida.
scene_change
Sale de la escena activa, si la hay, y entra en la escena solicitada.
Sintaxis
void scene_change(u8 scene_id);Parámetros
scene_idÍndice de la escena a la que entrar, de 0 a count−1.
Valor devuelto
No devuelve ningún valor.
Condiciones y límites
Se ignoran los ID fuera de rango. Un cambio válido ejecuta exit, guarda el nuevo ID y el indicador de cambio y después ejecuta enter. Seleccionar el mismo ID también ejecuta exit y enter. La tabla de escenas pertenece al código que llama a la función. Mantén válidos tanto la tabla como los destinos de sus punteros a funciones ordinarias mientras se utilicen. Se omiten las funciones de retorno nulas. No cambies de escena recursivamente ni sustituyas la tabla desde las funciones de retorno enter o exit.
Compila este ejemplo completo con la ABI Legacy predeterminada. Sus retrollamadas usan llamadas mediante punteros de función, que el compilador rechaza por no estar admitidas con --abi=stack. La misma restricción se aplica al usar un alias.
Ejemplo de uso
scene_change(0);scene_change(9);result[11]=events;result[12]=scene_was_changed();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El programa activa la escena 0, ignora el ID no válido 9, cambia de 0→1 y vuelve a entrar con 1→1 para comprobar el orden de las funciones de retorno.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_services.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_services.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/scene.h:20
Ignore invalid IDs; otherwise exit the current scene and enter the requested one. Selecting the current ID still performs exit/enter. Callbacks run synchronously.
kitaqgb/lib/scene.c:27
void scene_change(u8 scene_id)
{
SceneFunc fn;
if (scene_id >= scene_count) return;
// Exit/enter handlers must not recursively change scenes or replace this shared table.
if (scene_has_current != 0) {
fn = scene_table[(__safe_index u8)scene_current].exit;
if (fn != 0) fn();
}
scene_current = scene_id;
scene_has_current = 1;
scene_changed = 1;
fn = scene_table[(__safe_index u8)scene_current].enter;
if (fn != 0) fn();
}scene_draw
Llama una vez a la función de retorno draw de la escena activa.
Sintaxis
void scene_draw();Valor devuelto
No devuelve ningún valor.
Condiciones y límites
Si no hay una escena activa o la función de retorno draw es nula, no hace nada. No borra el indicador de cambio. Organiza las transferencias de pantalla y la sincronización de fotogramas en la función de retorno o en el bucle de juego que la llama. La tabla de escenas pertenece al código que llama a la función. Mantén válidos tanto la tabla como los destinos de sus punteros a funciones ordinarias mientras se utilicen. Se omiten las funciones de retorno nulas. No cambies de escena recursivamente ni sustituyas la tabla desde las funciones de retorno enter o exit.
Compila este ejemplo completo con la ABI Legacy predeterminada. Sus retrollamadas usan llamadas mediante punteros de función, que el compilador rechaza por no estar admitidas con --abi=stack. La misma restricción se aplica al usar un alias.
Ejemplo de uso
scene_draw();result[15]=events;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La secuencia contiene el evento 12 de draw en la escena 0 y el evento 22 de draw en la escena 1.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_services.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_services.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/scene.h:25
Call the active scene's draw handler if one exists; no current scene is a no-op.
kitaqgb/lib/scene.c:60
void scene_draw()
{
SceneFunc fn;
if (scene_has_current == 0) return;
fn = scene_table[(__safe_index u8)scene_current].draw;
if (fn != 0) fn();
}scene_get_current
Lee el ID de escena actual almacenado.
Sintaxis
u8 scene_get_current();Valor devuelto
Devuelve el ID almacenado de ocho bits; la inicialización también lo deja en cero.
Condiciones y límites
Un valor de retorno de cero no demuestra por sí solo que la escena 0 esté activa. Lleva la cuenta de si ya se ha llamado por primera vez a scene_change() después de inicializar.
Compila este ejemplo completo con la ABI Legacy predeterminada. Sus retrollamadas usan llamadas mediante punteros de función, que el compilador rechaza por no estar admitidas con --abi=stack. La misma restricción se aplica al usar un alias.
Ejemplo de uso
result[16]=scene_get_current();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo lee cero después de activar la escena 0 y uno después de cambiar a la escena 1.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_services.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_services.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/scene.h:27
Return the stored scene ID; zero is also returned before the first transition.
kitaqgb/lib/scene.c:70
u8 scene_get_current()
{
return scene_current;
}scene_init
Registra una tabla de escenas sin activar ninguna.
Sintaxis
void scene_init(const SceneDef* scenes, u8 count);Parámetros
scenesArray de entradas
SceneDefcon las funciones de retorno enter, update, draw y exit.countNúmero de entradas; si es cero, no hay ningún ID de escena válido.
Valor devuelto
No devuelve ningún valor.
Condiciones y límites
Restablece a cero el ID almacenado y el indicador de cambio. No llama a enter; usa scene_change() para activar una escena. La tabla de escenas pertenece al código que llama a la función. Mantén válidos tanto la tabla como los destinos de sus punteros a funciones ordinarias mientras se utilicen. Se omiten las funciones de retorno nulas. No cambies de escena recursivamente ni sustituyas la tabla desde las funciones de retorno enter o exit.
Compila este ejemplo completo con la ABI Legacy predeterminada. Sus retrollamadas usan llamadas mediante punteros de función, que el compilador rechaza por no estar admitidas con --abi=stack. La misma restricción se aplica al usar un alias.
Ejemplo de uso
scene_init(scenes,2);scene_update();scene_draw();result[9]=events;result[10]=scene_was_changed();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo registra dos escenas y comprueba que llamar a update y draw antes de activarlas no genera eventos.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_services.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_services.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/scene.h:15
Attach the caller-owned scene table and clear current-scene state without invoking callbacks.
kitaqgb/lib/scene.c:10
void scene_init(const SceneDef* scenes, u8 count)
{
scene_table = scenes;
scene_count = count;
scene_current = 0;
scene_changed = 0;
scene_has_current = 0;
}scene_set_table
Sustituye la tabla de escenas y deja todas las escenas inactivas.
Sintaxis
void scene_set_table(const SceneDef* scenes, u8 count);Parámetros
scenesArray de entradas
SceneDefcon las funciones de retorno enter, update, draw y exit.countNúmero de entradas; si es cero, no hay ningún ID de escena válido.
Valor devuelto
No devuelve ningún valor.
Condiciones y límites
Restablece el estado como scene_init(), sin llamar a la función de retorno exit anterior ni a una nueva función enter. La tabla de escenas pertenece al código que llama a la función. Mantén válidos tanto la tabla como los destinos de sus punteros a funciones ordinarias mientras se utilicen. Se omiten las funciones de retorno nulas. No cambies de escena recursivamente ni sustituyas la tabla desde las funciones de retorno enter o exit.
Compila este ejemplo completo con la ABI Legacy predeterminada. Sus retrollamadas usan llamadas mediante punteros de función, que el compilador rechaza por no estar admitidas con --abi=stack. La misma restricción se aplica al usar un alias.
Ejemplo de uso
scene_set_table(scenes,2);result[23]=events;result[24]=scene_was_changed();scene_draw();result[25]=events;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Al sustituir la tabla después de nueve eventos, el contador sigue en nueve, el indicador de cambio vuelve a cero y la siguiente llamada a draw no hace nada.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_services.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_services.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/scene.h:17
Replace the table by resetting scene state; this does not call the old scene's exit handler.
kitaqgb/lib/scene.c:20
void scene_set_table(const SceneDef* scenes, u8 count)
{
scene_init(scenes, count);
}scene_update
Llama una vez a la función de retorno update de la escena activa.
Sintaxis
void scene_update();Valor devuelto
No devuelve ningún valor.
Condiciones y límites
Si no hay una escena activa, no hace nada. En caso contrario, borra el indicador de cambio antes de invocar la función de retorno, de modo que un cambio realizado dentro de update sigue siendo detectable después. La tabla de escenas pertenece al código que llama a la función. Mantén válidos tanto la tabla como los destinos de sus punteros a funciones ordinarias mientras se utilicen. Se omiten las funciones de retorno nulas. No cambies de escena recursivamente ni sustituyas la tabla desde las funciones de retorno enter o exit.
Compila este ejemplo completo con la ABI Legacy predeterminada. Sus retrollamadas usan llamadas mediante punteros de función, que el compilador rechaza por no estar admitidas con --abi=stack. La misma restricción se aplica al usar un alias.
Ejemplo de uso
scene_update();result[13]=events;result[14]=scene_was_changed();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La función update de la escena 0 registra el evento 11. Tras esta actualización normal, el indicador de cambio pasa de uno a cero.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_services.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_services.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/scene.h:23
Clear the change flag before calling the active scene's update handler, so a transition made during that handler is visible afterward.
kitaqgb/lib/scene.c:49
void scene_update()
{
SceneFunc fn;
if (scene_has_current == 0) return;
scene_changed = 0;
fn = scene_table[(__safe_index u8)scene_current].update;
if (fn != 0) fn();
}scene_was_changed
Consulta si hay un cambio de escena registrado.
Sintaxis
u8 scene_was_changed();Valor devuelto
Devuelve 1 si el indicador de cambio está activado; en caso contrario, 0.
Condiciones y límites
La lectura no borra el indicador. Se borra al inicializar, sustituir la tabla o empezar a actualizar una escena activa. Un ID de escena no válido no lo modifica.
Compila este ejemplo completo con la ABI Legacy predeterminada. Sus retrollamadas usan llamadas mediante punteros de función, que el compilador rechaza por no estar admitidas con --abi=stack. La misma restricción se aplica al usar un alias.
Ejemplo de uso
result[17]=scene_was_changed();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Las comprobaciones esperan uno justo después de cambiar de escena, cero tras una actualización normal y cero tras sustituir la tabla.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_services.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_services.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/scene.h:29
Read the transition flag, which is cleared at the start of an active scene update.
kitaqgb/lib/scene.c:76
u8 scene_was_changed()
{
return scene_changed;
}scroll.h — Desplazamiento del fondo, la ventana y las zonas divididas
Controla el desplazamiento inmediato o mediante búfer del fondo y la ventana y hasta ocho divisiones de raster. Distingue los valores actuales gestionados por las funciones de lectura, los registros de hardware activos y los valores pendientes.
Scroll_BgAdd
Suma desplazamientos con signo a las coordenadas registradas del fondo y los aplica de inmediato.
Sintaxis
void Scroll_BgAdd(s8 dx, s8 dy);Parámetros
dxDesplazamiento horizontal con signo en píxeles, de −128 a 127.
dyDesplazamiento vertical con signo en píxeles, de −128 a 127.
Valor devuelto
No devuelve ningún valor. Esta entrada describe el estado afectado y cuándo surte efecto.
Condiciones y límites
No espera. Los ajustes y sumas inmediatos sincronizan el par de coordenadas pendiente afectado con los valores actuales y borran su indicador de modificación. Incluso ajustar de inmediato un solo eje cancela el otro eje pendiente del mismo par. Los resultados vuelven al inicio módulo 256. Las sumas parten de los valores actuales registrados, no de los pendientes ni de los valores temporales de los registros de raster. Esta función envuelve __scroll_bg_add.
Ejemplo de uso
Scroll_BgAdd(-20,3);result[22]=M_SCX;result[23]=M_SCY;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Usa las funciones Scroll para aprender actualización inmediata, preparación, aplicación, suma y visibilidad. Aplicar el búfer cambia BG X de 250 a 16 y WX de 23 a 39. El bit de ventana vale 32 tras mostrarla y 0 tras ocultarla.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_scroll_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_scroll_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kEjemplo de uso
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Con la cámara en (8,16), el rectángulo rojo de 32×24 aparece en pantalla en (24,16). La ventana muestra un marco azul de 64×64 en (96,80) y un cuadrado verde de 16×16 en (112,96). En DMG todas las figuras son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/scroll.h:73
Apply signed deltas to the byte-sized background-scroll coordinates.
kitaqgb/lib/scroll.c:41
void Scroll_BgAdd(s8 dx, s8 dy) { __scroll_bg_add(dx, dy); }Scroll_Flush
Aplica las coordenadas modificadas del fondo y la ventana al estado registrado y al hardware, y borra sus indicadores de actualización pendiente.
Sintaxis
void Scroll_Flush();Valor devuelto
No devuelve ningún valor. Esta entrada describe el estado afectado y cuándo surte efecto.
Condiciones y límites
Los pares de coordenadas sin cambios se dejan intactos. No enmascara interrupciones ni espera a VBlank; el código que llama debe organizar la sincronización necesaria. Esta función envuelve __scroll_flush.
Ejemplo de uso
Scroll_Flush();result[18]=M_SCX;result[19]=M_SCY;result[20]=M_WX;result[21]=M_WY;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Usa las funciones Scroll para aprender actualización inmediata, preparación, aplicación, suma y visibilidad. Aplicar el búfer cambia BG X de 250 a 16 y WX de 23 a 39. El bit de ventana vale 32 tras mostrarla y 0 tras ocultarla.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_scroll_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_scroll_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kEjemplo de uso
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Con la cámara en (8,16), el rectángulo rojo de 32×24 aparece en pantalla en (24,16). La ventana muestra un marco azul de 64×64 en (96,80) y un cuadrado verde de 16×16 en (112,96). En DMG todas las figuras son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/scroll.h:70
Apply the buffered scroll/window state through the compiler runtime.
kitaqgb/lib/scroll.c:38
void Scroll_Flush() { __scroll_flush(); }Scroll_GetBgX
Lee el valor actual registrado del desplazamiento horizontal del fondo.
Sintaxis
u8 Scroll_GetBgX();Valor devuelto
Devuelve el byte actual registrado, de 0 a 255. WX incluye su desplazamiento de hardware de siete píxeles.
Condiciones y límites
No es una lectura de un registro de hardware. No incluye los valores pendientes del búfer, las escrituras directas en registros ni los valores temporales aplicados por las divisiones de raster. Esta función envuelve __scroll_bg_x_get.
Ejemplo de uso
result[6]=Scroll_GetBgX();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Usa las funciones Scroll para aprender actualización inmediata, preparación, aplicación, suma y visibilidad. Aplicar el búfer cambia BG X de 250 a 16 y WX de 23 a 39. El bit de ventana vale 32 tras mostrarla y 0 tras ocultarla.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_scroll_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_scroll_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kEjemplo de uso
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Con la cámara en (8,16), el rectángulo rojo de 32×24 aparece en pantalla en (24,16). La ventana muestra un marco azul de 64×64 en (96,80) y un cuadrado verde de 16×16 en (112,96). En DMG todas las figuras son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/scroll.h:50
Read the tracked current background X; this is not a direct SCX register read.
kitaqgb/lib/scroll.c:18
u8 Scroll_GetBgX() { return __scroll_bg_x_get(); }Scroll_GetBgY
Lee el valor actual registrado del desplazamiento vertical del fondo.
Sintaxis
u8 Scroll_GetBgY();Valor devuelto
Devuelve el byte actual registrado, de 0 a 255. WX incluye su desplazamiento de hardware de siete píxeles.
Condiciones y límites
No es una lectura de un registro de hardware. No incluye los valores pendientes del búfer, las escrituras directas en registros ni los valores temporales aplicados por las divisiones de raster. Esta función envuelve __scroll_bg_y_get.
Ejemplo de uso
result[7]=Scroll_GetBgY();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Usa las funciones Scroll para aprender actualización inmediata, preparación, aplicación, suma y visibilidad. Aplicar el búfer cambia BG X de 250 a 16 y WX de 23 a 39. El bit de ventana vale 32 tras mostrarla y 0 tras ocultarla.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_scroll_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_scroll_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kEjemplo de uso
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Con la cámara en (8,16), el rectángulo rojo de 32×24 aparece en pantalla en (24,16). La ventana muestra un marco azul de 64×64 en (96,80) y un cuadrado verde de 16×16 en (112,96). En DMG todas las figuras son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/scroll.h:52
Read the tracked current background Y; pending and raster-only values are excluded.
kitaqgb/lib/scroll.c:20
u8 Scroll_GetBgY() { return __scroll_bg_y_get(); }Scroll_GetWindowX
Lee el valor WX actual registrado de la ventana.
Sintaxis
u8 Scroll_GetWindowX();Valor devuelto
Devuelve el byte actual registrado, de 0 a 255. WX incluye su desplazamiento de hardware de siete píxeles.
Condiciones y límites
No es una lectura de un registro de hardware. No incluye los valores pendientes del búfer, las escrituras directas en registros ni los valores temporales aplicados por las divisiones de raster. Esta función envuelve __scroll_win_x_get.
Ejemplo de uso
result[12]=Scroll_GetWindowX();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Usa las funciones Scroll para aprender actualización inmediata, preparación, aplicación, suma y visibilidad. Aplicar el búfer cambia BG X de 250 a 16 y WX de 23 a 39. El bit de ventana vale 32 tras mostrarla y 0 tras ocultarla.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_scroll_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_scroll_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kEjemplo de uso
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Con la cámara en (8,16), el rectángulo rojo de 32×24 aparece en pantalla en (24,16). La ventana muestra un marco azul de 64×64 en (96,80) y un cuadrado verde de 16×16 en (112,96). En DMG todas las figuras son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/scroll.h:61
Read tracked current WX, including its seven-pixel offset; not a live hardware read.
kitaqgb/lib/scroll.c:29
u8 Scroll_GetWindowX() { return __scroll_win_x_get(); }Scroll_GetWindowY
Lee el valor WY actual registrado de la ventana.
Sintaxis
u8 Scroll_GetWindowY();Valor devuelto
Devuelve el byte actual registrado, de 0 a 255. WX incluye su desplazamiento de hardware de siete píxeles.
Condiciones y límites
No es una lectura de un registro de hardware. No incluye los valores pendientes del búfer, las escrituras directas en registros ni los valores temporales aplicados por las divisiones de raster. Esta función envuelve __scroll_win_y_get.
Ejemplo de uso
result[13]=Scroll_GetWindowY();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Usa las funciones Scroll para aprender actualización inmediata, preparación, aplicación, suma y visibilidad. Aplicar el búfer cambia BG X de 250 a 16 y WX de 23 a 39. El bit de ventana vale 32 tras mostrarla y 0 tras ocultarla.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_scroll_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_scroll_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kEjemplo de uso
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Con la cámara en (8,16), el rectángulo rojo de 32×24 aparece en pantalla en (24,16). La ventana muestra un marco azul de 64×64 en (96,80) y un cuadrado verde de 16×16 en (112,96). En DMG todas las figuras son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/scroll.h:63
Read tracked current WY; pending and raster-only values are excluded.
kitaqgb/lib/scroll.c:31
u8 Scroll_GetWindowY() { return __scroll_win_y_get(); }Scroll_Init
Inicializa el desplazamiento del fondo en (0,0) y la posición de la ventana en WX=7, WY=0.
Sintaxis
void Scroll_Init();Valor devuelto
No devuelve ningún valor. Esta entrada describe el estado afectado y cuándo surte efecto.
Condiciones y límites
Sincroniza las coordenadas actuales y pendientes; no restablece la visibilidad de la ventana ni la tabla de divisiones.
Ejemplo de uso
Scroll_Init();result[0]=M_SCX;result[1]=M_SCY;result[2]=M_WX;result[3]=M_WY;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Usa las funciones Scroll para aprender actualización inmediata, preparación, aplicación, suma y visibilidad. Aplicar el búfer cambia BG X de 250 a 16 y WX de 23 a 39. El bit de ventana vale 32 tras mostrarla y 0 tras ocultarla.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_scroll_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_scroll_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kEjemplo de uso
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Con la cámara en (8,16), el rectángulo rojo de 32×24 aparece en pantalla en (24,16). La ventana muestra un marco azul de 64×64 en (96,80) y un cuadrado verde de 16×16 en (112,96). En DMG todas las figuras son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/scroll.h:42
Reset background scroll to zero and place the window at screen origin using hardware WX=7 and WY=0.
kitaqgb/lib/scroll.c:5
void Scroll_Init()
{
__scroll_bg_set(0, 0);
__scroll_win_set(7, 0);
}Scroll_SetBg
Establece de inmediato las dos coordenadas de desplazamiento del fondo.
Sintaxis
void Scroll_SetBg(u8 scx, u8 scy);Parámetros
scxDesplazamiento horizontal del fondo, de 0 a 255 píxeles; al aumentarlo, el fondo se mueve a la izquierda.
scyDesplazamiento vertical del fondo, de 0 a 255 píxeles; al aumentarlo, el fondo se mueve hacia arriba.
Valor devuelto
No devuelve ningún valor. Esta entrada describe el estado afectado y cuándo surte efecto.
Condiciones y límites
Envuelve __scroll_bg_set: sincroniza los valores actuales, pendientes y de hardware, y borra el indicador de modificación de BG sin esperar a VBlank.
Ejemplo de uso
Scroll_SetBg(8,16);result[28]=M_SCX;result[29]=M_SCY;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Usa las funciones Scroll para aprender actualización inmediata, preparación, aplicación, suma y visibilidad. Aplicar el búfer cambia BG X de 250 a 16 y WX de 23 a 39. El bit de ventana vale 32 tras mostrarla y 0 tras ocultarla.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_scroll_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_scroll_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kEjemplo de uso
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Con la cámara en (8,16), el rectángulo rojo de 32×24 aparece en pantalla en (24,16). La ventana muestra un marco azul de 64×64 en (96,80) y un cuadrado verde de 16×16 en (112,96). En DMG todas las figuras son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/scroll.h:44
Write both hardware background-scroll bytes immediately.
kitaqgb/lib/scroll.c:12
void Scroll_SetBg(u8 scx, u8 scy) { __scroll_bg_set(scx, scy); }Scroll_SetBgBuffered
Deja pendientes las dos coordenadas de desplazamiento del fondo para aplicarlas más tarde.
Sintaxis
void Scroll_SetBgBuffered(u8 scx, u8 scy);Parámetros
scxDesplazamiento horizontal del fondo, de 0 a 255 píxeles; al aumentarlo, el fondo se mueve a la izquierda.
scyDesplazamiento vertical del fondo, de 0 a 255 píxeles; al aumentarlo, el fondo se mueve hacia arriba.
Valor devuelto
No devuelve ningún valor. Esta entrada describe el estado afectado y cuándo surte efecto.
Condiciones y límites
No cambia los valores actuales registrados ni los registros de hardware. Aplícalos con __scroll_flush o Scroll_Flush; dejarlos pendientes no espera a VBlank. Esta función envuelve __scroll_bg_set_buffered.
Ejemplo de uso
Scroll_SetBgBuffered(16,24);result[14]=M_SCX;result[15]=Scroll_GetBgX();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Usa las funciones Scroll para aprender actualización inmediata, preparación, aplicación, suma y visibilidad. Aplicar el búfer cambia BG X de 250 a 16 y WX de 23 a 39. El bit de ventana vale 32 tras mostrarla y 0 tras ocultarla.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_scroll_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_scroll_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kEjemplo de uso
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Con la cámara en (8,16), el rectángulo rojo de 32×24 aparece en pantalla en (24,16). La ventana muestra un marco azul de 64×64 en (96,80) y un cuadrado verde de 16×16 en (112,96). En DMG todas las figuras son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/scroll.h:66
Stage background-scroll values in the intrinsic buffer for a later flush.
kitaqgb/lib/scroll.c:34
void Scroll_SetBgBuffered(u8 scx, u8 scy) { __scroll_bg_set_buffered(scx, scy); }Scroll_SetBgX
Establece de inmediato el desplazamiento horizontal del fondo.
Sintaxis
void Scroll_SetBgX(u8 scx);Parámetros
scxDesplazamiento horizontal del fondo, de 0 a 255 píxeles; al aumentarlo, el fondo se mueve a la izquierda.
Valor devuelto
No devuelve ningún valor. Esta entrada describe el estado afectado y cuándo surte efecto.
Condiciones y límites
No espera. Los ajustes y sumas inmediatos sincronizan el par de coordenadas pendiente afectado con los valores actuales y borran su indicador de modificación. Incluso ajustar de inmediato un solo eje cancela el otro eje pendiente del mismo par. Esta función envuelve __scroll_bg_x_set.
Ejemplo de uso
Scroll_SetBgX(250);result[4]=M_SCX;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Usa las funciones Scroll para aprender actualización inmediata, preparación, aplicación, suma y visibilidad. Aplicar el búfer cambia BG X de 250 a 16 y WX de 23 a 39. El bit de ventana vale 32 tras mostrarla y 0 tras ocultarla.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_scroll_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_scroll_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kEjemplo de uso
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Con la cámara en (8,16), el rectángulo rojo de 32×24 aparece en pantalla en (24,16). La ventana muestra un marco azul de 64×64 en (96,80) y un cuadrado verde de 16×16 en (112,96). En DMG todas las figuras son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/scroll.h:46
Write horizontal background scroll while leaving vertical scroll unchanged.
kitaqgb/lib/scroll.c:14
void Scroll_SetBgX(u8 scx) { __scroll_bg_x_set(scx); }Scroll_SetBgY
Establece de inmediato el desplazamiento vertical del fondo.
Sintaxis
void Scroll_SetBgY(u8 scy);Parámetros
scyDesplazamiento vertical del fondo, de 0 a 255 píxeles; al aumentarlo, el fondo se mueve hacia arriba.
Valor devuelto
No devuelve ningún valor. Esta entrada describe el estado afectado y cuándo surte efecto.
Condiciones y límites
No espera. Los ajustes y sumas inmediatos sincronizan el par de coordenadas pendiente afectado con los valores actuales y borran su indicador de modificación. Incluso ajustar de inmediato un solo eje cancela el otro eje pendiente del mismo par. Esta función envuelve __scroll_bg_y_set.
Ejemplo de uso
Scroll_SetBgY(2);result[5]=M_SCY;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Usa las funciones Scroll para aprender actualización inmediata, preparación, aplicación, suma y visibilidad. Aplicar el búfer cambia BG X de 250 a 16 y WX de 23 a 39. El bit de ventana vale 32 tras mostrarla y 0 tras ocultarla.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_scroll_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_scroll_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kEjemplo de uso
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Con la cámara en (8,16), el rectángulo rojo de 32×24 aparece en pantalla en (24,16). La ventana muestra un marco azul de 64×64 en (96,80) y un cuadrado verde de 16×16 en (112,96). En DMG todas las figuras son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/scroll.h:48
Write vertical background scroll while leaving horizontal scroll unchanged.
kitaqgb/lib/scroll.c:16
void Scroll_SetBgY(u8 scy) { __scroll_bg_y_set(scy); }Scroll_SetWindow
Establece de inmediato WX y WY de la ventana.
Sintaxis
void Scroll_SetWindow(u8 wx, u8 wy);Parámetros
wxByte WX sin ajustar, de 0 a 255: suma 7 a la X de pantalla deseada; el borde izquierdo usa 7.
wyParte superior de la ventana en píxeles Y de pantalla, de 0 a 255; las líneas visibles van de 0 a 143.
Valor devuelto
No devuelve ningún valor. Esta entrada describe el estado afectado y cuándo surte efecto.
Condiciones y límites
No espera. Los ajustes y sumas inmediatos sincronizan el par de coordenadas pendiente afectado con los valores actuales y borran su indicador de modificación. Incluso ajustar de inmediato un solo eje cancela el otro eje pendiente del mismo par. Esta función envuelve __scroll_win_set.
Ejemplo de uso
Scroll_SetWindow(15,8);result[8]=M_WX;result[9]=M_WY;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Usa las funciones Scroll para aprender actualización inmediata, preparación, aplicación, suma y visibilidad. Aplicar el búfer cambia BG X de 250 a 16 y WX de 23 a 39. El bit de ventana vale 32 tras mostrarla y 0 tras ocultarla.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_scroll_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_scroll_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kEjemplo de uso
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Con la cámara en (8,16), el rectángulo rojo de 32×24 aparece en pantalla en (24,16). La ventana muestra un marco azul de 64×64 en (96,80) y un cuadrado verde de 16×16 en (112,96). En DMG todas las figuras son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/scroll.h:55
Write raw hardware WX/WY values; callers add seven to a screen-space window X.
kitaqgb/lib/scroll.c:23
void Scroll_SetWindow(u8 wx, u8 wy) { __scroll_win_set(wx, wy); }Scroll_SetWindowBuffered
Deja pendientes las dos coordenadas de la ventana para aplicarlas más tarde.
Sintaxis
void Scroll_SetWindowBuffered(u8 wx, u8 wy);Parámetros
wxByte WX sin ajustar, de 0 a 255: suma 7 a la X de pantalla deseada; el borde izquierdo usa 7.
wyParte superior de la ventana en píxeles Y de pantalla, de 0 a 255; las líneas visibles van de 0 a 143.
Valor devuelto
No devuelve ningún valor. Esta entrada describe el estado afectado y cuándo surte efecto.
Condiciones y límites
No cambia los valores actuales registrados ni los registros de hardware. Aplícalos con __scroll_flush o Scroll_Flush; dejarlos pendientes no espera a VBlank. Esta función envuelve __scroll_win_set_buffered.
Ejemplo de uso
Scroll_SetWindowBuffered(39,32);result[16]=M_WX;result[17]=Scroll_GetWindowX();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Usa las funciones Scroll para aprender actualización inmediata, preparación, aplicación, suma y visibilidad. Aplicar el búfer cambia BG X de 250 a 16 y WX de 23 a 39. El bit de ventana vale 32 tras mostrarla y 0 tras ocultarla.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_scroll_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_scroll_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kEjemplo de uso
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Con la cámara en (8,16), el rectángulo rojo de 32×24 aparece en pantalla en (24,16). La ventana muestra un marco azul de 64×64 en (96,80) y un cuadrado verde de 16×16 en (112,96). En DMG todas las figuras son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/scroll.h:68
Stage raw window-coordinate values for a later flush.
kitaqgb/lib/scroll.c:36
void Scroll_SetWindowBuffered(u8 wx, u8 wy) { __scroll_win_set_buffered(wx, wy); }Scroll_SetWindowX
Establece de inmediato solo la coordenada WX sin ajustar de la ventana.
Sintaxis
void Scroll_SetWindowX(u8 wx);Parámetros
wxByte WX sin ajustar, de 0 a 255: suma 7 a la X de pantalla deseada; el borde izquierdo usa 7.
Valor devuelto
No devuelve ningún valor. Esta entrada describe el estado afectado y cuándo surte efecto.
Condiciones y límites
No espera. Los ajustes y sumas inmediatos sincronizan el par de coordenadas pendiente afectado con los valores actuales y borran su indicador de modificación. Incluso ajustar de inmediato un solo eje cancela el otro eje pendiente del mismo par. Esta función envuelve __scroll_win_x_set.
Ejemplo de uso
Scroll_SetWindowX(23);result[10]=M_WX;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Usa las funciones Scroll para aprender actualización inmediata, preparación, aplicación, suma y visibilidad. Aplicar el búfer cambia BG X de 250 a 16 y WX de 23 a 39. El bit de ventana vale 32 tras mostrarla y 0 tras ocultarla.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_scroll_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_scroll_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kEjemplo de uso
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Con la cámara en (8,16), el rectángulo rojo de 32×24 aparece en pantalla en (24,16). La ventana muestra un marco azul de 64×64 en (96,80) y un cuadrado verde de 16×16 en (112,96). En DMG todas las figuras son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/scroll.h:57
Write raw hardware WX without converting a screen-space X coordinate.
kitaqgb/lib/scroll.c:25
void Scroll_SetWindowX(u8 wx) { __scroll_win_x_set(wx); }Scroll_SetWindowY
Establece de inmediato solo la coordenada WY de la ventana.
Sintaxis
void Scroll_SetWindowY(u8 wy);Parámetros
wyParte superior de la ventana en píxeles Y de pantalla, de 0 a 255; las líneas visibles van de 0 a 143.
Valor devuelto
No devuelve ningún valor. Esta entrada describe el estado afectado y cuándo surte efecto.
Condiciones y límites
No espera. Los ajustes y sumas inmediatos sincronizan el par de coordenadas pendiente afectado con los valores actuales y borran su indicador de modificación. Incluso ajustar de inmediato un solo eje cancela el otro eje pendiente del mismo par. Esta función envuelve __scroll_win_y_set.
Ejemplo de uso
Scroll_SetWindowY(16);result[11]=M_WY;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Usa las funciones Scroll para aprender actualización inmediata, preparación, aplicación, suma y visibilidad. Aplicar el búfer cambia BG X de 250 a 16 y WX de 23 a 39. El bit de ventana vale 32 tras mostrarla y 0 tras ocultarla.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_scroll_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_scroll_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kEjemplo de uso
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Con la cámara en (8,16), el rectángulo rojo de 32×24 aparece en pantalla en (24,16). La ventana muestra un marco azul de 64×64 en (96,80) y un cuadrado verde de 16×16 en (112,96). En DMG todas las figuras son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/scroll.h:59
Write the window Y coordinate through the intrinsic.
kitaqgb/lib/scroll.c:27
void Scroll_SetWindowY(u8 wy) { __scroll_win_y_set(wy); }Scroll_SplitCommit
Guarda la visibilidad base de la ventana y prepara el primer evento de línea de la tabla de divisiones.
Sintaxis
void Scroll_SplitCommit();Valor devuelto
No devuelve ningún valor. Esta entrada describe el estado afectado y cuándo surte efecto.
Condiciones y límites
La tabla compartida admite ocho entradas. Añadirlas no las aplica ni las ordena, y las que exceden la capacidad se ignoran. Reconstrúyela con reset→push→commit en un límite de fotograma seguro y separa los eventos lo suficiente para que el manejador termine. La latencia de la interrupción puede hacer que la línea programada y el primer píxel afectado no coincidan. Una tabla no vacía activa VBlank/STAT en IE y ejecuta EI. Una tabla vacía desactiva la fuente LYC, pero no restaura IE ni el estado de interrupciones de la CPU. Esta función envuelve __scroll_split_commit.
Ejemplo de uso
Scroll_SplitCommit();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Usa las funciones envolventes Scroll para crear tres franjas de desplazamiento del fondo. Los eventos en LY=64 y 104 cambian X a 8 y 16, colocando los rectángulos de 24×16 en (32,16), (24,80) y (16,112). La imagen permite ver el desplazamiento de cada franja.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_split_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_split_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/scroll.h:92
Publish the pending split configuration through the compiler runtime.
kitaqgb/lib/scroll.c:66
void Scroll_SplitCommit() { __scroll_split_commit(); }Scroll_SplitPush
Añade una división que cambia el desplazamiento del fondo en el evento de línea de barrido indicado.
Sintaxis
void Scroll_SplitPush(u8 ly, u8 scx, u8 scy);Parámetros
lyNúmero de línea del evento; usa 0–143 para eventos visibles y añádelos en orden ascendente. Una primera entrada en cero se aplica durante VBlank.
scxDesplazamiento horizontal del fondo, de 0 a 255 píxeles; al aumentarlo, el fondo se mueve a la izquierda.
scyDesplazamiento vertical del fondo, de 0 a 255 píxeles; al aumentarlo, el fondo se mueve hacia arriba.
Valor devuelto
No devuelve ningún valor. Esta entrada describe el estado afectado y cuándo surte efecto.
Condiciones y límites
La tabla compartida admite ocho entradas. Añadirlas no las aplica ni las ordena, y las que exceden la capacidad se ignoran. Reconstrúyela con reset→push→commit en un límite de fotograma seguro y separa los eventos lo suficiente para que el manejador termine. La latencia de la interrupción puede hacer que la línea programada y el primer píxel afectado no coincidan. Esta función envuelve __scroll_split_push.
Ejemplo de uso
Scroll_SplitPush(64,8,0);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Usa las funciones envolventes Scroll para crear tres franjas de desplazamiento del fondo. Los eventos en LY=64 y 104 cambian X a 8 y 16, colocando los rectángulos de 24×16 en (32,16), (24,80) y (16,112). La imagen permite ver el desplazamiento de cada franja.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_split_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_split_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/scroll.h:85
Append a background-scroll split directly. Use Raster_Push when caller-side scanline ordering and capacity validation are desired.
kitaqgb/lib/scroll.c:53
void Scroll_SplitPush(u8 ly, u8 scx, u8 scy) { __scroll_split_push(ly, scx, scy); }Scroll_SplitPushBgColor0
Añade un evento que cambia el color cero de la paleta cero del fondo de CGB.
Sintaxis
void Scroll_SplitPushBgColor0(u8 ly, u16 rgb15);Parámetros
lyNúmero de línea del evento; usa 0–143 para eventos visibles y añádelos en orden ascendente. Una primera entrada en cero se aplica durante VBlank.
rgb15Color RGB555 de 15 bits: rojo en los bits 0–4, verde en 5–9 y azul en 10–14.
Valor devuelto
No devuelve ningún valor. Esta entrada describe el estado afectado y cuándo surte efecto.
Condiciones y límites
Solo para CGB. Usa una entrada de la tabla de ocho divisiones mediante la operación extendida. Las escrituras de paleta esperan a que se pueda acceder a la PPU. En este ejemplo de CGB a velocidad normal, los eventos LY=64/112 se ven a partir de las líneas 66/114. No confundas la línea del evento con la primera línea donde se dibuja su efecto.
Ejemplo de uso
Scroll_SplitPushBgColor0(0,0x7C00);Scroll_SplitPushBgColor0(64,0x001F);Scroll_SplitPushBgColor0(112,0x03E0);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Cambia el color cero del fondo de CGB durante el fotograma. A velocidad normal, este ejemplo dibuja las líneas 0–65 en azul, 66–113 en rojo y 114–143 en verde. Los eventos se programan en 0, 64 y 112; el manejo de interrupciones y el acceso a paletas añaden latencia. DMG no dispone de estas paletas de color.

Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_split_color.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_split_color.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/scroll.h:90
Reuse the two background-scroll fields to carry the low/high RGB15 bytes for a split whose operation flag selects background color zero.
kitaqgb/lib/scroll.c:61
void Scroll_SplitPushBgColor0(u8 ly, u16 rgb15)
{
__scroll_split_push_ex(ly, (u8)rgb15, (u8)(rgb15 >> 8), 0, 0, KQ_SCROLL_SPLIT_BG_COLOR0);
}Scroll_SplitPushEx
Añade una división cuyos indicadores seleccionan operaciones de fondo, ventana, visibilidad o color cero del fondo.
Sintaxis
void Scroll_SplitPushEx(u8 ly, u8 scx, u8 scy, u8 wx, u8 wy, u8 flags);Parámetros
lyNúmero de línea del evento; usa 0–143 para eventos visibles y añádelos en orden ascendente. Una primera entrada en cero se aplica durante VBlank.
scxDesplazamiento horizontal del fondo, de 0 a 255 píxeles; al aumentarlo, el fondo se mueve a la izquierda.
scyDesplazamiento vertical del fondo, de 0 a 255 píxeles; al aumentarlo, el fondo se mueve hacia arriba.
wxByte WX sin ajustar, de 0 a 255: suma 7 a la X de pantalla deseada; el borde izquierdo usa 7.
wyParte superior de la ventana en píxeles Y de pantalla, de 0 a 255; las líneas visibles van de 0 a 143.
flagsBits de operación: BG=1, posición de ventana=2, mostrar=4, ocultar=8, paleta de fondo CGB 0/color 0=16. Se descartan los bits desconocidos. El modo de color cero reutiliza scx/scy como bytes bajo/alto de RGB15.
Valor devuelto
No devuelve ningún valor. Esta entrada describe el estado afectado y cuándo surte efecto.
Condiciones y límites
La tabla compartida admite ocho entradas. Añadirlas no las aplica ni las ordena, y las que exceden la capacidad se ignoran. Reconstrúyela con reset→push→commit en un límite de fotograma seguro y separa los eventos lo suficiente para que el manejador termine. La latencia de la interrupción puede hacer que la línea programada y el primer píxel afectado no coincidan. Mostrar tiene prioridad si están activados ambos bits de visibilidad. El color cero es exclusivo de CGB; al combinarlo con el movimiento de BG, los mismos bytes scx/scy se usan para ambas operaciones. Esta función envuelve __scroll_split_push_ex.
Ejemplo de uso
Scroll_SplitPushEx(104,16,0,7,0,KQ_SCROLL_SPLIT_USE_BG|KQ_SCROLL_SPLIT_WIN_HIDE);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Usa las funciones envolventes Scroll para crear tres franjas de desplazamiento del fondo. Los eventos en LY=64 y 104 cambian X a 8 y 16, colocando los rectángulos de 24×16 en (32,16), (24,80) y (16,112). La imagen permite ver el desplazamiento de cada franja.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_split_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_split_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/scroll.h:87
Append an extended split with raw background/window fields and operation flags.
kitaqgb/lib/scroll.c:55
void Scroll_SplitPushEx(u8 ly, u8 scx, u8 scy, u8 wx, u8 wy, u8 flags)
{
__scroll_split_push_ex(ly, scx, scy, wx, wy, flags);
}Scroll_SplitReset
Pone a cero el número y el índice de las divisiones, desactiva su procesamiento y borra el bit de habilitación de la interrupción LYC en STAT.
Sintaxis
void Scroll_SplitReset();Valor devuelto
No devuelve ningún valor. Esta entrada describe el estado afectado y cuándo surte efecto.
Condiciones y límites
La tabla compartida admite ocho entradas. Añadirlas no las aplica ni las ordena, y las que exceden la capacidad se ignoran. Reconstrúyela con reset→push→commit en un límite de fotograma seguro y separa los eventos lo suficiente para que el manejador termine. La latencia de la interrupción puede hacer que la línea programada y el primer píxel afectado no coincidan. No borra los bytes de la tabla ni IE, ni desactiva las interrupciones de la CPU. Esta función envuelve __scroll_split_reset.
Ejemplo de uso
Scroll_SplitReset();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Usa las funciones envolventes Scroll para crear tres franjas de desplazamiento del fondo. Los eventos en LY=64 y 104 cambian X a 8 y 16, colocando los rectángulos de 24×16 en (32,16), (24,80) y (16,112). La imagen permite ver el desplazamiento de cada franja.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_split_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_split_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/scroll.h:82
Clear the pending split table before building a new raster configuration.
kitaqgb/lib/scroll.c:50
void Scroll_SplitReset() { __scroll_split_reset(); }Scroll_WindowAdd
Suma desplazamientos con signo a las coordenadas registradas de la ventana y los aplica de inmediato.
Sintaxis
void Scroll_WindowAdd(s8 dx, s8 dy);Parámetros
dxDesplazamiento horizontal con signo en píxeles, de −128 a 127.
dyDesplazamiento vertical con signo en píxeles, de −128 a 127.
Valor devuelto
No devuelve ningún valor. Esta entrada describe el estado afectado y cuándo surte efecto.
Condiciones y límites
No espera. Los ajustes y sumas inmediatos sincronizan el par de coordenadas pendiente afectado con los valores actuales y borran su indicador de modificación. Incluso ajustar de inmediato un solo eje cancela el otro eje pendiente del mismo par. Los resultados vuelven al inicio módulo 256. Las sumas parten de los valores actuales registrados, no de los pendientes ni de los valores temporales de los registros de raster. Esta función envuelve __scroll_win_add.
Ejemplo de uso
Scroll_WindowAdd(4,-40);result[24]=M_WX;result[25]=M_WY;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Usa las funciones Scroll para aprender actualización inmediata, preparación, aplicación, suma y visibilidad. Aplicar el búfer cambia BG X de 250 a 16 y WX de 23 a 39. El bit de ventana vale 32 tras mostrarla y 0 tras ocultarla.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_scroll_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_scroll_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kEjemplo de uso
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Con la cámara en (8,16), el rectángulo rojo de 32×24 aparece en pantalla en (24,16). La ventana muestra un marco azul de 64×64 en (96,80) y un cuadrado verde de 16×16 en (112,96). En DMG todas las figuras son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/scroll.h:75
Apply signed deltas to the byte-sized hardware window coordinates.
kitaqgb/lib/scroll.c:43
void Scroll_WindowAdd(s8 dx, s8 dy) { __scroll_win_add(dx, dy); }Scroll_WindowHide
Desactiva el bit de ventana de LCDC y el estado registrado de visibilidad de la ventana.
Sintaxis
void Scroll_WindowHide();Valor devuelto
No devuelve ningún valor. Esta entrada describe el estado afectado y cuándo surte efecto.
Condiciones y límites
No cambia las coordenadas ni la selección del mapa. Para que la ventana sea visible, el LCD y las funciones de fondo y ventana deben estar activados, y la ventana debe estar dentro del área visible. Esta función envuelve __scroll_win_hide.
Ejemplo de uso
Scroll_WindowHide();result[27]=M_LCDC&32;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Usa las funciones Scroll para aprender actualización inmediata, preparación, aplicación, suma y visibilidad. Aplicar el búfer cambia BG X de 250 a 16 y WX de 23 a 39. El bit de ventana vale 32 tras mostrarla y 0 tras ocultarla.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_scroll_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_scroll_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kEjemplo de uso
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Con la cámara en (8,16), el rectángulo rojo de 32×24 aparece en pantalla en (24,16). La ventana muestra un marco azul de 64×64 en (96,80) y un cuadrado verde de 16×16 en (112,96). En DMG todas las figuras son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/scroll.h:79
Request that the window be hidden through the compiler intrinsic.
kitaqgb/lib/scroll.c:47
void Scroll_WindowHide() { __scroll_win_hide(); }Scroll_WindowShow
Activa el bit de ventana de LCDC y el estado registrado de visibilidad de la ventana.
Sintaxis
void Scroll_WindowShow();Valor devuelto
No devuelve ningún valor. Esta entrada describe el estado afectado y cuándo surte efecto.
Condiciones y límites
No cambia las coordenadas ni la selección del mapa. Para que la ventana sea visible, el LCD y las funciones de fondo y ventana deben estar activados, y la ventana debe estar dentro del área visible. Esta función envuelve __scroll_win_show.
Ejemplo de uso
Scroll_WindowShow();result[26]=M_LCDC&32;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Usa las funciones Scroll para aprender actualización inmediata, preparación, aplicación, suma y visibilidad. Aplicar el búfer cambia BG X de 250 a 16 y WX de 23 a 39. El bit de ventana vale 32 tras mostrarla y 0 tras ocultarla.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_scroll_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_scroll_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kEjemplo de uso
Camera_Init(&view);
Camera_Set(&view,2048,4096);
Camera_ApplyBg(&view);
Scroll_SetWindow(103,80);
Scroll_WindowShow();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Con la cámara en (8,16), el rectángulo rojo de 32×24 aparece en pantalla en (24,16). La ventana muestra un marco azul de 64×64 en (96,80) y un cuadrado verde de 16×16 en (112,96). En DMG todas las figuras son negras.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/scroll.h:77
Request window visibility through the compiler intrinsic.
kitaqgb/lib/scroll.c:45
void Scroll_WindowShow() { __scroll_win_show(); }slg.h — Tableros, listas de jugadas y deshacer
Proporciona un tablero con valores de un byte, una lista de jugadas de capacidad limitada y una pila de registros para deshacer. El juego combina estas operaciones para aplicar jugadas o registros de deshacer al tablero.
slg_board_clear
Rellena todas las celdas del tablero con el valor indicado.
Sintaxis
void slg_board_clear(SLGBoard* board, u8 value);Parámetros
boardSLGBoardsobre el que operar; la inicialización requiere almacenamiento no NULL.valueValor de byte que se almacenará; el juego define su significado, como un tipo de pieza o de terreno.
Valor devuelto
No devuelve ningún valor. Esta entrada describe el estado afectado y cuándo surte efecto.
Condiciones y límites
El almacenamiento lo proporciona el código que llama. La inicialización no lo reserva ni lo borra. Las coordenadas del tablero se miden en celdas.
Ejemplo de uso
slg_board_clear(&board,0);result[1]=cells[0];result[2]=cells[11];Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo distingue las funciones del tablero, la lista de jugadas y los registros para deshacer. Inicializar el tablero conserva 9; un tercer añadido a una lista de dos posiciones devuelve 0. Extraer un registro no cambia el valor 8 del tablero; aplicarlo expresamente restaura 7.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_board.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_board.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/slg.h:33
Fill every cell with value; a null board is ignored. A valid board must own enough accessible cell storage for its declared dimensions.
kitaqgb/lib/slg_board.c:36
void slg_board_clear(SLGBoard* board, u8 value)
{
u16 total;
u16 i;
u8* p;
if (board == 0) return;
total = (u16)((u16)board->width * (u16)board->height);
i = 0;
p = board->cells;
while (i < total) {
*p = value;
p++;
i++;
}
}slg_board_get
Lee una celda; devuelve cero si el tablero es NULL o la coordenada está fuera de rango.
Sintaxis
u8 slg_board_get(const SLGBoard* board, u8 x, u8 y);Parámetros
boardSLGBoardsobre el que operar; la inicialización requiere almacenamiento no NULL.xColumna de la celda desde la izquierda, empezando en cero; registrar una jugada no comprueba los límites del tablero.
yFila de la celda desde arriba, empezando en cero; registrar una jugada no comprueba los límites del tablero.
Valor devuelto
Byte de la celda, o cero si la consulta no es válida. Cero por sí solo no distingue una celda vacía de una coordenada no válida.
Condiciones y límites
El almacenamiento lo proporciona el código que llama. La inicialización no lo reserva ni lo borra. Las coordenadas del tablero se miden en celdas.
Ejemplo de uso
result[3]=slg_board_get(&board,1,1);result[4]=slg_board_get(&board,4,1);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo distingue las funciones del tablero, la lista de jugadas y los registros para deshacer. Inicializar el tablero conserva 9; un tercer añadido a una lista de dos posiciones devuelve 0. Extraer un registro no cambia el valor 8 del tablero; aplicarlo expresamente restaura 7.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_board.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_board.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/slg.h:36
Return zero for a null board or out-of-range coordinate; otherwise read the cell. Zero therefore cannot distinguish an invalid lookup from an empty cell.
kitaqgb/lib/slg_board.c:54
u8 slg_board_get(const SLGBoard* board, u8 x, u8 y)
{
u8* p;
if (board == 0) return 0;
if (x >= board->width || y >= board->height) return 0;
p = slg_cell_ptr((SLGBoard*)board, x, y);
return *p;
}slg_board_init
Asocia las dimensiones de un tablero y un array de celdas, conservando su contenido.
Sintaxis
void slg_board_init(SLGBoard* board, u8 width, u8 height, u8* cells);Parámetros
boardSLGBoardsobre el que operar; la inicialización requiere almacenamiento no NULL.widthAncho del tablero en celdas; también es el paso entre filas.
heightNúmero de filas del tablero.
cellsArray accesible para escritura, ordenado por filas, de al menos
width*heightbytes de celdas.
Valor devuelto
No devuelve ningún valor. Esta entrada describe el estado afectado y cuándo surte efecto.
Condiciones y límites
El almacenamiento lo proporciona el código que llama. La inicialización no lo reserva ni lo borra. Las coordenadas del tablero se miden en celdas.
Ejemplo de uso
cells[0]=9;slg_board_init(&board,4,3,cells);result[0]=slg_board_get(&board,0,0);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo distingue las funciones del tablero, la lista de jugadas y los registros para deshacer. Inicializar el tablero conserva 9; un tercer añadido a una lista de dos posiciones devuelve 0. Extraer un registro no cambia el valor 8 del tablero; aplicarlo expresamente restaura 7.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_board.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_board.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/slg.h:30
Attach width * height bytes of caller-owned cell storage without clearing it.
kitaqgb/lib/slg_board.c:27
void slg_board_init(SLGBoard* board, u8 width, u8 height, u8* cells)
{
board->width = width;
board->height = height;
board->cells = cells;
}slg_board_set
Escribe en una celda válida del tablero; ignora un tablero NULL o una coordenada fuera de rango.
Sintaxis
void slg_board_set(SLGBoard* board, u8 x, u8 y, u8 value);Parámetros
boardSLGBoardsobre el que operar; la inicialización requiere almacenamiento no NULL.xColumna de la celda desde la izquierda, empezando en cero; registrar una jugada no comprueba los límites del tablero.
yFila de la celda desde arriba, empezando en cero; registrar una jugada no comprueba los límites del tablero.
valueValor de byte que se almacenará; el juego define su significado, como un tipo de pieza o de terreno.
Valor devuelto
No devuelve ningún valor. Esta entrada describe el estado afectado y cuándo surte efecto.
Condiciones y límites
El almacenamiento lo proporciona el código que llama. La inicialización no lo reserva ni lo borra. Las coordenadas del tablero se miden en celdas.
Ejemplo de uso
slg_board_set(&board,1,1,7);slg_board_set(&board,4,1,9);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo distingue las funciones del tablero, la lista de jugadas y los registros para deshacer. Inicializar el tablero conserva 9; un tercer añadido a una lista de dos posiciones devuelve 0. Extraer un registro no cambia el valor 8 del tablero; aplicarlo expresamente restaura 7.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_board.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_board.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/slg.h:38
Write a cell only when the board and coordinate are valid.
kitaqgb/lib/slg_board.c:64
void slg_board_set(SLGBoard* board, u8 x, u8 y, u8 value)
{
u8* p;
if (board == 0) return;
if (x >= board->width || y >= board->height) return;
p = slg_cell_ptr(board, x, y);
*p = value;
}slg_move_list_clear
Restablece el número de jugadas sin borrar los registros guardados.
Sintaxis
void slg_move_list_clear(SLGMoveList* list);Parámetros
listLista de jugadas sobre la que operar; la inicialización requiere un puntero no NULL.
Valor devuelto
No devuelve ningún valor. Esta entrada describe el estado afectado y cuándo surte efecto.
Condiciones y límites
El almacenamiento lo proporciona el código que llama. La inicialización no lo reserva ni lo borra. Las coordenadas del tablero se miden en celdas.
Ejemplo de uso
slg_move_list_clear(&moves);result[10]=moves.count;result[11]=move_data[0].value;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo distingue las funciones del tablero, la lista de jugadas y los registros para deshacer. Inicializar el tablero conserva 9; un tercer añadido a una lista de dos posiciones devuelve 0. Extraer un registro no cambia el valor 8 del tablero; aplicarlo expresamente restaura 7.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_board.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_board.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/slg.h:42
Forget the moves without erasing their storage; a null list is ignored.
kitaqgb/lib/slg_board.c:83
void slg_move_list_clear(SLGMoveList* list)
{
if (list == 0) return;
list->count = 0;
}slg_move_list_init
Asocia el almacenamiento de jugadas y su capacidad, y pone el contador a cero.
Sintaxis
void slg_move_list_init(SLGMoveList* list, SLGMove* items, u8 capacity);Parámetros
listLista de jugadas sobre la que operar; la inicialización requiere un puntero no NULL.
itemsArray propiedad del código que llama, con espacio para al menos
capacityregistrosSLGMove.capacityNúmero máximo de registros; cero no permite añadir ninguno. Cada registro contiene tres bytes: x, y y valor.
Valor devuelto
No devuelve ningún valor. Esta entrada describe el estado afectado y cuándo surte efecto.
Condiciones y límites
El almacenamiento lo proporciona el código que llama. La inicialización no lo reserva ni lo borra. Las coordenadas del tablero se miden en celdas.
Ejemplo de uso
slg_move_list_init(&moves,move_data,2);result[5]=moves.count;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo distingue las funciones del tablero, la lista de jugadas y los registros para deshacer. Inicializar el tablero conserva 9; un tercer añadido a una lista de dos posiciones devuelve 0. Extraer un registro no cambia el valor 8 del tablero; aplicarlo expresamente restaura 7.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_board.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_board.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/slg.h:40
Attach caller-owned move storage and reset the list length.
kitaqgb/lib/slg_board.c:75
void slg_move_list_init(SLGMoveList* list, SLGMove* items, u8 capacity)
{
list->items = items;
list->capacity = capacity;
list->count = 0;
}slg_move_list_push
Añade unas coordenadas y un valor a la lista de jugadas sin modificar el tablero.
Sintaxis
u8 slg_move_list_push(SLGMoveList* list, u8 x, u8 y, u8 value);Parámetros
listLista de jugadas sobre la que operar; la inicialización requiere un puntero no NULL.
xColumna de la celda desde la izquierda, empezando en cero; registrar una jugada no comprueba los límites del tablero.
yFila de la celda desde arriba, empezando en cero; registrar una jugada no comprueba los límites del tablero.
valueValor de byte que se almacenará; el juego define su significado, como un tipo de pieza o de terreno.
Valor devuelto
1 si se añade, 0 si es NULL o el almacenamiento está lleno; un fallo conserva el contador y los registros existentes.
Condiciones y límites
El almacenamiento lo proporciona el código que llama. La inicialización no lo reserva ni lo borra. Las coordenadas del tablero se miden en celdas.
Ejemplo de uso
result[6]=slg_move_list_push(&moves,1,1,7);result[7]=slg_move_list_push(&moves,2,1,8);result[8]=slg_move_list_push(&moves,3,1,9);result[9]=moves.count;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo distingue las funciones del tablero, la lista de jugadas y los registros para deshacer. Inicializar el tablero conserva 9; un tercer añadido a una lista de dos posiciones devuelve 0. Extraer un registro no cambia el valor 8 del tablero; aplicarlo expresamente restaura 7.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_board.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_board.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/slg.h:45
Append coordinates and a value to the bounded move list. Return zero on a null/full list without replacing any existing move.
kitaqgb/lib/slg_board.c:91
u8 slg_move_list_push(SLGMoveList* list, u8 x, u8 y, u8 value)
{
SLGMove* move;
if (list == 0) return 0;
if (list->count >= list->capacity) return 0;
move = &list->items[(__safe_index u8)list->count];
move->x = x;
move->y = y;
move->value = value;
list->count++;
return 1;
}slg_undo_init
Asocia el almacenamiento para deshacer y su capacidad, empezando con una pila vacía.
Sintaxis
void slg_undo_init(SLGUndoStack* stack, SLGMove* items, u8 capacity);Parámetros
stackPila para deshacer sobre la que operar; la inicialización requiere un puntero no NULL.
itemsArray propiedad del código que llama, con espacio para al menos
capacityregistrosSLGMove.capacityNúmero máximo de registros; cero no permite añadir ninguno. Cada registro contiene tres bytes: x, y y valor.
Valor devuelto
No devuelve ningún valor. Esta entrada describe el estado afectado y cuándo surte efecto.
Condiciones y límites
El almacenamiento lo proporciona el código que llama. La inicialización no lo reserva ni lo borra. Las coordenadas del tablero se miden en celdas.
Ejemplo de uso
slg_undo_init(&undo,undo_data,2);result[12]=undo.count;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo distingue las funciones del tablero, la lista de jugadas y los registros para deshacer. Inicializar el tablero conserva 9; un tercer añadido a una lista de dos posiciones devuelve 0. Extraer un registro no cambia el valor 8 del tablero; aplicarlo expresamente restaura 7.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_board.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_board.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/slg.h:47
Attach caller-owned undo records and initialize an empty stack.
kitaqgb/lib/slg_board.c:106
void slg_undo_init(SLGUndoStack* stack, SLGMove* items, u8 capacity)
{
stack->items = items;
stack->capacity = capacity;
stack->count = 0;
}slg_undo_pop
Extrae el registro más reciente para deshacer; el código que llama lo aplica al tablero.
Sintaxis
u8 slg_undo_pop(SLGUndoStack* stack, SLGMove* out_move);Parámetros
stackPila para deshacer sobre la que operar; la inicialización requiere un puntero no NULL.
out_moveDestino del registro extraído; NULL lo descarta sin copiarlo.
Valor devuelto
1 si se extrae un registro, 0 si la pila es NULL o está vacía; una pila vacía deja la salida intacta.
Condiciones y límites
El almacenamiento lo proporciona el código que llama. La inicialización no lo reserva ni lo borra. Las coordenadas del tablero se miden en celdas.
Ejemplo de uso
result[15]=slg_undo_pop(&undo,&old);result[16]=old.value;result[17]=slg_board_get(&board,1,1);slg_undo_pop(&undo,&old);slg_board_set(&board,old.x,old.y,old.value);result[18]=slg_board_get(&board,1,1);result[19]=slg_undo_pop(&undo,&old);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo distingue las funciones del tablero, la lista de jugadas y los registros para deshacer. Inicializar el tablero conserva 9; un tercer añadido a una lista de dos posiciones devuelve 0. Extraer un registro no cambia el valor 8 del tablero; aplicarlo expresamente restaura 7.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_board.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_board.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/slg.h:53
Remove the newest undo record and optionally copy it out. A null output still discards the record; a null or empty stack returns zero.
kitaqgb/lib/slg_board.c:128
u8 slg_undo_pop(SLGUndoStack* stack, SLGMove* out_move)
{
if (stack == 0) return 0;
if (stack->count == 0) return 0;
stack->count--;
if (out_move != 0) {
out_move->x = stack->items[stack->count].x;
out_move->y = stack->items[stack->count].y;
out_move->value = stack->items[stack->count].value;
}
return 1;
}slg_undo_push
Apila el valor anterior de una celda en la pila para deshacer sin modificar el tablero.
Sintaxis
u8 slg_undo_push(SLGUndoStack* stack, u8 x, u8 y, u8 old_value);Parámetros
stackPila para deshacer sobre la que operar; la inicialización requiere un puntero no NULL.
xColumna de la celda desde la izquierda, empezando en cero; registrar una jugada no comprueba los límites del tablero.
yFila de la celda desde arriba, empezando en cero; registrar una jugada no comprueba los límites del tablero.
old_valueValor de byte anterior de la celda; la función no lo lee automáticamente del tablero.
Valor devuelto
1 si se añade, 0 si es NULL o el almacenamiento está lleno; un fallo conserva el contador y los registros existentes.
Condiciones y límites
El almacenamiento lo proporciona el código que llama. La inicialización no lo reserva ni lo borra. Las coordenadas del tablero se miden en celdas.
Ejemplo de uso
result[13]=slg_undo_push(&undo,1,1,slg_board_get(&board,1,1));slg_board_set(&board,1,1,8);slg_undo_push(&undo,1,1,8);result[14]=slg_undo_push(&undo,0,0,9);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo distingue las funciones del tablero, la lista de jugadas y los registros para deshacer. Inicializar el tablero conserva 9; un tercer añadido a una lista de dos posiciones devuelve 0. Extraer un registro no cambia el valor 8 del tablero; aplicarlo expresamente restaura 7.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_board.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_board.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/slg.h:50
Record a cell's previous value for later undo. Return zero if the stack is null or full; this function does not change the board itself.
kitaqgb/lib/slg_board.c:115
u8 slg_undo_push(SLGUndoStack* stack, u8 x, u8 y, u8 old_value)
{
if (stack == 0) return 0;
if (stack->count >= stack->capacity) return 0;
stack->items[stack->count].x = x;
stack->items[stack->count].y = y;
stack->items[stack->count].value = old_value;
stack->count++;
return 1;
}sprite.h — Reserva y posición de OBJ, metasprites y animación
Los sprites son objetos móviles de hardware, normalmente de 8×8 u 8×16 píxeles, descritos en OAM, la memoria de atributos de objetos. Reserva entradas, configura posición, patrón y atributos en la copia de OAM y transfiérela. Un metasprite reúne varias entradas en un objeto. GB ofrece 40 entradas y un máximo de 10 por línea; FC, 64 y un máximo de 8 por línea.
Atributos GB: bit 4 elige OBP1 en DMG; 5/6 reflejan X/Y; 7 coloca el sprite detrás de píxeles de fondo con índice distinto de cero. En CGB, 0..2 eligen la paleta de objetos y 3 el banco VRAM de patrones; el bit de paleta DMG no selecciona colores nativos CGB.
El ejemplo usa la biblioteca GB completa. KQ_SPRITE_MINIMAL_RUNTIME excluye de sprite.c sprite_free, sprite_set_pos, sprite_count_used, las dos consultas de líneas, metasprite_draw y anim_update. No lo definas si utilizas esas funciones.
anim_update
Avanza el temporizador SpriteAnim y devuelve el patrón seleccionado. Cada ticks_per_frame llamadas pasa al siguiente patrón consecutivo y vuelve al primero tras frame_count fotogramas. Aplica el resultado con sprite_set_tile.
Sintaxis
u8 anim_update(SpriteAnim* anim);Parámetros
animEstado SpriteAnim modificable con first_tile, frame_count, frame, ticks y ticks_per_frame. Cuando los límites no sean cero, mantén frame por debajo de frame_count y ticks por debajo de ticks_per_frame.
Valor devuelto
Número de patrón de 8 bits; 0 si el puntero de estado es nulo. No escribe en OAM.
Condiciones y límites
frame_count=0 devuelve first_tile sin avanzar; ticks_per_frame=0 congela el fotograma actual. El temporizador cuenta llamadas, no fotogramas de vídeo. Los patrones vuelven a cero tras 255 y avanzan de uno en uno incluso en modo 8×16.
El ejemplo usa la biblioteca GB completa. KQ_SPRITE_MINIMAL_RUNTIME excluye de sprite.c sprite_free, sprite_set_pos, sprite_count_used, las dos consultas de líneas, metasprite_draw y anim_update. No lo definas si utilizas esas funciones.
Ejemplo de uso
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);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Con first_tile=128, dos fotogramas y dos llamadas por fotograma, la primera actualización devuelve la flecha 128 y la segunda el cuadrado 129. El cuadrado junto a ANIMATION demuestra que el resultado se aplicó a OAM.
El programa enseña asignación, posición, reflejos, objetos compuestos, solapamiento, animación y límite por línea. Las dos cifras de arriba a la derecha deben ser 00: todas las comprobaciones internas pasaron. Cada flecha y cuadrado ocupa un patrón de 8×8.
NORMAL muestra una flecha a la derecha en (88,16). FLIP X apunta a la izquierda en (88,32); FLIP Y invierte verticalmente la flecha en (88,48). META coloca dos flechas en (88,64) y (96,64). OVERLAP sitúa la flecha de (88,80) delante del cuadrado de (92,80), visible por los píxeles transparentes. ANIMATION muestra el cuadrado en (88,96). Las zonas (120,16) y (120,32) quedan vacías al ocultar y liberar sus entradas.
En CGB y FC la flecha tiene asta verde, contorno rojo y detalles azules en la punta; el cuadrado es verde. La transparencia deja ver el fondo blanco de GB o negro de FC. DMG sustituye rojo, verde y azul por gris claro, gris oscuro y negro.
La fila bajo SCAN LIMIT comienza en (8,128). Se envían 11 sprites en GB o 9 en FC, uno de más a propósito. Deben verse 10 flechas en GB y 8 en FC; la última enviada no aparece. Las comprobaciones del máximo de software y del aviso deben dar 11/9 y 1.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/sprite.h:86
Advance animation ticks/frame with wrapping frame selection and return the resulting tile. Zero ticks-per-frame freezes animation; null state returns zero.
kitaqgb/lib/sprite.c:211
u8 anim_update(SpriteAnim* anim)
{
if (anim == 0) return 0;
if (anim->frame_count == 0) return anim->first_tile;
if (anim->ticks_per_frame == 0) return (u8)(anim->first_tile + anim->frame);
anim->ticks++;
if (anim->ticks >= anim->ticks_per_frame) {
anim->ticks = 0;
anim->frame++;
if (anim->frame >= anim->frame_count) anim->frame = 0;
}
return (u8)(anim->first_tile + anim->frame);
}metasprite_draw
Consulte los cambios y la verificación del 2026-10-03 para las diferencias locales de esta API.
Coloca un array de partes de sprite en entradas consecutivas. Cada parte aporta desplazamientos con signo, patrón y atributos. Activa las entradas libres, sobrescribe las activas y se detiene en el límite de entradas.
Sintaxis
u8 metasprite_draw(u8 first_id, u8 x, u8 y, const MetaSpritePart* parts, u8 count);Parámetros
first_idID de entrada entre 0 y SPRITE_MAX-1; por defecto, 0..39 en GB y 0..63 en FC. Se ignoran los ID fuera de rango.
xPosición horizontal en píxeles, expresada como byte sin signo; no es una coordenada de patrón.
yCoordenada Y de pantalla en píxeles. La función de GB suma 16 antes de guardarla en OAM.
partsArray legible de al menos count registros MetaSpritePart. Cada registro de cuatro bytes contiene dx/dy con signo, patrón y atributos; no lleva terminador.
countNúmero de partes como byte sin signo. Cero no escribe nada. Si las entradas consecutivas alcanzan SPRITE_MAX, solo se escriben las partes que caben.
Valor devuelto
Número de partes escritas, entre 0 y count. Comprueba el resultado para detectar un recorte por falta de entradas.
Condiciones y límites
Las operaciones de posición, patrón, atributos y ocultación modifican la copia de trabajo. No reservan entradas ni actualizan OAM inmediatamente; transfiere el fotograma terminado con sprite_flush_oam.
Los desplazamientos son bytes con signo sumados al origen y reducidos a ocho bits. El array debe ser legible durante toda la llamada. Se sobrescriben las entradas activas; no se protegen las de otros objetos.
El ejemplo usa la biblioteca GB completa. KQ_SPRITE_MINIMAL_RUNTIME excluye de sprite.c sprite_free, sprite_set_pos, sprite_count_used, las dos consultas de líneas, metasprite_draw y anim_update. No lo definas si utilizas esas funciones.
Ejemplo de uso
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.Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La inicialización deja cero reservas. Ocho asignaciones devuelven 0..7. Ocultar la entrada 6 mantiene 8; liberar dos veces la 7 deja 7. Colocar el par en 10 y 11 eleva el total a 9.
El programa enseña asignación, posición, reflejos, objetos compuestos, solapamiento, animación y límite por línea. Las dos cifras de arriba a la derecha deben ser 00: todas las comprobaciones internas pasaron. Cada flecha y cuadrado ocupa un patrón de 8×8.
NORMAL muestra una flecha a la derecha en (88,16). FLIP X apunta a la izquierda en (88,32); FLIP Y invierte verticalmente la flecha en (88,48). META coloca dos flechas en (88,64) y (96,64). OVERLAP sitúa la flecha de (88,80) delante del cuadrado de (92,80), visible por los píxeles transparentes. ANIMATION muestra el cuadrado en (88,96). Las zonas (120,16) y (120,32) quedan vacías al ocultar y liberar sus entradas.
En CGB y FC la flecha tiene asta verde, contorno rojo y detalles azules en la punta; el cuadrado es verde. La transparencia deja ver el fondo blanco de GB o negro de FC. DMG sustituye rojo, verde y azul por gris claro, gris oscuro y negro.
La fila bajo SCAN LIMIT comienza en (8,128). Se envían 11 sprites en GB o 9 en FC, uno de más a propósito. Deben verse 10 flechas en GB y 8 en FC; la última enviada no aparece. Las comprobaciones del máximo de software y del aviso deben dar 11/9 y 1.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/sprite.h:83
Place consecutive parts, counting each newly activated slot once. Existing active slots are overwritten without increasing the allocation count. Return the number written; an invalid first slot or zero count writes nothing.
kitaqgb/lib/sprite.c:191
u8 metasprite_draw(u8 first_id, u8 x, u8 y, const MetaSpritePart* parts, u8 count)
{
u8 i = 0;
while (i < count) {
u8 id = (u8)(first_id + i);
if (id >= SPRITE_MAX) return i;
if (kq_sprite_active[id] == 0) {
kq_sprite_active[id] = 1;
kq_sprite_used = (u8)(kq_sprite_used + 1);
}
sprite_set_pos(id, (u8)(x + parts[i].dx), (u8)(y + parts[i].dy));
sprite_set_tile(id, parts[i].tile);
sprite_set_flags(id, parts[i].flags);
i++;
}
return count;
}sprite_alloc
Reserva la primera entrada libre y la oculta hasta que le asignes una posición. Ocultarla no libera la reserva; configura su patrón y atributos antes de mostrarla.
Sintaxis
u8 sprite_alloc();Valor devuelto
ID de la entrada reservada, o 0xFF si todas están activas.
Condiciones y límites
Las operaciones de posición, patrón, atributos y ocultación modifican la copia de trabajo. No reservan entradas ni actualizan OAM inmediatamente; transfiere el fotograma terminado con sprite_flush_oam.
El ejemplo usa la biblioteca GB completa. KQ_SPRITE_MINIMAL_RUNTIME excluye de sprite.c sprite_free, sprite_set_pos, sprite_count_used, las dos consultas de líneas, metasprite_draw y anim_update. No lo definas si utilizas esas funciones.
Ejemplo de uso
for(i=0;i<8;i++) sprite_example_expect(sprite_alloc()==i);
sprite_example_expect(sprite_count_used()==8);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La inicialización deja cero reservas. Ocho asignaciones devuelven 0..7. Ocultar la entrada 6 mantiene 8; liberar dos veces la 7 deja 7. Colocar el par en 10 y 11 eleva el total a 9.
El programa enseña asignación, posición, reflejos, objetos compuestos, solapamiento, animación y límite por línea. Las dos cifras de arriba a la derecha deben ser 00: todas las comprobaciones internas pasaron. Cada flecha y cuadrado ocupa un patrón de 8×8.
NORMAL muestra una flecha a la derecha en (88,16). FLIP X apunta a la izquierda en (88,32); FLIP Y invierte verticalmente la flecha en (88,48). META coloca dos flechas en (88,64) y (96,64). OVERLAP sitúa la flecha de (88,80) delante del cuadrado de (92,80), visible por los píxeles transparentes. ANIMATION muestra el cuadrado en (88,96). Las zonas (120,16) y (120,32) quedan vacías al ocultar y liberar sus entradas.
En CGB y FC la flecha tiene asta verde, contorno rojo y detalles azules en la punta; el cuadrado es verde. La transparencia deja ver el fondo blanco de GB o negro de FC. DMG sustituye rojo, verde y azul por gris claro, gris oscuro y negro.
La fila bajo SCAN LIMIT comienza en (8,128). Se envían 11 sprites en GB o 9 en FC, uno de más a propósito. Deben verse 10 flechas en GB y 8 en FC; la última enviada no aparece. Las comprobaciones del máximo de software y del aviso deben dar 11/9 y 1.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/sprite.h:53
Claim the first free slot, hide it, and return its ID; return 0xFF when full. Previously stored tile/flag bytes are retained until the caller replaces them.
kitaqgb/lib/sprite.c:60
u8 sprite_alloc()
{
u8 i = 0;
while (i < SPRITE_MAX) {
if (kq_sprite_active[i] == 0) {
kq_sprite_active[i] = 1;
kq_sprite_used++;
sprite_hide(i);
return i;
}
i++;
}
return 0xFF;
}sprite_count_used
Devuelve el número de entradas reservadas, incluidas las ocultas y las activadas por metasprite_draw. Cuenta reservas, no sprites visibles.
Sintaxis
u8 sprite_count_used();Valor devuelto
Byte sin signo entre 0 y SPRITE_MAX.
Condiciones y límites
El ejemplo usa la biblioteca GB completa. KQ_SPRITE_MINIMAL_RUNTIME excluye de sprite.c sprite_free, sprite_set_pos, sprite_count_used, las dos consultas de líneas, metasprite_draw y anim_update. No lo definas si utilizas esas funciones.
Ejemplo de uso
sprite_example_expect(sprite_count_used()==9); // After hiding, freeing and drawing the pair.Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La inicialización deja cero reservas. Ocho asignaciones devuelven 0..7. Ocultar la entrada 6 mantiene 8; liberar dos veces la 7 deja 7. Colocar el par en 10 y 11 eleva el total a 9.
El programa enseña asignación, posición, reflejos, objetos compuestos, solapamiento, animación y límite por línea. Las dos cifras de arriba a la derecha deben ser 00: todas las comprobaciones internas pasaron. Cada flecha y cuadrado ocupa un patrón de 8×8.
NORMAL muestra una flecha a la derecha en (88,16). FLIP X apunta a la izquierda en (88,32); FLIP Y invierte verticalmente la flecha en (88,48). META coloca dos flechas en (88,64) y (96,64). OVERLAP sitúa la flecha de (88,80) delante del cuadrado de (92,80), visible por los píxeles transparentes. ANIMATION muestra el cuadrado en (88,96). Las zonas (120,16) y (120,32) quedan vacías al ocultar y liberar sus entradas.
En CGB y FC la flecha tiene asta verde, contorno rojo y detalles azules en la punta; el cuadrado es verde. La transparencia deja ver el fondo blanco de GB o negro de FC. DMG sustituye rojo, verde y azul por gris claro, gris oscuro y negro.
La fila bajo SCAN LIMIT comienza en (8,128). Se envían 11 sprites en GB o 9 en FC, uno de más a propósito. Deben verse 10 flechas en GB y 8 en FC; la última enviada no aparece. Las comprobaciones del máximo de software y del aviso deben dar 11/9 y 1.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/sprite.h:73
Return the number of active slots, including slots activated by metasprite_draw. Hidden allocated slots remain active until sprite_free releases them.
kitaqgb/lib/sprite.c:148
u8 sprite_count_used()
{
return kq_sprite_used;
}sprite_flush_oam
Espera VBlank y transfiere la copia de OAM mediante sprite_flush_oam_now.
Sintaxis
void sprite_flush_oam();Valor devuelto
Ninguno (void).
Condiciones y límites
La rutina GB ejecuta DMA desde HRAM y copia 160 bytes de la OAM alineada. Deshabilita interrupciones durante el traslado y siempre las habilita al terminar; no restaura un estado previo deshabilitado.
El ejemplo usa la biblioteca GB completa. KQ_SPRITE_MINIMAL_RUNTIME excluye de sprite.c sprite_free, sprite_set_pos, sprite_count_used, las dos consultas de líneas, metasprite_draw y anim_update. No lo definas si utilizas esas funciones.
Ejemplo de uso
while(1) { sprite_flush_oam(); } // Transfer prepared sprites at the next frame boundary.Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
NORMAL muestra una flecha a la derecha en (88,16). FLIP X apunta a la izquierda en (88,32); FLIP Y invierte verticalmente la flecha en (88,48). META coloca dos flechas en (88,64) y (96,64). OVERLAP sitúa la flecha de (88,80) delante del cuadrado de (92,80), visible por los píxeles transparentes. ANIMATION muestra el cuadrado en (88,96). Las zonas (120,16) y (120,32) quedan vacías al ocultar y liberar sus entradas.
El programa enseña asignación, posición, reflejos, objetos compuestos, solapamiento, animación y límite por línea. Las dos cifras de arriba a la derecha deben ser 00: todas las comprobaciones internas pasaron. Cada flecha y cuadrado ocupa un patrón de 8×8.
En CGB y FC la flecha tiene asta verde, contorno rojo y detalles azules en la punta; el cuadrado es verde. La transparencia deja ver el fondo blanco de GB o negro de FC. DMG sustituye rojo, verde y azul por gris claro, gris oscuro y negro.
La fila bajo SCAN LIMIT comienza en (8,128). Se envían 11 sprites en GB o 9 en FC, uno de más a propósito. Deben verse 10 flechas en GB y 8 en FC; la última enviada no aparece. Las comprobaciones del máximo de software y del aviso deben dar 11/9 y 1.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/sprite.h:70
Wait for VBlank, then transfer shadow OAM using the immediate DMA routine.
kitaqgb/lib/sprite.c:139
void sprite_flush_oam()
{
__wait_vblank();
sprite_flush_oam_now();
}sprite_flush_oam_now
Transfiere inmediatamente la copia de OAM al hardware. No espera un intervalo de vídeo seguro; quien llama decide cuándo ejecutarla.
Sintaxis
void sprite_flush_oam_now();Valor devuelto
Ninguno (void).
Condiciones y límites
La rutina GB ejecuta DMA desde HRAM y copia 160 bytes de la OAM alineada. Deshabilita interrupciones durante el traslado y siempre las habilita al terminar; no restaura un estado previo deshabilitado.
El ejemplo usa la biblioteca GB completa. KQ_SPRITE_MINIMAL_RUNTIME excluye de sprite.c sprite_free, sprite_set_pos, sprite_count_used, las dos consultas de líneas, metasprite_draw y anim_update. No lo definas si utilizas esas funciones.
Ejemplo de uso
// Rendering is disabled here; all shadow entries have been prepared.
sprite_flush_oam_now();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
NORMAL muestra una flecha a la derecha en (88,16). FLIP X apunta a la izquierda en (88,32); FLIP Y invierte verticalmente la flecha en (88,48). META coloca dos flechas en (88,64) y (96,64). OVERLAP sitúa la flecha de (88,80) delante del cuadrado de (92,80), visible por los píxeles transparentes. ANIMATION muestra el cuadrado en (88,96). Las zonas (120,16) y (120,32) quedan vacías al ocultar y liberar sus entradas.
El programa enseña asignación, posición, reflejos, objetos compuestos, solapamiento, animación y límite por línea. Las dos cifras de arriba a la derecha deben ser 00: todas las comprobaciones internas pasaron. Cada flecha y cuadrado ocupa un patrón de 8×8.
En CGB y FC la flecha tiene asta verde, contorno rojo y detalles azules en la punta; el cuadrado es verde. La transparencia deja ver el fondo blanco de GB o negro de FC. DMG sustituye rojo, verde y azul por gris claro, gris oscuro y negro.
La fila bajo SCAN LIMIT comienza en (8,128). Se envían 11 sprites en GB o 9 en FC, uno de más a propósito. Deben verse 10 flechas en GB y 8 en FC; la última enviada no aparece. Las comprobaciones del máximo de software y del aviso deben dar 11/9 y 1.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/sprite.h:68
Install the HRAM stub lazily and execute OAM DMA with interrupts disabled. This routine does not wait for VBlank and always enables interrupts afterward; it does not restore the caller's previous interrupt-enable state.
kitaqgb/lib/sprite.c:122
void sprite_flush_oam_now()
{
SpriteDmaRoutine dma;
if (kq_sprite_dma_ready == 0) {
sprite_install_dma_stub();
}
dma = (SpriteDmaRoutine)kq_sprite_dma_stub;
__asm {
DI
}
dma();
__asm {
EI
}
}sprite_free
Libera una entrada reservada, la oculta y reduce en uno el número de entradas activas. Un ID fuera de rango o una entrada ya libre no produce cambios.
Sintaxis
void sprite_free(u8 id);Parámetros
idID de entrada entre 0 y SPRITE_MAX-1; por defecto, 0..39 en GB y 0..63 en FC. Se ignoran los ID fuera de rango.
Valor devuelto
Ninguno (void).
Condiciones y límites
Las operaciones de posición, patrón, atributos y ocultación modifican la copia de trabajo. No reservan entradas ni actualizan OAM inmediatamente; transfiere el fotograma terminado con sprite_flush_oam.
El ejemplo usa la biblioteca GB completa. KQ_SPRITE_MINIMAL_RUNTIME excluye de sprite.c sprite_free, sprite_set_pos, sprite_count_used, las dos consultas de líneas, metasprite_draw y anim_update. No lo definas si utilizas esas funciones.
Ejemplo de uso
sprite_free(7);sprite_free(7);
sprite_example_expect(sprite_count_used()==7); // Repeated release is ignored.Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La inicialización deja cero reservas. Ocho asignaciones devuelven 0..7. Ocultar la entrada 6 mantiene 8; liberar dos veces la 7 deja 7. Colocar el par en 10 y 11 eleva el total a 9.
El programa enseña asignación, posición, reflejos, objetos compuestos, solapamiento, animación y límite por línea. Las dos cifras de arriba a la derecha deben ser 00: todas las comprobaciones internas pasaron. Cada flecha y cuadrado ocupa un patrón de 8×8.
NORMAL muestra una flecha a la derecha en (88,16). FLIP X apunta a la izquierda en (88,32); FLIP Y invierte verticalmente la flecha en (88,48). META coloca dos flechas en (88,64) y (96,64). OVERLAP sitúa la flecha de (88,80) delante del cuadrado de (92,80), visible por los píxeles transparentes. ANIMATION muestra el cuadrado en (88,96). Las zonas (120,16) y (120,32) quedan vacías al ocultar y liberar sus entradas.
En CGB y FC la flecha tiene asta verde, contorno rojo y detalles azules en la punta; el cuadrado es verde. La transparencia deja ver el fondo blanco de GB o negro de FC. DMG sustituye rojo, verde y azul por gris claro, gris oscuro y negro.
La fila bajo SCAN LIMIT comienza en (8,128). Se envían 11 sprites en GB o 9 en FC, uno de más a propósito. Deben verse 10 flechas en GB y 8 en FC; la última enviada no aparece. Las comprobaciones del máximo de software y del aviso deben dar 11/9 y 1.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/sprite.h:55
Release an allocated valid slot and hide it. Repeated frees do not decrement the count.
kitaqgb/lib/sprite.c:78
void sprite_free(u8 id)
{
if (sprite_valid(id) == 0) return;
if (kq_sprite_active[id] == 0) return;
kq_sprite_active[id] = 0;
if (kq_sprite_used != 0) kq_sprite_used--;
sprite_hide(id);
}sprite_hide
Oculta un sprite cambiando su posición en la copia de OAM. Conserva la reserva, el patrón y los atributos; basta con darle una posición visible para mostrarlo de nuevo.
Sintaxis
void sprite_hide(u8 id);Parámetros
idID de entrada entre 0 y SPRITE_MAX-1; por defecto, 0..39 en GB y 0..63 en FC. Se ignoran los ID fuera de rango.
Valor devuelto
Ninguno (void).
Condiciones y límites
Las operaciones de posición, patrón, atributos y ocultación modifican la copia de trabajo. No reservan entradas ni actualizan OAM inmediatamente; transfiere el fotograma terminado con sprite_flush_oam.
El ejemplo usa la biblioteca GB completa. KQ_SPRITE_MINIMAL_RUNTIME excluye de sprite.c sprite_free, sprite_set_pos, sprite_count_used, las dos consultas de líneas, metasprite_draw y anim_update. No lo definas si utilizas esas funciones.
Ejemplo de uso
sprite_hide(6);
sprite_example_expect(sprite_count_used()==8); // Hiding retains allocation.Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La inicialización deja cero reservas. Ocho asignaciones devuelven 0..7. Ocultar la entrada 6 mantiene 8; liberar dos veces la 7 deja 7. Colocar el par en 10 y 11 eleva el total a 9.
El programa enseña asignación, posición, reflejos, objetos compuestos, solapamiento, animación y límite por línea. Las dos cifras de arriba a la derecha deben ser 00: todas las comprobaciones internas pasaron. Cada flecha y cuadrado ocupa un patrón de 8×8.
NORMAL muestra una flecha a la derecha en (88,16). FLIP X apunta a la izquierda en (88,32); FLIP Y invierte verticalmente la flecha en (88,48). META coloca dos flechas en (88,64) y (96,64). OVERLAP sitúa la flecha de (88,80) delante del cuadrado de (92,80), visible por los píxeles transparentes. ANIMATION muestra el cuadrado en (88,96). Las zonas (120,16) y (120,32) quedan vacías al ocultar y liberar sus entradas.
En CGB y FC la flecha tiene asta verde, contorno rojo y detalles azules en la punta; el cuadrado es verde. La transparencia deja ver el fondo blanco de GB o negro de FC. DMG sustituye rojo, verde y azul por gris claro, gris oscuro y negro.
La fila bajo SCAN LIMIT comienza en (8,128). Se envían 11 sprites en GB o 9 en FC, uno de más a propósito. Deben verse 10 flechas en GB y 8 en FC; la última enviada no aparece. Las comprobaciones del máximo de software y del aviso deben dar 11/9 y 1.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/sprite.h:64
Move a valid shadow slot off screen without freeing it.
kitaqgb/lib/sprite.c:112
void sprite_hide(u8 id)
{
if (sprite_valid(id) == 0) return;
kq_sprite_oam[id].y = 0;
kq_sprite_oam[id].x = 0;
}sprite_init
Reinicia la asignación de sprites y oculta todas las entradas en la copia de OAM. La altura de software pasa a 8 píxeles; el tamaño de hardware y la transferencia a OAM se configuran por separado.
Sintaxis
void sprite_init();Valor devuelto
Ninguno (void).
Condiciones y límites
En GB se borran los cuatro bytes de cada entrada y se reinicia la instalación de la rutina DMA en HRAM. Conserva SPRITE_MAX=40 salvo que tu fuente DMA personalizada proporcione los 160 bytes completos.
El ejemplo usa la biblioteca GB completa. KQ_SPRITE_MINIMAL_RUNTIME excluye de sprite.c sprite_free, sprite_set_pos, sprite_count_used, las dos consultas de líneas, metasprite_draw y anim_update. No lo definas si utilizas esas funciones.
Ejemplo de uso
sprite_init();
sprite_example_expect(sprite_count_used()==0);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La inicialización deja cero reservas. Ocho asignaciones devuelven 0..7. Ocultar la entrada 6 mantiene 8; liberar dos veces la 7 deja 7. Colocar el par en 10 y 11 eleva el total a 9.
El programa enseña asignación, posición, reflejos, objetos compuestos, solapamiento, animación y límite por línea. Las dos cifras de arriba a la derecha deben ser 00: todas las comprobaciones internas pasaron. Cada flecha y cuadrado ocupa un patrón de 8×8.
NORMAL muestra una flecha a la derecha en (88,16). FLIP X apunta a la izquierda en (88,32); FLIP Y invierte verticalmente la flecha en (88,48). META coloca dos flechas en (88,64) y (96,64). OVERLAP sitúa la flecha de (88,80) delante del cuadrado de (92,80), visible por los píxeles transparentes. ANIMATION muestra el cuadrado en (88,96). Las zonas (120,16) y (120,32) quedan vacías al ocultar y liberar sus entradas.
En CGB y FC la flecha tiene asta verde, contorno rojo y detalles azules en la punta; el cuadrado es verde. La transparencia deja ver el fondo blanco de GB o negro de FC. DMG sustituye rojo, verde y azul por gris claro, gris oscuro y negro.
La fila bajo SCAN LIMIT comienza en (8,128). Se envían 11 sprites en GB o 9 en FC, uno de más a propósito. Deben verse 10 flechas en GB y 8 en FC; la última enviada no aparece. Las comprobaciones del máximo de software y del aviso deben dar 11/9 y 1.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/sprite.h:50
Clear allocation and shadow OAM state and reset the DMA-stub installation flag. The default height is eight pixels; the hardware display mode is configured elsewhere.
kitaqgb/lib/sprite.c:22
void sprite_init()
{
u8 i = 0;
kq_sprite_used = 0;
kq_sprite_height = 8;
kq_sprite_dma_ready = 0;
while (i < SPRITE_MAX) {
kq_sprite_active[i] = 0;
kq_sprite_oam[i].y = 0;
kq_sprite_oam[i].x = 0;
kq_sprite_oam[i].tile = 0;
kq_sprite_oam[i].flags = 0;
i++;
}
}sprite_max_scanline_count
Estima el máximo de sprites activos que coinciden en una línea visible a partir de las posiciones verticales registradas y kq_sprite_height.
Sintaxis
u8 sprite_max_scanline_count();Valor devuelto
Byte sin signo entre 0 y SPRITE_MAX.
Condiciones y límites
Ajusta kq_sprite_height a la altura de hardware, 8 o 16. La estimación ignora transparencia, visibilidad horizontal y prioridad. FC lee las coordenadas de la biblioteca; los cambios directos mediante intrínsecas OAM no se reflejan.
El ejemplo usa la biblioteca GB completa. KQ_SPRITE_MINIMAL_RUNTIME excluye de sprite.c sprite_free, sprite_set_pos, sprite_count_used, las dos consultas de líneas, metasprite_draw y anim_update. No lo definas si utilizas esas funciones.
Ejemplo de uso
sprite_example_expect(sprite_max_scanline_count()==SPRITE_EXAMPLE_LINE_COUNT);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La fila bajo SCAN LIMIT comienza en (8,128). Se envían 11 sprites en GB o 9 en FC, uno de más a propósito. Deben verse 10 flechas en GB y 8 en FC; la última enviada no aparece. Las comprobaciones del máximo de software y del aviso deben dar 11/9 y 1.
El programa enseña asignación, posición, reflejos, objetos compuestos, solapamiento, animación y límite por línea. Las dos cifras de arriba a la derecha deben ser 00: todas las comprobaciones internas pasaron. Cada flecha y cuadrado ocupa un patrón de 8×8.
NORMAL muestra una flecha a la derecha en (88,16). FLIP X apunta a la izquierda en (88,32); FLIP Y invierte verticalmente la flecha en (88,48). META coloca dos flechas en (88,64) y (96,64). OVERLAP sitúa la flecha de (88,80) delante del cuadrado de (92,80), visible por los píxeles transparentes. ANIMATION muestra el cuadrado en (88,96). Las zonas (120,16) y (120,32) quedan vacías al ocultar y liberar sus entradas.
En CGB y FC la flecha tiene asta verde, contorno rojo y detalles azules en la punta; el cuadrado es verde. La transparencia deja ver el fondo blanco de GB o negro de FC. DMG sustituye rojo, verde y azul por gris claro, gris oscuro y negro.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/sprite.h:79
Estimate the largest overlap of active, non-hidden shadow sprites across visible scanlines using the configured sprite height. This is a software overlap count, not a rendered-pixel or hardware-priority simulation.
kitaqgb/lib/sprite.c:158
u8 sprite_max_scanline_count()
{
u8 line = 0;
u8 best = 0;
while (line < 144) {
u8 i = 0;
u8 count = 0;
u8 ly_oam = (u8)(line + 16);
while (i < SPRITE_MAX) {
u8 sy = kq_sprite_oam[i].y;
if (kq_sprite_active[i] != 0 && sy != 0) {
if (ly_oam >= sy && ly_oam < (u8)(sy + kq_sprite_height)) {
count++;
}
}
i++;
}
if (count > best) best = count;
line++;
}
return best;
}sprite_set_flags
Sustituye todo el byte de atributos. Combina las constantes de la plataforma para elegir reflejos, paleta y prioridad respecto al fondo; los bits no indicados quedan a cero.
Sintaxis
void sprite_set_flags(u8 id, u8 flags);Parámetros
idID de entrada entre 0 y SPRITE_MAX-1; por defecto, 0..39 en GB y 0..63 en FC. Se ignoran los ID fuera de rango.
flagsByte completo de atributos, formado con las constantes SPRITE_FLAG_* de la plataforma. Combina las banderas con OR bit a bit (|).
Valor devuelto
Ninguno (void).
Condiciones y límites
Las operaciones de posición, patrón, atributos y ocultación modifican la copia de trabajo. No reservan entradas ni actualizan OAM inmediatamente; transfiere el fotograma terminado con sprite_flush_oam.
Atributos GB: bit 4 elige OBP1 en DMG; 5/6 reflejan X/Y; 7 coloca el sprite detrás de píxeles de fondo con índice distinto de cero. En CGB, 0..2 eligen la paleta de objetos y 3 el banco VRAM de patrones; el bit de paleta DMG no selecciona colores nativos CGB.
El ejemplo usa la biblioteca GB completa. KQ_SPRITE_MINIMAL_RUNTIME excluye de sprite.c sprite_free, sprite_set_pos, sprite_count_used, las dos consultas de líneas, metasprite_draw y anim_update. No lo definas si utilizas esas funciones.
Ejemplo de uso
sprite_set_flags(1,SPRITE_FLAG_XFLIP);
sprite_set_flags(2,SPRITE_FLAG_YFLIP);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
NORMAL muestra una flecha a la derecha en (88,16). FLIP X apunta a la izquierda en (88,32); FLIP Y invierte verticalmente la flecha en (88,48). META coloca dos flechas en (88,64) y (96,64). OVERLAP sitúa la flecha de (88,80) delante del cuadrado de (92,80), visible por los píxeles transparentes. ANIMATION muestra el cuadrado en (88,96). Las zonas (120,16) y (120,32) quedan vacías al ocultar y liberar sus entradas.
El programa enseña asignación, posición, reflejos, objetos compuestos, solapamiento, animación y límite por línea. Las dos cifras de arriba a la derecha deben ser 00: todas las comprobaciones internas pasaron. Cada flecha y cuadrado ocupa un patrón de 8×8.
En CGB y FC la flecha tiene asta verde, contorno rojo y detalles azules en la punta; el cuadrado es verde. La transparencia deja ver el fondo blanco de GB o negro de FC. DMG sustituye rojo, verde y azul por gris claro, gris oscuro y negro.
La fila bajo SCAN LIMIT comienza en (8,128). Se envían 11 sprites en GB o 9 en FC, uno de más a propósito. Deben verse 10 flechas en GB y 8 en FC; la última enviada no aparece. Las comprobaciones del máximo de software y del aviso deben dar 11/9 y 1.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/sprite.h:62
Replace a valid shadow slot's complete hardware attribute byte.
kitaqgb/lib/sprite.c:105
void sprite_set_flags(u8 id, u8 flags)
{
if (sprite_valid(id) == 0) return;
kq_sprite_oam[id].flags = flags;
}sprite_set_pos
Mueve un sprite de GB en la copia de OAM usando coordenadas de pantalla en píxeles. Añade los desplazamientos de hardware: 8 a X y 16 a Y.
Sintaxis
void sprite_set_pos(u8 id, u8 x, u8 y);Parámetros
idID de entrada entre 0 y SPRITE_MAX-1; por defecto, 0..39 en GB y 0..63 en FC. Se ignoran los ID fuera de rango.
xPosición horizontal en píxeles, expresada como byte sin signo; no es una coordenada de patrón.
yCoordenada Y de pantalla en píxeles. La función de GB suma 16 antes de guardarla en OAM.
Valor devuelto
Ninguno (void).
Condiciones y límites
Las operaciones de posición, patrón, atributos y ocultación modifican la copia de trabajo. No reservan entradas ni actualizan OAM inmediatamente; transfiere el fotograma terminado con sprite_flush_oam.
Las sumas de coordenadas usan ocho bits y vuelven a cero al superar 255; no se recortan a la pantalla. Se puede editar una entrada válida aunque no esté reservada.
El ejemplo usa la biblioteca GB completa. KQ_SPRITE_MINIMAL_RUNTIME excluye de sprite.c sprite_free, sprite_set_pos, sprite_count_used, las dos consultas de líneas, metasprite_draw y anim_update. No lo definas si utilizas esas funciones.
Ejemplo de uso
sprite_set_pos(0,88,SPRITE_EXAMPLE_Y(16)); // Visible top-left: (88,16).Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
NORMAL muestra una flecha a la derecha en (88,16). FLIP X apunta a la izquierda en (88,32); FLIP Y invierte verticalmente la flecha en (88,48). META coloca dos flechas en (88,64) y (96,64). OVERLAP sitúa la flecha de (88,80) delante del cuadrado de (92,80), visible por los píxeles transparentes. ANIMATION muestra el cuadrado en (88,96). Las zonas (120,16) y (120,32) quedan vacías al ocultar y liberar sus entradas.
El programa enseña asignación, posición, reflejos, objetos compuestos, solapamiento, animación y límite por línea. Las dos cifras de arriba a la derecha deben ser 00: todas las comprobaciones internas pasaron. Cada flecha y cuadrado ocupa un patrón de 8×8.
En CGB y FC la flecha tiene asta verde, contorno rojo y detalles azules en la punta; el cuadrado es verde. La transparencia deja ver el fondo blanco de GB o negro de FC. DMG sustituye rojo, verde y azul por gris claro, gris oscuro y negro.
La fila bajo SCAN LIMIT comienza en (8,128). Se envían 11 sprites en GB o 9 en FC, uno de más a propósito. Deben verse 10 flechas en GB y 8 en FC; la última enviada no aparece. Las comprobaciones del máximo de software y del aviso deben dar 11/9 y 1.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/sprite.h:58
Convert screen coordinates to OAM coordinates by adding X=8 and Y=16. The byte additions wrap; this updates shadow storage even for an unallocated slot.
kitaqgb/lib/sprite.c:89
void sprite_set_pos(u8 id, u8 x, u8 y)
{
if (sprite_valid(id) == 0) return;
kq_sprite_oam[id].x = (u8)(x + 8);
kq_sprite_oam[id].y = (u8)(y + 16);
}sprite_set_tile
Sustituye el número de patrón de una entrada de OAM. Selecciona gráficos ya cargados en la memoria de patrones; no carga gráficos ni reserva un sprite.
Sintaxis
void sprite_set_tile(u8 id, u8 tile);Parámetros
idID de entrada entre 0 y SPRITE_MAX-1; por defecto, 0..39 en GB y 0..63 en FC. Se ignoran los ID fuera de rango.
tileNúmero de patrón de 8 bits. Carga antes sus gráficos. Se aplican las reglas de sprites de 8×16; la función no adapta el número a pares de patrones.
Valor devuelto
Ninguno (void).
Condiciones y límites
Las operaciones de posición, patrón, atributos y ocultación modifican la copia de trabajo. No reservan entradas ni actualizan OAM inmediatamente; transfiere el fotograma terminado con sprite_flush_oam.
El ejemplo usa la biblioteca GB completa. KQ_SPRITE_MINIMAL_RUNTIME excluye de sprite.c sprite_free, sprite_set_pos, sprite_count_used, las dos consultas de líneas, metasprite_draw y anim_update. No lo definas si utilizas esas funciones.
Ejemplo de uso
sprite_set_tile(5,129); // Select the green square beside ANIMATION.Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Con first_tile=128, dos fotogramas y dos llamadas por fotograma, la primera actualización devuelve la flecha 128 y la segunda el cuadrado 129. El cuadrado junto a ANIMATION demuestra que el resultado se aplicó a OAM.
El programa enseña asignación, posición, reflejos, objetos compuestos, solapamiento, animación y límite por línea. Las dos cifras de arriba a la derecha deben ser 00: todas las comprobaciones internas pasaron. Cada flecha y cuadrado ocupa un patrón de 8×8.
NORMAL muestra una flecha a la derecha en (88,16). FLIP X apunta a la izquierda en (88,32); FLIP Y invierte verticalmente la flecha en (88,48). META coloca dos flechas en (88,64) y (96,64). OVERLAP sitúa la flecha de (88,80) delante del cuadrado de (92,80), visible por los píxeles transparentes. ANIMATION muestra el cuadrado en (88,96). Las zonas (120,16) y (120,32) quedan vacías al ocultar y liberar sus entradas.
En CGB y FC la flecha tiene asta verde, contorno rojo y detalles azules en la punta; el cuadrado es verde. La transparencia deja ver el fondo blanco de GB o negro de FC. DMG sustituye rojo, verde y azul por gris claro, gris oscuro y negro.
La fila bajo SCAN LIMIT comienza en (8,128). Se envían 11 sprites en GB o 9 en FC, uno de más a propósito. Deben verse 10 flechas en GB y 8 en FC; la última enviada no aparece. Las comprobaciones del máximo de software y del aviso deben dar 11/9 y 1.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/sprite.h:60
Set a valid shadow slot's tile byte; allocation and hardware transfer are separate.
kitaqgb/lib/sprite.c:98
void sprite_set_tile(u8 id, u8 tile)
{
if (sprite_valid(id) == 0) return;
kq_sprite_oam[id].tile = tile;
}sprite_warn_scanline_overflow
Compara sprite_max_scanline_count con el límite por línea: 10 sprites en GB y 8 en FC. Es una estimación de software; no lee la bandera de desbordamiento del hardware.
Sintaxis
u8 sprite_warn_scanline_overflow();Valor devuelto
1 si la estimación supera el límite por línea; en caso contrario, 0.
Condiciones y límites
Ajusta kq_sprite_height a la altura de hardware, 8 o 16. La estimación ignora transparencia, visibilidad horizontal y prioridad. FC lee las coordenadas de la biblioteca; los cambios directos mediante intrínsecas OAM no se reflejan.
El ejemplo usa la biblioteca GB completa. KQ_SPRITE_MINIMAL_RUNTIME excluye de sprite.c sprite_free, sprite_set_pos, sprite_count_used, las dos consultas de líneas, metasprite_draw y anim_update. No lo definas si utilizas esas funciones.
Ejemplo de uso
sprite_example_expect(sprite_warn_scanline_overflow()==1);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La fila bajo SCAN LIMIT comienza en (8,128). Se envían 11 sprites en GB o 9 en FC, uno de más a propósito. Deben verse 10 flechas en GB y 8 en FC; la última enviada no aparece. Las comprobaciones del máximo de software y del aviso deben dar 11/9 y 1.
El programa enseña asignación, posición, reflejos, objetos compuestos, solapamiento, animación y límite por línea. Las dos cifras de arriba a la derecha deben ser 00: todas las comprobaciones internas pasaron. Cada flecha y cuadrado ocupa un patrón de 8×8.
NORMAL muestra una flecha a la derecha en (88,16). FLIP X apunta a la izquierda en (88,32); FLIP Y invierte verticalmente la flecha en (88,48). META coloca dos flechas en (88,64) y (96,64). OVERLAP sitúa la flecha de (88,80) delante del cuadrado de (92,80), visible por los píxeles transparentes. ANIMATION muestra el cuadrado en (88,96). Las zonas (120,16) y (120,32) quedan vacías al ocultar y liberar sus entradas.
En CGB y FC la flecha tiene asta verde, contorno rojo y detalles azules en la punta; el cuadrado es verde. La transparencia deja ver el fondo blanco de GB o negro de FC. DMG sustituye rojo, verde y azul por gris claro, gris oscuro y negro.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/sprite.h:75
Report whether the software overlap estimate exceeds ten sprites on a scanline.
kitaqgb/lib/sprite.c:182
u8 sprite_warn_scanline_overflow()
{
return (u8)(sprite_max_scanline_count() > 10);
}sprite_order.h — Selección de sprites por prioridad y rotación
sprite_order coloca primero los objetos importantes y rota el orden OAM entre prioridades iguales. Emite hasta 40 objetos de un máximo de 255 candidatos para gestionar el límite de diez por línea. La biblioteca sprite gestiona asignación y DMA; sprite_order, el orden de selección.
Incluye sprite_order.h y compila sprite_order.c exactamente una vez. Tras inicializar, llama en cada fotograma a begin, a push por cada candidato y después a build. Esta biblioteca de orden no requiere por sí sola sprite.c ni definiciones de variables globales.
El hardware selecciona los diez primeros objetos que cruzan cada línea, en orden OAM. Poner primero los valores de prioridad menores protege los objetos importantes en líneas saturadas. La rotación no garantiza igual frecuencia de aparición dentro de una prioridad. Si los objetos prioritarios ocupan las diez posiciones, los demás de esa línea siguen invisibles.
SpriteOrderOamEntry contiene cuatro bytes: Y, X, tile y flags. Para usar la copia OAM de sprite.h, escribe en (SpriteOrderOamEntry*)kq_sprite_oam. Mantén SPRITE_MAX en 40 y no mezcles las identidades de ranura del asignador con la salida reordenada: build no actualiza su registro interno.
sprite_order_begin
Borra el recuento de candidatos para el nuevo fotograma conservando memoria, altura y fase. A diferencia de reinicializar cada fotograma, permite continuar la rotación.
Sintaxis
void sprite_order_begin(SpriteOrder* order);Parámetros
orderDirección de un
SpriteOrderpropiedad del código que llama. Inicialízalo antes de usarlo y actualízalo desde el código principal.
Valor devuelto
Sin valor de retorno. Ignora order nulo. No borra los bytes antiguos ni el OAM ya construido.
Condiciones y límites
Incluye sprite_order.h y compila sprite_order.c exactamente una vez. Tras inicializar, llama en cada fotograma a begin, a push por cada candidato y después a build. Esta biblioteca de orden no requiere por sí sola sprite.c ni definiciones de variables globales.
El hardware selecciona los diez primeros objetos que cruzan cada línea, en orden OAM. Poner primero los valores de prioridad menores protege los objetos importantes en líneas saturadas. La rotación no garantiza igual frecuencia de aparición dentro de una prioridad. Si los objetos prioritarios ocupan las diez posiciones, los demás de esa línea siguen invisibles.
Ejemplo de uso
sprite_order_begin(&order_demo);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La lección muestra catorce objetos en una fila. Los dos rombos bajo HIGH tienen prioridad alta; los doce cuadrados bajo NORMAL, normal. CGB usa rombos rojos y cuadrados azules; DMG, gris y negro. Ambos rombos permanecen visibles y solo aparecen ocho cuadrados. 0..B identifica sus posiciones: PHASE 04 muestra 4..B; PHASE 08 muestra 8..B y 0..3. La compilación normal avanza PHASE cada 60 esperas de fotograma. Las capturas fijan la fase del mismo programa; también se comprobó el cambio de selección en ejecución.



Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_order_demo.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_order_demo.gb --cgb=cgb --profile=dev --rst-disable --stack-bank=fixed --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/sprite_order.h:42
Discard this frame's submissions while preserving storage, height and phase. A null state is ignored. Call once before submitting the next frame's sprites.
kitaqgb/lib/sprite_order.c:24
void sprite_order_begin(SpriteOrder* order)
{
if (order != 0) order->count = 0;
}sprite_order_build
Construye 160 bytes de OAM en RAM según prioridad y orden cíclico. Oculta todas las ranuras libres poniéndolas a cero y avanza la fase para la siguiente construcción. No reordena los candidatos guardados.
Sintaxis
u8 sprite_order_build(SpriteOrder* order, SpriteOrderOamEntry* output, u8 limit);Parámetros
orderDirección de un
SpriteOrderpropiedad del código que llama. Inicialízalo antes de usarlo y actualízalo desde el código principal.outputArray escribible de 40
SpriteOrderOamEntry. Escribe los 160 bytes aunque limit sea cero o menor que 40.limitMáximo de objetos emitidos, de 0 a 40; valores mayores se limitan a 40. Limita todo OAM, no cada línea.
Valor devuelto
Devuelve la cantidad emitida, de 0 a 40. Una cola vacía válida borra todas las ranuras y pone phase=0. Si no, normaliza phase módulo count, usa ese inicio cíclico en cada prioridad ascendente y después incrementa y hace circular phase. Un límite cero también avanza la fase. order/output nulo, estado deshabilitado, altura inválida o count>capacity devuelve cero sin cambiar salida ni fase.
Condiciones y límites
El hardware selecciona los diez primeros objetos que cruzan cada línea, en orden OAM. Poner primero los valores de prioridad menores protege los objetos importantes en líneas saturadas. La rotación no garantiza igual frecuencia de aparición dentro de una prioridad. Si los objetos prioritarios ocupan las diez posiciones, los demás de esa línea siguen invisibles.
El argumento priority controla la selección independientemente del atributo detrás del fondo. En DMG, entre objetos seleccionados que se solapan gana el menor X; OAM resuelve empates. El modo color CGB normal usa OAM, aunque sigue aplicándose una configuración de orden DMG elegida mediante OPRI. La biblioteca no cambia las reglas del hardware.
SpriteOrderOamEntry contiene cuatro bytes: Y, X, tile y flags. Para usar la copia OAM de sprite.h, escribe en (SpriteOrderOamEntry*)kq_sprite_oam. Mantén SPRITE_MAX en 40 y no mezcles las identidades de ranura del asignador con la salida reordenada: build no actualiza su registro interno.
build solo escribe RAM. Proporciona un array de salida de 160 bytes que no se solape con el estado ni los candidatos. Un búfer DMA OAM debe empezar en un límite de 256 bytes. Termina de construir antes de transferir en VBlank; una interrupción no debe transferir un búfer a medias. El ejemplo usa sprite_flush_oam.
Cada envío tiene un coste acotado. Construir borra 160 bytes de OAM en RAM y recorre los candidatos hasta cuatro veces, sin ordenar el array ni necesitar un búfer temporal de ordenación. No garantiza que 255 candidatos quepan en el presupuesto de un fotograma; envía solo los necesarios.
Ejemplo de uso
order_demo_state[1]=sprite_order_build(&order_demo,(SpriteOrderOamEntry*)kq_sprite_oam,40);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La lección muestra catorce objetos en una fila. Los dos rombos bajo HIGH tienen prioridad alta; los doce cuadrados bajo NORMAL, normal. CGB usa rombos rojos y cuadrados azules; DMG, gris y negro. Ambos rombos permanecen visibles y solo aparecen ocho cuadrados. 0..B identifica sus posiciones: PHASE 04 muestra 4..B; PHASE 08 muestra 8..B y 0..3. La compilación normal avanza PHASE cada 60 esperas de fotograma. Las capturas fijan la fase del mismo programa; también se comprobó el cambio de selección en ejecución.



Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_order_demo.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_order_demo.gb --cgb=cgb --profile=dev --rst-disable --stack-bank=fixed --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/sprite_order.h:62
Write a complete 160-byte shadow OAM: ascending priority, then cyclic order within each priority. Clamp limit to 40, return the number emitted and zero all unused entries (including Y) so they cannot consume scanline slots. Advance phase once for a nonempty valid queue, even when limit is zero. Empty queues reset phase to zero. Null/disabled/corrupt state or null output returns 0 without modifying output or phase. Output must provide 40 entries and must not overlap item/state storage. This only writes RAM. Build in foreground, then transfer during VBlank. DMG overlap priority also depends on X: this cannot override that hardware rule. OAM order chooses the first ten sprites per scanline on both DMG/CGB. It neither updates sprite_alloc's bookkeeping nor performs OAM DMA.
kitaqgb/lib/sprite_order.c:57
u8 sprite_order_build(SpriteOrder* order, SpriteOrderOamEntry* output, u8 limit)
{
u8 i;
u8 count;
u8 phase;
u8 priority;
u8 visited;
u8 written;
SpriteOrderItem* item;
if (order == 0 || output == 0) return 0;
if (order->items == 0 || order->capacity == 0) return 0;
if (order->count > order->capacity) return 0;
if (order->height != 8 && order->height != 16) return 0;
// Clear all hardware slots regardless of the requested emission limit.
for (i = 0; i < SPRITE_ORDER_OAM_COUNT; i++) {
output[i].y = 0;
output[i].x = 0;
output[i].tile = 0;
output[i].flags = 0;
}
count = order->count;
if (count == 0) {
order->phase = 0;
return 0;
}
if (limit > SPRITE_ORDER_OAM_COUNT) limit = SPRITE_ORDER_OAM_COUNT;
phase = order->phase;
while (phase >= count) phase = (u8)(phase - count);
written = 0;
for (priority = 0; priority < SPRITE_ORDER_LEVELS && written < limit; priority++) {
i = phase;
visited = 0;
while (visited < count && written < limit) {
item = &order->items[i];
if (item->priority == priority) {
output[written].y = item->oam.y;
output[written].x = item->oam.x;
output[written].tile = item->oam.tile;
output[written].flags = item->oam.flags;
written++;
}
visited++;
i++;
if (i >= count) i = 0;
}
}
phase++;
if (phase >= count) phase = 0;
order->phase = phase;
return written;
}sprite_order_init
Asocia el almacenamiento de candidatos al estado de orden y reinicia recuento y fase de rotación. Úsalo al empezar una escena o cambiar almacenamiento.
Sintaxis
u8 sprite_order_init(SpriteOrder* order, SpriteOrderItem* items, u8 capacity, u8 height);Parámetros
orderDirección de un
SpriteOrderpropiedad del código que llama. Inicialízalo antes de usarlo y actualízalo desde el código principal.itemsArray
SpriteOrderItemescribible, cinco bytes por elemento. Reserva capacity elementos y mantén la memoria válida durante su uso.capacityCapacidad del array, de 1 a 255 elementos; no bytes ni ranuras de hardware.
heightTodos los objetos comparten altura. Pasa 8 o 16 según el ajuste 8×8/8×16 de LCDC; la biblioteca no configura LCDC. En 8×16, el hardware ignora el bit bajo del número de tile.
Valor devuelto
Devuelve 1 si tiene éxito, 0 si items es nulo, la capacidad es cero, la altura no es 8/16 u order es nulo. Con order válido, el fallo lo deja deshabilitado: items=NULL, capacity=count=phase=0 y height=8. El array queda intacto.
Condiciones y límites
Incluye sprite_order.h y compila sprite_order.c exactamente una vez. Tras inicializar, llama en cada fotograma a begin, a push por cada candidato y después a build. Esta biblioteca de orden no requiere por sí sola sprite.c ni definiciones de variables globales.
Ejemplo de uso
sprite_init();sprite_order_init(&order_demo,order_demo_items,14,8);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La lección muestra catorce objetos en una fila. Los dos rombos bajo HIGH tienen prioridad alta; los doce cuadrados bajo NORMAL, normal. CGB usa rombos rojos y cuadrados azules; DMG, gris y negro. Ambos rombos permanecen visibles y solo aparecen ocho cuadrados. 0..B identifica sus posiciones: PHASE 04 muestra 4..B; PHASE 08 muestra 8..B y 0..3. La compilación normal avanza PHASE cada 60 esperas de fotograma. Las capturas fijan la fase del mismo programa; también se comprobó el cambio de selección en ejecución.



Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_order_demo.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_order_demo.gb --cgb=cgb --profile=dev --rst-disable --stack-bank=fixed --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/sprite_order.h:38
Bind writable item storage and select the hardware sprite height (8 or 16). Return 1 on success. Invalid storage, zero capacity or another height returns 0 and leaves a non-null state disabled. A null state returns 0 without writes.
kitaqgb/lib/sprite_order.c:6
u8 sprite_order_init(SpriteOrder* order, SpriteOrderItem* items, u8 capacity, u8 height)
{
if (order == 0) return 0;
order->items = 0;
order->capacity = 0;
order->count = 0;
order->height = 8;
order->phase = 0;
if (items == 0 || capacity == 0) return 0;
if (height != 8 && height != 16) return 0;
order->items = items;
order->capacity = capacity;
order->height = height;
return 1;
}sprite_order_push
Envía un sprite que cruza al menos un píxel de la pantalla visible. Los candidatos totalmente fuera se rechazan antes de consumir posiciones OAM.
Sintaxis
u8 sprite_order_push(SpriteOrder* order, s16 x, s16 y, u8 tile, u8 flags, u8 priority);Parámetros
orderDirección de un
SpriteOrderpropiedad del código que llama. Inicialízalo antes de usarlo y actualízalo desde el código principal.xX de pantalla con signo desde la esquina superior izquierda. Se aceptan bordes izquierdos −7..159; ≤−8 o ≥160 queda totalmente fuera. Al guardar suma 8 para coordenadas OAM.
yY de pantalla con signo desde la esquina superior izquierda. Acepta −7..143 con altura 8 y −15..143 con altura 16. Al guardar suma 16 para OAM.
tileNúmero de tile de 0 a 255, guardado sin cambios. Consulta las notas de altura para 8×16.
flagsByte de atributos de hardware sin cambios: volteos, prioridad detrás del fondo, paleta DMG/CGB y banco VRAM CGB conservan sus significados habituales.
priorityPrioridad de selección por software de 0 a 3, cero primero. Se rechazan valores de cuatro o más. Es independiente del byte flags del hardware.
Valor devuelto
Devuelve 1 e incrementa count si se acepta. Estado nulo/deshabilitado, altura inválida, memoria llena, prioridad inválida u objeto totalmente fuera: devuelve 0 sin cambiar items ni count.
Condiciones y límites
Todos los objetos comparten altura. Pasa 8 o 16 según el ajuste 8×8/8×16 de LCDC; la biblioteca no configura LCDC. En 8×16, el hardware ignora el bit bajo del número de tile.
El hardware selecciona los diez primeros objetos que cruzan cada línea, en orden OAM. Poner primero los valores de prioridad menores protege los objetos importantes en líneas saturadas. La rotación no garantiza igual frecuencia de aparición dentro de una prioridad. Si los objetos prioritarios ocupan las diez posiciones, los demás de esa línea siguen invisibles.
El argumento priority controla la selección independientemente del atributo detrás del fondo. En DMG, entre objetos seleccionados que se solapan gana el menor X; OAM resuelve empates. El modo color CGB normal usa OAM, aunque sigue aplicándose una configuración de orden DMG elegida mediante OPRI. La biblioteca no cambia las reglas del hardware.
Ejemplo de uso
sprite_order_push(&order_demo,8,64,128,0,0);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
La lección muestra catorce objetos en una fila. Los dos rombos bajo HIGH tienen prioridad alta; los doce cuadrados bajo NORMAL, normal. CGB usa rombos rojos y cuadrados azules; DMG, gris y negro. Ambos rombos permanecen visibles y solo aparecen ocho cuadrados. 0..B identifica sus posiciones: PHASE 04 muestra 4..B; PHASE 08 muestra 8..B y 0..3. La compilación normal avanza PHASE cada 60 esperas de fotograma. Las capturas fijan la fase del mismo programa; también se comprobó el cambio de selección en ejecución.



Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_order_demo.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_order_demo.gb --cgb=cgb --profile=dev --rst-disable --stack-bank=fixed --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/sprite_order.h:49
Submit one sprite at signed, top-left SCREEN pixel coordinates. Preserve the tile and attribute bytes; use priority 0 (first) through 3 (last). Fully off-screen sprites, invalid priorities, disabled state and full storage return 0 without consuming a slot. Partly visible sprites are accepted. Return 1 on acceptance. Hardware 8x16 mode still ignores the tile index's low bit.
kitaqgb/lib/sprite_order.c:31
u8 sprite_order_push(SpriteOrder* order, s16 x, s16 y, u8 tile, u8 flags, u8 priority)
{
SpriteOrderItem* item;
if (order == 0) return 0;
if (order->items == 0 || order->capacity == 0) return 0;
if (order->height != 8 && order->height != 16) return 0;
if (order->count >= order->capacity || priority >= SPRITE_ORDER_LEVELS) return 0;
if (x <= -8 || x >= 160 || y >= 144) return 0;
if (order->height == 16) {
if (y <= -16) return 0;
} else {
if (y <= -8) return 0;
}
item = &order->items[order->count];
item->oam.y = (u8)(y + 16);
item->oam.x = (u8)(x + 8);
item->oam.tile = tile;
item->oam.flags = flags;
item->priority = priority;
order->count++;
return 1;
}system.h — Arranque, contadores de fotogramas, esperas e interrupciones
Gestiona el número de esperas de fotograma, las funciones de retorno posteriores y las interrupciones enmascarables de la CPU.
gb_disable_interrupts
gb_disable_interrupts es un alias de system_disable_interrupts. Deshabilita las interrupciones de CPU en GB.
Desactiva las interrupciones enmascarables de la CPU.
Sintaxis
void gb_disable_interrupts();Valor devuelto
No devuelve ningún valor.
Condiciones y límites
La cabecera define una macro de tipo objeto que se expande al nombre de la implementación. Los argumentos, valores devueltos y acceso al estado son los mismos que en el destino; el alias no añade estado ni procesamiento propio. Usa input.h/input.c para entradas o system.h/system.c para servicios de fotograma, como en el ejemplo completo y su comando de compilación.
Mantén breves las actualizaciones protegidas y restaura las interrupciones de forma adecuada al terminar. El enmascaramiento de interrupciones es independiente de las condiciones que necesita una rutina de espera de fotograma.
En GB, la espera termina inmediatamente si el LCD está apagado, pero la función envolvente sigue incrementando su contador y llamando a su función de retorno. La inicialización por sí sola no configura el LCD ni las fuentes de interrupción.
Compila este ejemplo completo con la ABI Legacy predeterminada. Sus retrollamadas usan llamadas mediante punteros de función, que el compilador rechaza por no estar admitidas con --abi=stack. La misma restricción se aplica al usar un alias.
Ejemplo de uso
gb_disable_interrupts();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo combina la desactivación con la activación. Los programas de verificación específicos también inspeccionan el estado de interrupciones de la CPU.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\system_aliases.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\system_aliases.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/system.h:32
#define gb_disable_interrupts system_disable_interruptskitaqgb/lib/system.c:52
void system_disable_interrupts()
{
__asm {
DI
RET
}
}gb_enable_interrupts
gb_enable_interrupts es un alias de system_enable_interrupts. Habilita las interrupciones de CPU en GB.
Activa las interrupciones enmascarables de la CPU.
Sintaxis
void gb_enable_interrupts();Valor devuelto
No devuelve ningún valor.
Condiciones y límites
La cabecera define una macro de tipo objeto que se expande al nombre de la implementación. Los argumentos, valores devueltos y acceso al estado son los mismos que en el destino; el alias no añade estado ni procesamiento propio. Usa input.h/input.c para entradas o system.h/system.c para servicios de fotograma, como en el ejemplo completo y su comando de compilación.
Prepara las fuentes de interrupción y sus manejadores antes de activarlas. En FC, esta operación es independiente de activar o desactivar NMI.
En GB, la espera termina inmediatamente si el LCD está apagado, pero la función envolvente sigue incrementando su contador y llamando a su función de retorno. La inicialización por sí sola no configura el LCD ni las fuentes de interrupción.
Compila este ejemplo completo con la ABI Legacy predeterminada. Sus retrollamadas usan llamadas mediante punteros de función, que el compilador rechaza por no estar admitidas con --abi=stack. La misma restricción se aplica al usar un alias.
Ejemplo de uso
gb_enable_interrupts();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo restaura las interrupciones. El programa FC desactiva primero las fuentes de IRQ de fotograma de la APU y DMC para evitar atender repetidamente una IRQ sin reconocer.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\system_aliases.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\system_aliases.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/system.h:31
#define gb_enable_interrupts system_enable_interruptskitaqgb/lib/system.c:43
void system_enable_interrupts()
{
__asm {
EI
RET
}
}gb_frame_count
gb_frame_count es un alias de system_get_frame. Lee el contador de 16 bits por software de las esperas completadas por la función envolvente.
Lee el contador de 16 bits de la función de espera de fotograma.
Sintaxis
u16 gb_frame_count();Valor devuelto
Devuelve el valor actual del contador, de 0 a 65535.
Condiciones y límites
La cabecera define una macro de tipo objeto que se expande al nombre de la implementación. Los argumentos, valores devueltos y acceso al estado son los mismos que en el destino; el alias no añade estado ni procesamiento propio. Usa input.h/input.c para entradas o system.h/system.c para servicios de fotograma, como en el ejemplo completo y su comando de compilación.
El contador cuenta las esperas realizadas mediante esta función envoltorio; no mide automáticamente los fotogramas de hardware transcurridos. Vuelve a cero al superar el rango de 16 bits.
En GB, la espera termina inmediatamente si el LCD está apagado, pero la función envolvente sigue incrementando su contador y llamando a su función de retorno. La inicialización por sí sola no configura el LCD ni las fuentes de interrupción.
Compila este ejemplo completo con la ABI Legacy predeterminada. Sus retrollamadas usan llamadas mediante punteros de función, que el compilador rechaza por no estar admitidas con --abi=stack. La misma restricción se aplica al usar un alias.
Ejemplo de uso
result[3]=gb_frame_count();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo lee tres después de tres esperas. Para comprobar el retorno a cero, establece explícitamente el contador en 65535 y verifica cero tras la siguiente espera.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\system_aliases.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\system_aliases.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/system.h:30
#define gb_frame_count system_get_framekitaqgb/lib/system.c:31
u16 system_get_frame()
{
return kq_system_frame;
}gb_init
gb_init es un alias de system_init. Reinicia el contador de fotogramas por software y el registro de la retrollamada.
Inicializa la gestión de fotogramas poniendo a cero el contador y eliminando la función de retorno registrada.
Sintaxis
void gb_init();Valor devuelto
No devuelve ningún valor.
Condiciones y límites
La cabecera define una macro de tipo objeto que se expande al nombre de la implementación. Los argumentos, valores devueltos y acceso al estado son los mismos que en el destino; el alias no añade estado ni procesamiento propio. Usa input.h/input.c para entradas o system.h/system.c para servicios de fotograma, como en el ejemplo completo y su comando de compilación.
El contador cuenta las esperas realizadas mediante esta función envoltorio; no mide automáticamente los fotogramas de hardware transcurridos. Vuelve a cero al superar el rango de 16 bits.
En GB, la espera termina inmediatamente si el LCD está apagado, pero la función envolvente sigue incrementando su contador y llamando a su función de retorno. La inicialización por sí sola no configura el LCD ni las fuentes de interrupción.
Compila este ejemplo completo con la ABI Legacy predeterminada. Sus retrollamadas usan llamadas mediante punteros de función, que el compilador rechaza por no estar admitidas con --abi=stack. La misma restricción se aplica al usar un alias.
Ejemplo de uso
gb_init();result[0]=gb_frame_count();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo confirma que el número de fotograma inicial sea cero antes de registrar su función de retorno.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\system_aliases.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\system_aliases.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/system.h:27
#define gb_init system_initkitaqgb/lib/system.c:7
void system_init()
{
kq_system_frame = 0;
system_vblank_callback = 0;
}gb_set_vblank_callback
gb_set_vblank_callback es un alias de system_set_vblank_callback. Registra o elimina la retrollamada invocada de forma síncrona tras esperar un fotograma.
Registra, sustituye o elimina la función que se llama después de esperar un fotograma.
Sintaxis
void gb_set_vblank_callback(SystemCallback callback);Parámetros
callbackFunción que se va a invocar; 0 elimina la función de retorno.
Valor devuelto
No devuelve ningún valor.
Condiciones y límites
La cabecera define una macro de tipo objeto que se expande al nombre de la implementación. Los argumentos, valores devueltos y acceso al estado son los mismos que en el destino; el alias no añade estado ni procesamiento propio. Usa input.h/input.c para entradas o system.h/system.c para servicios de fotograma, como en el ejemplo completo y su comando de compilación.
Es un puntero ordinario a una función sin argumentos ni valor de retorno. No incluye un número de banco; mantén mapeado el código de destino mientras pueda ser invocado.
En GB, la espera termina inmediatamente si el LCD está apagado, pero la función envolvente sigue incrementando su contador y llamando a su función de retorno. La inicialización por sí sola no configura el LCD ni las fuentes de interrupción.
Compila este ejemplo completo con la ABI Legacy predeterminada. Sus retrollamadas usan llamadas mediante punteros de función, que el compilador rechaza por no estar admitidas con --abi=stack. La misma restricción se aplica al usar un alias.
Ejemplo de uso
gb_set_vblank_callback(on_frame);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Tras tres invocaciones, registrar 0 desactiva la función de retorno. La siguiente espera lleva el fotograma a cuatro, mientras el número de invocaciones sigue siendo tres.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\system_aliases.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\system_aliases.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/system.h:29
#define gb_set_vblank_callback system_set_vblank_callbackkitaqgb/lib/system.c:25
void system_set_vblank_callback(SystemCallback callback)
{
system_vblank_callback = callback;
}gb_wait_vblank
gb_wait_vblank es un alias de system_wait_vblank. Espera el límite de fotograma, incrementa el contador por software y llama a la retrollamada registrada.
Espera al siguiente fotograma, incrementa el contador e invoca la función de retorno registrada.
Sintaxis
void gb_wait_vblank();Valor devuelto
No devuelve ningún valor.
Condiciones y límites
La cabecera define una macro de tipo objeto que se expande al nombre de la implementación. Los argumentos, valores devueltos y acceso al estado son los mismos que en el destino; el alias no añade estado ni procesamiento propio. Usa input.h/input.c para entradas o system.h/system.c para servicios de fotograma, como en el ejemplo completo y su comando de compilación.
La función de retorno se ejecuta de forma síncrona dentro de esta función; registrarla no instala un manejador de interrupciones. El contador cuenta las esperas de esta función envoltorio, no los fotogramas de hardware transcurridos automáticamente. Vuelve a cero al superar el rango de 16 bits.
En GB, la espera termina inmediatamente si el LCD está apagado, pero la función envolvente sigue incrementando su contador y llamando a su función de retorno. La inicialización por sí sola no configura el LCD ni las fuentes de interrupción.
Compila este ejemplo completo con la ABI Legacy predeterminada. Sus retrollamadas usan llamadas mediante punteros de función, que el compilador rechaza por no estar admitidas con --abi=stack. La misma restricción se aplica al usar un alias.
Ejemplo de uso
gb_wait_vblank();gb_wait_vblank();gb_wait_vblank();result[1]=frame_calls;result[2]=frame_seen;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Tres esperas invocan tres veces la función de retorno, y el último valor del contador observado dentro de ella es tres.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\system_aliases.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\system_aliases.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/system.h:28
#define gb_wait_vblank system_wait_vblankkitaqgb/lib/system.c:15
void system_wait_vblank()
{
__wait_vblank();
kq_system_frame++;
if (system_vblank_callback != 0) {
system_vblank_callback();
}
}system_disable_interrupts
Desactiva las interrupciones enmascarables de la CPU.
Sintaxis
void system_disable_interrupts();Valor devuelto
No devuelve ningún valor.
Condiciones y límites
Mantén breves las actualizaciones protegidas y restaura las interrupciones de forma adecuada al terminar. El enmascaramiento de interrupciones es independiente de las condiciones que necesita una rutina de espera de fotograma.
En GB, la espera termina inmediatamente si el LCD está apagado, pero la función envolvente sigue incrementando su contador y llamando a su función de retorno. La inicialización por sí sola no configura el LCD ni las fuentes de interrupción.
Compila este ejemplo completo con la ABI Legacy predeterminada. Sus retrollamadas usan llamadas mediante punteros de función, que el compilador rechaza por no estar admitidas con --abi=stack. La misma restricción se aplica al usar un alias.
Ejemplo de uso
system_disable_interrupts();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo combina la desactivación con la activación. Los programas de verificación específicos también inspeccionan el estado de interrupciones de la CPU.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_services.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_services.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/system.h:25
Disable CPU interrupts and return; callers must explicitly re-enable them later.
kitaqgb/lib/system.c:52
void system_disable_interrupts()
{
__asm {
DI
RET
}
}system_enable_interrupts
Activa las interrupciones enmascarables de la CPU.
Sintaxis
void system_enable_interrupts();Valor devuelto
No devuelve ningún valor.
Condiciones y límites
Prepara las fuentes de interrupción y sus manejadores antes de activarlas. En FC, esta operación es independiente de activar o desactivar NMI.
En GB, la espera termina inmediatamente si el LCD está apagado, pero la función envolvente sigue incrementando su contador y llamando a su función de retorno. La inicialización por sí sola no configura el LCD ni las fuentes de interrupción.
Compila este ejemplo completo con la ABI Legacy predeterminada. Sus retrollamadas usan llamadas mediante punteros de función, que el compilador rechaza por no estar admitidas con --abi=stack. La misma restricción se aplica al usar un alias.
Ejemplo de uso
system_enable_interrupts();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo restaura las interrupciones. El programa FC desactiva primero las fuentes de IRQ de fotograma de la APU y DMC para evitar atender repetidamente una IRQ sin reconocer.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_services.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_services.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/system.h:23
Enable CPU interrupts and return using the inline-assembly function body.
kitaqgb/lib/system.c:43
void system_enable_interrupts()
{
__asm {
EI
RET
}
}system_get_frame
Lee el contador de 16 bits de la función de espera de fotograma.
Sintaxis
u16 system_get_frame();Valor devuelto
Devuelve el valor actual del contador, de 0 a 65535.
Condiciones y límites
El contador cuenta las esperas realizadas mediante esta función envoltorio; no mide automáticamente los fotogramas de hardware transcurridos. Vuelve a cero al superar el rango de 16 bits.
En GB, la espera termina inmediatamente si el LCD está apagado, pero la función envolvente sigue incrementando su contador y llamando a su función de retorno. La inicialización por sí sola no configura el LCD ni las fuentes de interrupción.
Compila este ejemplo completo con la ABI Legacy predeterminada. Sus retrollamadas usan llamadas mediante punteros de función, que el compilador rechaza por no estar admitidas con --abi=stack. La misma restricción se aplica al usar un alias.
Ejemplo de uso
result[3]=system_get_frame();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo lee tres después de tres esperas. Para comprobar el retorno a cero, establece explícitamente el contador en 65535 y verifica cero tras la siguiente espera.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_services.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_services.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/system.h:19
Read the software count of completed system_wait_vblank calls.
kitaqgb/lib/system.c:31
u16 system_get_frame()
{
return kq_system_frame;
}system_get_frame8
Lee los ocho bits menos significativos del contador de fotogramas para intervalos cortos y repetitivos.
Sintaxis
u8 system_get_frame8();Valor devuelto
Devuelve el byte menos significativo, de 0 a 255.
Condiciones y límites
El contador cuenta las esperas realizadas mediante esta función envoltorio; no mide automáticamente los fotogramas de hardware transcurridos. Vuelve a cero al superar el rango de 16 bits.
En GB, la espera termina inmediatamente si el LCD está apagado, pero la función envolvente sigue incrementando su contador y llamando a su función de retorno. La inicialización por sí sola no configura el LCD ni las fuentes de interrupción.
Compila este ejemplo completo con la ABI Legacy predeterminada. Sus retrollamadas usan llamadas mediante punteros de función, que el compilador rechaza por no estar admitidas con --abi=stack. La misma restricción se aplica al usar un alias.
Ejemplo de uso
result[4]=system_get_frame8();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo lee tres después de tres esperas y cero cuando el contador de 16 bits vuelve a cero.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_services.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_services.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/system.h:21
Return the low byte of the software frame counter for wrapping 8-bit timing.
kitaqgb/lib/system.c:37
u8 system_get_frame8()
{
return (u8)kq_system_frame;
}system_init
Inicializa la gestión de fotogramas poniendo a cero el contador y eliminando la función de retorno registrada.
Sintaxis
void system_init();Valor devuelto
No devuelve ningún valor.
Condiciones y límites
El contador cuenta las esperas realizadas mediante esta función envoltorio; no mide automáticamente los fotogramas de hardware transcurridos. Vuelve a cero al superar el rango de 16 bits.
En GB, la espera termina inmediatamente si el LCD está apagado, pero la función envolvente sigue incrementando su contador y llamando a su función de retorno. La inicialización por sí sola no configura el LCD ni las fuentes de interrupción.
Compila este ejemplo completo con la ABI Legacy predeterminada. Sus retrollamadas usan llamadas mediante punteros de función, que el compilador rechaza por no estar admitidas con --abi=stack. La misma restricción se aplica al usar un alias.
Ejemplo de uso
system_init();result[0]=system_get_frame();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El ejemplo confirma que el número de fotograma inicial sea cero antes de registrar su función de retorno.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_services.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_services.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/system.h:12
Reset the software frame counter and remove any registered callback.
kitaqgb/lib/system.c:7
void system_init()
{
kq_system_frame = 0;
system_vblank_callback = 0;
}system_set_vblank_callback
Registra, sustituye o elimina la función que se llama después de esperar un fotograma.
Sintaxis
void system_set_vblank_callback(SystemCallback callback);Parámetros
callbackFunción que se va a invocar; 0 elimina la función de retorno.
Valor devuelto
No devuelve ningún valor.
Condiciones y límites
Es un puntero ordinario a una función sin argumentos ni valor de retorno. No incluye un número de banco; mantén mapeado el código de destino mientras pueda ser invocado.
En GB, la espera termina inmediatamente si el LCD está apagado, pero la función envolvente sigue incrementando su contador y llamando a su función de retorno. La inicialización por sí sola no configura el LCD ni las fuentes de interrupción.
Compila este ejemplo completo con la ABI Legacy predeterminada. Sus retrollamadas usan llamadas mediante punteros de función, que el compilador rechaza por no estar admitidas con --abi=stack. La misma restricción se aplica al usar un alias.
Ejemplo de uso
system_set_vblank_callback(on_frame);Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Tras tres invocaciones, registrar 0 desactiva la función de retorno. La siguiente espera lleva el fotograma a cuatro, mientras el número de invocaciones sigue siendo tres.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_services.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_services.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/system.h:17
Replace the callback used by system_wait_vblank; null disables the callback.
kitaqgb/lib/system.c:25
void system_set_vblank_callback(SystemCallback callback)
{
system_vblank_callback = callback;
}system_wait_vblank
Espera al siguiente fotograma, incrementa el contador e invoca la función de retorno registrada.
Sintaxis
void system_wait_vblank();Valor devuelto
No devuelve ningún valor.
Condiciones y límites
La función de retorno se ejecuta de forma síncrona dentro de esta función; registrarla no instala un manejador de interrupciones. El contador cuenta las esperas de esta función envoltorio, no los fotogramas de hardware transcurridos automáticamente. Vuelve a cero al superar el rango de 16 bits.
En GB, la espera termina inmediatamente si el LCD está apagado, pero la función envolvente sigue incrementando su contador y llamando a su función de retorno. La inicialización por sí sola no configura el LCD ni las fuentes de interrupción.
Compila este ejemplo completo con la ABI Legacy predeterminada. Sus retrollamadas usan llamadas mediante punteros de función, que el compilador rechaza por no estar admitidas con --abi=stack. La misma restricción se aplica al usar un alias.
Ejemplo de uso
system_wait_vblank();system_wait_vblank();system_wait_vblank();result[1]=frame_calls;result[2]=frame_seen;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Tres esperas invocan tres veces la función de retorno, y el último valor del contador observado dentro de ella es tres.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_services.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_services.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64kImplementación y código fuente
kitaqgb/lib/system.h:15
Wait for VBlank, count this wrapper call, then invoke the callback synchronously. The counter wraps at 16 bits and is not an independent hardware frame clock.
kitaqgb/lib/system.c:15
void system_wait_vblank()
{
__wait_vblank();
kq_system_frame++;
if (system_vblank_callback != 0) {
system_vblank_callback();
}
}vram.h — Actualizaciones de VRAM en cola y transferencias
Inicializa vacía la cola de escrituras VRAM diferidas y borra su indicador de desbordamiento. No borra la pantalla, carga gráficos de tiles ni reserva VRAM física.
GB cuenta espacios de comando: la capacidad predeterminada es 32. Cada función de inserción usa uno, incluso para transferencias grandes o de longitud cero. Define VRAM_QUEUE_MAX de forma uniforme en todas las unidades, entre 1 y 255. Una cola vacía tiene used=0 y free=capacity.
Espera con __wait_vblank y llama a vram_flush_now. Úsala para un lote moderado de cambios de pantalla. Una sola espera no limita la transferencia ni garantiza terminar todo el lote dentro de un VBlank.
Coordina las fases de construcción y ejecución de la cola. No añadas durante su ejecución en una interrupción, alteres sus contadores directamente ni sobrescribas por accidente los datos retenidos. Estas API no ofrecen bloqueo ni doble búfer. La capacidad es la del búfer de comandos, no los bytes libres de VRAM física.
vram_clear_queue
Descarta los comandos VRAM pendientes y borra la marca de desbordamiento sin ejecutarlos.
Sintaxis
void vram_clear_queue();Valor devuelto
Ninguno (void).
Condiciones y límites
GB cuenta espacios de comando: la capacidad predeterminada es 32. Cada función de inserción usa uno, incluso para transferencias grandes o de longitud cero. Define VRAM_QUEUE_MAX de forma uniforme en todas las unidades, entre 1 y 255. Una cola vacía tiene used=0 y free=capacity.
Coordina las fases de construcción y ejecución de la cola. No añadas durante su ejecución en una interrupción, alteres sus contadores directamente ni sobrescribas por accidente los datos retenidos. Estas API no ofrecen bloqueo ni doble búfer. La capacidad es la del búfer de comandos, no los bytes libres de VRAM física.
Ejemplo de uso
vram_clear_queue();
if (vram_get_queue_used()!=0 || vram_get_overflowed()!=0) failures++;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El programa completo enseña escrituras diferidas, control de capacidad y recuperación del desbordamiento. Siete llamadas de dibujo usan 7 de 32 espacios en GB, o 52 de 128 bytes en FC: CAPACITY/USED/FREE muestra 032/007/025 o 128/052/076. AFTER FLUSH y FAILED CHECKS deben ser 000; OVERFLOW SEEN, 001. Se intenta añadir a una cola llena para comprobar el indicador: leer o ejecutar no lo borra; vaciar la cola sí. En FC también se comprueba que la ejecución directa sin confirmar conserve la cola pendiente.
Las coordenadas de imagen son píxeles desde la esquina superior izquierda. Deben aparecer cuadrados sólidos de 8 × 8 en (16,16) y (32,16), un rectángulo sólido de 32 × 24 en (16,32) y una barra horizontal de 40 × 8 en (80,64). La escritura final en VBlank añade un cuadrado de 8 × 8 en (144,80). La escritura descartada en (144,24) debe dejar esa casilla vacía. DMG muestra figuras negras sobre blanco; CGB, rojas, azules y verdes sobre blanco; FC, rojas, azules y verdes sobre negro. Estas imágenes de emulador no acreditan una prueba en hardware real.
Tres patrones originales de 8 × 8 distinguen las copias: el 1 es sólido, el 2 llena las cuatro columnas izquierdas y el 3 es un triángulo alineado a la izquierda que crece de un píxel arriba a ocho abajo. El bloque de 3 × 2 casillas en (80,32) debe mostrar [1,2,3] / [3,0,2], con 0 vacío. Su primer byte cambia después de encolarlo; el patrón sólido superior izquierdo demuestra que se conserva el puntero. La copia en (16,64) muestra [1,2,3]; el alias tiles en (48,64), [2,3]. Sus tamaños son, respectivamente, 24 × 16, 24 × 8 y 16 × 8 píxeles.
En CGB, los dos cuadrados superiores, la copia de tres patrones y el cuadrado final de VBlank son rojos. El rectángulo de 32 × 24 y la copia de dos patrones son azules. El bloque de 3 × 2 casillas y la barra de 40 × 8 son verdes. El texto sigue negro sobre blanco. Se comprueba el color de cada píxel dibujado además de la geometría.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\vram.c .\kitaq-docs\samples\api-examples\gb\vram_queue_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/vram.h:41
Discard pending commands and clear the latched overflow flag without writing VRAM.
kitaqgb/lib/vram.c:41
void vram_clear_queue()
{
kq_vram_queue_used = 0;
kq_vram_queue_overflowed = 0;
}vram_flush
Espera con __wait_vblank y llama a vram_flush_now. Úsala para un lote moderado de cambios de pantalla. Una sola espera no limita la transferencia ni garantiza terminar todo el lote dentro de un VBlank.
Sintaxis
void vram_flush();Valor devuelto
Ninguno (void).
Condiciones y límites
GB cuenta espacios de comando: la capacidad predeterminada es 32. Cada función de inserción usa uno, incluso para transferencias grandes o de longitud cero. Define VRAM_QUEUE_MAX de forma uniforme en todas las unidades, entre 1 y 255. Una cola vacía tiene used=0 y free=capacity.
Coordina las fases de construcción y ejecución de la cola. No añadas durante su ejecución en una interrupción, alteres sus contadores directamente ni sobrescribas por accidente los datos retenidos. Estas API no ofrecen bloqueo ni doble búfer. La capacidad es la del búfer de comandos, no los bytes libres de VRAM física.
Dirección de destino en bytes dentro de VRAM (0x8000–0x9FFF), en el banco seleccionado al ejecutar. La transferencia es contigua, sin saltos de fila. Todo el intervalo debe ser válido. Con el LCD encendido, las rutas de escritura segura pueden habilitar interrupciones; no conservan un estado de entrada con interrupciones deshabilitadas.
Ejemplo de uso
vram_flush(); // One small write through the VBlank/NMI path.
if (vram_get_queue_used()!=0) failures++;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El programa completo enseña escrituras diferidas, control de capacidad y recuperación del desbordamiento. Siete llamadas de dibujo usan 7 de 32 espacios en GB, o 52 de 128 bytes en FC: CAPACITY/USED/FREE muestra 032/007/025 o 128/052/076. AFTER FLUSH y FAILED CHECKS deben ser 000; OVERFLOW SEEN, 001. Se intenta añadir a una cola llena para comprobar el indicador: leer o ejecutar no lo borra; vaciar la cola sí. En FC también se comprueba que la ejecución directa sin confirmar conserve la cola pendiente.
Las coordenadas de imagen son píxeles desde la esquina superior izquierda. Deben aparecer cuadrados sólidos de 8 × 8 en (16,16) y (32,16), un rectángulo sólido de 32 × 24 en (16,32) y una barra horizontal de 40 × 8 en (80,64). La escritura final en VBlank añade un cuadrado de 8 × 8 en (144,80). La escritura descartada en (144,24) debe dejar esa casilla vacía. DMG muestra figuras negras sobre blanco; CGB, rojas, azules y verdes sobre blanco; FC, rojas, azules y verdes sobre negro. Estas imágenes de emulador no acreditan una prueba en hardware real.
Tres patrones originales de 8 × 8 distinguen las copias: el 1 es sólido, el 2 llena las cuatro columnas izquierdas y el 3 es un triángulo alineado a la izquierda que crece de un píxel arriba a ocho abajo. El bloque de 3 × 2 casillas en (80,32) debe mostrar [1,2,3] / [3,0,2], con 0 vacío. Su primer byte cambia después de encolarlo; el patrón sólido superior izquierdo demuestra que se conserva el puntero. La copia en (16,64) muestra [1,2,3]; el alias tiles en (48,64), [2,3]. Sus tamaños son, respectivamente, 24 × 16, 24 × 8 y 16 × 8 píxeles.
En CGB, los dos cuadrados superiores, la copia de tres patrones y el cuadrado final de VBlank son rojos. El rectángulo de 32 × 24 y la copia de dos patrones son azules. El bloque de 3 × 2 casillas y la barra de 40 × 8 son verdes. El texto sigue negro sobre blanco. Se comprueba el color de cada píxel dibujado además de la geometría.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\vram.c .\kitaq-docs\samples\api-examples\gb\vram_queue_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/vram.h:64
Wait for VBlank before executing the queue. Waiting once does not itself limit the queued workload to the available VBlank duration.
kitaqgb/lib/vram.c:148
void vram_flush()
{
__wait_vblank();
vram_flush_now();
}vram_flush_now
Ejecuta todos los comandos en orden y pone a cero el número usado. No espera a VBlank por sí misma. Con el LCD encendido, las intrínsecas seguras esperan los periodos escribibles, pero una cola grande puede abarcar varias líneas o fotogramas. El indicador de desbordamiento se conserva.
Sintaxis
void vram_flush_now();Valor devuelto
Ninguno (void).
Condiciones y límites
GB cuenta espacios de comando: la capacidad predeterminada es 32. Cada función de inserción usa uno, incluso para transferencias grandes o de longitud cero. Define VRAM_QUEUE_MAX de forma uniforme en todas las unidades, entre 1 y 255. Una cola vacía tiene used=0 y free=capacity.
Coordina las fases de construcción y ejecución de la cola. No añadas durante su ejecución en una interrupción, alteres sus contadores directamente ni sobrescribas por accidente los datos retenidos. Estas API no ofrecen bloqueo ni doble búfer. La capacidad es la del búfer de comandos, no los bytes libres de VRAM física.
Dirección de destino en bytes dentro de VRAM (0x8000–0x9FFF), en el banco seleccionado al ejecutar. La transferencia es contigua, sin saltos de fila. Todo el intervalo debe ser válido. Con el LCD encendido, las rutas de escritura segura pueden habilitar interrupciones; no conservan un estado de entrada con interrupciones deshabilitadas.
Ejemplo de uso
// Rendering is stopped here. On FC, commit readiness before direct execution.
vram_flush_now();
after_flush=vram_get_queue_used();
if (after_flush!=0) failures++;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El programa completo enseña escrituras diferidas, control de capacidad y recuperación del desbordamiento. Siete llamadas de dibujo usan 7 de 32 espacios en GB, o 52 de 128 bytes en FC: CAPACITY/USED/FREE muestra 032/007/025 o 128/052/076. AFTER FLUSH y FAILED CHECKS deben ser 000; OVERFLOW SEEN, 001. Se intenta añadir a una cola llena para comprobar el indicador: leer o ejecutar no lo borra; vaciar la cola sí. En FC también se comprueba que la ejecución directa sin confirmar conserve la cola pendiente.
Las coordenadas de imagen son píxeles desde la esquina superior izquierda. Deben aparecer cuadrados sólidos de 8 × 8 en (16,16) y (32,16), un rectángulo sólido de 32 × 24 en (16,32) y una barra horizontal de 40 × 8 en (80,64). La escritura final en VBlank añade un cuadrado de 8 × 8 en (144,80). La escritura descartada en (144,24) debe dejar esa casilla vacía. DMG muestra figuras negras sobre blanco; CGB, rojas, azules y verdes sobre blanco; FC, rojas, azules y verdes sobre negro. Estas imágenes de emulador no acreditan una prueba en hardware real.
Tres patrones originales de 8 × 8 distinguen las copias: el 1 es sólido, el 2 llena las cuatro columnas izquierdas y el 3 es un triángulo alineado a la izquierda que crece de un píxel arriba a ocho abajo. El bloque de 3 × 2 casillas en (80,32) debe mostrar [1,2,3] / [3,0,2], con 0 vacío. Su primer byte cambia después de encolarlo; el patrón sólido superior izquierdo demuestra que se conserva el puntero. La copia en (16,64) muestra [1,2,3]; el alias tiles en (48,64), [2,3]. Sus tamaños son, respectivamente, 24 × 16, 24 × 8 y 16 × 8 píxeles.
En CGB, los dos cuadrados superiores, la copia de tres patrones y el cuadrado final de VBlank son rojos. El rectángulo de 32 × 24 y la copia de dos patrones son azules. El bloque de 3 × 2 casillas y la barra de 40 × 8 son verdes. El texto sigue negro sobre blanco. Se comprueba el color de cada píxel dibujado además de la geometría.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\vram.c .\kitaq-docs\samples\api-examples\gb\vram_queue_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/vram.h:61
Execute pending commands in insertion order without waiting for VBlank here. The caller must arrange suitable VRAM access timing and a sufficient transfer budget. Only the used count is cleared; overflow stays latched until an explicit reset.
kitaqgb/lib/vram.c:125
void vram_flush_now()
{
u8 i = 0;
while (i < kq_vram_queue_used) {
VramCommand* cmd = &kq_vram_queue[(__safe_index u8)i];
if (cmd->kind == VRAM_CMD_BG_TILE) {
__settile_xy(cmd->x, cmd->y, cmd->value);
} else if (cmd->kind == VRAM_CMD_BG_RECT) {
__settile_rect(cmd->x, cmd->y, cmd->w, cmd->h, cmd->value);
} else if (cmd->kind == VRAM_CMD_BG_BLOCK) {
__settilemap_rect(cmd->dst, cmd->x, cmd->y, cmd->w, cmd->h, cmd->src);
} else if (cmd->kind == VRAM_CMD_MEMCPY) {
__vram_copy(cmd->dst, cmd->src, cmd->len);
} else if (cmd->kind == VRAM_CMD_MEMSET) {
__vram_fill(cmd->dst, cmd->value, cmd->len);
}
i++;
}
kq_vram_queue_used = 0;
}vram_get_overflowed
Lee la marca de desbordamiento sin borrarla; puede reflejar un fallo anterior.
Sintaxis
u8 vram_get_overflowed();Valor devuelto
0 si no hay desbordamiento memorizado; 1 tras rechazar una inserción hasta un reinicio explícito. Ejecutar la cola no lo borra.
Condiciones y límites
GB cuenta espacios de comando: la capacidad predeterminada es 32. Cada función de inserción usa uno, incluso para transferencias grandes o de longitud cero. Define VRAM_QUEUE_MAX de forma uniforme en todas las unidades, entre 1 y 255. Una cola vacía tiene used=0 y free=capacity.
Coordina las fases de construcción y ejecución de la cola. No añadas durante su ejecución en una interrupción, alteres sus contadores directamente ni sobrescribas por accidente los datos retenidos. Estas API no ofrecen bloqueo ni doble búfer. La capacidad es la del búfer de comandos, no los bytes libres de VRAM física.
Ejemplo de uso
overflow_seen=vram_get_overflowed();
if (overflow_seen!=1) failures++;
// Reading the latch again does not clear it.
if (vram_get_overflowed()!=1) failures++;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El programa completo enseña escrituras diferidas, control de capacidad y recuperación del desbordamiento. Siete llamadas de dibujo usan 7 de 32 espacios en GB, o 52 de 128 bytes en FC: CAPACITY/USED/FREE muestra 032/007/025 o 128/052/076. AFTER FLUSH y FAILED CHECKS deben ser 000; OVERFLOW SEEN, 001. Se intenta añadir a una cola llena para comprobar el indicador: leer o ejecutar no lo borra; vaciar la cola sí. En FC también se comprueba que la ejecución directa sin confirmar conserve la cola pendiente.
Las coordenadas de imagen son píxeles desde la esquina superior izquierda. Deben aparecer cuadrados sólidos de 8 × 8 en (16,16) y (32,16), un rectángulo sólido de 32 × 24 en (16,32) y una barra horizontal de 40 × 8 en (80,64). La escritura final en VBlank añade un cuadrado de 8 × 8 en (144,80). La escritura descartada en (144,24) debe dejar esa casilla vacía. DMG muestra figuras negras sobre blanco; CGB, rojas, azules y verdes sobre blanco; FC, rojas, azules y verdes sobre negro. Estas imágenes de emulador no acreditan una prueba en hardware real.
Tres patrones originales de 8 × 8 distinguen las copias: el 1 es sólido, el 2 llena las cuatro columnas izquierdas y el 3 es un triángulo alineado a la izquierda que crece de un píxel arriba a ocho abajo. El bloque de 3 × 2 casillas en (80,32) debe mostrar [1,2,3] / [3,0,2], con 0 vacío. Su primer byte cambia después de encolarlo; el patrón sólido superior izquierdo demuestra que se conserva el puntero. La copia en (16,64) muestra [1,2,3]; el alias tiles en (48,64), [2,3]. Sus tamaños son, respectivamente, 24 × 16, 24 × 8 y 16 × 8 píxeles.
En CGB, los dos cuadrados superiores, la copia de tres patrones y el cuadrado final de VBlank son rojos. El rectángulo de 32 × 24 y la copia de dos patrones son azules. El bloque de 3 × 2 casillas y la barra de 40 × 8 son verdes. El texto sigue negro sobre blanco. Se comprueba el color de cada píxel dibujado además de la geometría.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\vram.c .\kitaq-docs\samples\api-examples\gb\vram_queue_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/vram.h:73
Read the overflow latch without clearing it.
kitaqgb/lib/vram.c:175
u8 vram_get_overflowed()
{
return kq_vram_queue_overflowed;
}vram_get_queue_capacity
Consulte los cambios y la verificación del 2026-10-03 para las diferencias locales de esta API.
Devuelve la capacidad total del búfer de comandos, independientemente de su uso actual.
Sintaxis
u8 vram_get_queue_capacity();Valor devuelto
Un byte sin signo en las unidades de la plataforma indicadas aquí. Leerlo no modifica ni ejecuta la cola.
Condiciones y límites
GB cuenta espacios de comando: la capacidad predeterminada es 32. Cada función de inserción usa uno, incluso para transferencias grandes o de longitud cero. Define VRAM_QUEUE_MAX de forma uniforme en todas las unidades, entre 1 y 255. Una cola vacía tiene used=0 y free=capacity.
Coordina las fases de construcción y ejecución de la cola. No añadas durante su ejecución en una interrupción, alteres sus contadores directamente ni sobrescribas por accidente los datos retenidos. Estas API no ofrecen bloqueo ni doble búfer. La capacidad es la del búfer de comandos, no los bytes libres de VRAM física.
Ejemplo de uso
capacity=vram_get_queue_capacity();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El programa completo enseña escrituras diferidas, control de capacidad y recuperación del desbordamiento. Siete llamadas de dibujo usan 7 de 32 espacios en GB, o 52 de 128 bytes en FC: CAPACITY/USED/FREE muestra 032/007/025 o 128/052/076. AFTER FLUSH y FAILED CHECKS deben ser 000; OVERFLOW SEEN, 001. Se intenta añadir a una cola llena para comprobar el indicador: leer o ejecutar no lo borra; vaciar la cola sí. En FC también se comprueba que la ejecución directa sin confirmar conserve la cola pendiente.
Las coordenadas de imagen son píxeles desde la esquina superior izquierda. Deben aparecer cuadrados sólidos de 8 × 8 en (16,16) y (32,16), un rectángulo sólido de 32 × 24 en (16,32) y una barra horizontal de 40 × 8 en (80,64). La escritura final en VBlank añade un cuadrado de 8 × 8 en (144,80). La escritura descartada en (144,24) debe dejar esa casilla vacía. DMG muestra figuras negras sobre blanco; CGB, rojas, azules y verdes sobre blanco; FC, rojas, azules y verdes sobre negro. Estas imágenes de emulador no acreditan una prueba en hardware real.
Tres patrones originales de 8 × 8 distinguen las copias: el 1 es sólido, el 2 llena las cuatro columnas izquierdas y el 3 es un triángulo alineado a la izquierda que crece de un píxel arriba a ocho abajo. El bloque de 3 × 2 casillas en (80,32) debe mostrar [1,2,3] / [3,0,2], con 0 vacío. Su primer byte cambia después de encolarlo; el patrón sólido superior izquierdo demuestra que se conserva el puntero. La copia en (16,64) muestra [1,2,3]; el alias tiles en (48,64), [2,3]. Sus tamaños son, respectivamente, 24 × 16, 24 × 8 y 16 × 8 píxeles.
En CGB, los dos cuadrados superiores, la copia de tres patrones y el cuadrado final de VBlank son rojos. El rectángulo de 32 × 24 y la copia de dos patrones son azules. El bloque de 3 × 2 casillas y la barra de 40 × 8 son verdes. El texto sigue negro sobre blanco. Se comprueba el color de cada píxel dibujado además de la geometría.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\vram.c .\kitaq-docs\samples\api-examples\gb\vram_queue_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/vram.h:69
Return the total number of command slots, independent of queue usage. This is command-buffer capacity, not free space in hardware VRAM.
kitaqgb/lib/vram.c:162
u8 vram_get_queue_capacity()
{
return VRAM_QUEUE_MAX;
}vram_get_queue_free
Devuelve la capacidad total menos el uso actual. Comprueba antes de añadir si cabe todo el registro o lote siguiente; esta consulta no reserva espacio.
Sintaxis
u8 vram_get_queue_free();Valor devuelto
Un byte sin signo en las unidades de la plataforma indicadas aquí. Leerlo no modifica ni ejecuta la cola.
Condiciones y límites
GB cuenta espacios de comando: la capacidad predeterminada es 32. Cada función de inserción usa uno, incluso para transferencias grandes o de longitud cero. Define VRAM_QUEUE_MAX de forma uniforme en todas las unidades, entre 1 y 255. Una cola vacía tiene used=0 y free=capacity.
Coordina las fases de construcción y ejecución de la cola. No añadas durante su ejecución en una interrupción, alteres sus contadores directamente ni sobrescribas por accidente los datos retenidos. Estas API no ofrecen bloqueo ni doble búfer. La capacidad es la del búfer de comandos, no los bytes libres de VRAM física.
Ejemplo de uso
available=vram_get_queue_free();
if (used+available!=capacity) failures++;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El programa completo enseña escrituras diferidas, control de capacidad y recuperación del desbordamiento. Siete llamadas de dibujo usan 7 de 32 espacios en GB, o 52 de 128 bytes en FC: CAPACITY/USED/FREE muestra 032/007/025 o 128/052/076. AFTER FLUSH y FAILED CHECKS deben ser 000; OVERFLOW SEEN, 001. Se intenta añadir a una cola llena para comprobar el indicador: leer o ejecutar no lo borra; vaciar la cola sí. En FC también se comprueba que la ejecución directa sin confirmar conserve la cola pendiente.
Las coordenadas de imagen son píxeles desde la esquina superior izquierda. Deben aparecer cuadrados sólidos de 8 × 8 en (16,16) y (32,16), un rectángulo sólido de 32 × 24 en (16,32) y una barra horizontal de 40 × 8 en (80,64). La escritura final en VBlank añade un cuadrado de 8 × 8 en (144,80). La escritura descartada en (144,24) debe dejar esa casilla vacía. DMG muestra figuras negras sobre blanco; CGB, rojas, azules y verdes sobre blanco; FC, rojas, azules y verdes sobre negro. Estas imágenes de emulador no acreditan una prueba en hardware real.
Tres patrones originales de 8 × 8 distinguen las copias: el 1 es sólido, el 2 llena las cuatro columnas izquierdas y el 3 es un triángulo alineado a la izquierda que crece de un píxel arriba a ocho abajo. El bloque de 3 × 2 casillas en (80,32) debe mostrar [1,2,3] / [3,0,2], con 0 vacío. Su primer byte cambia después de encolarlo; el patrón sólido superior izquierdo demuestra que se conserva el puntero. La copia en (16,64) muestra [1,2,3]; el alias tiles en (48,64), [2,3]. Sus tamaños son, respectivamente, 24 × 16, 24 × 8 y 16 × 8 píxeles.
En CGB, los dos cuadrados superiores, la copia de tres patrones y el cuadrado final de VBlank son rojos. El rectángulo de 32 × 24 y la copia de dos patrones son azules. El bloque de 3 × 2 casillas y la barra de 40 × 8 son verdes. El texto sigue negro sobre blanco. Se comprueba el color de cada píxel dibujado además de la geometría.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\vram.c .\kitaq-docs\samples\api-examples\gb\vram_queue_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/vram.h:71
Return the remaining command-slot capacity.
kitaqgb/lib/vram.c:169
u8 vram_get_queue_free()
{
return (u8)(VRAM_QUEUE_MAX - kq_vram_queue_used);
}vram_get_queue_used
Devuelve el espacio del búfer ocupado por los comandos pendientes, no los bytes que se escribirán en memoria de vídeo.
Sintaxis
u8 vram_get_queue_used();Valor devuelto
Un byte sin signo en las unidades de la plataforma indicadas aquí. Leerlo no modifica ni ejecuta la cola.
Condiciones y límites
GB cuenta espacios de comando: la capacidad predeterminada es 32. Cada función de inserción usa uno, incluso para transferencias grandes o de longitud cero. Define VRAM_QUEUE_MAX de forma uniforme en todas las unidades, entre 1 y 255. Una cola vacía tiene used=0 y free=capacity.
Coordina las fases de construcción y ejecución de la cola. No añadas durante su ejecución en una interrupción, alteres sus contadores directamente ni sobrescribas por accidente los datos retenidos. Estas API no ofrecen bloqueo ni doble búfer. La capacidad es la del búfer de comandos, no los bytes libres de VRAM física.
Ejemplo de uso
used=vram_get_queue_used();Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El programa completo enseña escrituras diferidas, control de capacidad y recuperación del desbordamiento. Siete llamadas de dibujo usan 7 de 32 espacios en GB, o 52 de 128 bytes en FC: CAPACITY/USED/FREE muestra 032/007/025 o 128/052/076. AFTER FLUSH y FAILED CHECKS deben ser 000; OVERFLOW SEEN, 001. Se intenta añadir a una cola llena para comprobar el indicador: leer o ejecutar no lo borra; vaciar la cola sí. En FC también se comprueba que la ejecución directa sin confirmar conserve la cola pendiente.
Las coordenadas de imagen son píxeles desde la esquina superior izquierda. Deben aparecer cuadrados sólidos de 8 × 8 en (16,16) y (32,16), un rectángulo sólido de 32 × 24 en (16,32) y una barra horizontal de 40 × 8 en (80,64). La escritura final en VBlank añade un cuadrado de 8 × 8 en (144,80). La escritura descartada en (144,24) debe dejar esa casilla vacía. DMG muestra figuras negras sobre blanco; CGB, rojas, azules y verdes sobre blanco; FC, rojas, azules y verdes sobre negro. Estas imágenes de emulador no acreditan una prueba en hardware real.
Tres patrones originales de 8 × 8 distinguen las copias: el 1 es sólido, el 2 llena las cuatro columnas izquierdas y el 3 es un triángulo alineado a la izquierda que crece de un píxel arriba a ocho abajo. El bloque de 3 × 2 casillas en (80,32) debe mostrar [1,2,3] / [3,0,2], con 0 vacío. Su primer byte cambia después de encolarlo; el patrón sólido superior izquierdo demuestra que se conserva el puntero. La copia en (16,64) muestra [1,2,3]; el alias tiles en (48,64), [2,3]. Sus tamaños son, respectivamente, 24 × 16, 24 × 8 y 16 × 8 píxeles.
En CGB, los dos cuadrados superiores, la copia de tres patrones y el cuadrado final de VBlank son rojos. El rectángulo de 32 × 24 y la copia de dos patrones son azules. El bloque de 3 × 2 casillas y la barra de 40 × 8 son verdes. El texto sigue negro sobre blanco. Se comprueba el color de cada píxel dibujado además de la geometría.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\vram.c .\kitaq-docs\samples\api-examples\gb\vram_queue_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/vram.h:66
Return the number of queued commands, not the number of transfer bytes.
kitaqgb/lib/vram.c:155
u8 vram_get_queue_used()
{
return kq_vram_queue_used;
}vram_init
Inicializa vacía la cola de escrituras VRAM diferidas y borra su indicador de desbordamiento. No borra la pantalla, carga gráficos de tiles ni reserva VRAM física.
Sintaxis
void vram_init();Valor devuelto
Ninguno (void).
Condiciones y límites
GB cuenta espacios de comando: la capacidad predeterminada es 32. Cada función de inserción usa uno, incluso para transferencias grandes o de longitud cero. Define VRAM_QUEUE_MAX de forma uniforme en todas las unidades, entre 1 y 255. Una cola vacía tiene used=0 y free=capacity.
Coordina las fases de construcción y ejecución de la cola. No añadas durante su ejecución en una interrupción, alteres sus contadores directamente ni sobrescribas por accidente los datos retenidos. Estas API no ofrecen bloqueo ni doble búfer. La capacidad es la del búfer de comandos, no los bytes libres de VRAM física.
Ejemplo de uso
vram_init();
if (vram_get_queue_used()!=0 || vram_get_overflowed()!=0) failures++;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El programa completo enseña escrituras diferidas, control de capacidad y recuperación del desbordamiento. Siete llamadas de dibujo usan 7 de 32 espacios en GB, o 52 de 128 bytes en FC: CAPACITY/USED/FREE muestra 032/007/025 o 128/052/076. AFTER FLUSH y FAILED CHECKS deben ser 000; OVERFLOW SEEN, 001. Se intenta añadir a una cola llena para comprobar el indicador: leer o ejecutar no lo borra; vaciar la cola sí. En FC también se comprueba que la ejecución directa sin confirmar conserve la cola pendiente.
Las coordenadas de imagen son píxeles desde la esquina superior izquierda. Deben aparecer cuadrados sólidos de 8 × 8 en (16,16) y (32,16), un rectángulo sólido de 32 × 24 en (16,32) y una barra horizontal de 40 × 8 en (80,64). La escritura final en VBlank añade un cuadrado de 8 × 8 en (144,80). La escritura descartada en (144,24) debe dejar esa casilla vacía. DMG muestra figuras negras sobre blanco; CGB, rojas, azules y verdes sobre blanco; FC, rojas, azules y verdes sobre negro. Estas imágenes de emulador no acreditan una prueba en hardware real.
Tres patrones originales de 8 × 8 distinguen las copias: el 1 es sólido, el 2 llena las cuatro columnas izquierdas y el 3 es un triángulo alineado a la izquierda que crece de un píxel arriba a ocho abajo. El bloque de 3 × 2 casillas en (80,32) debe mostrar [1,2,3] / [3,0,2], con 0 vacío. Su primer byte cambia después de encolarlo; el patrón sólido superior izquierdo demuestra que se conserva el puntero. La copia en (16,64) muestra [1,2,3]; el alias tiles en (48,64), [2,3]. Sus tamaños son, respectivamente, 24 × 16, 24 × 8 y 16 × 8 píxeles.
En CGB, los dos cuadrados superiores, la copia de tres patrones y el cuadrado final de VBlank son rojos. El rectángulo de 32 × 24 y la copia de dos patrones son azules. El bloque de 3 × 2 casillas y la barra de 40 × 8 son verdes. El texto sigue negro sobre blanco. Se comprueba el color de cada píxel dibujado además de la geometría.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\vram.c .\kitaq-docs\samples\api-examples\gb\vram_queue_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/vram.h:39
Start with an empty command queue and a clear overflow flag.
kitaqgb/lib/vram.c:34
void vram_init()
{
kq_vram_queue_used = 0;
kq_vram_queue_overflowed = 0;
}vram_queue_bg_block
Encola un rectángulo de w × h números de tile desde src al mapa en base. Cada fila de origen ocupa w bytes consecutivos; las filas de destino están separadas por 32 bytes. Se conserva el puntero, por lo que modificar el origen antes de ejecutar cambia el bloque mostrado.
Sintaxis
u8 vram_queue_bg_block(u16 base, u8 x, u8 y, u8 w, u8 h, const u8* src);Parámetros
baseLos comandos de casilla y rectángulo eligen el mapa de fondo mediante el bit 3 de LCDC al ejecutarse. En CGB, usa el banco VRAM 0 para los índices de patrón. El bloque utiliza la base indicada, normalmente
0x9800o0x9C00. Cada fila ocupa 32 bytes y no se recortan las coordenadas.x, yCoordenadas superiores izquierdas en tiles de 8×8, no píxeles. No hay recorte. Mantén
x + w <= 32yy + h <= 32en GB, o<= 30en el área de tiles de una nametable FC. Un tile individual tiene ancho y alto 1.w, hAncho y alto en tiles como bytes sin signo. El bloque fuente contiene
w * hbytes por filas. Dimensiones cero no producen escrituras visibles, pero el consumo de cola sigue las reglas de la plataforma.srcPuntero cercano a bytes legibles, conservado hasta la ejecución. Mantén los datos vivos y su banco de memoria o ROM visible durante toda la ejecución; no se guarda un número de banco ni una copia. Una transferencia no vacía necesita un origen válido. No uses un array local que haya caducado.
Valor devuelto
1 si este comando se encoló; 0 si no había espacio. El fallo activa el indicador de desbordamiento y conserva los comandos previos. Un desbordamiento anterior no hace que una inserción posterior correcta devuelva 0.
Condiciones y límites
GB cuenta espacios de comando: la capacidad predeterminada es 32. Cada función de inserción usa uno, incluso para transferencias grandes o de longitud cero. Define VRAM_QUEUE_MAX de forma uniforme en todas las unidades, entre 1 y 255. Una cola vacía tiene used=0 y free=capacity.
Los comandos de casilla y rectángulo eligen el mapa de fondo mediante el bit 3 de LCDC al ejecutarse. En CGB, usa el banco VRAM 0 para los índices de patrón. El bloque utiliza la base indicada, normalmente 0x9800 o 0x9C00. Cada fila ocupa 32 bytes y no se recortan las coordenadas.
Coordina las fases de construcción y ejecución de la cola. No añadas durante su ejecución en una interrupción, alteres sus contadores directamente ni sobrescribas por accidente los datos retenidos. Estas API no ofrecen bloqueo ni doble búfer. La capacidad es la del búfer de comandos, no los bytes libres de VRAM física.
Ejemplo de uso
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++;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El programa completo enseña escrituras diferidas, control de capacidad y recuperación del desbordamiento. Siete llamadas de dibujo usan 7 de 32 espacios en GB, o 52 de 128 bytes en FC: CAPACITY/USED/FREE muestra 032/007/025 o 128/052/076. AFTER FLUSH y FAILED CHECKS deben ser 000; OVERFLOW SEEN, 001. Se intenta añadir a una cola llena para comprobar el indicador: leer o ejecutar no lo borra; vaciar la cola sí. En FC también se comprueba que la ejecución directa sin confirmar conserve la cola pendiente.
Las coordenadas de imagen son píxeles desde la esquina superior izquierda. Deben aparecer cuadrados sólidos de 8 × 8 en (16,16) y (32,16), un rectángulo sólido de 32 × 24 en (16,32) y una barra horizontal de 40 × 8 en (80,64). La escritura final en VBlank añade un cuadrado de 8 × 8 en (144,80). La escritura descartada en (144,24) debe dejar esa casilla vacía. DMG muestra figuras negras sobre blanco; CGB, rojas, azules y verdes sobre blanco; FC, rojas, azules y verdes sobre negro. Estas imágenes de emulador no acreditan una prueba en hardware real.
Tres patrones originales de 8 × 8 distinguen las copias: el 1 es sólido, el 2 llena las cuatro columnas izquierdas y el 3 es un triángulo alineado a la izquierda que crece de un píxel arriba a ocho abajo. El bloque de 3 × 2 casillas en (80,32) debe mostrar [1,2,3] / [3,0,2], con 0 vacío. Su primer byte cambia después de encolarlo; el patrón sólido superior izquierdo demuestra que se conserva el puntero. La copia en (16,64) muestra [1,2,3]; el alias tiles en (48,64), [2,3]. Sus tamaños son, respectivamente, 24 × 16, 24 × 8 y 16 × 8 píxeles.
En CGB, los dos cuadrados superiores, la copia de tres patrones y el cuadrado final de VBlank son rojos. El rectángulo de 32 × 24 y la copia de dos patrones son azules. El bloque de 3 × 2 casillas y la barra de 40 × 8 son verdes. El texto sigue negro sobre blanco. Se comprueba el color de cada píxel dibujado además de la geometría.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\vram.c .\kitaq-docs\samples\api-examples\gb\vram_queue_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/vram.h:50
Queue a tile-map rectangle while retaining src rather than copying its bytes. Keep the source data and its ROM bank accessible until the queue is flushed.
kitaqgb/lib/vram.c:79
u8 vram_queue_bg_block(u16 base, u8 x, u8 y, u8 w, u8 h, const u8* src)
{
VramCommand* cmd = vram_push(VRAM_CMD_BG_BLOCK);
if (cmd == 0) return 0;
cmd->dst = base;
cmd->x = x;
cmd->y = y;
cmd->w = w;
cmd->h = h;
cmd->src = src;
return 1;
}vram_queue_bg_rect
Encola un rectángulo del mapa de fondo relleno con el mismo número de tile. La esquina superior izquierda es (x, y) y el tamaño es w × h tiles. Un tile uniforme forma un rectángulo sólido; uno con dibujo repite ese dibujo en cada celda.
Sintaxis
u8 vram_queue_bg_rect(u8 x, u8 y, u8 w, u8 h, u8 tile);Parámetros
x, yCoordenadas superiores izquierdas en tiles de 8×8, no píxeles. No hay recorte. Mantén
x + w <= 32yy + h <= 32en GB, o<= 30en el área de tiles de una nametable FC. Un tile individual tiene ancho y alto 1.w, hAncho y alto en tiles como bytes sin signo. El bloque fuente contiene
w * hbytes por filas. Dimensiones cero no producen escrituras visibles, pero el consumo de cola sigue las reglas de la plataforma.tileByte del mapa, de 0 a 255. Carga el gráfico por separado y selecciona la tabla de patrones o modo de direccionamiento adecuado. No es un puntero ni un color.
Valor devuelto
1 si este comando se encoló; 0 si no había espacio. El fallo activa el indicador de desbordamiento y conserva los comandos previos. Un desbordamiento anterior no hace que una inserción posterior correcta devuelva 0.
Condiciones y límites
GB cuenta espacios de comando: la capacidad predeterminada es 32. Cada función de inserción usa uno, incluso para transferencias grandes o de longitud cero. Define VRAM_QUEUE_MAX de forma uniforme en todas las unidades, entre 1 y 255. Una cola vacía tiene used=0 y free=capacity.
Los comandos de casilla y rectángulo eligen el mapa de fondo mediante el bit 3 de LCDC al ejecutarse. En CGB, usa el banco VRAM 0 para los índices de patrón. El bloque utiliza la base indicada, normalmente 0x9800 o 0x9C00. Cada fila ocupa 32 bytes y no se recortan las coordenadas.
Coordina las fases de construcción y ejecución de la cola. No añadas durante su ejecución en una interrupción, alteres sus contadores directamente ni sobrescribas por accidente los datos retenidos. Estas API no ofrecen bloqueo ni doble búfer. La capacidad es la del búfer de comandos, no los bytes libres de VRAM física.
Ejemplo de uso
check_result=vram_queue_bg_rect(2,4,4,3,1); // A filled 32x24 rectangle at (16,32).
if (check_result!=1) failures++;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El programa completo enseña escrituras diferidas, control de capacidad y recuperación del desbordamiento. Siete llamadas de dibujo usan 7 de 32 espacios en GB, o 52 de 128 bytes en FC: CAPACITY/USED/FREE muestra 032/007/025 o 128/052/076. AFTER FLUSH y FAILED CHECKS deben ser 000; OVERFLOW SEEN, 001. Se intenta añadir a una cola llena para comprobar el indicador: leer o ejecutar no lo borra; vaciar la cola sí. En FC también se comprueba que la ejecución directa sin confirmar conserve la cola pendiente.
Las coordenadas de imagen son píxeles desde la esquina superior izquierda. Deben aparecer cuadrados sólidos de 8 × 8 en (16,16) y (32,16), un rectángulo sólido de 32 × 24 en (16,32) y una barra horizontal de 40 × 8 en (80,64). La escritura final en VBlank añade un cuadrado de 8 × 8 en (144,80). La escritura descartada en (144,24) debe dejar esa casilla vacía. DMG muestra figuras negras sobre blanco; CGB, rojas, azules y verdes sobre blanco; FC, rojas, azules y verdes sobre negro. Estas imágenes de emulador no acreditan una prueba en hardware real.
Tres patrones originales de 8 × 8 distinguen las copias: el 1 es sólido, el 2 llena las cuatro columnas izquierdas y el 3 es un triángulo alineado a la izquierda que crece de un píxel arriba a ocho abajo. El bloque de 3 × 2 casillas en (80,32) debe mostrar [1,2,3] / [3,0,2], con 0 vacío. Su primer byte cambia después de encolarlo; el patrón sólido superior izquierdo demuestra que se conserva el puntero. La copia en (16,64) muestra [1,2,3]; el alias tiles en (48,64), [2,3]. Sus tamaños son, respectivamente, 24 × 16, 24 × 8 y 16 × 8 píxeles.
En CGB, los dos cuadrados superiores, la copia de tres patrones y el cuadrado final de VBlank son rojos. El rectángulo de 32 × 24 y la copia de dos patrones son azules. El bloque de 3 × 2 casillas y la barra de 40 × 8 son verdes. El texto sigue negro sobre blanco. Se comprueba el color de cada píxel dibujado además de la geometría.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\vram.c .\kitaq-docs\samples\api-examples\gb\vram_queue_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/vram.h:47
Queue a rectangle filled with one tile value; coordinates and dimensions are in tiles.
kitaqgb/lib/vram.c:65
u8 vram_queue_bg_rect(u8 x, u8 y, u8 w, u8 h, u8 tile)
{
VramCommand* cmd = vram_push(VRAM_CMD_BG_RECT);
if (cmd == 0) return 0;
cmd->x = x;
cmd->y = y;
cmd->w = w;
cmd->h = h;
cmd->value = tile;
return 1;
}vram_queue_bg_tile
Encola la escritura de un número de tile de fondo en (x, y). El cambio visible ocurre al ejecutar la cola. Escribe una entrada del mapa; no carga los píxeles del tile ni cambia sus atributos de paleta.
Sintaxis
u8 vram_queue_bg_tile(u8 x, u8 y, u8 tile);Parámetros
x, yCoordenadas superiores izquierdas en tiles de 8×8, no píxeles. No hay recorte. Mantén
x + w <= 32yy + h <= 32en GB, o<= 30en el área de tiles de una nametable FC. Un tile individual tiene ancho y alto 1.tileByte del mapa, de 0 a 255. Carga el gráfico por separado y selecciona la tabla de patrones o modo de direccionamiento adecuado. No es un puntero ni un color.
Valor devuelto
1 si este comando se encoló; 0 si no había espacio. El fallo activa el indicador de desbordamiento y conserva los comandos previos. Un desbordamiento anterior no hace que una inserción posterior correcta devuelva 0.
Condiciones y límites
GB cuenta espacios de comando: la capacidad predeterminada es 32. Cada función de inserción usa uno, incluso para transferencias grandes o de longitud cero. Define VRAM_QUEUE_MAX de forma uniforme en todas las unidades, entre 1 y 255. Una cola vacía tiene used=0 y free=capacity.
Los comandos de casilla y rectángulo eligen el mapa de fondo mediante el bit 3 de LCDC al ejecutarse. En CGB, usa el banco VRAM 0 para los índices de patrón. El bloque utiliza la base indicada, normalmente 0x9800 o 0x9C00. Cada fila ocupa 32 bytes y no se recortan las coordenadas.
Coordina las fases de construcción y ejecución de la cola. No añadas durante su ejecución en una interrupción, alteres sus contadores directamente ni sobrescribas por accidente los datos retenidos. Estas API no ofrecen bloqueo ni doble búfer. La capacidad es la del búfer de comandos, no los bytes libres de VRAM física.
Ejemplo de uso
check_result=vram_queue_bg_tile(2,2,1); // A solid 8x8 tile at pixel (16,16).
if (check_result!=1) failures++;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El programa completo enseña escrituras diferidas, control de capacidad y recuperación del desbordamiento. Siete llamadas de dibujo usan 7 de 32 espacios en GB, o 52 de 128 bytes en FC: CAPACITY/USED/FREE muestra 032/007/025 o 128/052/076. AFTER FLUSH y FAILED CHECKS deben ser 000; OVERFLOW SEEN, 001. Se intenta añadir a una cola llena para comprobar el indicador: leer o ejecutar no lo borra; vaciar la cola sí. En FC también se comprueba que la ejecución directa sin confirmar conserve la cola pendiente.
Las coordenadas de imagen son píxeles desde la esquina superior izquierda. Deben aparecer cuadrados sólidos de 8 × 8 en (16,16) y (32,16), un rectángulo sólido de 32 × 24 en (16,32) y una barra horizontal de 40 × 8 en (80,64). La escritura final en VBlank añade un cuadrado de 8 × 8 en (144,80). La escritura descartada en (144,24) debe dejar esa casilla vacía. DMG muestra figuras negras sobre blanco; CGB, rojas, azules y verdes sobre blanco; FC, rojas, azules y verdes sobre negro. Estas imágenes de emulador no acreditan una prueba en hardware real.
Tres patrones originales de 8 × 8 distinguen las copias: el 1 es sólido, el 2 llena las cuatro columnas izquierdas y el 3 es un triángulo alineado a la izquierda que crece de un píxel arriba a ocho abajo. El bloque de 3 × 2 casillas en (80,32) debe mostrar [1,2,3] / [3,0,2], con 0 vacío. Su primer byte cambia después de encolarlo; el patrón sólido superior izquierdo demuestra que se conserva el puntero. La copia en (16,64) muestra [1,2,3]; el alias tiles en (48,64), [2,3]. Sus tamaños son, respectivamente, 24 × 16, 24 × 8 y 16 × 8 píxeles.
En CGB, los dos cuadrados superiores, la copia de tres patrones y el cuadrado final de VBlank son rojos. El rectángulo de 32 × 24 y la copia de dos patrones son azules. El bloque de 3 × 2 casillas y la barra de 40 × 8 son verdes. El texto sigue negro sobre blanco. Se comprueba el color de cada píxel dibujado además de la geometría.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\vram.c .\kitaq-docs\samples\api-examples\gb\vram_queue_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/vram.h:43
Queue a single background tile write; return zero if no command slot is available.
kitaqgb/lib/vram.c:48
u8 vram_queue_bg_tile(u8 x, u8 y, u8 tile)
{
VramCommand* cmd = vram_push(VRAM_CMD_BG_TILE);
if (cmd == 0) return 0;
cmd->x = x;
cmd->y = y;
cmd->value = tile;
return 1;
}vram_queue_memcpy
Encola una copia de len bytes consecutivos de src a dst. Ambos avanzan byte a byte, sin salto entre filas de tiles. Puede transferir bytes de mapa o patrones escribibles, pero no convierte formatos ni calcula los bytes que ocupa un tile.
Sintaxis
u8 vram_queue_memcpy(u16 dst, const void* src, u16 len);Parámetros
dstDirección de destino en bytes dentro de VRAM (
0x8000–0x9FFF), en el banco seleccionado al ejecutar. La transferencia es contigua, sin saltos de fila. Todo el intervalo debe ser válido. Con el LCD encendido, las rutas de escritura segura pueden habilitar interrupciones; no conservan un estado de entrada con interrupciones deshabilitadas.srcPuntero cercano a bytes legibles, conservado hasta la ejecución. Mantén los datos vivos y su banco de memoria o ROM visible durante toda la ejecución; no se guarda un número de banco ni una copia. Una transferencia no vacía necesita un origen válido. No uses un array local que haya caducado.
lenNúmero de bytes consecutivos, de 0 a 65535, no de tiles. Mantén todo el rango dentro de origen válido y destino escribible; la API no comprueba límites ni evita el desbordamiento de direcciones de 16 bits.
Valor devuelto
1 si este comando se encoló; 0 si no había espacio. El fallo activa el indicador de desbordamiento y conserva los comandos previos. Un desbordamiento anterior no hace que una inserción posterior correcta devuelva 0.
Condiciones y límites
GB cuenta espacios de comando: la capacidad predeterminada es 32. Cada función de inserción usa uno, incluso para transferencias grandes o de longitud cero. Define VRAM_QUEUE_MAX de forma uniforme en todas las unidades, entre 1 y 255. Una cola vacía tiene used=0 y free=capacity.
Coordina las fases de construcción y ejecución de la cola. No añadas durante su ejecución en una interrupción, alteres sus contadores directamente ni sobrescribas por accidente los datos retenidos. Estas API no ofrecen bloqueo ni doble búfer. La capacidad es la del búfer de comandos, no los bytes libres de VRAM física.
Ejemplo de uso
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.Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El programa completo enseña escrituras diferidas, control de capacidad y recuperación del desbordamiento. Siete llamadas de dibujo usan 7 de 32 espacios en GB, o 52 de 128 bytes en FC: CAPACITY/USED/FREE muestra 032/007/025 o 128/052/076. AFTER FLUSH y FAILED CHECKS deben ser 000; OVERFLOW SEEN, 001. Se intenta añadir a una cola llena para comprobar el indicador: leer o ejecutar no lo borra; vaciar la cola sí. En FC también se comprueba que la ejecución directa sin confirmar conserve la cola pendiente.
Las coordenadas de imagen son píxeles desde la esquina superior izquierda. Deben aparecer cuadrados sólidos de 8 × 8 en (16,16) y (32,16), un rectángulo sólido de 32 × 24 en (16,32) y una barra horizontal de 40 × 8 en (80,64). La escritura final en VBlank añade un cuadrado de 8 × 8 en (144,80). La escritura descartada en (144,24) debe dejar esa casilla vacía. DMG muestra figuras negras sobre blanco; CGB, rojas, azules y verdes sobre blanco; FC, rojas, azules y verdes sobre negro. Estas imágenes de emulador no acreditan una prueba en hardware real.
Tres patrones originales de 8 × 8 distinguen las copias: el 1 es sólido, el 2 llena las cuatro columnas izquierdas y el 3 es un triángulo alineado a la izquierda que crece de un píxel arriba a ocho abajo. El bloque de 3 × 2 casillas en (80,32) debe mostrar [1,2,3] / [3,0,2], con 0 vacío. Su primer byte cambia después de encolarlo; el patrón sólido superior izquierdo demuestra que se conserva el puntero. La copia en (16,64) muestra [1,2,3]; el alias tiles en (48,64), [2,3]. Sus tamaños son, respectivamente, 24 × 16, 24 × 8 y 16 × 8 píxeles.
En CGB, los dos cuadrados superiores, la copia de tres patrones y el cuadrado final de VBlank son rojos. El rectángulo de 32 × 24 y la copia de dos patrones son azules. El bloque de 3 × 2 casillas y la barra de 40 × 8 son verdes. El texto sigue negro sobre blanco. Se comprueba el color de cada píxel dibujado además de la geometría.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\vram.c .\kitaq-docs\samples\api-examples\gb\vram_queue_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/vram.h:53
Queue a byte transfer and retain the source pointer. The source must remain valid and visible until flush; len is measured in bytes, not tiles.
kitaqgb/lib/vram.c:94
u8 vram_queue_memcpy(u16 dst, const void* src, u16 len)
{
VramCommand* cmd = vram_push(VRAM_CMD_MEMCPY);
if (cmd == 0) return 0;
cmd->dst = dst;
cmd->src = (const u8*)src;
cmd->len = len;
return 1;
}vram_queue_memset
Encola un relleno de len bytes consecutivos en dst con el byte value. Repite un byte, no un patrón de tile de varios bytes, y no introduce un salto de fila de mapa de 32 bytes.
Sintaxis
u8 vram_queue_memset(u16 dst, u8 value, u16 len);Parámetros
dstDirección de destino en bytes dentro de VRAM (
0x8000–0x9FFF), en el banco seleccionado al ejecutar. La transferencia es contigua, sin saltos de fila. Todo el intervalo debe ser válido. Con el LCD encendido, las rutas de escritura segura pueden habilitar interrupciones; no conservan un estado de entrada con interrupciones deshabilitadas.valueUn byte de 0 a 255 que se repite. Su efecto visible depende de si el destino contiene índices de tiles, planos de píxeles u otra estructura de bytes.
lenNúmero de bytes consecutivos, de 0 a 65535, no de tiles. Mantén todo el rango dentro de origen válido y destino escribible; la API no comprueba límites ni evita el desbordamiento de direcciones de 16 bits.
Valor devuelto
1 si este comando se encoló; 0 si no había espacio. El fallo activa el indicador de desbordamiento y conserva los comandos previos. Un desbordamiento anterior no hace que una inserción posterior correcta devuelva 0.
Condiciones y límites
GB cuenta espacios de comando: la capacidad predeterminada es 32. Cada función de inserción usa uno, incluso para transferencias grandes o de longitud cero. Define VRAM_QUEUE_MAX de forma uniforme en todas las unidades, entre 1 y 255. Una cola vacía tiene used=0 y free=capacity.
Coordina las fases de construcción y ejecución de la cola. No añadas durante su ejecución en una interrupción, alteres sus contadores directamente ni sobrescribas por accidente los datos retenidos. Estas API no ofrecen bloqueo ni doble búfer. La capacidad es la del búfer de comandos, no los bytes libres de VRAM física.
Ejemplo de uso
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.Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El programa completo enseña escrituras diferidas, control de capacidad y recuperación del desbordamiento. Siete llamadas de dibujo usan 7 de 32 espacios en GB, o 52 de 128 bytes en FC: CAPACITY/USED/FREE muestra 032/007/025 o 128/052/076. AFTER FLUSH y FAILED CHECKS deben ser 000; OVERFLOW SEEN, 001. Se intenta añadir a una cola llena para comprobar el indicador: leer o ejecutar no lo borra; vaciar la cola sí. En FC también se comprueba que la ejecución directa sin confirmar conserve la cola pendiente.
Las coordenadas de imagen son píxeles desde la esquina superior izquierda. Deben aparecer cuadrados sólidos de 8 × 8 en (16,16) y (32,16), un rectángulo sólido de 32 × 24 en (16,32) y una barra horizontal de 40 × 8 en (80,64). La escritura final en VBlank añade un cuadrado de 8 × 8 en (144,80). La escritura descartada en (144,24) debe dejar esa casilla vacía. DMG muestra figuras negras sobre blanco; CGB, rojas, azules y verdes sobre blanco; FC, rojas, azules y verdes sobre negro. Estas imágenes de emulador no acreditan una prueba en hardware real.
Tres patrones originales de 8 × 8 distinguen las copias: el 1 es sólido, el 2 llena las cuatro columnas izquierdas y el 3 es un triángulo alineado a la izquierda que crece de un píxel arriba a ocho abajo. El bloque de 3 × 2 casillas en (80,32) debe mostrar [1,2,3] / [3,0,2], con 0 vacío. Su primer byte cambia después de encolarlo; el patrón sólido superior izquierdo demuestra que se conserva el puntero. La copia en (16,64) muestra [1,2,3]; el alias tiles en (48,64), [2,3]. Sus tamaños son, respectivamente, 24 × 16, 24 × 8 y 16 × 8 píxeles.
En CGB, los dos cuadrados superiores, la copia de tres patrones y el cuadrado final de VBlank son rojos. El rectángulo de 32 × 24 y la copia de dos patrones son azules. El bloque de 3 × 2 casillas y la barra de 40 × 8 son verdes. El texto sigue negro sobre blanco. Se comprueba el color de cada píxel dibujado además de la geometría.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\vram.c .\kitaq-docs\samples\api-examples\gb\vram_queue_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/vram.h:57
Queue a byte fill and return zero if the command queue is full.
kitaqgb/lib/vram.c:111
u8 vram_queue_memset(u16 dst, u8 value, u16 len)
{
VramCommand* cmd = vram_push(VRAM_CMD_MEMSET);
if (cmd == 0) return 0;
cmd->dst = dst;
cmd->value = value;
cmd->len = len;
return 1;
}vram_queue_tile
vram_queue_tile llama directamente a vram_queue_bg_tile con los mismos argumentos y devuelve su resultado. Es el nombre corto para una entrada del mapa de fondo, no una operación de sprites ni una carga de gráficos.
Sintaxis
u8 vram_queue_tile(u8 x, u8 y, u8 tile);Parámetros
x, yCoordenadas superiores izquierdas en tiles de 8×8, no píxeles. No hay recorte. Mantén
x + w <= 32yy + h <= 32en GB, o<= 30en el área de tiles de una nametable FC. Un tile individual tiene ancho y alto 1.tileByte del mapa, de 0 a 255. Carga el gráfico por separado y selecciona la tabla de patrones o modo de direccionamiento adecuado. No es un puntero ni un color.
Valor devuelto
1 si este comando se encoló; 0 si no había espacio. El fallo activa el indicador de desbordamiento y conserva los comandos previos. Un desbordamiento anterior no hace que una inserción posterior correcta devuelva 0.
Condiciones y límites
GB cuenta espacios de comando: la capacidad predeterminada es 32. Cada función de inserción usa uno, incluso para transferencias grandes o de longitud cero. Define VRAM_QUEUE_MAX de forma uniforme en todas las unidades, entre 1 y 255. Una cola vacía tiene used=0 y free=capacity.
Los comandos de casilla y rectángulo eligen el mapa de fondo mediante el bit 3 de LCDC al ejecutarse. En CGB, usa el banco VRAM 0 para los índices de patrón. El bloque utiliza la base indicada, normalmente 0x9800 o 0x9C00. Cada fila ocupa 32 bytes y no se recortan las coordenadas.
Coordina las fases de construcción y ejecución de la cola. No añadas durante su ejecución en una interrupción, alteres sus contadores directamente ni sobrescribas por accidente los datos retenidos. Estas API no ofrecen bloqueo ni doble búfer. La capacidad es la del búfer de comandos, no los bytes libres de VRAM física.
Ejemplo de uso
check_result=vram_queue_tile(4,2,1); // The short alias draws at pixel (32,16).
if (check_result!=1) failures++;Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El programa completo enseña escrituras diferidas, control de capacidad y recuperación del desbordamiento. Siete llamadas de dibujo usan 7 de 32 espacios en GB, o 52 de 128 bytes en FC: CAPACITY/USED/FREE muestra 032/007/025 o 128/052/076. AFTER FLUSH y FAILED CHECKS deben ser 000; OVERFLOW SEEN, 001. Se intenta añadir a una cola llena para comprobar el indicador: leer o ejecutar no lo borra; vaciar la cola sí. En FC también se comprueba que la ejecución directa sin confirmar conserve la cola pendiente.
Las coordenadas de imagen son píxeles desde la esquina superior izquierda. Deben aparecer cuadrados sólidos de 8 × 8 en (16,16) y (32,16), un rectángulo sólido de 32 × 24 en (16,32) y una barra horizontal de 40 × 8 en (80,64). La escritura final en VBlank añade un cuadrado de 8 × 8 en (144,80). La escritura descartada en (144,24) debe dejar esa casilla vacía. DMG muestra figuras negras sobre blanco; CGB, rojas, azules y verdes sobre blanco; FC, rojas, azules y verdes sobre negro. Estas imágenes de emulador no acreditan una prueba en hardware real.
Tres patrones originales de 8 × 8 distinguen las copias: el 1 es sólido, el 2 llena las cuatro columnas izquierdas y el 3 es un triángulo alineado a la izquierda que crece de un píxel arriba a ocho abajo. El bloque de 3 × 2 casillas en (80,32) debe mostrar [1,2,3] / [3,0,2], con 0 vacío. Su primer byte cambia después de encolarlo; el patrón sólido superior izquierdo demuestra que se conserva el puntero. La copia en (16,64) muestra [1,2,3]; el alias tiles en (48,64), [2,3]. Sus tamaños son, respectivamente, 24 × 16, 24 × 8 y 16 × 8 píxeles.
En CGB, los dos cuadrados superiores, la copia de tres patrones y el cuadrado final de VBlank son rojos. El rectángulo de 32 × 24 y la copia de dos patrones son azules. El bloque de 3 × 2 casillas y la barra de 40 × 8 son verdes. El texto sigue negro sobre blanco. Se comprueba el color de cada píxel dibujado además de la geometría.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\vram.c .\kitaq-docs\samples\api-examples\gb\vram_queue_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/vram.h:45
Provide the short alias for a queued background tile write.
kitaqgb/lib/vram.c:59
u8 vram_queue_tile(u8 x, u8 y, u8 tile)
{
return vram_queue_bg_tile(x, y, tile);
}vram_queue_tiles
vram_queue_tiles llama directamente a vram_queue_memcpy. len sigue contando bytes, no tiles. Conserva el mismo puntero de origen y usa los mismos registros, resultado y momento de ejecución.
Sintaxis
u8 vram_queue_tiles(u16 dst, const void* src, u16 len);Parámetros
dstDirección de destino en bytes dentro de VRAM (
0x8000–0x9FFF), en el banco seleccionado al ejecutar. La transferencia es contigua, sin saltos de fila. Todo el intervalo debe ser válido. Con el LCD encendido, las rutas de escritura segura pueden habilitar interrupciones; no conservan un estado de entrada con interrupciones deshabilitadas.srcPuntero cercano a bytes legibles, conservado hasta la ejecución. Mantén los datos vivos y su banco de memoria o ROM visible durante toda la ejecución; no se guarda un número de banco ni una copia. Una transferencia no vacía necesita un origen válido. No uses un array local que haya caducado.
lenNúmero de bytes consecutivos, de 0 a 65535, no de tiles. Mantén todo el rango dentro de origen válido y destino escribible; la API no comprueba límites ni evita el desbordamiento de direcciones de 16 bits.
Valor devuelto
1 si este comando se encoló; 0 si no había espacio. El fallo activa el indicador de desbordamiento y conserva los comandos previos. Un desbordamiento anterior no hace que una inserción posterior correcta devuelva 0.
Condiciones y límites
GB cuenta espacios de comando: la capacidad predeterminada es 32. Cada función de inserción usa uno, incluso para transferencias grandes o de longitud cero. Define VRAM_QUEUE_MAX de forma uniforme en todas las unidades, entre 1 y 255. Una cola vacía tiene used=0 y free=capacity.
Coordina las fases de construcción y ejecución de la cola. No añadas durante su ejecución en una interrupción, alteres sus contadores directamente ni sobrescribas por accidente los datos retenidos. Estas API no ofrecen bloqueo ni doble búfer. La capacidad es la del búfer de comandos, no los bytes libres de VRAM física.
Ejemplo de uso
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.Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
El programa completo enseña escrituras diferidas, control de capacidad y recuperación del desbordamiento. Siete llamadas de dibujo usan 7 de 32 espacios en GB, o 52 de 128 bytes en FC: CAPACITY/USED/FREE muestra 032/007/025 o 128/052/076. AFTER FLUSH y FAILED CHECKS deben ser 000; OVERFLOW SEEN, 001. Se intenta añadir a una cola llena para comprobar el indicador: leer o ejecutar no lo borra; vaciar la cola sí. En FC también se comprueba que la ejecución directa sin confirmar conserve la cola pendiente.
Las coordenadas de imagen son píxeles desde la esquina superior izquierda. Deben aparecer cuadrados sólidos de 8 × 8 en (16,16) y (32,16), un rectángulo sólido de 32 × 24 en (16,32) y una barra horizontal de 40 × 8 en (80,64). La escritura final en VBlank añade un cuadrado de 8 × 8 en (144,80). La escritura descartada en (144,24) debe dejar esa casilla vacía. DMG muestra figuras negras sobre blanco; CGB, rojas, azules y verdes sobre blanco; FC, rojas, azules y verdes sobre negro. Estas imágenes de emulador no acreditan una prueba en hardware real.
Tres patrones originales de 8 × 8 distinguen las copias: el 1 es sólido, el 2 llena las cuatro columnas izquierdas y el 3 es un triángulo alineado a la izquierda que crece de un píxel arriba a ocho abajo. El bloque de 3 × 2 casillas en (80,32) debe mostrar [1,2,3] / [3,0,2], con 0 vacío. Su primer byte cambia después de encolarlo; el patrón sólido superior izquierdo demuestra que se conserva el puntero. La copia en (16,64) muestra [1,2,3]; el alias tiles en (48,64), [2,3]. Sus tamaños son, respectivamente, 24 × 16, 24 × 8 y 16 × 8 píxeles.
En CGB, los dos cuadrados superiores, la copia de tres patrones y el cuadrado final de VBlank son rojos. El rectángulo de 32 × 24 y la copia de dos patrones son azules. El bloque de 3 × 2 casillas y la barra de 40 × 8 son verdes. El texto sigue negro sobre blanco. Se comprueba el color de cada píxel dibujado además de la geometría.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\vram.c .\kitaq-docs\samples\api-examples\gb\vram_queue_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/vram.h:55
Alias the queued byte-copy operation; this does not convert a tile count to bytes.
kitaqgb/lib/vram.c:105
u8 vram_queue_tiles(u16 dst, const void* src, u16 len)
{
return vram_queue_memcpy(dst, src, len);
}wire3d.h — Gráficos de alambre para DMG
Dibujo de líneas 3D monocromas. Proporciona vértices, aristas y caras del modelo, además de posición, rotación y escala del objeto. Sigue el orden de inicialización, inicio del fotograma, dibujo y transferencia. La física se gestiona aparte. Los ángulos tienen dieciséis pasos por vuelta; la escala 256 equivale a la unidad.
Vec3 contiene x/y/z, Edge los índices de vértice a/b y Face los índices del triángulo a/b/c. Los campos vertices, edges y faces de Model apuntan a esos arrays; cada contador indica su longitud. edge_faces contiene los índices de caras adyacentes f0/f1, con FACE_NONE para una cara ausente. MODEL_HIDDEN_LINES en flags solicita selección de aristas basada en caras. El área proyectada con signo determina la orientación de la cara, por lo que importa el orden de los vértices.
Object guarda una referencia al modelo, posición x/y/z, ángulos rx/ry/rz, scale_q8 y visible. Los objetos pueden compartir un modelo, pero el dibujo no copia tablas ni cambia automáticamente sus bancos ROM. Mantén legibles los datos referenciados durante todo el dibujo. Object de CGB también tiene un índice de color.
El Model de altura 96 también contiene edge_masks y edge_mask_count. Proporciona una tabla RAM de máscaras de aristas de 16 bits seleccionadas por la guiñada del objeto, o pon ambos campos a cero si no se usan.
Wire3D_BeginFrame
Inicia el dibujo de un fotograma y desactiva la prueba de oclusión.
Sintaxis
void Wire3D_BeginFrame();Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 96. Borra los píxeles preparados y la máscara de oclusión y desactiva el filtrado de oclusión. No modifica el fotograma visible de VRAM ni la cola de tiles BG pendientes.
Este ejemplo usa el perfil 128×96; su ventana gráfica empieza en (0,0) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
Ejemplo de uso
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3D_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
Wire3D_SetCamera(8,0,0,0,0,0);
result[1]=Wire3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
result[2]=projected_x; result[3]=projected_y;
projected_x=91; projected_y=92;
result[4]=Wire3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
result[5]=projected_x; result[6]=projected_y;
Wire3D_SetCamera(0,0,0,0,0,0);
Wire3D_BeginFrame();
Wire3D_DrawLine2D(8,8,56,8);
Wire3D_DrawLine2D(56,8,56,40);
Wire3D_DrawLine2D(56,40,8,40);
Wire3D_DrawLine2D(8,40,8,8);
Wire3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
Wire3D_DrawLine3D(-24,-24,96,24,24,96);
// Copy the viewport's top-left frame corner to a separate map cell.
Wire3D_PutBgTile(18,1,157);
Wire3D_EndFrame();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Este ejemplo muestra líneas, puntos, borrado y proyección en un fotograma. Se borra el centro del borde superior del marco de arriba a la izquierda y se proyecta una diagonal cerca del centro. Una proyección rechazada conserva las salidas 91 y 92.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_raster.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d.h:34
WIRE3D_DMG_HEIGHT = 96. Clear staged pixels and occlusion mask and disable occlusion filtering. This leaves the displayed VRAM frame and pending BG tile queue unchanged.
kitaqgb/lib/wire3d_dmg.c:2641
void Wire3DDMG_BeginFrame()
{
w3ddmg_clear_stage_asm();
w3ddmg_clear_occlusion_mask();
w3ddmg_occlusion_active = 0;
}Wire3D_DrawLine2D
Dibuja en el área de preparación una línea de pantalla con conectividad de cuatro vecinos, incluidos los extremos.
Sintaxis
void Wire3D_DrawLine2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by);Parámetros
axCoordenada X del vértice A en píxeles de la ventana gráfica.
ayCoordenada Y del vértice A en píxeles de la ventana gráfica.
bxCoordenada X del vértice B en píxeles de la ventana gráfica.
byCoordenada Y del vértice B en píxeles de la ventana gráfica.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 96. Dibuja una línea conectada en el área de preparación de 128×96, incluidos los extremos. Durante DrawScene usa el rechazo aproximado de oclusión de cinco muestras; en otros casos dibuja directamente. Proporciona coordenadas de la ventana gráfica. Solo EndFrame actualiza VRAM.
Este ejemplo usa el perfil 128×96; su ventana gráfica empieza en (0,0) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
Ejemplo de uso
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3D_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
Wire3D_SetCamera(8,0,0,0,0,0);
result[1]=Wire3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
result[2]=projected_x; result[3]=projected_y;
projected_x=91; projected_y=92;
result[4]=Wire3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
result[5]=projected_x; result[6]=projected_y;
Wire3D_SetCamera(0,0,0,0,0,0);
Wire3D_BeginFrame();
Wire3D_DrawLine2D(8,8,56,8);
Wire3D_DrawLine2D(56,8,56,40);
Wire3D_DrawLine2D(56,40,8,40);
Wire3D_DrawLine2D(8,40,8,8);
Wire3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
Wire3D_DrawLine3D(-24,-24,96,24,24,96);
// Copy the viewport's top-left frame corner to a separate map cell.
Wire3D_PutBgTile(18,1,157);
Wire3D_EndFrame();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Este ejemplo muestra líneas, puntos, borrado y proyección en un fotograma. Se borra el centro del borde superior del marco de arriba a la izquierda y se proyecta una diagonal cerca del centro. Una proyección rechazada conserva las salidas 91 y 92.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_raster.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d.h:35
WIRE3D_DMG_HEIGHT = 96. Draw a connected line into the 128x96 stage, including endpoints. During DrawScene, use the coarse five-sample occlusion rejection; otherwise draw directly. Supply viewport coordinates. VRAM is updated only by EndFrame.
kitaqgb/lib/wire3d_dmg.c:2685
void Wire3DDMG_DrawLine2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by)
{
if (w3ddmg_occlusion_active)
{
w3ddmg_line_stage_masked_c(ax, ay, bx, by);
return;
}
w3ddmg_line_x0 = ax;
w3ddmg_line_y0 = ay;
w3ddmg_line_x1 = bx;
w3ddmg_line_y1 = by;
if (ax < 128 && bx < 128 && ay < WIRE3D_DMG_SCREEN_H && by < WIRE3D_DMG_SCREEN_H)
w3ddmg_line_inside_asm();
else
w3ddmg_line_stage_asm();
}Wire3D_DrawLine3D
Proyecta dos extremos en coordenadas del mundo y dibuja una línea entre ellos.
Sintaxis
void Wire3D_DrawLine3D(w3ddmg_i16 ax, w3ddmg_i16 ay, w3ddmg_i16 az, w3ddmg_i16 bx, w3ddmg_i16 by, w3ddmg_i16 bz);Parámetros
axComponente X del punto inicial en coordenadas del mundo.
ayComponente Y del punto inicial en coordenadas del mundo.
azComponente Z del punto inicial en coordenadas del mundo.
bxComponente X del punto final en coordenadas del mundo.
byComponente Y del punto final en coordenadas del mundo.
bzComponente Z del punto final en coordenadas del mundo.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 96. Proyecta ambos extremos del mundo y solo dibuja si los dos pasan el rango de profundidad. No calcula intersecciones de segmentos que crucen los planos cercano o lejano; cada extremo proyectado se limita por separado a los bordes de pantalla.
Este ejemplo usa el perfil 128×96; su ventana gráfica empieza en (0,0) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
Ejemplo de uso
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3D_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
Wire3D_SetCamera(8,0,0,0,0,0);
result[1]=Wire3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
result[2]=projected_x; result[3]=projected_y;
projected_x=91; projected_y=92;
result[4]=Wire3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
result[5]=projected_x; result[6]=projected_y;
Wire3D_SetCamera(0,0,0,0,0,0);
Wire3D_BeginFrame();
Wire3D_DrawLine2D(8,8,56,8);
Wire3D_DrawLine2D(56,8,56,40);
Wire3D_DrawLine2D(56,40,8,40);
Wire3D_DrawLine2D(8,40,8,8);
Wire3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
Wire3D_DrawLine3D(-24,-24,96,24,24,96);
// Copy the viewport's top-left frame corner to a separate map cell.
Wire3D_PutBgTile(18,1,157);
Wire3D_EndFrame();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Este ejemplo muestra líneas, puntos, borrado y proyección en un fotograma. Se borra el centro del borde superior del marco de arriba a la izquierda y se proyecta una diagonal cerca del centro. Una proyección rechazada conserva las salidas 91 y 92.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_raster.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d.h:36
WIRE3D_DMG_HEIGHT = 96. Project both world endpoints and draw only when both pass the depth range. Do not intersect a crossing segment with near/far planes; projected endpoints are independently clamped to the screen edges.
kitaqgb/lib/wire3d_dmg.c:2808
void Wire3DDMG_DrawLine3D(w3ddmg_i16 ax, w3ddmg_i16 ay, w3ddmg_i16 az, w3ddmg_i16 bx, w3ddmg_i16 by, w3ddmg_i16 bz)
{
w3ddmg_u8 sx0;
w3ddmg_u8 sy0;
w3ddmg_u8 sx1;
w3ddmg_u8 sy1;
if (w3ddmg_project_world(ax, ay, az, &sx0, &sy0) == 0) return;
if (w3ddmg_project_world(bx, by, bz, &sx1, &sy1) == 0) return;
Wire3DDMG_DrawLine2D(sx0, sy0, sx1, sy1);
}Wire3D_DrawModel
Dibuja un modelo de vértices y aristas en la posición y con la rotación indicadas, a escala unitaria.
Sintaxis
void Wire3D_DrawModel(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz);Parámetros
modelModelo que contiene los arrays de vértices, aristas y caras y sus cantidades; las tablas deben permanecer legibles durante la llamada.
xComponente X del punto o del origen del objeto en coordenadas del mundo.
yComponente Y del punto o del origen del objeto en coordenadas del mundo.
zComponente Z del punto o del origen del objeto en coordenadas del mundo.
rxRotación alrededor de X; dieciséis pasos forman una vuelta completa.
ryRotación alrededor de Y; dieciséis pasos forman una vuelta completa.
rzRotación alrededor de Z; dieciséis pasos forman una vuelta completa.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 96. Dibuja un modelo sin cambiar su tamaño mediante DrawModelScaled con escala 256.
Este ejemplo usa el perfil 128×96; su ventana gráfica empieza en (0,0) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
Ejemplo de uso
#pragma bank 0
// Compare direct model scaling with an object-array scene.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3D_Vec3 vertices[8]={{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}};
__prg_rom Wire3D_Edge edges[12]={{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}};
Wire3D_Model cube;
Wire3D_Object objects[2];
u16 masks[2];
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3D_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
cube.vertices=vertices;cube.edges=edges;cube.faces=0;cube.edge_faces=0;
cube.vertex_count=8;cube.edge_count=12;cube.face_count=0;cube.flags=0;
cube.edge_masks=0; cube.edge_mask_count=0;
Wire3D_BeginFrame();
// Upper pair: direct model calls at unity and half scale.
Wire3D_DrawModel(&cube,-32,32,96,0,0,0);
Wire3D_DrawModelScaled(&cube,32,32,96,0,0,0,128);
// Lower pair: the caller owns both object records and the model tables.
for(i=0;i<2;i++) {
objects[i].model=&cube;objects[i].x=-32+(s16)i*64;
objects[i].y=-32;objects[i].z=96;
objects[i].rx=0;objects[i].ry=0;objects[i].rz=0;
objects[i].scale_q8=256-(s16)i*128;objects[i].visible=1;
}
Wire3D_DrawScene(objects,2);
// Numeric checks cover the operation supplied by this viewport profile.
masks[0]=3;masks[1]=12;cube.edge_masks=masks; cube.edge_mask_count=2;
result[1]=Wire3D_SelectEdgeMask(&cube,0,0,0);
result[2]=Wire3D_SelectEdgeMask(&cube,0,8,0);
Wire3D_EndFrame(); result[7]=0xA55A;
while(1) {}
}Resultado esperado
Los modelos a escala unitaria y a media escala aparecen sobre una escena de un array de objetos con esas mismas escalas, para mostrar la proyección y el escalado.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_models.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d.h:37
WIRE3D_DMG_HEIGHT = 96. Draw an unscaled model by delegating to DrawModelScaled with scale 256.
kitaqgb/lib/wire3d_dmg.c:2825
void Wire3DDMG_DrawModel(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz)
{
Wire3DDMG_DrawModelScaled(model, x, y, z, rx, ry, rz, 256);
}Wire3D_DrawModelScaled
Escala un modelo, lo rota en orden Y/X/Z, traslada y proyecta sus vértices y dibuja las aristas.
Sintaxis
void Wire3D_DrawModelScaled(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz, w3ddmg_i16 scale_q8);Parámetros
modelModelo que contiene los arrays de vértices, aristas y caras y sus cantidades; las tablas deben permanecer legibles durante la llamada.
xComponente X del punto o del origen del objeto en coordenadas del mundo.
yComponente Y del punto o del origen del objeto en coordenadas del mundo.
zComponente Z del punto o del origen del objeto en coordenadas del mundo.
rxRotación alrededor de X; dieciséis pasos forman una vuelta completa.
ryRotación alrededor de Y; dieciséis pasos forman una vuelta completa.
rzRotación alrededor de Z; dieciséis pasos forman una vuelta completa.
scale_q8Escala con 256 como unidad; los valores no positivos también equivalen a la unidad.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 96. Escala hasta 24 vértices, los rota en orden Y/X/Z, los traslada y proyecta; después dibuja hasta 16 aristas filtradas por máscaras de guiñada y, opcionalmente, por caras frontales. Una escala no positiva pasa a ser unitaria (256). Ignora punteros null de modelo, vértices o aristas; las tablas referenciadas deben seguir siendo legibles. Mantén productos de escala y traslaciones en el rango de 16 bits con signo. Las aristas que cruzan límites de profundidad se descartan, no se recortan.
Este ejemplo usa el perfil 128×96; su ventana gráfica empieza en (0,0) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
Ejemplo de uso
#pragma bank 0
// Compare direct model scaling with an object-array scene.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3D_Vec3 vertices[8]={{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}};
__prg_rom Wire3D_Edge edges[12]={{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}};
Wire3D_Model cube;
Wire3D_Object objects[2];
u16 masks[2];
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3D_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
cube.vertices=vertices;cube.edges=edges;cube.faces=0;cube.edge_faces=0;
cube.vertex_count=8;cube.edge_count=12;cube.face_count=0;cube.flags=0;
cube.edge_masks=0; cube.edge_mask_count=0;
Wire3D_BeginFrame();
// Upper pair: direct model calls at unity and half scale.
Wire3D_DrawModel(&cube,-32,32,96,0,0,0);
Wire3D_DrawModelScaled(&cube,32,32,96,0,0,0,128);
// Lower pair: the caller owns both object records and the model tables.
for(i=0;i<2;i++) {
objects[i].model=&cube;objects[i].x=-32+(s16)i*64;
objects[i].y=-32;objects[i].z=96;
objects[i].rx=0;objects[i].ry=0;objects[i].rz=0;
objects[i].scale_q8=256-(s16)i*128;objects[i].visible=1;
}
Wire3D_DrawScene(objects,2);
// Numeric checks cover the operation supplied by this viewport profile.
masks[0]=3;masks[1]=12;cube.edge_masks=masks; cube.edge_mask_count=2;
result[1]=Wire3D_SelectEdgeMask(&cube,0,0,0);
result[2]=Wire3D_SelectEdgeMask(&cube,0,8,0);
Wire3D_EndFrame(); result[7]=0xA55A;
while(1) {}
}Resultado esperado
Los modelos a escala unitaria y a media escala aparecen sobre una escena de un array de objetos con esas mismas escalas, para mostrar la proyección y el escalado.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_models.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d.h:38
WIRE3D_DMG_HEIGHT = 96. Scale, rotate in Y/X/Z order, translate and project at most 24 vertices; then draw up to 16 edges filtered by yaw masks and optional front-facing faces. Nonpositive scale becomes unity (256). Null model/vertex/edge pointers are ignored; referenced tables must remain readable. Keep scale products and translations in signed 16-bit range. Depth-crossing edges are dropped, not clipped.
kitaqgb/lib/wire3d_dmg.c:2965
void Wire3DDMG_DrawModelScaled(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz, w3ddmg_i16 scale_q8)
{
w3ddmg_u8 i;
w3ddmg_u8 count;
w3ddmg_u8 edge_count;
w3ddmg_u8 face_count;
if (model == 0) return;
if (model->vertices == 0) return;
if (model->edges == 0) return;
if (scale_q8 <= 0) scale_q8 = 256;
count = model->vertex_count;
if (count > WIRE3D_DMG_MODEL_VERTEX_LIMIT) count = WIRE3D_DMG_MODEL_VERTEX_LIMIT;
i = 0;
while (i < count)
{
const Wire3DDMG_Vec3* v;
w3ddmg_i16 vx;
w3ddmg_i16 vy;
w3ddmg_i16 vz;
w3ddmg_u8 sx;
w3ddmg_u8 sy;
v = &model->vertices[(__safe_index w3ddmg_u8)i];
vx = (w3ddmg_i16)((v->x * scale_q8) >> 8);
vy = (w3ddmg_i16)((v->y * scale_q8) >> 8);
vz = (w3ddmg_i16)((v->z * scale_q8) >> 8);
w3ddmg_rotate_y(&vx, &vz, (w3ddmg_i8)ry);
w3ddmg_rotate_x(&vy, &vz, (w3ddmg_i8)rx);
w3ddmg_rotate_z(&vx, &vy, (w3ddmg_i8)rz);
vx = (w3ddmg_i16)(vx + x);
vy = (w3ddmg_i16)(vy + y);
vz = (w3ddmg_i16)(vz + z);
if (w3ddmg_project_world(vx, vy, vz, &sx, &sy))
{
w3ddmg_screen_x[(__safe_index w3ddmg_u8)i] = sx;
w3ddmg_screen_y[(__safe_index w3ddmg_u8)i] = sy;
w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 1;
}
else
{
w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 0;
}
i = (w3ddmg_u8)(i + 1);
}
face_count = model->face_count;
if (face_count > WIRE3D_DMG_MODEL_FACE_LIMIT) face_count = WIRE3D_DMG_MODEL_FACE_LIMIT;
if ((model->flags & WIRE3D_DMG_MODEL_HIDDEN_LINES) && (model->faces != 0) && (model->edge_faces != 0))
{
w3ddmg_build_face_visibility(model, count, face_count);
}
edge_count = model->edge_count;
if (edge_count > WIRE3D_DMG_MODEL_EDGE_LIMIT) edge_count = WIRE3D_DMG_MODEL_EDGE_LIMIT;
w3ddmg_build_edge_flags(model, edge_count, face_count, rx, ry, rz);
i = 0;
while (i < edge_count)
{
const Wire3DDMG_Edge* e;
e = &model->edges[(__safe_index w3ddmg_u8)i];
if ((e->a < count) && (e->b < count))
{
if (w3ddmg_screen_visible[(__safe_index w3ddmg_u8)e->a] &&
w3ddmg_screen_visible[(__safe_index w3ddmg_u8)e->b] &&
w3ddmg_edge_flags[(__safe_index w3ddmg_u8)i])
{
Wire3DDMG_DrawLine2D(
w3ddmg_screen_x[(__safe_index w3ddmg_u8)e->a],
w3ddmg_screen_y[(__safe_index w3ddmg_u8)e->a],
w3ddmg_screen_x[(__safe_index w3ddmg_u8)e->b],
w3ddmg_screen_y[(__safe_index w3ddmg_u8)e->b]);
}
}
i = (w3ddmg_u8)(i + 1);
}
}Wire3D_DrawScene
Dibuja hasta ocho objetos de cerca a lejos, usando las caras cercanas para ocultar las aristas posteriores.
Sintaxis
void Wire3D_DrawScene(Wire3DDMG_Object* objects, w3ddmg_u8 count);Parámetros
objectsArray de objetos con posiciones, rotaciones, escalas e indicadores de visibilidad.
countCantidad de entradas proporcionadas; consulta el límite de procesamiento de cada operación.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 96. Procesa como máximo los primeros ocho objetos, ordenados de cerca a lejos por la profundidad de su origen transformado. Dibuja modelos visibles y válidos y marca los rectángulos envolventes de sus caras frontales para rechazar líneas posteriores cuyos puntos de muestreo queden todos ocultos. Aproxima la oclusión entre objetos; no es un búfer de profundidad. Borra su máscara, pero conserva los píxeles ya preparados. Ignora arrays null; los objetos y sus datos deben seguir siendo legibles.
Este ejemplo usa el perfil 128×96; su ventana gráfica empieza en (0,0) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
Ejemplo de uso
#pragma bank 0
// Compare direct model scaling with an object-array scene.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3D_Vec3 vertices[8]={{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}};
__prg_rom Wire3D_Edge edges[12]={{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}};
Wire3D_Model cube;
Wire3D_Object objects[2];
u16 masks[2];
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3D_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
cube.vertices=vertices;cube.edges=edges;cube.faces=0;cube.edge_faces=0;
cube.vertex_count=8;cube.edge_count=12;cube.face_count=0;cube.flags=0;
cube.edge_masks=0; cube.edge_mask_count=0;
Wire3D_BeginFrame();
// Upper pair: direct model calls at unity and half scale.
Wire3D_DrawModel(&cube,-32,32,96,0,0,0);
Wire3D_DrawModelScaled(&cube,32,32,96,0,0,0,128);
// Lower pair: the caller owns both object records and the model tables.
for(i=0;i<2;i++) {
objects[i].model=&cube;objects[i].x=-32+(s16)i*64;
objects[i].y=-32;objects[i].z=96;
objects[i].rx=0;objects[i].ry=0;objects[i].rz=0;
objects[i].scale_q8=256-(s16)i*128;objects[i].visible=1;
}
Wire3D_DrawScene(objects,2);
// Numeric checks cover the operation supplied by this viewport profile.
masks[0]=3;masks[1]=12;cube.edge_masks=masks; cube.edge_mask_count=2;
result[1]=Wire3D_SelectEdgeMask(&cube,0,0,0);
result[2]=Wire3D_SelectEdgeMask(&cube,0,8,0);
Wire3D_EndFrame(); result[7]=0xA55A;
while(1) {}
}Resultado esperado
Los modelos a escala unitaria y a media escala aparecen sobre una escena de un array de objetos con esas mismas escalas, para mostrar la proyección y el escalado.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_models.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d.h:39
WIRE3D_DMG_HEIGHT = 96. Process at most the first eight objects, sorted near to far by transformed origin depth. Draw visible valid models, then mark their front-face bounding rectangles to reject fully sampled later lines. This approximates inter-object occlusion, not a depth buffer. It clears its mask but retains existing staged pixels. Null arrays are ignored; objects and their data must remain readable.
kitaqgb/lib/wire3d_dmg.c:2723
void Wire3DDMG_DrawScene(Wire3DDMG_Object* objects, w3ddmg_u8 count)
{
w3ddmg_u8 scene_count;
w3ddmg_u8 i;
if (objects == 0) return;
scene_count = count;
if (scene_count > WIRE3D_DMG_SCENE_OBJECT_LIMIT) scene_count = WIRE3D_DMG_SCENE_OBJECT_LIMIT;
i = 0;
while (i < scene_count)
{
w3ddmg_scene_order[(__safe_index w3ddmg_u8)i] = i;
w3ddmg_scene_depth[(__safe_index w3ddmg_u8)i] = w3ddmg_scene_object_depth(&objects[(__safe_index w3ddmg_u8)i]);
i = (w3ddmg_u8)(i + 1);
}
i = 0;
while (i < scene_count)
{
w3ddmg_u8 j;
j = (w3ddmg_u8)(i + 1);
while (j < scene_count)
{
w3ddmg_u8 oi;
w3ddmg_u8 oj;
oi = w3ddmg_scene_order[(__safe_index w3ddmg_u8)i];
oj = w3ddmg_scene_order[(__safe_index w3ddmg_u8)j];
// Put the nearer origin first so its face bounds can suppress later lines.
// The array itself stays in caller order; only the scratch index list is sorted.
if (w3ddmg_scene_depth[(__safe_index w3ddmg_u8)oj] < w3ddmg_scene_depth[(__safe_index w3ddmg_u8)oi])
{
w3ddmg_scene_order[(__safe_index w3ddmg_u8)i] = oj;
w3ddmg_scene_order[(__safe_index w3ddmg_u8)j] = oi;
}
j = (w3ddmg_u8)(j + 1);
}
i = (w3ddmg_u8)(i + 1);
}
w3ddmg_clear_occlusion_mask();
w3ddmg_occlusion_active = 1;
i = 0;
while (i < scene_count)
{
Wire3DDMG_Object* obj;
obj = &objects[(__safe_index w3ddmg_u8)w3ddmg_scene_order[(__safe_index w3ddmg_u8)i]];
if ((obj->visible != 0) && (obj->model != 0))
{
Wire3DDMG_DrawModelScaled(obj->model, obj->x, obj->y, obj->z, (w3ddmg_i8)obj->rx, (w3ddmg_i8)obj->ry, (w3ddmg_i8)obj->rz, obj->scale_q8);
w3ddmg_mark_model_occluder(obj->model);
}
i = (w3ddmg_u8)(i + 1);
}
w3ddmg_occlusion_active = 0;
}Wire3D_EndFrame
Envía a VRAM las escrituras del fondo pendientes y el dibujo preparado.
Sintaxis
void Wire3D_EndFrame();Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 96. Espera al siguiente VBlank, aplica las escrituras BG pendientes y copia el área de preparación a VRAM consultando los intervalos de acceso. La copia consume los píxeles preparados. La transferencia puede prolongarse más allá de VBlank; no es un intercambio atómico de fotograma.
Este ejemplo usa el perfil 128×96; su ventana gráfica empieza en (0,0) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
Ejemplo de uso
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3D_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
Wire3D_SetCamera(8,0,0,0,0,0);
result[1]=Wire3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
result[2]=projected_x; result[3]=projected_y;
projected_x=91; projected_y=92;
result[4]=Wire3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
result[5]=projected_x; result[6]=projected_y;
Wire3D_SetCamera(0,0,0,0,0,0);
Wire3D_BeginFrame();
Wire3D_DrawLine2D(8,8,56,8);
Wire3D_DrawLine2D(56,8,56,40);
Wire3D_DrawLine2D(56,40,8,40);
Wire3D_DrawLine2D(8,40,8,8);
Wire3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
Wire3D_DrawLine3D(-24,-24,96,24,24,96);
// Copy the viewport's top-left frame corner to a separate map cell.
Wire3D_PutBgTile(18,1,157);
Wire3D_EndFrame();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Este ejemplo muestra líneas, puntos, borrado y proyección en un fotograma. Se borra el centro del borde superior del marco de arriba a la izquierda y se proyecta una diagonal cerca del centro. Una proyección rechazada conserva las salidas 91 y 92.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_raster.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d.h:42
WIRE3D_DMG_HEIGHT = 96. Wait for the next VBlank, flush pending BG map writes, then copy the stage to VRAM while polling access windows. Copying consumes the staged pixels. The transfer may extend beyond VBlank; this is not an atomic frame swap.
kitaqgb/lib/wire3d_dmg.c:3081
void Wire3DDMG_EndFrame()
{
w3ddmg_wait_vblank_start();
w3ddmg_flush_bg_queue();
w3ddmg_transfer_stage_asm();
}Wire3D_EraseModelFaces
Proyecta los triángulos frontales del modelo y borra los píxeles preparados de su interior.
Sintaxis
void Wire3D_EraseModelFaces(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz, w3ddmg_i16 scale_q8);Parámetros
modelModelo que contiene los arrays de vértices, aristas y caras y sus cantidades; las tablas deben permanecer legibles durante la llamada.
xComponente X del punto o del origen del objeto en coordenadas del mundo.
yComponente Y del punto o del origen del objeto en coordenadas del mundo.
zComponente Z del punto o del origen del objeto en coordenadas del mundo.
rxRotación alrededor de X; dieciséis pasos forman una vuelta completa.
ryRotación alrededor de Y; dieciséis pasos forman una vuelta completa.
rzRotación alrededor de Z; dieciséis pasos forman una vuelta completa.
scale_q8Escala con 256 como unidad; los valores no positivos también equivalen a la unidad.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 96. Proyecta hasta 24 vértices y borra del área de preparación el interior de los triángulos frontales de un modelo con indicadores de líneas ocultas y datos de caras. Una escala no positiva significa 256, la unidad. Examina hasta 16 caras y omite las que cruzan límites de profundidad. También sustituye las cachés de proyección compartidas, pero no actualiza VRAM.
Este ejemplo usa el perfil 128×96; su ventana gráfica empieza en (0,0) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
Ejemplo de uso
#pragma bank 0
// Erase a screen triangle and a projected model face from separate filled panels.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3D_Vec3 vertices[4]={{-24,-24,0},{24,-24,0},{24,24,0},{-24,24,0}};
__prg_rom Wire3D_Edge edges[4]={{0,1},{1,2},{2,3},{3,0}};
__prg_rom Wire3D_Face faces[2]={{0,2,1},{0,3,2}};
Wire3D_Model plane;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3D_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
plane.vertices=vertices;plane.edges=edges;plane.faces=faces;plane.edge_faces=0;
plane.vertex_count=4;plane.edge_count=4;plane.face_count=2;plane.flags=1;plane.edge_masks=0;plane.edge_mask_count=0;
Wire3D_BeginFrame();
// Separate panels show a direct screen triangle and a projected square face.
for(i=8;i<=32;i++) Wire3D_DrawLine2D(8,i,32,i);
for(i=24;i<=72;i++) Wire3D_DrawLine2D(40,i,88,i);
Wire3D_EraseTriangle2D(12,12,28,12,12,28);
Wire3D_EraseModelFaces(&plane,0,0,64,0,0,0,256);
Wire3D_EndFrame(); result[7]=0xA55A; while(1) {}
}Resultado esperado
Las caras proyectadas borran una región rellena y permiten distinguir las zonas conservadas de las borradas.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_faces.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_faces.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d.h:43
WIRE3D_DMG_HEIGHT = 96. Project up to 24 vertices and erase front-facing triangle interiors from the stage for a model with hidden-line flags and face data. Nonpositive scale means 256 (unity). Up to 16 faces are considered; depth-crossing faces are skipped. This also replaces shared projection caches, but does not update VRAM.
kitaqgb/lib/wire3d_dmg.c:2841
void Wire3DDMG_EraseModelFaces(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz, w3ddmg_i16 scale_q8)
{
w3ddmg_u8 i;
w3ddmg_u8 count;
w3ddmg_u8 face_count;
if (model == 0) return;
if (model->vertices == 0) return;
if (model->faces == 0) return;
if ((model->flags & WIRE3D_DMG_MODEL_HIDDEN_LINES) == 0) return;
if (scale_q8 <= 0) scale_q8 = 256;
count = model->vertex_count;
if (count > WIRE3D_DMG_MODEL_VERTEX_LIMIT) count = WIRE3D_DMG_MODEL_VERTEX_LIMIT;
i = 0;
while (i < count)
{
const Wire3DDMG_Vec3* v;
w3ddmg_i16 vx;
w3ddmg_i16 vy;
w3ddmg_i16 vz;
w3ddmg_u8 sx;
w3ddmg_u8 sy;
v = &model->vertices[(__safe_index w3ddmg_u8)i];
vx = (w3ddmg_i16)((v->x * scale_q8) >> 8);
vy = (w3ddmg_i16)((v->y * scale_q8) >> 8);
vz = (w3ddmg_i16)((v->z * scale_q8) >> 8);
w3ddmg_rotate_y(&vx, &vz, (w3ddmg_i8)ry);
w3ddmg_rotate_x(&vy, &vz, (w3ddmg_i8)rx);
w3ddmg_rotate_z(&vx, &vy, (w3ddmg_i8)rz);
vx = (w3ddmg_i16)(vx + x);
vy = (w3ddmg_i16)(vy + y);
vz = (w3ddmg_i16)(vz + z);
if (w3ddmg_project_world(vx, vy, vz, &sx, &sy))
{
w3ddmg_screen_x[(__safe_index w3ddmg_u8)i] = sx;
w3ddmg_screen_y[(__safe_index w3ddmg_u8)i] = sy;
w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 1;
}
else
{
w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 0;
}
i = (w3ddmg_u8)(i + 1);
}
face_count = model->face_count;
if (face_count > WIRE3D_DMG_MODEL_FACE_LIMIT) face_count = WIRE3D_DMG_MODEL_FACE_LIMIT;
w3ddmg_build_face_visibility(model, count, face_count);
i = 0;
while (i < face_count)
{
const Wire3DDMG_Face* f;
f = &model->faces[(__safe_index w3ddmg_u8)i];
if (w3ddmg_face_visible[(__safe_index w3ddmg_u8)i] &&
w3ddmg_screen_visible[(__safe_index w3ddmg_u8)f->a] &&
w3ddmg_screen_visible[(__safe_index w3ddmg_u8)f->b] &&
w3ddmg_screen_visible[(__safe_index w3ddmg_u8)f->c])
{
w3ddmg_clear_triangle(
w3ddmg_screen_x[(__safe_index w3ddmg_u8)f->a],
w3ddmg_screen_y[(__safe_index w3ddmg_u8)f->a],
w3ddmg_screen_x[(__safe_index w3ddmg_u8)f->b],
w3ddmg_screen_y[(__safe_index w3ddmg_u8)f->b],
w3ddmg_screen_x[(__safe_index w3ddmg_u8)f->c],
w3ddmg_screen_y[(__safe_index w3ddmg_u8)f->c]);
}
i = (w3ddmg_u8)(i + 1);
}
}Wire3D_EraseSpan2D
Borra un tramo horizontal, con ambos extremos incluidos, de una fila preparada.
Sintaxis
void Wire3D_EraseSpan2D(w3ddmg_u8 y, w3ddmg_u8 x0, w3ddmg_u8 x1);Parámetros
yCoordenada Y en píxeles de la fila que se va a borrar.
x0Extremo X inferior, en píxeles de la ventana gráfica; el orden y el recorte siguen las notas de esta operación.
x1Extremo X superior, en píxeles de la ventana gráfica; el orden y el recorte siguen las notas de esta operación.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 96. Ordena los extremos X y borra el tramo preparado, incluidos ambos extremos. Los dos deben estar en 0..127; un Y inválido se ignora. La rutina no recorta X automáticamente.
Este ejemplo usa el perfil 128×96; su ventana gráfica empieza en (0,0) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
Ejemplo de uso
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3D_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
Wire3D_SetCamera(8,0,0,0,0,0);
result[1]=Wire3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
result[2]=projected_x; result[3]=projected_y;
projected_x=91; projected_y=92;
result[4]=Wire3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
result[5]=projected_x; result[6]=projected_y;
Wire3D_SetCamera(0,0,0,0,0,0);
Wire3D_BeginFrame();
Wire3D_DrawLine2D(8,8,56,8);
Wire3D_DrawLine2D(56,8,56,40);
Wire3D_DrawLine2D(56,40,8,40);
Wire3D_DrawLine2D(8,40,8,8);
Wire3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
Wire3D_DrawLine3D(-24,-24,96,24,24,96);
// Copy the viewport's top-left frame corner to a separate map cell.
Wire3D_PutBgTile(18,1,157);
Wire3D_EndFrame();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Este ejemplo muestra líneas, puntos, borrado y proyección en un fotograma. Se borra el centro del borde superior del marco de arriba a la izquierda y se proyecta una diagonal cerca del centro. Una proyección rechazada conserva las salidas 91 y 92.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_raster.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d.h:44
WIRE3D_DMG_HEIGHT = 96. Order the X endpoints and erase the inclusive staged span. Both endpoints must be in 0..127; invalid Y is ignored. The routine does not clip X for you.
kitaqgb/lib/wire3d_dmg.c:2943
void Wire3DDMG_EraseSpan2D(w3ddmg_u8 y, w3ddmg_u8 x0, w3ddmg_u8 x1)
{
w3ddmg_u8 tx;
if (x0 > x1)
{
tx = x0;
x0 = x1;
x1 = tx;
}
w3ddmg_stage_clear_span(y, x0, x1);
}Wire3D_EraseTriangle2D
Borra un triángulo de pantalla del área de preparación mediante tramos horizontales de líneas de barrido.
Sintaxis
void Wire3D_EraseTriangle2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by, w3ddmg_u8 cx, w3ddmg_u8 cy);Parámetros
axCoordenada X del vértice A en píxeles de la ventana gráfica.
ayCoordenada Y del vértice A en píxeles de la ventana gráfica.
bxCoordenada X del vértice B en píxeles de la ventana gráfica.
byCoordenada Y del vértice B en píxeles de la ventana gráfica.
cxCoordenada X del vértice C en píxeles de la ventana gráfica.
cyCoordenada Y del vértice C en píxeles de la ventana gráfica.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 96. Borra un triángulo de los píxeles preparados usando intersecciones enteras con líneas de barrido. Proporciona coordenadas de la ventana gráfica. Ignora triángulos degenerados; la máscara de oclusión y VRAM no cambian.
Este ejemplo usa el perfil 128×96; su ventana gráfica empieza en (0,0) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
Ejemplo de uso
#pragma bank 0
// Erase a screen triangle and a projected model face from separate filled panels.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3D_Vec3 vertices[4]={{-24,-24,0},{24,-24,0},{24,24,0},{-24,24,0}};
__prg_rom Wire3D_Edge edges[4]={{0,1},{1,2},{2,3},{3,0}};
__prg_rom Wire3D_Face faces[2]={{0,2,1},{0,3,2}};
Wire3D_Model plane;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3D_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
plane.vertices=vertices;plane.edges=edges;plane.faces=faces;plane.edge_faces=0;
plane.vertex_count=4;plane.edge_count=4;plane.face_count=2;plane.flags=1;plane.edge_masks=0;plane.edge_mask_count=0;
Wire3D_BeginFrame();
// Separate panels show a direct screen triangle and a projected square face.
for(i=8;i<=32;i++) Wire3D_DrawLine2D(8,i,32,i);
for(i=24;i<=72;i++) Wire3D_DrawLine2D(40,i,88,i);
Wire3D_EraseTriangle2D(12,12,28,12,12,28);
Wire3D_EraseModelFaces(&plane,0,0,64,0,0,0,256);
Wire3D_EndFrame(); result[7]=0xA55A; while(1) {}
}Resultado esperado
Las caras proyectadas borran una región rellena y permiten distinguir las zonas conservadas de las borradas.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_faces.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_faces.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d.h:45
WIRE3D_DMG_HEIGHT = 96. Erase a triangle from staged pixels using integer scanline intersections. Supply viewport coordinates. Degenerate triangles are ignored; the occlusion mask and VRAM are unchanged.
kitaqgb/lib/wire3d_dmg.c:2933
void Wire3DDMG_EraseTriangle2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by, w3ddmg_u8 cx, w3ddmg_u8 cy)
{
w3ddmg_clear_triangle(ax, ay, bx, by, cx, cy);
}Wire3D_Init
Inicializa el LCD, los tiles y el mapa del fondo para una ventana gráfica de alambre monocroma.
Sintaxis
void Wire3D_Init();Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 96. Toma el control del LCD: espera a VBlank, lo apaga, borra 6144 bytes de tiles y el mapa BG, instala los tiles del HUD y la ventana gráfica de 128×96 con números de tile con signo, y activa el fondo con desplazamiento cero y BGP=0xB4. Reinicia cámara, cola BG y área de preparación. Reserva 0xD000..0xDFFF para esa área y conserva su mapeo de banco de WRAM. Llama a BeginFrame antes de dibujar para inicializar también la oclusión.
Este ejemplo usa el perfil 128×96; su ventana gráfica empieza en (0,0) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
Ejemplo de uso
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3D_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
Wire3D_SetCamera(8,0,0,0,0,0);
result[1]=Wire3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
result[2]=projected_x; result[3]=projected_y;
projected_x=91; projected_y=92;
result[4]=Wire3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
result[5]=projected_x; result[6]=projected_y;
Wire3D_SetCamera(0,0,0,0,0,0);
Wire3D_BeginFrame();
Wire3D_DrawLine2D(8,8,56,8);
Wire3D_DrawLine2D(56,8,56,40);
Wire3D_DrawLine2D(56,40,8,40);
Wire3D_DrawLine2D(8,40,8,8);
Wire3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
Wire3D_DrawLine3D(-24,-24,96,24,24,96);
// Copy the viewport's top-left frame corner to a separate map cell.
Wire3D_PutBgTile(18,1,157);
Wire3D_EndFrame();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Este ejemplo muestra líneas, puntos, borrado y proyección en un fotograma. Se borra el centro del borde superior del marco de arriba a la izquierda y se proyecta una diagonal cerca del centro. Una proyección rechazada conserva las salidas 91 y 92.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_raster.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d.h:47
WIRE3D_DMG_HEIGHT = 96. Take over the LCD: wait for VBlank, switch it off, clear 6144 tile bytes and the BG map, install HUD tiles and the 128x96 signed-tile viewport, then enable BG display with scroll zero and BGP=0xB4. Reset camera, BG queue and stage. Reserve 0xD000..0xDFFF for staging and retain its WRAM bank mapping. Call BeginFrame before drawing to initialize the occlusion state as well.
kitaqgb/lib/wire3d_dmg.c:2572
void Wire3DDMG_Init()
{
w3ddmg_u8 row;
w3ddmg_u8 col;
w3ddmg_u8 tid;
w3ddmg_u16 off;
w3ddmg_wait_vblank_start();
w3ddmg_reg_lcdc = 0;
w3ddmg_clear_vram_asm();
w3ddmg_load_hud_tiles();
w3ddmg_fill_bg_map_asm();
row = 0;
tid = 0x90;
while (row < WIRE3D_DMG_TILE_H)
{
off = (w3ddmg_u16)((w3ddmg_u16)row << 5);
col = 0;
while (col < WIRE3D_DMG_TILE_W)
{
w3ddmg_bg_map_9800[(w3ddmg_u16)(off + (w3ddmg_u16)col)] = tid;
tid = (w3ddmg_u8)(tid + WIRE3D_DMG_TILE_H);
col = (w3ddmg_u8)(col + 1);
}
row = (w3ddmg_u8)(row + 1);
tid = (w3ddmg_u8)(0x90 + row);
}
w3ddmg_reg_scx = 0;
w3ddmg_reg_scy = 0;
w3ddmg_reg_bgp = 0xB4;
w3ddmg_reg_lcdc = 0x81;
w3ddmg_bgq_count = 0;
Wire3DDMG_SetCamera(0, 0, 0, 0, 0, 0);
w3ddmg_clear_stage_asm();
}Wire3D_ProjectPoint
Proyecta un punto del mundo mediante la cámara a coordenadas de la ventana gráfica.
Sintaxis
w3ddmg_u8 Wire3D_ProjectPoint(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8* sx, w3ddmg_u8* sy);Parámetros
xComponente X del punto o del origen del objeto en coordenadas del mundo.
yComponente Y del punto o del origen del objeto en coordenadas del mundo.
zComponente Z del punto o del origen del objeto en coordenadas del mundo.
sxPuntero u8 válido y escribible que recibe la coordenada X proyectada.
syPuntero u8 válido y escribible que recibe la coordenada Y proyectada.
Valor devuelto
Devuelve 1 si la proyección tiene éxito o 0 si se rechaza por profundidad.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 96. Proyecta un punto del mundo con la cámara actual. Una profundidad rechazada devuelve cero sin cambiar las salidas; si tiene éxito, escribe coordenadas limitadas a 128×96. Los punteros de salida deben ser válidos. Limitar coordenadas a la pantalla no es recorte geométrico.
Este ejemplo usa el perfil 128×96; su ventana gráfica empieza en (0,0) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
Ejemplo de uso
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3D_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
Wire3D_SetCamera(8,0,0,0,0,0);
result[1]=Wire3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
result[2]=projected_x; result[3]=projected_y;
projected_x=91; projected_y=92;
result[4]=Wire3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
result[5]=projected_x; result[6]=projected_y;
Wire3D_SetCamera(0,0,0,0,0,0);
Wire3D_BeginFrame();
Wire3D_DrawLine2D(8,8,56,8);
Wire3D_DrawLine2D(56,8,56,40);
Wire3D_DrawLine2D(56,40,8,40);
Wire3D_DrawLine2D(8,40,8,8);
Wire3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
Wire3D_DrawLine3D(-24,-24,96,24,24,96);
// Copy the viewport's top-left frame corner to a separate map cell.
Wire3D_PutBgTile(18,1,157);
Wire3D_EndFrame();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Este ejemplo muestra líneas, puntos, borrado y proyección en un fotograma. Se borra el centro del borde superior del marco de arriba a la izquierda y se proyecta una diagonal cerca del centro. Una proyección rechazada conserva las salidas 91 y 92.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_raster.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d.h:50
WIRE3D_DMG_HEIGHT = 96. Project a world point with the current camera. Return zero for rejected depth, leaving outputs unchanged; success writes clamped 128x96 coordinates. Output pointers must be valid. Screen clamping is not geometric clipping.
kitaqgb/lib/wire3d_dmg.c:549
w3ddmg_u8 Wire3DDMG_ProjectPoint(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8* sx, w3ddmg_u8* sy)
{
return w3ddmg_project_world(x, y, z, sx, sy);
}Wire3D_PutBgTile
Encola una escritura de número de tile en una celda del mapa del fondo.
Sintaxis
void Wire3D_PutBgTile(w3ddmg_u8 x, w3ddmg_u8 y, w3ddmg_u8 tile);Parámetros
xCoordenada X de tile en el mapa del fondo de 32×32.
yCoordenada Y de tile en el mapa del fondo de 32×32.
tileNúmero de tile de ocho bits para la celda del fondo.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 96. Encola una escritura de tile en el mapa de 32×32 en 0x9800 para EndFrame. Ignora sin aviso las coordenadas inválidas y las solicitudes que superen las 48 escrituras pendientes. Esta cola es independiente de la cola general de la biblioteca vram.
Este ejemplo usa el perfil 128×96; su ventana gráfica empieza en (0,0) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
Ejemplo de uso
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3D_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
Wire3D_SetCamera(8,0,0,0,0,0);
result[1]=Wire3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
result[2]=projected_x; result[3]=projected_y;
projected_x=91; projected_y=92;
result[4]=Wire3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
result[5]=projected_x; result[6]=projected_y;
Wire3D_SetCamera(0,0,0,0,0,0);
Wire3D_BeginFrame();
Wire3D_DrawLine2D(8,8,56,8);
Wire3D_DrawLine2D(56,8,56,40);
Wire3D_DrawLine2D(56,40,8,40);
Wire3D_DrawLine2D(8,40,8,8);
Wire3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
Wire3D_DrawLine3D(-24,-24,96,24,24,96);
// Copy the viewport's top-left frame corner to a separate map cell.
Wire3D_PutBgTile(18,1,157);
Wire3D_EndFrame();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Este ejemplo muestra líneas, puntos, borrado y proyección en un fotograma. Se borra el centro del borde superior del marco de arriba a la izquierda y se proyecta una diagonal cerca del centro. Una proyección rechazada conserva las salidas 91 y 92.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_raster.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d.h:51
WIRE3D_DMG_HEIGHT = 96. Queue a tile write to the 32x32 map at 0x9800 for EndFrame. Invalid map coordinates and submissions beyond 48 pending writes are silently ignored. This queue is separate from the general vram library queue.
kitaqgb/lib/wire3d_dmg.c:582
void Wire3DDMG_PutBgTile(w3ddmg_u8 x, w3ddmg_u8 y, w3ddmg_u8 tile)
{
if (x >= 32) return;
if (y >= 32) return;
if (w3ddmg_bgq_count >= WIRE3D_DMG_BG_QUEUE_LIMIT) return;
w3ddmg_bgq_x[(__safe_index w3ddmg_u8)w3ddmg_bgq_count] = x;
w3ddmg_bgq_y[(__safe_index w3ddmg_u8)w3ddmg_bgq_count] = y;
w3ddmg_bgq_tile[(__safe_index w3ddmg_u8)w3ddmg_bgq_count] = tile;
w3ddmg_bgq_count = (w3ddmg_u8)(w3ddmg_bgq_count + 1);
}Wire3D_SelectEdgeMask
Selecciona una máscara precalculada de visibilidad de aristas según la guiñada del objeto.
Sintaxis
w3ddmg_u16 Wire3D_SelectEdgeMask(const Wire3DDMG_Model* model, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz);Parámetros
modelModelo que contiene los arrays de vértices, aristas y caras y sus cantidades; las tablas deben permanecer legibles durante la llamada.
rxRotación alrededor de X; dieciséis pasos forman una vuelta completa.
ryRotación alrededor de Y; dieciséis pasos forman una vuelta completa.
rzRotación alrededor de Z; dieciséis pasos forman una vuelta completa.
Valor devuelto
Máscara de visibilidad de aristas de 16 bits, o 0xFFFF si no se proporciona una tabla.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 96. Selecciona una máscara precalculada con los cuatro bits bajos de la guiñada del objeto; ignora cabeceo, alabeo y orientación de cámara. Usa 16, 8, 4 o 2 sectores; otras cantidades positivas eligen la entrada cero, salvo que las cantidades >=16 usan las primeras 16. Si faltan datos, devuelve 0xFFFF. La tabla de máscaras debe seguir siendo legible con el mapeo actual del puntero de datos.
Este ejemplo usa el perfil 128×96; su ventana gráfica empieza en (0,0) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
Ejemplo de uso
#pragma bank 0
// Compare direct model scaling with an object-array scene.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3D_Vec3 vertices[8]={{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}};
__prg_rom Wire3D_Edge edges[12]={{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}};
Wire3D_Model cube;
Wire3D_Object objects[2];
u16 masks[2];
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3D_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
cube.vertices=vertices;cube.edges=edges;cube.faces=0;cube.edge_faces=0;
cube.vertex_count=8;cube.edge_count=12;cube.face_count=0;cube.flags=0;
cube.edge_masks=0; cube.edge_mask_count=0;
Wire3D_BeginFrame();
// Upper pair: direct model calls at unity and half scale.
Wire3D_DrawModel(&cube,-32,32,96,0,0,0);
Wire3D_DrawModelScaled(&cube,32,32,96,0,0,0,128);
// Lower pair: the caller owns both object records and the model tables.
for(i=0;i<2;i++) {
objects[i].model=&cube;objects[i].x=-32+(s16)i*64;
objects[i].y=-32;objects[i].z=96;
objects[i].rx=0;objects[i].ry=0;objects[i].rz=0;
objects[i].scale_q8=256-(s16)i*128;objects[i].visible=1;
}
Wire3D_DrawScene(objects,2);
// Numeric checks cover the operation supplied by this viewport profile.
masks[0]=3;masks[1]=12;cube.edge_masks=masks; cube.edge_mask_count=2;
result[1]=Wire3D_SelectEdgeMask(&cube,0,0,0);
result[2]=Wire3D_SelectEdgeMask(&cube,0,8,0);
Wire3D_EndFrame(); result[7]=0xA55A;
while(1) {}
}Resultado esperado
Los modelos a escala unitaria y a media escala aparecen sobre una escena de un array de objetos con esas mismas escalas, para mostrar la proyección y el escalado.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_models.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d.h:52
WIRE3D_DMG_HEIGHT = 96. Select a precomputed mask from the low four bits of object yaw; pitch, roll and camera orientation are ignored. Use 16, 8, 4 or 2 bins; other positive counts select entry zero (counts >=16 use the first 16). Missing data returns 0xFFFF. Keep the mask table readable through the current data-pointer mapping.
kitaqgb/lib/wire3d_dmg.c:1109
w3ddmg_u16 Wire3DDMG_SelectEdgeMask(const Wire3DDMG_Model* model, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz)
{
w3ddmg_u8 count;
w3ddmg_u8 bin;
if (model == 0) return 0xFFFF;
if (model->edge_masks == 0) return 0xFFFF;
count = model->edge_mask_count;
if (count == 0) return 0xFFFF;
(void)rx;
(void)rz;
bin = (w3ddmg_u8)(((w3ddmg_u8)ry) & 15);
if (count >= 16) return model->edge_masks[(__safe_index w3ddmg_u8)bin];
if (count == 8) bin = (w3ddmg_u8)(bin >> 1);
else if (count == 4) bin = (w3ddmg_u8)(bin >> 2);
else if (count == 2) bin = (w3ddmg_u8)(bin >> 3);
else bin = 0;
if (bin >= count) bin = (w3ddmg_u8)(count - 1);
return model->edge_masks[(__safe_index w3ddmg_u8)bin];
}Wire3D_SetCamera
Guarda la posición y la orientación de la cámara para las proyecciones posteriores.
Sintaxis
void Wire3D_SetCamera(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 pitch, w3ddmg_i8 yaw, w3ddmg_i8 roll);Parámetros
xComponente X de la cámara en coordenadas del mundo.
yComponente Y de la cámara en coordenadas del mundo.
zComponente Z de la cámara en coordenadas del mundo.
pitchRotación alrededor de X; dieciséis pasos forman una vuelta completa.
yawRotación alrededor de Y; dieciséis pasos forman una vuelta completa.
rollRotación alrededor de Z; dieciséis pasos forman una vuelta completa.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 96. Guarda la posición y los ángulos de cámara para dibujos posteriores; una vuelta tiene 16 pasos angulares. No vuelve a proyectar lo ya dibujado ni valida los rangos de entrada.
Este ejemplo usa el perfil 128×96; su ventana gráfica empieza en (0,0) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
Ejemplo de uso
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3D_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
Wire3D_SetCamera(8,0,0,0,0,0);
result[1]=Wire3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
result[2]=projected_x; result[3]=projected_y;
projected_x=91; projected_y=92;
result[4]=Wire3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
result[5]=projected_x; result[6]=projected_y;
Wire3D_SetCamera(0,0,0,0,0,0);
Wire3D_BeginFrame();
Wire3D_DrawLine2D(8,8,56,8);
Wire3D_DrawLine2D(56,8,56,40);
Wire3D_DrawLine2D(56,40,8,40);
Wire3D_DrawLine2D(8,40,8,8);
Wire3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
Wire3D_DrawLine3D(-24,-24,96,24,24,96);
// Copy the viewport's top-left frame corner to a separate map cell.
Wire3D_PutBgTile(18,1,157);
Wire3D_EndFrame();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Este ejemplo muestra líneas, puntos, borrado y proyección en un fotograma. Se borra el centro del borde superior del marco de arriba a la izquierda y se proyecta una diagonal cerca del centro. Una proyección rechazada conserva las salidas 91 y 92.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_raster.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d.h:53
WIRE3D_DMG_HEIGHT = 96. Store camera position and angles for later draws; a full turn is 16 angle steps. No existing drawing is reprojected and no input range validation occurs.
kitaqgb/lib/wire3d_dmg.c:2659
void Wire3DDMG_SetCamera(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 pitch, w3ddmg_i8 yaw, w3ddmg_i8 roll)
{
w3ddmg_cam_x = x;
w3ddmg_cam_y = y;
w3ddmg_cam_z = z;
w3ddmg_cam_pitch = pitch;
w3ddmg_cam_yaw = yaw;
w3ddmg_cam_roll = roll;
}Wire3D_SetPalette
Escribe la correspondencia de cuatro tonos en el registro de paleta del fondo monocromo BGP.
Sintaxis
void Wire3D_SetPalette(w3ddmg_u8 bgp);Parámetros
bgpValor del registro BGP con cuatro asignaciones de tono de dos bits.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 96. Escribe inmediatamente la codificación directa de la paleta DMG BGP, sin sincronización de fotograma.
Este ejemplo usa el perfil 128×96; su ventana gráfica empieza en (0,0) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
Ejemplo de uso
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3D_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
Wire3D_SetCamera(8,0,0,0,0,0);
result[1]=Wire3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
result[2]=projected_x; result[3]=projected_y;
projected_x=91; projected_y=92;
result[4]=Wire3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
result[5]=projected_x; result[6]=projected_y;
Wire3D_SetCamera(0,0,0,0,0,0);
Wire3D_BeginFrame();
Wire3D_DrawLine2D(8,8,56,8);
Wire3D_DrawLine2D(56,8,56,40);
Wire3D_DrawLine2D(56,40,8,40);
Wire3D_DrawLine2D(8,40,8,8);
Wire3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
Wire3D_DrawLine3D(-24,-24,96,24,24,96);
// Copy the viewport's top-left frame corner to a separate map cell.
Wire3D_PutBgTile(18,1,157);
Wire3D_EndFrame();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Este ejemplo muestra líneas, puntos, borrado y proyección en un fotograma. Se borra el centro del borde superior del marco de arriba a la izquierda y se proyecta una diagonal cerca del centro. Una proyección rechazada conserva las salidas 91 y 92.


Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_raster.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d.h:54
WIRE3D_DMG_HEIGHT = 96. Write the raw DMG BGP palette encoding immediately; no frame synchronization occurs.
kitaqgb/lib/wire3d_dmg.c:597
void Wire3DDMG_SetPalette(w3ddmg_u8 bgp)
{
w3ddmg_reg_bgp = bgp;
}wire3d_cgb.h — Gráficos de alambre en color para CGB
Uso de las rutas de renderizado rápido
El renderizador normal de 128×96 avanza las direcciones de dibujo de forma incremental. Para líneas sin oclusión, selecciona el plano de color una vez por línea y mantiene la cantidad de píxeles y el error en registros de CPU. Las líneas con oclusión también seleccionan los planos una vez por línea y avanzan de forma incremental las direcciones de dibujo y de máscara. Cada píxel comprueba su bit de máscara y solo se escribe si no está cubierto. El renderizador de 160×144 y FastMap tienen rutas específicas. Las rotaciones de 0, 90, 180 y 270 grados limitan las entradas y luego intercambian coordenadas y cambian signos. El rendimiento global también depende de la cantidad de vértices, la longitud de las aristas, la oclusión y las transferencias a VRAM. Mida cada operación por separado del tiempo necesario para completar una imagen visible.
Modelos de alambre en color para CGB. El renderizador de píxeles de 128×96, el asignador de tiles de 160×144 y FastMap con tiles de contorno tienen secuencias distintas de inicialización y transferencia. El código que llama es propietario de los vértices, aristas y caras triangulares del modelo. Este módulo no simula física.
Vec3 contiene x/y/z, Edge los índices de vértice a/b y Face los índices del triángulo a/b/c. Los campos vertices, edges y faces de Model apuntan a esos arrays; cada contador indica su longitud. edge_faces contiene los índices de caras adyacentes f0/f1, con FACE_NONE para una cara ausente. MODEL_HIDDEN_LINES en flags solicita selección de aristas basada en caras. El área proyectada con signo determina la orientación de la cara, por lo que importa el orden de los vértices.
Object guarda una referencia al modelo, posición x/y/z, ángulos rx/ry/rz, scale_q8 y visible. Los objetos pueden compartir un modelo, pero el dibujo no copia tablas ni cambia automáticamente sus bancos ROM. Mantén legibles los datos referenciados durante todo el dibujo. Object de CGB también tiene un índice de color.
Los x/y de FastCube son desplazamientos respecto al centro de pantalla; z elige tamaño u orden de dibujo. FastCubes ignora los ángulos, mientras que FastCubeFrame usa rx/ry/rz para elegir entre cuatro variantes de patrón. Estas representaciones simplificadas tienen usos distintos de DrawModel, que proyecta mediante la cámara.
Wire3DCGB_BeginFrame
Inicia un fotograma vacío en el modo de renderizado seleccionado.
Sintaxis
void Wire3DCGB_BeginFrame();Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
En modo normal, selecciona la transferencia de toda el área de preparación, borra sus píxeles y la máscara de mapa de bits, reinicia los límites de la máscara y desactiva la oclusión. En pantalla completa reinicia en su lugar el asignador y los tramos de ese modo. Las escrituras BG pendientes siguen en la cola. Requiere compilar con el entorno de ejecución completo.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Al iniciar sparse en CGB, el primer uso de cada banco de destino (los dos primeros fotogramas) actualiza toda la vista y elimina los mosaicos de inicialización. La medición incluye ese coste. DrawLine2D no registra regiones sparse: use DrawLineClipped2D o llame explícitamente a MarkDirtyRect2D.
Ejemplo de uso
#pragma bank 0
// CGB raster paths: a red frame, blue diagonal, green marker and clipped line.
// Build this source together with lib/wire3d_cgb.c in an MBC5 256 KB CGB ROM.
#include "wire3d_cgb.h"
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4D) u8 sample_key1;
__location(0xC110) u16 result[8];
__prg_rom u8 lower_lines[8]={80,56,112,56,112,56,112,80};
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3DCGB_EnableDoubleSpeed();
Wire3DCGB_Init(); // Already at double speed: its internal request is a no-op.
result[2]=(u8)(sample_key1&128);
// Palette writes are performed with the LCD off, after entering VBlank.
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0;
Wire3DCGB_SetPaletteRGB15(WIRE3DCGB_RGB15(0,0,0),WIRE3DCGB_RGB15(31,0,0),WIRE3DCGB_RGB15(0,0,31),WIRE3DCGB_RGB15(0,31,0));
sample_lcdc=0x81;
Wire3DCGB_SetScreenOffset(0,0);
Wire3DCGB_SetCamera(0,0,0,0,0,0);
Wire3DCGB_BeginFrame();
Wire3DCGB_SetLineColor(1);
Wire3DCGB_DrawLine2D(8,8,56,8);
Wire3DCGB_DrawLine2D(56,8,56,40);
Wire3DCGB_DrawLine2D(56,40,8,40);
Wire3DCGB_DrawLine2D(8,40,8,8);
Wire3DCGB_DrawLine2DColor(8,40,56,8,2);
result[0]=Wire3DCGB_GetLineColor(); // Temporary blue restores red.
Wire3DCGB_SetLineColor(3);
Wire3DCGB_DrawPoint2D(64,48);
Wire3DCGB_DrawLineClipped2D(-10,72,140,72,3);
Wire3DCGB_DrawLineList2DColor(lower_lines,2,2);
result[1]=Wire3DCGB_GetLineColor(); // The blue line list restores green.
Wire3DCGB_PutBgTile(18,1,0x80); // Queue the supplied zero glyph outside the viewport.
Wire3DCGB_EndFrame();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Este ejemplo muestra líneas, puntos, borrado y proyección básicos en un solo fotograma. Un marco rojo contiene una diagonal azul, un punto y una línea horizontal verdes, una L azul y un cero verde en la esquina superior derecha.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_raster.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:122
kitaqgb/lib/wire3d_cgb.c:8154
void Wire3DCGB_BeginFrame()
{
if (w3dcgb_full_mode != 0)
{
w3dcgb_full_begin_asm();
return;
}
w3dcgb_full_frame_transfer = 1;
w3dcgb_clear_stage_asm();
w3dcgb_clear_occlusion_mask_asm();
w3dcgb_occ_min_x = (w3dcgb_u8)(WIRE3DCGB_SCREEN_W - 1);
w3dcgb_occ_min_y = (w3dcgb_u8)(WIRE3DCGB_SCREEN_H - 1);
w3dcgb_occ_max_x = 0;
w3dcgb_occ_max_y = 0;
w3dcgb_occlusion_active = 0;
}Wire3DCGB_BeginFrameFast
Inicia un fotograma limpio e invalida los rangos parciales anteriores para cubrir toda la ventana gráfica.
Sintaxis
void Wire3DCGB_BeginFrameFast();Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Realiza el mismo reinicio de fotograma normal o de pantalla completa que BeginFrame, pero primero amplía ambos rangos anteriores del historial parcial a toda la ventana gráfica de 192 tiles. Así evita que una transferencia parcial posterior confíe en bancos desactualizados.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Al iniciar sparse en CGB, el primer uso de cada banco de destino (los dos primeros fotogramas) actualiza toda la vista y elimina los mosaicos de inicialización. La medición incluye ese coste. DrawLine2D no registra regiones sparse: use DrawLineClipped2D o llame explícitamente a MarkDirtyRect2D.
Ejemplo de uso
#pragma bank 0
// Reuse both VRAM banks and remove old geometry while presenting sparse frames.
#include "wire_cgb_example.h"
void main() {
wire_results_clear(); Wire3DCGB_Init();
Wire3DCGB_ClearFrameTiles();
Wire3DCGB_EnableAtomicMaps(); wire_colors();
// First frame: red on the left. Fast begin invalidates both bank histories.
Wire3DCGB_BeginFrameFast(); wire_frame(8,8,32,32,1);
Wire3DCGB_EndFrameFast();
// Second frame: blue in the middle, with the old red frame removed.
Wire3DCGB_BeginFrameSparse(); wire_frame(40,40,64,64,2);
Wire3DCGB_EndFrameSparse();
// Third frame: explicitly clearing a stage discards its first green point.
Wire3DCGB_BeginFrameSparse();
Wire3DCGB_SetLineColor(3); Wire3DCGB_DrawPoint2D(4,4);
Wire3DCGB_ClearSparseStageFast();
// The final image contains only this green frame on the right.
wire_frame(80,8,112,32,3);
Wire3DCGB_MarkDirtyRect2D(80,8,112,32);
Wire3DCGB_InvalidateFrameHistory();
Wire3DCGB_EndFrameSparseNow();
result[0]=Wire3DCGB_GetLineColor();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Desaparecen los marcos rojo y azul dibujados antes y solo queda el marco verde final en (80,8)..(112,32), mostrando la transferencia parcial y la gestión del historial.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_sparse.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_sparse.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:123
kitaqgb/lib/wire3d_cgb.c:8175
void Wire3DCGB_BeginFrameFast()
{
w3dcgb_older_dirty_min_tile = 0;
w3dcgb_older_dirty_max_tile = (w3dcgb_u8)(WIRE3DCGB_TILE_COUNT - 1);
w3dcgb_prev_dirty_min_tile = 0;
w3dcgb_prev_dirty_max_tile = (w3dcgb_u8)(WIRE3DCGB_TILE_COUNT - 1);
if (w3dcgb_full_mode != 0)
{
w3dcgb_full_begin_asm();
return;
}
w3dcgb_full_frame_transfer = 1;
w3dcgb_clear_stage_asm();
w3dcgb_clear_occlusion_mask_asm();
w3dcgb_occ_min_x = (w3dcgb_u8)(WIRE3DCGB_SCREEN_W - 1);
w3dcgb_occ_min_y = (w3dcgb_u8)(WIRE3DCGB_SCREEN_H - 1);
w3dcgb_occ_max_x = 0;
w3dcgb_occ_max_y = 0;
w3dcgb_occlusion_active = 0;
}Wire3DCGB_BeginFrameSparse
Inicia un fotograma para transferir rangos parciales.
Sintaxis
void Wire3DCGB_BeginFrameSparse();Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Selecciona la transferencia parcial y borra toda el área de preparación de 128×96 para evitar píxeles antiguos cuando crezca la zona modificada. Reinicia los límites de la máscara y desactiva la oclusión; las compilaciones PAINTER_ONLY omiten el borrado de la máscara de mapa de bits que no utilizan. El modo de pantalla completa delega en el reinicio de su propio asignador.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Al iniciar sparse en CGB, el primer uso de cada banco de destino (los dos primeros fotogramas) actualiza toda la vista y elimina los mosaicos de inicialización. La medición incluye ese coste. DrawLine2D no registra regiones sparse: use DrawLineClipped2D o llame explícitamente a MarkDirtyRect2D.
Ejemplo de uso
#pragma bank 0
// Reuse both VRAM banks and remove old geometry while presenting sparse frames.
#include "wire_cgb_example.h"
void main() {
wire_results_clear(); Wire3DCGB_Init();
Wire3DCGB_ClearFrameTiles();
Wire3DCGB_EnableAtomicMaps(); wire_colors();
// First frame: red on the left. Fast begin invalidates both bank histories.
Wire3DCGB_BeginFrameFast(); wire_frame(8,8,32,32,1);
Wire3DCGB_EndFrameFast();
// Second frame: blue in the middle, with the old red frame removed.
Wire3DCGB_BeginFrameSparse(); wire_frame(40,40,64,64,2);
Wire3DCGB_EndFrameSparse();
// Third frame: explicitly clearing a stage discards its first green point.
Wire3DCGB_BeginFrameSparse();
Wire3DCGB_SetLineColor(3); Wire3DCGB_DrawPoint2D(4,4);
Wire3DCGB_ClearSparseStageFast();
// The final image contains only this green frame on the right.
wire_frame(80,8,112,32,3);
Wire3DCGB_MarkDirtyRect2D(80,8,112,32);
Wire3DCGB_InvalidateFrameHistory();
Wire3DCGB_EndFrameSparseNow();
result[0]=Wire3DCGB_GetLineColor();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Desaparecen los marcos rojo y azul dibujados antes y solo queda el marco verde final en (80,8)..(112,32), mostrando la transferencia parcial y la gestión del historial.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_sparse.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_sparse.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:124
kitaqgb/lib/wire3d_cgb.c:8200
void Wire3DCGB_BeginFrameSparse()
{
if (w3dcgb_full_mode != 0)
{
w3dcgb_full_begin_asm();
return;
}
w3dcgb_full_frame_transfer = 0;
w3dcgb_dirty_count = 0;
/* One ASM pass is faster than repeated range-growth clears and guarantees
that newly exposed dirty tiles can never copy stale stage pixels. */
w3dcgb_clear_stage_asm();
#ifndef WIRE3DCGB_PAINTER_ONLY
/* A Z-sorted painter erases silhouettes directly in the stage and never
reads the separate front-to-back coverage mask. */
w3dcgb_clear_occlusion_mask_asm();
#endif
w3dcgb_occ_min_x = (w3dcgb_u8)(WIRE3DCGB_SCREEN_W - 1);
w3dcgb_occ_min_y = (w3dcgb_u8)(WIRE3DCGB_SCREEN_H - 1);
w3dcgb_occ_max_x = 0;
w3dcgb_occ_max_y = 0;
w3dcgb_occlusion_active = 0;
}Wire3DCGB_ClearFrameTiles
Borra los tiles del fotograma visible de 128×96 y el área de preparación.
Sintaxis
void Wire3DCGB_ClearFrameTiles();Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Para el renderizador de 128×96, espera a VBlank, apaga el LCD, borra el área de preparación y los rangos de tiles del fotograma en ambos bancos, reinicia los atributos del mapa y activa LCDC 0x81. Borra las marcas y los contadores de cambios, pero conserva el historial min/max de las transferencias parciales. No reinicia full_mode ni sirve para reinicializar el modo de pantalla completa.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Al iniciar sparse en CGB, el primer uso de cada banco de destino (los dos primeros fotogramas) actualiza toda la vista y elimina los mosaicos de inicialización. La medición incluye ese coste. DrawLine2D no registra regiones sparse: use DrawLineClipped2D o llame explícitamente a MarkDirtyRect2D.
Ejemplo de uso
#pragma bank 0
// Reuse both VRAM banks and remove old geometry while presenting sparse frames.
#include "wire_cgb_example.h"
void main() {
wire_results_clear(); Wire3DCGB_Init();
Wire3DCGB_ClearFrameTiles();
Wire3DCGB_EnableAtomicMaps(); wire_colors();
// First frame: red on the left. Fast begin invalidates both bank histories.
Wire3DCGB_BeginFrameFast(); wire_frame(8,8,32,32,1);
Wire3DCGB_EndFrameFast();
// Second frame: blue in the middle, with the old red frame removed.
Wire3DCGB_BeginFrameSparse(); wire_frame(40,40,64,64,2);
Wire3DCGB_EndFrameSparse();
// Third frame: explicitly clearing a stage discards its first green point.
Wire3DCGB_BeginFrameSparse();
Wire3DCGB_SetLineColor(3); Wire3DCGB_DrawPoint2D(4,4);
Wire3DCGB_ClearSparseStageFast();
// The final image contains only this green frame on the right.
wire_frame(80,8,112,32,3);
Wire3DCGB_MarkDirtyRect2D(80,8,112,32);
Wire3DCGB_InvalidateFrameHistory();
Wire3DCGB_EndFrameSparseNow();
result[0]=Wire3DCGB_GetLineColor();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Desaparecen los marcos rojo y azul dibujados antes y solo queda el marco verde final en (80,8)..(112,32), mostrando la transferencia parcial y la gestión del historial.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_sparse.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_sparse.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:121
kitaqgb/lib/wire3d_cgb.c:8240
void Wire3DCGB_ClearFrameTiles()
{
w3dcgb_u8 i;
w3dcgb_wait_vblank_start();
w3dcgb_reg_lcdc = 0;
w3dcgb_clear_stage_asm();
w3dcgb_clear_frame_tiles_vram_asm();
w3dcgb_fill_attr_map_asm();
w3dcgb_reg_lcdc = 0x81;
i = 0;
while (i < W3DCGB_DIRTY_TILE_LIMIT)
{
w3dcgb_dirty_flags[(__safe_index w3dcgb_u8)i] = 0;
w3dcgb_prev_dirty_flags[(__safe_index w3dcgb_u8)i] = 0;
i = (w3dcgb_u8)(i + 1);
}
w3dcgb_dirty_count = 0;
w3dcgb_prev_dirty_count = 0;
}Wire3DCGB_ClearOcclusionMask
Borra el mapa de bits de oclusión o el historial de tramos de pantalla completa.
Sintaxis
void Wire3DCGB_ClearOcclusionMask();Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Si full_mode está activo, borra el historial de tramos de pantalla completa; si no, borra la máscara de mapa de bits de 128×96 y sus límites. No borra los píxeles visibles o preparados ni cambia si la prueba de oclusión está habilitada.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Red/blue scanlines stop inside masks; green outlines identify the triangle.
#include "wire_cgb_example.h"
__prg_rom u8 silhouette[5]={0x73,0x74,0xFF,0x75,0x73};
void main() {
u8 y;
wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
// Clearing this first test mask must leave the upper-left scanline intact.
Wire3DCGB_MarkTriangle2D(8,8,16,8,8,16);
Wire3DCGB_ClearOcclusionMask();
Wire3DCGB_MarkTriangle2D(32,16,64,16,32,48);
Wire3DCGB_MarkPackedSilhouette2D(silhouette,5,-2,104,32);
Wire3DCGB_SetOcclusionActive(1);
for(y=8;y<=56;y=y+4) Wire3DCGB_DrawLine2DColor(8,y,88,y,1);
for(y=28;y<=36;y++) Wire3DCGB_DrawLine2DColor(92,y,120,y,2);
Wire3DCGB_SetOcclusionActive(0);
Wire3DCGB_DrawLine2DColor(32,16,64,16,3);
Wire3DCGB_DrawLine2DColor(64,16,32,48,3);
Wire3DCGB_DrawLine2DColor(32,48,32,16,3);
Wire3DCGB_EndFrame(); result[7]=0xA55A;
while(1) {}
}Resultado esperado
Un triángulo oculta la parte central de las líneas de barrido rojas; una silueta empaquetada oculta las líneas azules. Los contornos verdes señalan la zona que produce la oclusión.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_mask.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_mask.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:148
kitaqgb/lib/wire3d_cgb.c:1962
void Wire3DCGB_ClearOcclusionMask()
{
if (w3dcgb_full_mode != 0) w3dcgb_full_clear_spans_asm();
else w3dcgb_clear_occlusion_mask();
}Wire3DCGB_ClearSparseStageFast
Borra toda el área de preparación y marca para transferencia la ventana gráfica completa de 128×96.
Sintaxis
void Wire3DCGB_ClearSparseStageFast();Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Borra toda el área de preparación del banco 2 y marca como modificada toda la ventana gráfica de 128×96. Pese a su nombre, no es un borrado parcial ni conserva píxeles preparados. No borra el estado de oclusión ni selecciona un modo de transferencia.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Reuse both VRAM banks and remove old geometry while presenting sparse frames.
#include "wire_cgb_example.h"
void main() {
wire_results_clear(); Wire3DCGB_Init();
Wire3DCGB_ClearFrameTiles();
Wire3DCGB_EnableAtomicMaps(); wire_colors();
// First frame: red on the left. Fast begin invalidates both bank histories.
Wire3DCGB_BeginFrameFast(); wire_frame(8,8,32,32,1);
Wire3DCGB_EndFrameFast();
// Second frame: blue in the middle, with the old red frame removed.
Wire3DCGB_BeginFrameSparse(); wire_frame(40,40,64,64,2);
Wire3DCGB_EndFrameSparse();
// Third frame: explicitly clearing a stage discards its first green point.
Wire3DCGB_BeginFrameSparse();
Wire3DCGB_SetLineColor(3); Wire3DCGB_DrawPoint2D(4,4);
Wire3DCGB_ClearSparseStageFast();
// The final image contains only this green frame on the right.
wire_frame(80,8,112,32,3);
Wire3DCGB_MarkDirtyRect2D(80,8,112,32);
Wire3DCGB_InvalidateFrameHistory();
Wire3DCGB_EndFrameSparseNow();
result[0]=Wire3DCGB_GetLineColor();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Desaparecen los marcos rojo y azul dibujados antes y solo queda el marco verde final en (80,8)..(112,32), mostrando la transferencia parcial y la gestión del historial.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_sparse.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_sparse.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:125
kitaqgb/lib/wire3d_cgb.c:8227
void Wire3DCGB_ClearSparseStageFast()
{
w3dcgb_clear_stage_asm();
w3dcgb_mark_dirty_rect(0, 0,
(w3dcgb_u8)(WIRE3DCGB_SCREEN_W - 1),
(w3dcgb_u8)(WIRE3DCGB_SCREEN_H - 1));
}Wire3DCGB_DrawEdgeList2D
Dibuja hasta 64 aristas a partir de desplazamientos de vértices preproyectados de tipo byte con signo.
Sintaxis
void Wire3DCGB_DrawEdgeList2D(const Wire3DCGB_Edge* edges, w3dcgb_u8 edge_count, const w3dcgb_i8* vertex_x, const w3dcgb_i8* vertex_y, w3dcgb_u8 x, w3dcgb_u8 y, w3dcgb_u8 color);Parámetros
edgesÍndices de los vértices de cada arista, en el formato declarado de estructura o de pares de bytes.
edge_countCantidad de aristas.
vertex_xArray de desplazamientos X de los vértices preproyectados.
vertex_yArray de desplazamientos Y de los vértices preproyectados.
xCoordenada X del centro en píxeles de la ventana gráfica.
yCoordenada Y del centro en píxeles de la ventana gráfica.
colorÍndice de color de dibujo; las paletas de ejemplo usan 1=rojo, 2=azul y 3=verde.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Dibuja hasta 64 aristas indexadas desde desplazamientos de tipo byte con signo alrededor de (cx,cy). Ignora arrays null; los índices deben apuntar a vértices legibles. Mantén los extremos trasladados en la ventana gráfica antes de la conversión a bytes, que puede producir desbordamiento modular. Despacha según el modo y conserva el color anterior; no comprueba la cantidad de vértices.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Preprojected edge arrays, a clipped square, a tiny marker and a projectile.
#include "wire_cgb_example.h"
__prg_rom Wire3DCGB_Edge edges[4]={{0,1},{1,2},{2,3},{3,0}};
__prg_rom s8 vx8[4]={-8,8,8,-8};
__prg_rom s8 vy8[4]={-8,-8,8,8};
__prg_rom s16 vx16[4]={-12,12,12,-12};
__prg_rom s16 vy16[4]={-8,-8,8,8};
__prg_rom u8 mask[1]={5};
Wire3DCGB_Model shape;
void main() {
wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
shape.vertices=0;shape.edges=edges;shape.faces=0;shape.edge_faces=0;
shape.vertex_count=4;shape.edge_count=4;shape.face_count=0;shape.flags=0;
Wire3DCGB_SetLineColor(2);
Wire3DCGB_DrawMaskedModel2D(&shape,vx8,vy8,mask,24,24,1);
Wire3DCGB_DrawEdgeList2D(edges,4,vx8,vy8,64,24,2);
Wire3DCGB_DrawEdgeListClipped2D(edges,4,vx16,vy16,4,4,64,3);
Wire3DCGB_DrawTinyModel2D(104,24,16,3);
result[0]=Wire3DCGB_ProjectAxis48(48,96);
result[1]=Wire3DCGB_ProjectAxis48(-48,96);
Wire3DCGB_DrawFastProjectile(96,64,64,0,1);
result[2]=Wire3DCGB_GetLineColor();
Wire3DCGB_EndFrame();result[7]=0xA55A;
while(1) {}
}Resultado esperado
Dos aristas horizontales rojas, un cuadrado azul, un marco verde recortado, un marcador verde de seis píxeles y un proyectil rojo permiten comparar los formatos de lista.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_lists.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_lists.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:183
kitaqgb/lib/wire3d_cgb.c:8524
void Wire3DCGB_DrawEdgeList2D(const Wire3DCGB_Edge* edges, w3dcgb_u8 edge_count,
const w3dcgb_i8* vertex_x, const w3dcgb_i8* vertex_y,
w3dcgb_u8 x, w3dcgb_u8 y, w3dcgb_u8 color)
{
w3dcgb_u8 i;
w3dcgb_u8 a;
w3dcgb_u8 b;
w3dcgb_u8 old_color;
if (edges == 0) return;
if (vertex_x == 0) return;
if (vertex_y == 0) return;
if (edge_count > WIRE3DCGB_MODEL_EDGE_LIMIT) edge_count = WIRE3DCGB_MODEL_EDGE_LIMIT;
old_color = w3dcgb_line_color;
w3dcgb_line_color = (w3dcgb_u8)(color & 3);
if (w3dcgb_full_mode == 0)
{
w3dcgb_edge_list_ptr = edges;
w3dcgb_edge_x_ptr = vertex_x;
w3dcgb_edge_y_ptr = vertex_y;
w3dcgb_edge_remaining = edge_count;
w3dcgb_edge_center_x = x;
w3dcgb_edge_center_y = y;
w3dcgb_edge_list_asm();
w3dcgb_line_color = old_color;
return;
}
i = 0;
while (i < edge_count)
{
a = edges[(__safe_index w3dcgb_u8)i].a;
b = edges[(__safe_index w3dcgb_u8)i].b;
w3dcgb_line_x0 = (w3dcgb_u8)((w3dcgb_i16)x + (w3dcgb_i16)vertex_x[(__safe_index w3dcgb_u8)a]);
w3dcgb_line_y0 = (w3dcgb_u8)((w3dcgb_i16)y + (w3dcgb_i16)vertex_y[(__safe_index w3dcgb_u8)a]);
w3dcgb_line_x1 = (w3dcgb_u8)((w3dcgb_i16)x + (w3dcgb_i16)vertex_x[(__safe_index w3dcgb_u8)b]);
w3dcgb_line_y1 = (w3dcgb_u8)((w3dcgb_i16)y + (w3dcgb_i16)vertex_y[(__safe_index w3dcgb_u8)b]);
if (w3dcgb_full_mode != 0) w3dcgb_full_line_fast_asm();
else w3dcgb_line_stage_asm();
i = (w3dcgb_u8)(i + 1);
}
w3dcgb_line_color = old_color;
}Wire3DCGB_DrawEdgeListClipped2D
Valida los vértices proyectados con signo y las aristas, y después recorta y dibuja la lista de aristas.
Sintaxis
void Wire3DCGB_DrawEdgeListClipped2D(const Wire3DCGB_Edge* edges, w3dcgb_u8 edge_count, const w3dcgb_i16* vx, const w3dcgb_i16* vy, w3dcgb_u8 vertex_count, w3dcgb_i16 cx, w3dcgb_i16 cy, w3dcgb_u8 color);Parámetros
edgesÍndices de los vértices de cada arista, en el formato declarado de estructura o de pares de bytes.
edge_countCantidad de aristas.
vxArray de desplazamientos X de 16 bits con signo antes del recorte.
vyArray de desplazamientos Y de 16 bits con signo antes del recorte.
vertex_countCantidad de entradas del array de vértices.
cxCoordenada X del centro en píxeles de la ventana gráfica.
cyCoordenada Y del centro en píxeles de la ventana gráfica.
colorÍndice de color de dibujo; las paletas de ejemplo usan 1=rojo, 2=azul y 3=verde.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Antes de dibujar, valida los punteros, entre 1 y 24 vértices, hasta 64 aristas, todos los índices y las coordenadas y centros de entrada dentro de ±2047. La geometría totalmente visible usa un búfer temporal de bytes con signo y la ruta indexada rápida; las demás aristas usan el recortador de líneas con signo. Este puede rechazar extremos trasladados fuera de ±2047 aunque cada entrada haya pasado la validación. Sustituye el búfer temporal de pantalla compartido y conserva el color anterior mediante las API de líneas que llama.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Preprojected edge arrays, a clipped square, a tiny marker and a projectile.
#include "wire_cgb_example.h"
__prg_rom Wire3DCGB_Edge edges[4]={{0,1},{1,2},{2,3},{3,0}};
__prg_rom s8 vx8[4]={-8,8,8,-8};
__prg_rom s8 vy8[4]={-8,-8,8,8};
__prg_rom s16 vx16[4]={-12,12,12,-12};
__prg_rom s16 vy16[4]={-8,-8,8,8};
__prg_rom u8 mask[1]={5};
Wire3DCGB_Model shape;
void main() {
wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
shape.vertices=0;shape.edges=edges;shape.faces=0;shape.edge_faces=0;
shape.vertex_count=4;shape.edge_count=4;shape.face_count=0;shape.flags=0;
Wire3DCGB_SetLineColor(2);
Wire3DCGB_DrawMaskedModel2D(&shape,vx8,vy8,mask,24,24,1);
Wire3DCGB_DrawEdgeList2D(edges,4,vx8,vy8,64,24,2);
Wire3DCGB_DrawEdgeListClipped2D(edges,4,vx16,vy16,4,4,64,3);
Wire3DCGB_DrawTinyModel2D(104,24,16,3);
result[0]=Wire3DCGB_ProjectAxis48(48,96);
result[1]=Wire3DCGB_ProjectAxis48(-48,96);
Wire3DCGB_DrawFastProjectile(96,64,64,0,1);
result[2]=Wire3DCGB_GetLineColor();
Wire3DCGB_EndFrame();result[7]=0xA55A;
while(1) {}
}Resultado esperado
Dos aristas horizontales rojas, un cuadrado azul, un marco verde recortado, un marcador verde de seis píxeles y un proyectil rojo permiten comparar los formatos de lista.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_lists.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_lists.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:138
kitaqgb/lib/wire3d_cgb.c:9806
void Wire3DCGB_DrawEdgeListClipped2D(const Wire3DCGB_Edge* edges, w3dcgb_u8 edge_count,
const w3dcgb_i16* vx, const w3dcgb_i16* vy, w3dcgb_u8 vertex_count,
w3dcgb_i16 cx, w3dcgb_i16 cy, w3dcgb_u8 color)
{
w3dcgb_u8 i;
w3dcgb_u8 a;
w3dcgb_u8 b;
w3dcgb_u8 inside;
w3dcgb_i16 x;
w3dcgb_i16 y;
w3dcgb_i16 min_x;
w3dcgb_i16 min_y;
w3dcgb_i16 max_x;
w3dcgb_i16 max_y;
if ((edges == 0) || (vx == 0) || (vy == 0)) return;
if ((cx < -2047) || (cx > 2047) || (cy < -2047) || (cy > 2047)) return;
if ((vertex_count == 0) || (vertex_count > WIRE3DCGB_MODEL_VERTEX_LIMIT) ||
(edge_count > WIRE3DCGB_MODEL_EDGE_LIMIT)) return;
i = 0;
while (i < edge_count)
{
if ((edges[(__safe_index w3dcgb_u8)i].a >= vertex_count) ||
(edges[(__safe_index w3dcgb_u8)i].b >= vertex_count)) return;
i = (w3dcgb_u8)(i + 1);
}
min_x = 32767;
min_y = 32767;
max_x = -32767;
max_y = -32767;
inside = 1;
i = 0;
while (i < vertex_count)
{
if ((vx[(__safe_index w3dcgb_u8)i] < -2047) ||
(vx[(__safe_index w3dcgb_u8)i] > 2047) ||
(vy[(__safe_index w3dcgb_u8)i] < -2047) ||
(vy[(__safe_index w3dcgb_u8)i] > 2047)) return;
x = (w3dcgb_i16)(cx + vx[(__safe_index w3dcgb_u8)i]);
y = (w3dcgb_i16)(cy + vy[(__safe_index w3dcgb_u8)i]);
if (x < min_x) min_x = x;
if (x > max_x) max_x = x;
if (y < min_y) min_y = y;
if (y > max_y) max_y = y;
/* Reuse projected-vertex scratch; drawing is non-reentrant. */
w3dcgb_screen_x[(__safe_index w3dcgb_u8)i] = (w3dcgb_u8)(x - 64);
w3dcgb_screen_y[(__safe_index w3dcgb_u8)i] = (w3dcgb_u8)(y - 48);
i = (w3dcgb_u8)(i + 1);
}
if ((w3dcgb_clip_outcode(min_x, min_y) | w3dcgb_clip_outcode(max_x, max_y)) != 0) inside = 0;
if (inside != 0)
{
if (w3dcgb_full_mode == 0) w3dcgb_mark_dirty_rect((w3dcgb_u8)min_x,
(w3dcgb_u8)min_y, (w3dcgb_u8)max_x, (w3dcgb_u8)max_y);
Wire3DCGB_DrawEdgeList2D(edges, edge_count, (const w3dcgb_i8*)w3dcgb_screen_x,
(const w3dcgb_i8*)w3dcgb_screen_y, 64, 48, color);
return;
}
i = 0;
while (i < edge_count)
{
a = edges[(__safe_index w3dcgb_u8)i].a;
b = edges[(__safe_index w3dcgb_u8)i].b;
Wire3DCGB_DrawLineClipped2D((w3dcgb_i16)(cx + vx[(__safe_index w3dcgb_u8)a]),
(w3dcgb_i16)(cy + vy[(__safe_index w3dcgb_u8)a]),
(w3dcgb_i16)(cx + vx[(__safe_index w3dcgb_u8)b]),
(w3dcgb_i16)(cy + vy[(__safe_index w3dcgb_u8)b]), color);
i = (w3dcgb_u8)(i + 1);
}
}Wire3DCGB_DrawFastCubeFrame
Sustituye el fotograma anterior de patrones de cubo y transfiere hasta tres patrones junto con los indicadores de estado.
Sintaxis
void Wire3DCGB_DrawFastCubeFrame(Wire3DCGB_FastCube* cubes, w3dcgb_u8 count, w3dcgb_u8 hidden_enabled, w3dcgb_u8 selected);Parámetros
cubesArray de posiciones, ángulos y colores para dibujar cubos de forma rápida.
countCantidad de entradas proporcionadas; consulta el límite de procesamiento de cada operación.
hidden_enabledCero incluye las aristas ocultas; un valor distinto de cero selecciona su eliminación simplificada.
selectedÍndice del objeto seleccionado en el array original; la API de patrones lo usa para un indicador de estado.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Prepara el mapa, borra los límites y las celdas de estado anteriores, ordena hasta tres patrones de cubo de lejos a cerca por el Z sin transformar, los dibuja y transfiere números y atributos en VBlank. No reordena el array del código que llama. Un array no nulo con count cero borra los patrones anteriores; un array null no hace nada. selected & 3 elige solo la celda de estado, no resalta un cubo. Requiere los patrones cargados, el entorno de ejecución completo y un mapeo WRAM de FastMap coherente; no los inicializa.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Al iniciar sparse en CGB, el primer uso de cada banco de destino (los dos primeros fotogramas) actualiza toda la vista y elimina los mosaicos de inicialización. La medición incluye ese coste. DrawLine2D no registra regiones sparse: use DrawLineClipped2D o llame explícitamente a MarkDirtyRect2D.
Ejemplo de uso
#pragma bank 0
// A complete cube-stamp frame removes the preceding stamp's old map cells.
#include "wire_cgb_example.h"
Wire3DCGB_FastCube cube[1];
void main() {
u8 bank;
wire_results_clear(); Wire3DCGB_Init(); wire_colors();
cube[0].x=-24;cube[0].y=0;cube[0].z=96;
cube[0].rx=0;cube[0].ry=0;cube[0].rz=0;cube[0].color=1;
bank=sample_svbk;sample_svbk=2;
Wire3DCGB_DrawFastCubeFrame(cube,1,1,0);
cube[0].x=24;
Wire3DCGB_DrawFastCubeFrame(cube,1,1,0);
sample_svbk=bank;result[0]=cube[0].x;result[7]=0xA55A;
while(1) {}
}Resultado esperado
Desaparece el patrón de cubo anterior. Un cubo rojo de 32×32 empieza en (72,32), con indicadores de estado verdes en la parte superior.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_stamp.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_stamp.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:158
kitaqgb/lib/wire3d_cgb.c:10800
void Wire3DCGB_DrawFastCubeFrame(Wire3DCGB_FastCube* cubes, w3dcgb_u8 count, w3dcgb_u8 hidden_enabled, w3dcgb_u8 selected)
{
w3dcgb_u8 i;
w3dcgb_u8 scene_count;
w3dcgb_u8 a;
w3dcgb_u8 b;
w3dcgb_u8 c;
w3dcgb_u8 x;
if (cubes == 0) return;
scene_count = count;
if (scene_count > 3) scene_count = 3;
w3dcgb_fast_map_prepare();
i = 0;
while (i < w3dcgb_fast_prev_count)
{
w3dcgb_fast_map_clear_rect(
w3dcgb_fast_prev_x[(__safe_index w3dcgb_u8)i],
w3dcgb_fast_prev_y[(__safe_index w3dcgb_u8)i],
w3dcgb_fast_prev_w[(__safe_index w3dcgb_u8)i],
w3dcgb_fast_prev_h[(__safe_index w3dcgb_u8)i]);
i = (w3dcgb_u8)(i + 1);
}
w3dcgb_fast_map_clear_rect(0, 0, 4, 1);
w3dcgb_fast_map_clear_rect(14, 0, 2, 1);
if (scene_count == 0)
{
w3dcgb_fast_prev_count = 0;
w3dcgb_wait_vblank_start();
w3dcgb_fast_map_flush_gdma_asm();
return;
}
a = 0;
b = 1;
c = 2;
if (scene_count == 1)
{
w3dcgb_fast_map_draw_cube_one(&cubes[0], hidden_enabled, (w3dcgb_u8)(selected == 0), 0);
w3dcgb_fast_prev_count = 1;
}
else if (scene_count == 2)
{
if (cubes[0].z < cubes[1].z)
{
w3dcgb_fast_map_draw_cube_one(&cubes[1], hidden_enabled, (w3dcgb_u8)(selected == 1), 1);
w3dcgb_fast_map_draw_cube_one(&cubes[0], hidden_enabled, (w3dcgb_u8)(selected == 0), 0);
}
else
{
w3dcgb_fast_map_draw_cube_one(&cubes[0], hidden_enabled, (w3dcgb_u8)(selected == 0), 0);
w3dcgb_fast_map_draw_cube_one(&cubes[1], hidden_enabled, (w3dcgb_u8)(selected == 1), 1);
}
w3dcgb_fast_prev_count = 2;
}
else
{
if (cubes[a].z < cubes[b].z)
{
w3dcgb_u8 t;
t = a;
a = b;
b = t;
}
if (cubes[b].z < cubes[c].z)
{
w3dcgb_u8 t;
t = b;
b = c;
c = t;
}
if (cubes[a].z < cubes[b].z)
{
w3dcgb_u8 t;
t = a;
a = b;
b = t;
}
w3dcgb_fast_map_draw_cube_one(&cubes[a], hidden_enabled, (w3dcgb_u8)(selected == a), a);
w3dcgb_fast_map_draw_cube_one(&cubes[b], hidden_enabled, (w3dcgb_u8)(selected == b), b);
w3dcgb_fast_map_draw_cube_one(&cubes[c], hidden_enabled, (w3dcgb_u8)(selected == c), c);
w3dcgb_fast_prev_count = 3;
}
x = (w3dcgb_u8)(selected & 3);
w3dcgb_fast_map_or_cell((w3dcgb_i16)x, (w3dcgb_i16)0, WIRE3DCGB_COLOR_HIGH, 15);
if (hidden_enabled != 0) w3dcgb_fast_map_or_cell((w3dcgb_i16)15, (w3dcgb_i16)0, WIRE3DCGB_COLOR_HIGH, 15);
else w3dcgb_fast_map_or_cell((w3dcgb_i16)14, (w3dcgb_i16)0, WIRE3DCGB_COLOR_LOW, 15);
w3dcgb_wait_vblank_start();
w3dcgb_fast_map_flush_gdma_asm();
}Wire3DCGB_DrawFastCubes
Dibuja hasta tres cubos como contornos 2D cuyo tamaño depende de la profundidad.
Sintaxis
void Wire3DCGB_DrawFastCubes(Wire3DCGB_FastCube* cubes, w3dcgb_u8 count, w3dcgb_u8 hidden_enabled, w3dcgb_u8 selected);Parámetros
cubesArray de posiciones, ángulos y colores para dibujar cubos de forma rápida.
countCantidad de entradas proporcionadas; consulta el límite de procesamiento de cada operación.
hidden_enabledCero incluye las aristas ocultas; un valor distinto de cero selecciona su eliminación simplificada.
selectedÍndice del objeto seleccionado en el array original; la API de patrones lo usa para un indicador de estado.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Dibuja hasta tres aproximaciones 2D de cubos, ordenadas de lejos a cerca por el Z sin transformar, sin reordenar el array del código que llama. Ignora null o entradas vacías. selected es un índice del array original. No usa cámara ni rotación y no restaura el color.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Fast cube approximations use screen offsets and depth size bands, not a camera.
#include "wire_cgb_example.h"
Wire3DCGB_FastCube cubes[2];
void main() {
u8 i;
wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
for(i=0;i<2;i++){cubes[i].rx=0;cubes[i].ry=0;cubes[i].rz=0;}
cubes[0].x=-32;cubes[0].y=-8;cubes[0].z=90;cubes[0].color=1;
cubes[1].x=32;cubes[1].y=8;cubes[1].z=160;cubes[1].color=2;
Wire3DCGB_SetCamera(100,0,0,4,4,4); // FastCubes intentionally ignores this.
Wire3DCGB_DrawFastCubes(cubes,2,1,0);
Wire3DCGB_DrawFastStatus(1,0);
result[0]=Wire3DCGB_GetLineColor();
result[1]=cubes[0].z;result[2]=cubes[1].z;
Wire3DCGB_EndFrame();result[7]=0xA55A;
while(1) {}
}Resultado esperado
El cubo rojo cercano de la izquierda es mayor que el cubo azul lejano de la derecha. Una cruz verde marca el cubo rojo seleccionado.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_cubes.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_cubes.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:156
kitaqgb/lib/wire3d_cgb.c:8765
void Wire3DCGB_DrawFastCubes(Wire3DCGB_FastCube* cubes, w3dcgb_u8 count, w3dcgb_u8 hidden_enabled, w3dcgb_u8 selected)
{
w3dcgb_u8 scene_count;
w3dcgb_u8 a;
w3dcgb_u8 b;
w3dcgb_u8 c;
w3dcgb_u8 x;
if (cubes == 0) return;
scene_count = count;
if (scene_count == 0) return;
if (scene_count > 3) scene_count = 3;
a = 0;
b = 1;
c = 2;
if (scene_count == 1)
{
w3dcgb_draw_fast_cube_one(&cubes[0], hidden_enabled, (w3dcgb_u8)(selected == 0));
return;
}
if (scene_count == 2)
{
if (cubes[0].z < cubes[1].z)
{
w3dcgb_draw_fast_cube_one(&cubes[1], hidden_enabled, (w3dcgb_u8)(selected == 1));
w3dcgb_draw_fast_cube_one(&cubes[0], hidden_enabled, (w3dcgb_u8)(selected == 0));
}
else
{
w3dcgb_draw_fast_cube_one(&cubes[0], hidden_enabled, (w3dcgb_u8)(selected == 0));
w3dcgb_draw_fast_cube_one(&cubes[1], hidden_enabled, (w3dcgb_u8)(selected == 1));
}
return;
}
if (cubes[a].z < cubes[b].z)
{
w3dcgb_u8 t;
t = a;
a = b;
b = t;
}
if (cubes[b].z < cubes[c].z)
{
w3dcgb_u8 t;
t = b;
b = c;
c = t;
}
if (cubes[a].z < cubes[b].z)
{
w3dcgb_u8 t;
t = a;
a = b;
b = t;
}
w3dcgb_draw_fast_cube_one(&cubes[a], hidden_enabled, (w3dcgb_u8)(selected == a));
w3dcgb_draw_fast_cube_one(&cubes[b], hidden_enabled, (w3dcgb_u8)(selected == b));
w3dcgb_draw_fast_cube_one(&cubes[c], hidden_enabled, (w3dcgb_u8)(selected == c));
}Wire3DCGB_DrawFastProjectile
Dibuja un proyectil de seis aristas en un centro ya proyectado, con tamaño y orientación elegidos por profundidad y fase.
Sintaxis
void Wire3DCGB_DrawFastProjectile(w3dcgb_u8 x, w3dcgb_u8 y, w3dcgb_i16 z, w3dcgb_u8 phase, w3dcgb_u8 color);Parámetros
xCoordenada X del centro en píxeles de la ventana gráfica.
yCoordenada Y del centro en píxeles de la ventana gráfica.
zProfundidad usada para elegir el tamaño o calcular la proyección.
phaseFase de rotación; avanza una orientación cada ocho unidades del contador.
colorÍndice de color de dibujo; las paletas de ejemplo usan 1=rojo, 2=azul y 3=verde.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Dibuja un proyectil de seis aristas en un centro ya proyectado, con cuatro franjas de tamaño según profundidad y cuatro orientaciones según fase. Rechaza centros fuera de X=10..117 o Y=10..85, marca los límites modificados y deja seleccionado el color solicitado. Usa el rasterizador normal y no aplica la cámara.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Preprojected edge arrays, a clipped square, a tiny marker and a projectile.
#include "wire_cgb_example.h"
__prg_rom Wire3DCGB_Edge edges[4]={{0,1},{1,2},{2,3},{3,0}};
__prg_rom s8 vx8[4]={-8,8,8,-8};
__prg_rom s8 vy8[4]={-8,-8,8,8};
__prg_rom s16 vx16[4]={-12,12,12,-12};
__prg_rom s16 vy16[4]={-8,-8,8,8};
__prg_rom u8 mask[1]={5};
Wire3DCGB_Model shape;
void main() {
wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
shape.vertices=0;shape.edges=edges;shape.faces=0;shape.edge_faces=0;
shape.vertex_count=4;shape.edge_count=4;shape.face_count=0;shape.flags=0;
Wire3DCGB_SetLineColor(2);
Wire3DCGB_DrawMaskedModel2D(&shape,vx8,vy8,mask,24,24,1);
Wire3DCGB_DrawEdgeList2D(edges,4,vx8,vy8,64,24,2);
Wire3DCGB_DrawEdgeListClipped2D(edges,4,vx16,vy16,4,4,64,3);
Wire3DCGB_DrawTinyModel2D(104,24,16,3);
result[0]=Wire3DCGB_ProjectAxis48(48,96);
result[1]=Wire3DCGB_ProjectAxis48(-48,96);
Wire3DCGB_DrawFastProjectile(96,64,64,0,1);
result[2]=Wire3DCGB_GetLineColor();
Wire3DCGB_EndFrame();result[7]=0xA55A;
while(1) {}
}Resultado esperado
Dos aristas horizontales rojas, un cuadrado azul, un marco verde recortado, un marcador verde de seis píxeles y un proyectil rojo permiten comparar los formatos de lista.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_lists.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_lists.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:159
kitaqgb/lib/wire3d_cgb.c:8833
void Wire3DCGB_DrawFastProjectile(w3dcgb_u8 x, w3dcgb_u8 y, w3dcgb_i16 z,
w3dcgb_u8 phase, w3dcgb_u8 color)
{
w3dcgb_u8 radius;
w3dcgb_u8 half;
w3dcgb_u8 depth;
w3dcgb_u8 ax;
w3dcgb_u8 ay;
w3dcgb_u8 bx;
w3dcgb_u8 by;
w3dcgb_u8 cx;
w3dcgb_u8 cy;
w3dcgb_u8 dx;
w3dcgb_u8 dy;
w3dcgb_u8 spin;
if ((x < 10) || (x > 117) || (y < 10) || (y > 85)) return;
radius = 3;
depth = 1;
if (z <= 160) { radius = 4; depth = 2; }
if (z <= 112) { radius = 5; depth = 3; }
if (z <= 64) { radius = 7; depth = 4; }
half = (w3dcgb_u8)(radius >> 1);
ax = x;
ay = (w3dcgb_u8)(y - radius);
bx = (w3dcgb_u8)(x - radius);
by = (w3dcgb_u8)(y + half);
cx = (w3dcgb_u8)(x + radius);
cy = by;
spin = (w3dcgb_u8)((phase >> 3) & 3);
dx = (w3dcgb_u8)(x + depth);
dy = (w3dcgb_u8)(y - depth);
if (spin == 1) dy = (w3dcgb_u8)(y + depth);
else if (spin == 2)
{
dx = (w3dcgb_u8)(x - depth);
dy = (w3dcgb_u8)(y + depth);
}
else if (spin == 3) dx = (w3dcgb_u8)(x - depth);
w3dcgb_mark_dirty_rect((w3dcgb_u8)(x - radius), (w3dcgb_u8)(y - radius),
(w3dcgb_u8)(x + radius), (w3dcgb_u8)(y + radius));
w3dcgb_line_color = color;
w3dcgb_draw_line_raw(ax, ay, bx, by);
w3dcgb_draw_line_raw(bx, by, cx, cy);
w3dcgb_draw_line_raw(cx, cy, ax, ay);
w3dcgb_draw_line_raw(ax, ay, dx, dy);
w3dcgb_draw_line_raw(bx, by, dx, dy);
w3dcgb_draw_line_raw(cx, cy, dx, dy);
}Wire3DCGB_DrawFastStatus
Dibuja pequeños indicadores de líneas para la selección de objetos y el modo de líneas ocultas.
Sintaxis
void Wire3DCGB_DrawFastStatus(w3dcgb_u8 hidden_enabled, w3dcgb_u8 selected);Parámetros
hidden_enabledCero incluye las aristas ocultas; un valor distinto de cero selecciona su eliminación simplificada.
selectedÍndice del objeto seleccionado en el array original; la API de patrones lo usa para un indicador de estado.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Dibuja pequeños indicadores de selección y de modo de líneas ocultas en color 3 y marca sus límites del modo normal como modificados. Se espera selected en 0..2, sin comprobarlo. Los indicadores usan líneas, no tiles de fuente, y no restauran el color anterior.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Fast cube approximations use screen offsets and depth size bands, not a camera.
#include "wire_cgb_example.h"
Wire3DCGB_FastCube cubes[2];
void main() {
u8 i;
wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
for(i=0;i<2;i++){cubes[i].rx=0;cubes[i].ry=0;cubes[i].rz=0;}
cubes[0].x=-32;cubes[0].y=-8;cubes[0].z=90;cubes[0].color=1;
cubes[1].x=32;cubes[1].y=8;cubes[1].z=160;cubes[1].color=2;
Wire3DCGB_SetCamera(100,0,0,4,4,4); // FastCubes intentionally ignores this.
Wire3DCGB_DrawFastCubes(cubes,2,1,0);
Wire3DCGB_DrawFastStatus(1,0);
result[0]=Wire3DCGB_GetLineColor();
result[1]=cubes[0].z;result[2]=cubes[1].z;
Wire3DCGB_EndFrame();result[7]=0xA55A;
while(1) {}
}Resultado esperado
El cubo rojo cercano de la izquierda es mayor que el cubo azul lejano de la derecha. Una cruz verde marca el cubo rojo seleccionado.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_cubes.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_cubes.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:157
kitaqgb/lib/wire3d_cgb.c:8888
void Wire3DCGB_DrawFastStatus(w3dcgb_u8 hidden_enabled, w3dcgb_u8 selected)
{
w3dcgb_u8 x;
w3dcgb_mark_dirty_rect(0, 0, 31, 7);
w3dcgb_mark_dirty_rect(116, 0, 127, 7);
x = (w3dcgb_u8)(4 + (selected * 8));
w3dcgb_line_color = WIRE3DCGB_COLOR_HIGH;
w3dcgb_draw_line_raw(x, 3, (w3dcgb_u8)(x + 5), 3);
w3dcgb_draw_line_raw(x, 6, (w3dcgb_u8)(x + 5), 6);
if (hidden_enabled != 0)
{
w3dcgb_draw_line_raw(118, 3, 124, 3);
w3dcgb_draw_line_raw(118, 6, 124, 6);
}
else
{
w3dcgb_draw_line_raw(118, 3, 124, 6);
w3dcgb_draw_line_raw(118, 6, 124, 3);
}
}Wire3DCGB_DrawLine2D
Dibuja una línea en coordenadas de pantalla, incluidos ambos extremos, con el renderizador activo.
Sintaxis
void Wire3DCGB_DrawLine2D(w3dcgb_u8 ax, w3dcgb_u8 ay, w3dcgb_u8 bx, w3dcgb_u8 by);Parámetros
axCoordenada X del vértice A en píxeles de la ventana gráfica.
ayCoordenada Y del vértice A en píxeles de la ventana gráfica.
bxCoordenada X del vértice B en píxeles de la ventana gráfica.
byCoordenada Y del vértice B en píxeles de la ventana gráfica.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Guarda los extremos de tipo byte e invoca el rasterizador normal o de pantalla completa. Las coordenadas deben estar dentro de la ventana gráfica seleccionada; usa DrawLineClipped2D para geometría con signo o fuera de pantalla. Las líneas normales combinan planos de color mediante OR y no marcan límites parciales; usa la API con recorte o InvalidateFrameHistory antes de una transferencia parcial. Las líneas de pantalla completa sustituyen colores y asignan tiles. Ambas rutas interpretan el color cero como 3, no como borrado.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// CGB raster paths: a red frame, blue diagonal, green marker and clipped line.
// Build this source together with lib/wire3d_cgb.c in an MBC5 256 KB CGB ROM.
#include "wire3d_cgb.h"
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4D) u8 sample_key1;
__location(0xC110) u16 result[8];
__prg_rom u8 lower_lines[8]={80,56,112,56,112,56,112,80};
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3DCGB_EnableDoubleSpeed();
Wire3DCGB_Init(); // Already at double speed: its internal request is a no-op.
result[2]=(u8)(sample_key1&128);
// Palette writes are performed with the LCD off, after entering VBlank.
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0;
Wire3DCGB_SetPaletteRGB15(WIRE3DCGB_RGB15(0,0,0),WIRE3DCGB_RGB15(31,0,0),WIRE3DCGB_RGB15(0,0,31),WIRE3DCGB_RGB15(0,31,0));
sample_lcdc=0x81;
Wire3DCGB_SetScreenOffset(0,0);
Wire3DCGB_SetCamera(0,0,0,0,0,0);
Wire3DCGB_BeginFrame();
Wire3DCGB_SetLineColor(1);
Wire3DCGB_DrawLine2D(8,8,56,8);
Wire3DCGB_DrawLine2D(56,8,56,40);
Wire3DCGB_DrawLine2D(56,40,8,40);
Wire3DCGB_DrawLine2D(8,40,8,8);
Wire3DCGB_DrawLine2DColor(8,40,56,8,2);
result[0]=Wire3DCGB_GetLineColor(); // Temporary blue restores red.
Wire3DCGB_SetLineColor(3);
Wire3DCGB_DrawPoint2D(64,48);
Wire3DCGB_DrawLineClipped2D(-10,72,140,72,3);
Wire3DCGB_DrawLineList2DColor(lower_lines,2,2);
result[1]=Wire3DCGB_GetLineColor(); // The blue line list restores green.
Wire3DCGB_PutBgTile(18,1,0x80); // Queue the supplied zero glyph outside the viewport.
Wire3DCGB_EndFrame();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Este ejemplo muestra líneas, puntos, borrado y proyección básicos en un solo fotograma. Un marco rojo contiene una diagonal azul, un punto y una línea horizontal verdes, una L azul y un cero verde en la esquina superior derecha.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_raster.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:177
kitaqgb/lib/wire3d_cgb.c:8363
void Wire3DCGB_DrawLine2D(w3dcgb_u8 ax, w3dcgb_u8 ay, w3dcgb_u8 bx, w3dcgb_u8 by)
{
w3dcgb_line_x0 = ax;
w3dcgb_line_y0 = ay;
w3dcgb_line_x1 = bx;
w3dcgb_line_y1 = by;
if (w3dcgb_full_mode != 0) w3dcgb_full_line_fast_asm();
else w3dcgb_line_stage_asm();
}Wire3DCGB_DrawLine2DColor
Dibuja una línea en coordenadas de pantalla con un color temporal, conservando el color seleccionado.
Sintaxis
void Wire3DCGB_DrawLine2DColor(w3dcgb_u8 ax, w3dcgb_u8 ay, w3dcgb_u8 bx, w3dcgb_u8 by, w3dcgb_u8 color);Parámetros
axCoordenada X del vértice A en píxeles de la ventana gráfica.
ayCoordenada Y del vértice A en píxeles de la ventana gráfica.
bxCoordenada X del vértice B en píxeles de la ventana gráfica.
byCoordenada Y del vértice B en píxeles de la ventana gráfica.
colorÍndice de color de dibujo; las paletas de ejemplo usan 1=rojo, 2=azul y 3=verde.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Configura color & 3 durante DrawLine2D y restaura el color anterior. Sigue sus condiciones de coordenadas, combinación de colores y rangos parciales; cero no borra una línea en ninguno de los dos renderizadores activos.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// CGB raster paths: a red frame, blue diagonal, green marker and clipped line.
// Build this source together with lib/wire3d_cgb.c in an MBC5 256 KB CGB ROM.
#include "wire3d_cgb.h"
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4D) u8 sample_key1;
__location(0xC110) u16 result[8];
__prg_rom u8 lower_lines[8]={80,56,112,56,112,56,112,80};
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3DCGB_EnableDoubleSpeed();
Wire3DCGB_Init(); // Already at double speed: its internal request is a no-op.
result[2]=(u8)(sample_key1&128);
// Palette writes are performed with the LCD off, after entering VBlank.
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0;
Wire3DCGB_SetPaletteRGB15(WIRE3DCGB_RGB15(0,0,0),WIRE3DCGB_RGB15(31,0,0),WIRE3DCGB_RGB15(0,0,31),WIRE3DCGB_RGB15(0,31,0));
sample_lcdc=0x81;
Wire3DCGB_SetScreenOffset(0,0);
Wire3DCGB_SetCamera(0,0,0,0,0,0);
Wire3DCGB_BeginFrame();
Wire3DCGB_SetLineColor(1);
Wire3DCGB_DrawLine2D(8,8,56,8);
Wire3DCGB_DrawLine2D(56,8,56,40);
Wire3DCGB_DrawLine2D(56,40,8,40);
Wire3DCGB_DrawLine2D(8,40,8,8);
Wire3DCGB_DrawLine2DColor(8,40,56,8,2);
result[0]=Wire3DCGB_GetLineColor(); // Temporary blue restores red.
Wire3DCGB_SetLineColor(3);
Wire3DCGB_DrawPoint2D(64,48);
Wire3DCGB_DrawLineClipped2D(-10,72,140,72,3);
Wire3DCGB_DrawLineList2DColor(lower_lines,2,2);
result[1]=Wire3DCGB_GetLineColor(); // The blue line list restores green.
Wire3DCGB_PutBgTile(18,1,0x80); // Queue the supplied zero glyph outside the viewport.
Wire3DCGB_EndFrame();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Este ejemplo muestra líneas, puntos, borrado y proyección básicos en un solo fotograma. Un marco rojo contiene una diagonal azul, un punto y una línea horizontal verdes, una L azul y un cero verde en la esquina superior derecha.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_raster.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:178
kitaqgb/lib/wire3d_cgb.c:8376
void Wire3DCGB_DrawLine2DColor(w3dcgb_u8 ax, w3dcgb_u8 ay, w3dcgb_u8 bx, w3dcgb_u8 by, w3dcgb_u8 color)
{
w3dcgb_u8 old_color;
old_color = w3dcgb_line_color;
Wire3DCGB_SetLineColor(color);
Wire3DCGB_DrawLine2D(ax, ay, bx, by);
w3dcgb_line_color = old_color;
}Wire3DCGB_DrawLine3D
Proyecta los extremos del mundo mediante la cámara y dibuja una línea con el color actual.
Sintaxis
void Wire3DCGB_DrawLine3D(w3dcgb_i16 ax, w3dcgb_i16 ay, w3dcgb_i16 az, w3dcgb_i16 bx, w3dcgb_i16 by, w3dcgb_i16 bz);Parámetros
axComponente X del punto inicial en coordenadas del mundo.
ayComponente Y del punto inicial en coordenadas del mundo.
azComponente Z del punto inicial en coordenadas del mundo.
bxComponente X del punto final en coordenadas del mundo.
byComponente Y del punto final en coordenadas del mundo.
bzComponente Z del punto final en coordenadas del mundo.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Proyecta ambos extremos mediante la cámara a la ventana gráfica de 128×96. Rechaza toda la línea si cualquier extremo falla la prueba de profundidad; no recorta los cruces del plano cercano. DrawLine2D despacha según el modo, pero la proyección sigue siendo de 128×96. Las líneas normales acumulan los planos de color y no marcan límites parciales; usa una transferencia completa o invalida explícitamente el historial antes de una transferencia parcial.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Four cubes compare unity/half scale and persistent/temporary line colors.
#include "wire_cgb_example.h"
__prg_rom Wire3DCGB_Vec3 vertices[8]={
{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},
{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}
};
__prg_rom Wire3DCGB_Edge edges[12]={
{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},
{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}
};
Wire3DCGB_Model cube;
u8 sx;
u8 sy;
void main() {
wire_results_clear();
cube.vertices=vertices; cube.edges=edges;
cube.faces=0; cube.edge_faces=0;
cube.vertex_count=8; cube.edge_count=12; cube.face_count=0; cube.flags=0;
Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
Wire3DCGB_SetLineColor(1);
Wire3DCGB_DrawModel(&cube,-32,32,96,0,0,0);
Wire3DCGB_DrawModelScaled(&cube,32,32,96,0,0,0,128);
Wire3DCGB_DrawModelColor(&cube,-32,-32,96,0,0,0,2);
Wire3DCGB_DrawModelScaledColor(&cube,32,-32,96,0,0,0,128,3);
result[0]=Wire3DCGB_GetLineColor();
Wire3DCGB_DrawLine3D(0,56,96,0,-56,96);
Wire3DCGB_DrawLine3DColor(-80,0,96,80,0,96,3);
result[1]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
result[2]=sx; result[3]=sy;
// Camera setters affect future projection, leaving the staged cubes intact.
Wire3DCGB_SetCamera(0,0,0,0,4,0);
result[4]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
result[5]=Wire3DCGB_ProjectPointNoRotation(0,0,96,&sx,&sy);
result[6]=sx;
Wire3DCGB_EndFrame(); result[7]=0xA55A;
while(1) {}
}Resultado esperado
Compara modelos a escala unitaria y redimensionados en rojo, azul y verde, además de líneas 3D que se cruzan. Los valores de RAM también comprueban la proyección de cámara y su variante sin rotación.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_models.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:172
kitaqgb/lib/wire3d_cgb.c:8992
void Wire3DCGB_DrawLine3D(w3dcgb_i16 ax, w3dcgb_i16 ay, w3dcgb_i16 az, w3dcgb_i16 bx, w3dcgb_i16 by, w3dcgb_i16 bz)
{
w3dcgb_u8 sx0;
w3dcgb_u8 sy0;
w3dcgb_u8 sx1;
w3dcgb_u8 sy1;
if (w3dcgb_project_world(ax, ay, az, &sx0, &sy0) == 0) return;
if (w3dcgb_project_world(bx, by, bz, &sx1, &sy1) == 0) return;
Wire3DCGB_DrawLine2D(sx0, sy0, sx1, sy1);
}Wire3DCGB_DrawLine3DColor
Dibuja una línea 3D con un color temporal.
Sintaxis
void Wire3DCGB_DrawLine3DColor(w3dcgb_i16 ax, w3dcgb_i16 ay, w3dcgb_i16 az, w3dcgb_i16 bx, w3dcgb_i16 by, w3dcgb_i16 bz, w3dcgb_u8 color);Parámetros
axComponente X del punto inicial en coordenadas del mundo.
ayComponente Y del punto inicial en coordenadas del mundo.
azComponente Z del punto inicial en coordenadas del mundo.
bxComponente X del punto final en coordenadas del mundo.
byComponente Y del punto final en coordenadas del mundo.
bzComponente Z del punto final en coordenadas del mundo.
colorÍndice de color de dibujo; las paletas de ejemplo usan 1=rojo, 2=azul y 3=verde.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Selecciona temporalmente color & 3 para DrawLine3D y después restaura el color anterior.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Four cubes compare unity/half scale and persistent/temporary line colors.
#include "wire_cgb_example.h"
__prg_rom Wire3DCGB_Vec3 vertices[8]={
{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},
{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}
};
__prg_rom Wire3DCGB_Edge edges[12]={
{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},
{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}
};
Wire3DCGB_Model cube;
u8 sx;
u8 sy;
void main() {
wire_results_clear();
cube.vertices=vertices; cube.edges=edges;
cube.faces=0; cube.edge_faces=0;
cube.vertex_count=8; cube.edge_count=12; cube.face_count=0; cube.flags=0;
Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
Wire3DCGB_SetLineColor(1);
Wire3DCGB_DrawModel(&cube,-32,32,96,0,0,0);
Wire3DCGB_DrawModelScaled(&cube,32,32,96,0,0,0,128);
Wire3DCGB_DrawModelColor(&cube,-32,-32,96,0,0,0,2);
Wire3DCGB_DrawModelScaledColor(&cube,32,-32,96,0,0,0,128,3);
result[0]=Wire3DCGB_GetLineColor();
Wire3DCGB_DrawLine3D(0,56,96,0,-56,96);
Wire3DCGB_DrawLine3DColor(-80,0,96,80,0,96,3);
result[1]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
result[2]=sx; result[3]=sy;
// Camera setters affect future projection, leaving the staged cubes intact.
Wire3DCGB_SetCamera(0,0,0,0,4,0);
result[4]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
result[5]=Wire3DCGB_ProjectPointNoRotation(0,0,96,&sx,&sy);
result[6]=sx;
Wire3DCGB_EndFrame(); result[7]=0xA55A;
while(1) {}
}Resultado esperado
Compara modelos a escala unitaria y redimensionados en rojo, azul y verde, además de líneas 3D que se cruzan. Los valores de RAM también comprueban la proyección de cámara y su variante sin rotación.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_models.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:173
kitaqgb/lib/wire3d_cgb.c:9005
void Wire3DCGB_DrawLine3DColor(w3dcgb_i16 ax, w3dcgb_i16 ay, w3dcgb_i16 az, w3dcgb_i16 bx, w3dcgb_i16 by, w3dcgb_i16 bz, w3dcgb_u8 color)
{
w3dcgb_u8 old_color;
old_color = w3dcgb_line_color;
Wire3DCGB_SetLineColor(color);
Wire3DCGB_DrawLine3D(ax, ay, az, bx, by, bz);
w3dcgb_line_color = old_color;
}Wire3DCGB_DrawLineClipped2D
Recorta las coordenadas de pantalla con signo a la ventana gráfica y dibuja una línea con el color solicitado.
Sintaxis
void Wire3DCGB_DrawLineClipped2D(w3dcgb_i16 x0, w3dcgb_i16 y0, w3dcgb_i16 x1, w3dcgb_i16 y1, w3dcgb_u8 color);Parámetros
x0Extremo X inferior, en píxeles de la ventana gráfica; el orden y el recorte siguen las notas de esta operación.
y0Extremo Y inferior, en píxeles de la ventana gráfica; el orden y el recorte siguen las notas de esta operación.
x1Extremo X superior, en píxeles de la ventana gráfica; el orden y el recorte siguen las notas de esta operación.
y1Extremo Y superior, en píxeles de la ventana gráfica; el orden y el recorte siguen las notas de esta operación.
colorÍndice de color de dibujo; las paletas de ejemplo usan 1=rojo, 2=azul y 3=verde.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Los extremos son valores con signo y se recortan antes de convertirlos a la ABI u8 del rasterizador. Recorta una línea 2D con signo a la ventana gráfica seleccionada y la dibuja con un color temporal. Rechaza entradas fuera de ±2047. Las líneas totalmente contenidas en 128×96 usan una ruta rápida; las demás usan códigos de región e intersecciones enteras acotadas, con un límite de ocho iteraciones. Las líneas aceptadas en modo normal marcan los límites modificados. Solo recorta en pantalla: no realiza proyección 3D ni recorte en profundidad.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// CGB raster paths: a red frame, blue diagonal, green marker and clipped line.
// Build this source together with lib/wire3d_cgb.c in an MBC5 256 KB CGB ROM.
#include "wire3d_cgb.h"
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4D) u8 sample_key1;
__location(0xC110) u16 result[8];
__prg_rom u8 lower_lines[8]={80,56,112,56,112,56,112,80};
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3DCGB_EnableDoubleSpeed();
Wire3DCGB_Init(); // Already at double speed: its internal request is a no-op.
result[2]=(u8)(sample_key1&128);
// Palette writes are performed with the LCD off, after entering VBlank.
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0;
Wire3DCGB_SetPaletteRGB15(WIRE3DCGB_RGB15(0,0,0),WIRE3DCGB_RGB15(31,0,0),WIRE3DCGB_RGB15(0,0,31),WIRE3DCGB_RGB15(0,31,0));
sample_lcdc=0x81;
Wire3DCGB_SetScreenOffset(0,0);
Wire3DCGB_SetCamera(0,0,0,0,0,0);
Wire3DCGB_BeginFrame();
Wire3DCGB_SetLineColor(1);
Wire3DCGB_DrawLine2D(8,8,56,8);
Wire3DCGB_DrawLine2D(56,8,56,40);
Wire3DCGB_DrawLine2D(56,40,8,40);
Wire3DCGB_DrawLine2D(8,40,8,8);
Wire3DCGB_DrawLine2DColor(8,40,56,8,2);
result[0]=Wire3DCGB_GetLineColor(); // Temporary blue restores red.
Wire3DCGB_SetLineColor(3);
Wire3DCGB_DrawPoint2D(64,48);
Wire3DCGB_DrawLineClipped2D(-10,72,140,72,3);
Wire3DCGB_DrawLineList2DColor(lower_lines,2,2);
result[1]=Wire3DCGB_GetLineColor(); // The blue line list restores green.
Wire3DCGB_PutBgTile(18,1,0x80); // Queue the supplied zero glyph outside the viewport.
Wire3DCGB_EndFrame();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Este ejemplo muestra líneas, puntos, borrado y proyección básicos en un solo fotograma. Un marco rojo contiene una diagonal azul, un punto y una línea horizontal verdes, una L azul y un cero verde en la esquina superior derecha.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_raster.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:136
Signed endpoints, clipped before conversion to the rasterizer's u8 ABI.
kitaqgb/lib/wire3d_cgb.c:9745
void Wire3DCGB_DrawLineClipped2D(w3dcgb_i16 x0, w3dcgb_i16 y0,
w3dcgb_i16 x1, w3dcgb_i16 y1, w3dcgb_u8 color)
{
w3dcgb_u8 c0;
w3dcgb_u8 c1;
w3dcgb_u8 outside;
w3dcgb_u8 guard;
w3dcgb_i16 x;
w3dcgb_i16 y;
c0 = 0;
c1 = 0;
if ((((x0 | y0 | x1 | y1) & 0xFF80) != 0) || (y0 >= WIRE3DCGB_SCREEN_H) || (y1 >= WIRE3DCGB_SCREEN_H))
{
if ((x0 < -2047) || (x0 > 2047) || (y0 < -2047) || (y0 > 2047) ||
(x1 < -2047) || (x1 > 2047) || (y1 < -2047) || (y1 > 2047)) return;
c0 = w3dcgb_clip_outcode(x0, y0);
c1 = w3dcgb_clip_outcode(x1, y1);
}
guard = 0;
while (guard < 8)
{
if ((c0 | c1) == 0)
{
/* The existing ASM rasterizer handles the hot, in-window path. */
if (w3dcgb_full_mode == 0) w3dcgb_mark_dirty_line((w3dcgb_u8)x0, (w3dcgb_u8)y0,
(w3dcgb_u8)x1, (w3dcgb_u8)y1);
Wire3DCGB_DrawLine2DColor((w3dcgb_u8)x0, (w3dcgb_u8)y0,
(w3dcgb_u8)x1, (w3dcgb_u8)y1, color);
return;
}
if ((c0 & c1) != 0) return;
outside = c0;
if (outside == 0) outside = c1;
if ((outside & 12) != 0)
{
y = 0;
if ((outside & 8) != 0) y = WIRE3DCGB_SCREEN_H - 1;
if (((outside & 8) != 0) && (w3dcgb_full_mode != 0)) y = WIRE3DCGB_FULL_SCREEN_H - 1;
x = (w3dcgb_i16)(x0 + w3dcgb_clip_muldiv((w3dcgb_i16)(x1 - x0),
(w3dcgb_i16)(y - y0), (w3dcgb_i16)(y1 - y0)));
}
else
{
x = 0;
if ((outside & 2) != 0) x = WIRE3DCGB_SCREEN_W - 1;
if (((outside & 2) != 0) && (w3dcgb_full_mode != 0)) x = WIRE3DCGB_FULL_SCREEN_W - 1;
y = (w3dcgb_i16)(y0 + w3dcgb_clip_muldiv((w3dcgb_i16)(y1 - y0),
(w3dcgb_i16)(x - x0), (w3dcgb_i16)(x1 - x0)));
}
if (outside == c0) { x0 = x; y0 = y; c0 = w3dcgb_clip_outcode(x0, y0); }
else { x1 = x; y1 = y; c1 = w3dcgb_clip_outcode(x1, y1); }
guard = (w3dcgb_u8)(guard + 1);
}
}Wire3DCGB_DrawLineList2DColor
Dibuja una lista de registros de líneas de pantalla de cuatro bytes con el color elegido.
Sintaxis
void Wire3DCGB_DrawLineList2DColor(const w3dcgb_u8* line_xy, w3dcgb_u8 line_count, w3dcgb_u8 color);Parámetros
line_xyArray de bytes con registros x0,y0,x1,y1.
line_countCantidad de registros de líneas; se procesan como máximo 64.
colorÍndice de color de dibujo; las paletas de ejemplo usan 1=rojo, 2=azul y 3=verde.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Dibuja hasta 64 registros de cuatro bytes (x0,y0,x1,y1) e ignora una lista null. Los extremos deben estar dentro de la ventana gráfica seleccionada. Conserva el color anterior y envía cada línea al rasterizador normal o de pantalla completa.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// CGB raster paths: a red frame, blue diagonal, green marker and clipped line.
// Build this source together with lib/wire3d_cgb.c in an MBC5 256 KB CGB ROM.
#include "wire3d_cgb.h"
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4D) u8 sample_key1;
__location(0xC110) u16 result[8];
__prg_rom u8 lower_lines[8]={80,56,112,56,112,56,112,80};
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3DCGB_EnableDoubleSpeed();
Wire3DCGB_Init(); // Already at double speed: its internal request is a no-op.
result[2]=(u8)(sample_key1&128);
// Palette writes are performed with the LCD off, after entering VBlank.
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0;
Wire3DCGB_SetPaletteRGB15(WIRE3DCGB_RGB15(0,0,0),WIRE3DCGB_RGB15(31,0,0),WIRE3DCGB_RGB15(0,0,31),WIRE3DCGB_RGB15(0,31,0));
sample_lcdc=0x81;
Wire3DCGB_SetScreenOffset(0,0);
Wire3DCGB_SetCamera(0,0,0,0,0,0);
Wire3DCGB_BeginFrame();
Wire3DCGB_SetLineColor(1);
Wire3DCGB_DrawLine2D(8,8,56,8);
Wire3DCGB_DrawLine2D(56,8,56,40);
Wire3DCGB_DrawLine2D(56,40,8,40);
Wire3DCGB_DrawLine2D(8,40,8,8);
Wire3DCGB_DrawLine2DColor(8,40,56,8,2);
result[0]=Wire3DCGB_GetLineColor(); // Temporary blue restores red.
Wire3DCGB_SetLineColor(3);
Wire3DCGB_DrawPoint2D(64,48);
Wire3DCGB_DrawLineClipped2D(-10,72,140,72,3);
Wire3DCGB_DrawLineList2DColor(lower_lines,2,2);
result[1]=Wire3DCGB_GetLineColor(); // The blue line list restores green.
Wire3DCGB_PutBgTile(18,1,0x80); // Queue the supplied zero glyph outside the viewport.
Wire3DCGB_EndFrame();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Este ejemplo muestra líneas, puntos, borrado y proyección básicos en un solo fotograma. Un marco rojo contiene una diagonal azul, un punto y una línea horizontal verdes, una L azul y un cero verde en la esquina superior derecha.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_raster.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:186
kitaqgb/lib/wire3d_cgb.c:8571
void Wire3DCGB_DrawLineList2DColor(const w3dcgb_u8* line_xy,
w3dcgb_u8 line_count, w3dcgb_u8 color)
{
w3dcgb_u8 i;
w3dcgb_u8 offset;
w3dcgb_u8 old_color;
if (line_xy == 0) return;
if (line_count > WIRE3DCGB_MODEL_EDGE_LIMIT) line_count = WIRE3DCGB_MODEL_EDGE_LIMIT;
old_color = w3dcgb_line_color;
w3dcgb_line_color = (w3dcgb_u8)(color & 3);
i = 0;
offset = 0;
while (i < line_count)
{
w3dcgb_line_x0 = line_xy[(__safe_index w3dcgb_u8)offset];
offset = (w3dcgb_u8)(offset + 1);
w3dcgb_line_y0 = line_xy[(__safe_index w3dcgb_u8)offset];
offset = (w3dcgb_u8)(offset + 1);
w3dcgb_line_x1 = line_xy[(__safe_index w3dcgb_u8)offset];
offset = (w3dcgb_u8)(offset + 1);
w3dcgb_line_y1 = line_xy[(__safe_index w3dcgb_u8)offset];
offset = (w3dcgb_u8)(offset + 1);
if (w3dcgb_full_mode != 0) w3dcgb_full_line_fast_asm();
else w3dcgb_line_stage_asm();
i = (w3dcgb_u8)(i + 1);
}
w3dcgb_line_color = old_color;
}Wire3DCGB_DrawMaskedModel2D
Dibuja las aristas habilitadas a partir de vértices preproyectados y una máscara de bits de aristas.
Sintaxis
void Wire3DCGB_DrawMaskedModel2D(const Wire3DCGB_Model* model, const w3dcgb_i8* vertex_x, const w3dcgb_i8* vertex_y, const w3dcgb_u8* edge_mask, w3dcgb_u8 x, w3dcgb_u8 y, w3dcgb_u8 color);Parámetros
modelModelo que contiene los arrays de vértices, aristas y caras y sus cantidades; las tablas deben permanecer legibles durante la llamada.
vertex_xArray de desplazamientos X de los vértices preproyectados.
vertex_yArray de desplazamientos Y de los vértices preproyectados.
edge_maskArray de bytes con un bit de visibilidad por arista, empezando por el menos significativo.
xCoordenada X del centro en píxeles de la ventana gráfica.
yCoordenada Y del centro en píxeles de la ventana gráfica.
colorÍndice de color de dibujo; las paletas de ejemplo usan 1=rojo, 2=azul y 3=verde.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Dibuja las aristas habilitadas del modelo usando desplazamientos preproyectados de tipo byte con signo alrededor de (x,y). Los bits de máscara van desde el menos significativo, ocho aristas por byte. Todos los punteros e índices deben ser válidos; edge_mask[0] se lee incluso con cero aristas. No limita ninguna cantidad. Mantén los extremos trasladados dentro de la ventana gráfica antes de convertirlos a bytes; los negativos sufrirían un desbordamiento modular. Conserva el color anterior y despacha según el modo activo.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Preprojected edge arrays, a clipped square, a tiny marker and a projectile.
#include "wire_cgb_example.h"
__prg_rom Wire3DCGB_Edge edges[4]={{0,1},{1,2},{2,3},{3,0}};
__prg_rom s8 vx8[4]={-8,8,8,-8};
__prg_rom s8 vy8[4]={-8,-8,8,8};
__prg_rom s16 vx16[4]={-12,12,12,-12};
__prg_rom s16 vy16[4]={-8,-8,8,8};
__prg_rom u8 mask[1]={5};
Wire3DCGB_Model shape;
void main() {
wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
shape.vertices=0;shape.edges=edges;shape.faces=0;shape.edge_faces=0;
shape.vertex_count=4;shape.edge_count=4;shape.face_count=0;shape.flags=0;
Wire3DCGB_SetLineColor(2);
Wire3DCGB_DrawMaskedModel2D(&shape,vx8,vy8,mask,24,24,1);
Wire3DCGB_DrawEdgeList2D(edges,4,vx8,vy8,64,24,2);
Wire3DCGB_DrawEdgeListClipped2D(edges,4,vx16,vy16,4,4,64,3);
Wire3DCGB_DrawTinyModel2D(104,24,16,3);
result[0]=Wire3DCGB_ProjectAxis48(48,96);
result[1]=Wire3DCGB_ProjectAxis48(-48,96);
Wire3DCGB_DrawFastProjectile(96,64,64,0,1);
result[2]=Wire3DCGB_GetLineColor();
Wire3DCGB_EndFrame();result[7]=0xA55A;
while(1) {}
}Resultado esperado
Dos aristas horizontales rojas, un cuadrado azul, un marco verde recortado, un marcador verde de seis píxeles y un proyectil rojo permiten comparar los formatos de lista.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_lists.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_lists.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:179
kitaqgb/lib/wire3d_cgb.c:8392
void Wire3DCGB_DrawMaskedModel2D(const Wire3DCGB_Model* model,
const w3dcgb_i8* vertex_x, const w3dcgb_i8* vertex_y,
const w3dcgb_u8* edge_mask,
w3dcgb_u8 x, w3dcgb_u8 y, w3dcgb_u8 color)
{
w3dcgb_u8 i;
w3dcgb_u8 bit;
w3dcgb_u8 mask_index;
w3dcgb_u8 mask;
w3dcgb_u8 a;
w3dcgb_u8 b;
w3dcgb_u8 old_color;
old_color = w3dcgb_line_color;
w3dcgb_line_color = (w3dcgb_u8)(color & 3);
i = 0;
bit = 1;
mask_index = 0;
mask = edge_mask[0];
while (i < model->edge_count)
{
if ((mask & bit) != 0)
{
a = model->edges[(__safe_index w3dcgb_u8)i].a;
b = model->edges[(__safe_index w3dcgb_u8)i].b;
w3dcgb_line_x0 = (w3dcgb_u8)((w3dcgb_i16)x + (w3dcgb_i16)vertex_x[(__safe_index w3dcgb_u8)a]);
w3dcgb_line_y0 = (w3dcgb_u8)((w3dcgb_i16)y + (w3dcgb_i16)vertex_y[(__safe_index w3dcgb_u8)a]);
w3dcgb_line_x1 = (w3dcgb_u8)((w3dcgb_i16)x + (w3dcgb_i16)vertex_x[(__safe_index w3dcgb_u8)b]);
w3dcgb_line_y1 = (w3dcgb_u8)((w3dcgb_i16)y + (w3dcgb_i16)vertex_y[(__safe_index w3dcgb_u8)b]);
if (w3dcgb_full_mode != 0) w3dcgb_full_line_fast_asm();
else w3dcgb_line_stage_asm();
}
i = (w3dcgb_u8)(i + 1);
bit = (w3dcgb_u8)(bit << 1);
if ((bit == 0) && (i < model->edge_count))
{
bit = 1;
mask_index = (w3dcgb_u8)(mask_index + 1);
mask = edge_mask[(__safe_index w3dcgb_u8)mask_index];
}
}
w3dcgb_line_color = old_color;
}Wire3DCGB_DrawModel
Dibuja un modelo 3D en la posición y con la rotación indicadas, a escala unitaria.
Sintaxis
void Wire3DCGB_DrawModel(const Wire3DCGB_Model* model, w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 rx, w3dcgb_i8 ry, w3dcgb_i8 rz);Parámetros
modelModelo que contiene los arrays de vértices, aristas y caras y sus cantidades; las tablas deben permanecer legibles durante la llamada.
xComponente X del punto o del origen del objeto en coordenadas del mundo.
yComponente Y del punto o del origen del objeto en coordenadas del mundo.
zComponente Z del punto o del origen del objeto en coordenadas del mundo.
rxRotación alrededor de X; dieciséis pasos forman una vuelta completa.
ryRotación alrededor de Y; dieciséis pasos forman una vuelta completa.
rzRotación alrededor de Z; dieciséis pasos forman una vuelta completa.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Dibuja un modelo a escala Q8 unitaria (256), siguiendo el contrato de DrawModelScaled.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Four cubes compare unity/half scale and persistent/temporary line colors.
#include "wire_cgb_example.h"
__prg_rom Wire3DCGB_Vec3 vertices[8]={
{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},
{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}
};
__prg_rom Wire3DCGB_Edge edges[12]={
{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},
{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}
};
Wire3DCGB_Model cube;
u8 sx;
u8 sy;
void main() {
wire_results_clear();
cube.vertices=vertices; cube.edges=edges;
cube.faces=0; cube.edge_faces=0;
cube.vertex_count=8; cube.edge_count=12; cube.face_count=0; cube.flags=0;
Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
Wire3DCGB_SetLineColor(1);
Wire3DCGB_DrawModel(&cube,-32,32,96,0,0,0);
Wire3DCGB_DrawModelScaled(&cube,32,32,96,0,0,0,128);
Wire3DCGB_DrawModelColor(&cube,-32,-32,96,0,0,0,2);
Wire3DCGB_DrawModelScaledColor(&cube,32,-32,96,0,0,0,128,3);
result[0]=Wire3DCGB_GetLineColor();
Wire3DCGB_DrawLine3D(0,56,96,0,-56,96);
Wire3DCGB_DrawLine3DColor(-80,0,96,80,0,96,3);
result[1]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
result[2]=sx; result[3]=sy;
// Camera setters affect future projection, leaving the staged cubes intact.
Wire3DCGB_SetCamera(0,0,0,0,4,0);
result[4]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
result[5]=Wire3DCGB_ProjectPointNoRotation(0,0,96,&sx,&sy);
result[6]=sx;
Wire3DCGB_EndFrame(); result[7]=0xA55A;
while(1) {}
}Resultado esperado
Compara modelos a escala unitaria y redimensionados en rojo, azul y verde, además de líneas 3D que se cruzan. Los valores de RAM también comprueban la proyección de cámara y su variante sin rotación.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_models.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:128
kitaqgb/lib/wire3d_cgb.c:9015
void Wire3DCGB_DrawModel(const Wire3DCGB_Model* model, w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 rx, w3dcgb_i8 ry, w3dcgb_i8 rz)
{
Wire3DCGB_DrawModelScaled(model, x, y, z, rx, ry, rz, 256);
}Wire3DCGB_DrawModelColor
Dibuja un modelo a escala unitaria con un color temporal.
Sintaxis
void Wire3DCGB_DrawModelColor(const Wire3DCGB_Model* model, w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 rx, w3dcgb_i8 ry, w3dcgb_i8 rz, w3dcgb_u8 color);Parámetros
modelModelo que contiene los arrays de vértices, aristas y caras y sus cantidades; las tablas deben permanecer legibles durante la llamada.
xComponente X del punto o del origen del objeto en coordenadas del mundo.
yComponente Y del punto o del origen del objeto en coordenadas del mundo.
zComponente Z del punto o del origen del objeto en coordenadas del mundo.
rxRotación alrededor de X; dieciséis pasos forman una vuelta completa.
ryRotación alrededor de Y; dieciséis pasos forman una vuelta completa.
rzRotación alrededor de Z; dieciséis pasos forman una vuelta completa.
colorÍndice de color de dibujo; las paletas de ejemplo usan 1=rojo, 2=azul y 3=verde.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Dibuja un modelo a escala Q8 unitaria con un color temporal y restaura el color anterior al terminar.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Four cubes compare unity/half scale and persistent/temporary line colors.
#include "wire_cgb_example.h"
__prg_rom Wire3DCGB_Vec3 vertices[8]={
{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},
{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}
};
__prg_rom Wire3DCGB_Edge edges[12]={
{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},
{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}
};
Wire3DCGB_Model cube;
u8 sx;
u8 sy;
void main() {
wire_results_clear();
cube.vertices=vertices; cube.edges=edges;
cube.faces=0; cube.edge_faces=0;
cube.vertex_count=8; cube.edge_count=12; cube.face_count=0; cube.flags=0;
Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
Wire3DCGB_SetLineColor(1);
Wire3DCGB_DrawModel(&cube,-32,32,96,0,0,0);
Wire3DCGB_DrawModelScaled(&cube,32,32,96,0,0,0,128);
Wire3DCGB_DrawModelColor(&cube,-32,-32,96,0,0,0,2);
Wire3DCGB_DrawModelScaledColor(&cube,32,-32,96,0,0,0,128,3);
result[0]=Wire3DCGB_GetLineColor();
Wire3DCGB_DrawLine3D(0,56,96,0,-56,96);
Wire3DCGB_DrawLine3DColor(-80,0,96,80,0,96,3);
result[1]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
result[2]=sx; result[3]=sy;
// Camera setters affect future projection, leaving the staged cubes intact.
Wire3DCGB_SetCamera(0,0,0,0,4,0);
result[4]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
result[5]=Wire3DCGB_ProjectPointNoRotation(0,0,96,&sx,&sy);
result[6]=sx;
Wire3DCGB_EndFrame(); result[7]=0xA55A;
while(1) {}
}Resultado esperado
Compara modelos a escala unitaria y redimensionados en rojo, azul y verde, además de líneas 3D que se cruzan. Los valores de RAM también comprueban la proyección de cámara y su variante sin rotación.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_models.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:130
kitaqgb/lib/wire3d_cgb.c:9021
void Wire3DCGB_DrawModelColor(const Wire3DCGB_Model* model, w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 rx, w3dcgb_i8 ry, w3dcgb_i8 rz, w3dcgb_u8 color)
{
Wire3DCGB_DrawModelScaledColor(model, x, y, z, rx, ry, rz, 256, color);
}Wire3DCGB_DrawModelScaled
Escala, rota y proyecta un modelo y dibuja las aristas seleccionadas con el color actual.
Sintaxis
void Wire3DCGB_DrawModelScaled(const Wire3DCGB_Model* model, w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 rx, w3dcgb_i8 ry, w3dcgb_i8 rz, w3dcgb_i16 scale_q8);Parámetros
modelModelo que contiene los arrays de vértices, aristas y caras y sus cantidades; las tablas deben permanecer legibles durante la llamada.
xComponente X del punto o del origen del objeto en coordenadas del mundo.
yComponente Y del punto o del origen del objeto en coordenadas del mundo.
zComponente Z del punto o del origen del objeto en coordenadas del mundo.
rxRotación alrededor de X; dieciséis pasos forman una vuelta completa.
ryRotación alrededor de Y; dieciséis pasos forman una vuelta completa.
rzRotación alrededor de Z; dieciséis pasos forman una vuelta completa.
scale_q8Escala con 256 como unidad; los valores no positivos también equivalen a la unidad.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Proyecta hasta 24 vértices con una escala Q8 positiva; una escala no positiva equivale a la unidad. Omite la multiplicación por uno y las rotaciones de ángulo cero. Los resultados intermedios deben caber en s16. Si hay filtrado por adyacencia, genera hasta 16 indicadores de caras frontales y dibuja las aristas con profundidad e índices de vértice válidos. La cantidad de aristas no está limitada a 64. No hay recorte contra el plano cercano. Sustituye la caché de proyección compartida y combina mediante OR los colores de línea en el área normal de 128×96. Esta ruta no marca los límites parciales; prepara una transferencia completa o invalida explícitamente el historial antes de una transferencia parcial.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Four cubes compare unity/half scale and persistent/temporary line colors.
#include "wire_cgb_example.h"
__prg_rom Wire3DCGB_Vec3 vertices[8]={
{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},
{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}
};
__prg_rom Wire3DCGB_Edge edges[12]={
{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},
{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}
};
Wire3DCGB_Model cube;
u8 sx;
u8 sy;
void main() {
wire_results_clear();
cube.vertices=vertices; cube.edges=edges;
cube.faces=0; cube.edge_faces=0;
cube.vertex_count=8; cube.edge_count=12; cube.face_count=0; cube.flags=0;
Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
Wire3DCGB_SetLineColor(1);
Wire3DCGB_DrawModel(&cube,-32,32,96,0,0,0);
Wire3DCGB_DrawModelScaled(&cube,32,32,96,0,0,0,128);
Wire3DCGB_DrawModelColor(&cube,-32,-32,96,0,0,0,2);
Wire3DCGB_DrawModelScaledColor(&cube,32,-32,96,0,0,0,128,3);
result[0]=Wire3DCGB_GetLineColor();
Wire3DCGB_DrawLine3D(0,56,96,0,-56,96);
Wire3DCGB_DrawLine3DColor(-80,0,96,80,0,96,3);
result[1]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
result[2]=sx; result[3]=sy;
// Camera setters affect future projection, leaving the staged cubes intact.
Wire3DCGB_SetCamera(0,0,0,0,4,0);
result[4]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
result[5]=Wire3DCGB_ProjectPointNoRotation(0,0,96,&sx,&sy);
result[6]=sx;
Wire3DCGB_EndFrame(); result[7]=0xA55A;
while(1) {}
}Resultado esperado
Compara modelos a escala unitaria y redimensionados en rojo, azul y verde, además de líneas 3D que se cruzan. Los valores de RAM también comprueban la proyección de cámara y su variante sin rotación.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_models.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:129
kitaqgb/lib/wire3d_cgb.c:9396
void Wire3DCGB_DrawModelScaled(const Wire3DCGB_Model* model, w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 rx, w3dcgb_i8 ry, w3dcgb_i8 rz, w3dcgb_i16 scale_q8)
{
w3dcgb_u8 i;
w3dcgb_u8 count;
w3dcgb_u8 edge_count;
w3dcgb_u8 face_count;
w3dcgb_u8 camera_unrotated;
w3dcgb_u8 unit_scale;
if (model == 0) return;
if (model->vertices == 0) return;
if (model->edges == 0) return;
if (scale_q8 <= 0) scale_q8 = 256;
count = model->vertex_count;
if (count > WIRE3DCGB_MODEL_VERTEX_LIMIT) count = WIRE3DCGB_MODEL_VERTEX_LIMIT;
unit_scale = 0;
if (scale_q8 == 256) unit_scale = 1;
camera_unrotated = 0;
if ((w3dcgb_cam_yaw == 0) && (w3dcgb_cam_pitch == 0) && (w3dcgb_cam_roll == 0))
{
camera_unrotated = 1;
}
i = 0;
while (i < count)
{
const Wire3DCGB_Vec3* v;
w3dcgb_i16 vx;
w3dcgb_i16 vy;
w3dcgb_i16 vz;
w3dcgb_u8 sx;
w3dcgb_u8 sy;
w3dcgb_u8 projected;
v = &model->vertices[(__safe_index w3dcgb_u8)i];
if (unit_scale != 0)
{
vx = v->x;
vy = v->y;
vz = v->z;
}
else
{
vx = (w3dcgb_i16)((v->x * scale_q8) >> 8);
vy = (w3dcgb_i16)((v->y * scale_q8) >> 8);
vz = (w3dcgb_i16)((v->z * scale_q8) >> 8);
}
if (ry != 0) w3dcgb_rotate_y(&vx, &vz, (w3dcgb_i8)ry);
if (rx != 0) w3dcgb_rotate_x(&vy, &vz, (w3dcgb_i8)rx);
if (rz != 0) w3dcgb_rotate_z(&vx, &vy, (w3dcgb_i8)rz);
vx = (w3dcgb_i16)(vx + x);
vy = (w3dcgb_i16)(vy + y);
vz = (w3dcgb_i16)(vz + z);
if (camera_unrotated != 0)
{
vx = (w3dcgb_i16)(vx - w3dcgb_cam_x);
vy = (w3dcgb_i16)(vy - w3dcgb_cam_y);
vz = (w3dcgb_i16)(vz - w3dcgb_cam_z);
projected = w3dcgb_project_camera_space(vx, vy, vz, &sx, &sy);
}
else
{
projected = w3dcgb_project_world(vx, vy, vz, &sx, &sy);
}
if (projected != 0)
{
w3dcgb_screen_x[(__safe_index w3dcgb_u8)i] = sx;
w3dcgb_screen_y[(__safe_index w3dcgb_u8)i] = sy;
w3dcgb_screen_visible[(__safe_index w3dcgb_u8)i] = 1;
}
else
{
w3dcgb_screen_visible[(__safe_index w3dcgb_u8)i] = 0;
}
i = (w3dcgb_u8)(i + 1);
}
face_count = model->face_count;
if (face_count > WIRE3DCGB_MODEL_FACE_LIMIT) face_count = WIRE3DCGB_MODEL_FACE_LIMIT;
if ((model->flags & WIRE3DCGB_MODEL_HIDDEN_LINES) && (model->faces != 0) && (model->edge_faces != 0))
{
w3dcgb_build_face_visibility(model, count, face_count);
}
edge_count = model->edge_count;
i = 0;
while (i < edge_count)
{
const Wire3DCGB_Edge* e;
e = &model->edges[(__safe_index w3dcgb_u8)i];
if ((e->a < count) && (e->b < count))
{
if (w3dcgb_screen_visible[(__safe_index w3dcgb_u8)e->a] &&
w3dcgb_screen_visible[(__safe_index w3dcgb_u8)e->b] &&
w3dcgb_is_edge_visible(model, i, face_count))
{
w3dcgb_draw_model_line(
w3dcgb_screen_x[(__safe_index w3dcgb_u8)e->a],
w3dcgb_screen_y[(__safe_index w3dcgb_u8)e->a],
w3dcgb_screen_x[(__safe_index w3dcgb_u8)e->b],
w3dcgb_screen_y[(__safe_index w3dcgb_u8)e->b]);
}
}
i = (w3dcgb_u8)(i + 1);
}
}Wire3DCGB_DrawModelScaledColor
Dibuja un modelo con la escala elegida y un color de línea temporal.
Sintaxis
void Wire3DCGB_DrawModelScaledColor(const Wire3DCGB_Model* model, w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 rx, w3dcgb_i8 ry, w3dcgb_i8 rz, w3dcgb_i16 scale_q8, w3dcgb_u8 color);Parámetros
modelModelo que contiene los arrays de vértices, aristas y caras y sus cantidades; las tablas deben permanecer legibles durante la llamada.
xComponente X del punto o del origen del objeto en coordenadas del mundo.
yComponente Y del punto o del origen del objeto en coordenadas del mundo.
zComponente Z del punto o del origen del objeto en coordenadas del mundo.
rxRotación alrededor de X; dieciséis pasos forman una vuelta completa.
ryRotación alrededor de Y; dieciséis pasos forman una vuelta completa.
rzRotación alrededor de Z; dieciséis pasos forman una vuelta completa.
scale_q8Escala con 256 como unidad; los valores no positivos también equivalen a la unidad.
colorÍndice de color de dibujo; las paletas de ejemplo usan 1=rojo, 2=azul y 3=verde.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Selecciona color & 3 durante DrawModelScaled y restaura el color de entrada al terminar.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Four cubes compare unity/half scale and persistent/temporary line colors.
#include "wire_cgb_example.h"
__prg_rom Wire3DCGB_Vec3 vertices[8]={
{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},
{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}
};
__prg_rom Wire3DCGB_Edge edges[12]={
{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},
{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}
};
Wire3DCGB_Model cube;
u8 sx;
u8 sy;
void main() {
wire_results_clear();
cube.vertices=vertices; cube.edges=edges;
cube.faces=0; cube.edge_faces=0;
cube.vertex_count=8; cube.edge_count=12; cube.face_count=0; cube.flags=0;
Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
Wire3DCGB_SetLineColor(1);
Wire3DCGB_DrawModel(&cube,-32,32,96,0,0,0);
Wire3DCGB_DrawModelScaled(&cube,32,32,96,0,0,0,128);
Wire3DCGB_DrawModelColor(&cube,-32,-32,96,0,0,0,2);
Wire3DCGB_DrawModelScaledColor(&cube,32,-32,96,0,0,0,128,3);
result[0]=Wire3DCGB_GetLineColor();
Wire3DCGB_DrawLine3D(0,56,96,0,-56,96);
Wire3DCGB_DrawLine3DColor(-80,0,96,80,0,96,3);
result[1]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
result[2]=sx; result[3]=sy;
// Camera setters affect future projection, leaving the staged cubes intact.
Wire3DCGB_SetCamera(0,0,0,0,4,0);
result[4]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
result[5]=Wire3DCGB_ProjectPointNoRotation(0,0,96,&sx,&sy);
result[6]=sx;
Wire3DCGB_EndFrame(); result[7]=0xA55A;
while(1) {}
}Resultado esperado
Compara modelos a escala unitaria y redimensionados en rojo, azul y verde, además de líneas 3D que se cruzan. Los valores de RAM también comprueban la proyección de cámara y su variante sin rotación.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_models.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:131
kitaqgb/lib/wire3d_cgb.c:9510
void Wire3DCGB_DrawModelScaledColor(const Wire3DCGB_Model* model, w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 rx, w3dcgb_i8 ry, w3dcgb_i8 rz, w3dcgb_i16 scale_q8, w3dcgb_u8 color)
{
w3dcgb_u8 old_color;
old_color = w3dcgb_line_color;
Wire3DCGB_SetLineColor(color);
Wire3DCGB_DrawModelScaled(model, x, y, z, rx, ry, rz, scale_q8);
w3dcgb_line_color = old_color;
}Wire3DCGB_DrawPoint2D
Escribe un píxel con el color actual.
Sintaxis
void Wire3DCGB_DrawPoint2D(w3dcgb_u8 x, w3dcgb_u8 y);Parámetros
xCoordenada X del centro en píxeles de la ventana gráfica.
yCoordenada Y del centro en píxeles de la ventana gráfica.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
En modo normal, rechaza coordenadas fuera de 128×96, marca los límites parciales y sustituye el píxel preparado por el color actual, incluido cero. En pantalla completa dibuja en su lugar una línea rápida con extremos coincidentes: cero significa color 3 y las coordenadas inválidas activan el indicador de desbordamiento del fotograma. La transferencia a pantalla se realiza después.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// CGB raster paths: a red frame, blue diagonal, green marker and clipped line.
// Build this source together with lib/wire3d_cgb.c in an MBC5 256 KB CGB ROM.
#include "wire3d_cgb.h"
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4D) u8 sample_key1;
__location(0xC110) u16 result[8];
__prg_rom u8 lower_lines[8]={80,56,112,56,112,56,112,80};
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3DCGB_EnableDoubleSpeed();
Wire3DCGB_Init(); // Already at double speed: its internal request is a no-op.
result[2]=(u8)(sample_key1&128);
// Palette writes are performed with the LCD off, after entering VBlank.
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0;
Wire3DCGB_SetPaletteRGB15(WIRE3DCGB_RGB15(0,0,0),WIRE3DCGB_RGB15(31,0,0),WIRE3DCGB_RGB15(0,0,31),WIRE3DCGB_RGB15(0,31,0));
sample_lcdc=0x81;
Wire3DCGB_SetScreenOffset(0,0);
Wire3DCGB_SetCamera(0,0,0,0,0,0);
Wire3DCGB_BeginFrame();
Wire3DCGB_SetLineColor(1);
Wire3DCGB_DrawLine2D(8,8,56,8);
Wire3DCGB_DrawLine2D(56,8,56,40);
Wire3DCGB_DrawLine2D(56,40,8,40);
Wire3DCGB_DrawLine2D(8,40,8,8);
Wire3DCGB_DrawLine2DColor(8,40,56,8,2);
result[0]=Wire3DCGB_GetLineColor(); // Temporary blue restores red.
Wire3DCGB_SetLineColor(3);
Wire3DCGB_DrawPoint2D(64,48);
Wire3DCGB_DrawLineClipped2D(-10,72,140,72,3);
Wire3DCGB_DrawLineList2DColor(lower_lines,2,2);
result[1]=Wire3DCGB_GetLineColor(); // The blue line list restores green.
Wire3DCGB_PutBgTile(18,1,0x80); // Queue the supplied zero glyph outside the viewport.
Wire3DCGB_EndFrame();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Este ejemplo muestra líneas, puntos, borrado y proyección básicos en un solo fotograma. Un marco rojo contiene una diagonal azul, un punto y una línea horizontal verdes, una L azul y un cero verde en la esquina superior derecha.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_raster.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:174
kitaqgb/lib/wire3d_cgb.c:8283
void Wire3DCGB_DrawPoint2D(w3dcgb_u8 x, w3dcgb_u8 y)
{
w3dcgb_u8 tile;
if (w3dcgb_full_mode != 0)
{
w3dcgb_line_x0 = x;
w3dcgb_line_y0 = y;
w3dcgb_line_x1 = x;
w3dcgb_line_y1 = y;
w3dcgb_full_line_fast_asm();
return;
}
if (x >= WIRE3DCGB_SCREEN_W) return;
if (y >= WIRE3DCGB_SCREEN_H) return;
if (w3dcgb_full_frame_transfer == 0)
{
tile = (w3dcgb_u8)(((x >> 3) * W3DCGB_TILE_H) + (y >> 3));
if (tile < w3dcgb_dirty_min_tile) w3dcgb_dirty_min_tile = tile;
if (tile > w3dcgb_dirty_max_tile) w3dcgb_dirty_max_tile = tile;
}
w3dcgb_plot_x = x;
w3dcgb_plot_y = y;
w3dcgb_plot_stage_asm();
}Wire3DCGB_DrawScene
Dibuja hasta ocho objetos de cerca a lejos, usando las caras anteriores para ocultar las líneas posteriores.
Sintaxis
void Wire3DCGB_DrawScene(Wire3DCGB_Object* objects, w3dcgb_u8 count);Parámetros
objectsArray de objetos con posiciones, rotaciones, escalas e indicadores de visibilidad.
countCantidad de entradas proporcionadas; consulta el límite de procesamiento de cada operación.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Ordena hasta ocho objetos de cerca a lejos según la profundidad de su origen en el espacio de cámara, sin modificar el array del código que llama. Borra la máscara, dibuja los modelos visibles teniendo en cuenta las zonas ya cubiertas y añade sus caras como oclusores. Los arrays de modelos y los índices de caras deben ser válidos. El color cero hereda el color actual, que puede proceder del objeto anterior. Al terminar, restaura el color de entrada y desactiva la oclusión. Esta ruta usa el área normal de 128×96.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// A near square hides the middle of a farther blue line, regardless of array order.
#include "wire_cgb_example.h"
#include "wire_cgb_plane.h"
__prg_rom Wire3DCGB_Vec3 back_vertices[2]={{-96,0,0},{96,0,0}};
__prg_rom Wire3DCGB_Edge back_edges[1]={{0,1}};
Wire3DCGB_Model back;
Wire3DCGB_Object objects[2];
void main() {
u8 i;
wire_results_clear();wire_plane_setup();
back.vertices=back_vertices;back.edges=back_edges;back.faces=0;back.edge_faces=0;
back.vertex_count=2;back.edge_count=1;back.face_count=0;back.flags=0;
for(i=0;i<2;i++) {
objects[i].x=0;objects[i].y=0;objects[i].rx=0;objects[i].ry=0;objects[i].rz=0;
objects[i].scale_q8=256;objects[i].visible=1;
}
objects[0].model=&back;objects[0].z=128;objects[0].color=2;
objects[1].model=&plane;objects[1].z=64;objects[1].color=1;
Wire3DCGB_Init();wire_colors();Wire3DCGB_BeginFrame();Wire3DCGB_SetLineColor(3);
Wire3DCGB_DrawScene(objects,2);
result[0]=objects[0].z;result[1]=objects[1].z;result[2]=Wire3DCGB_GetLineColor();
Wire3DCGB_EndFrame();result[7]=0xA55A;
while(1) {}
}Resultado esperado
Un cuadrado rojo cercano en (46,30)..(82,66) oculta la parte central de una línea horizontal azul más lejana; solo quedan visibles los segmentos izquierdo y derecho.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_scene.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_scene.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:155
kitaqgb/lib/wire3d_cgb.c:8918
void Wire3DCGB_DrawScene(Wire3DCGB_Object* objects, w3dcgb_u8 count)
{
w3dcgb_u8 scene_count;
w3dcgb_u8 i;
w3dcgb_u8 old_color;
if (objects == 0) return;
scene_count = count;
if (scene_count > WIRE3DCGB_SCENE_OBJECT_LIMIT) scene_count = WIRE3DCGB_SCENE_OBJECT_LIMIT;
i = 0;
while (i < scene_count)
{
w3dcgb_scene_order[(__safe_index w3dcgb_u8)i] = i;
w3dcgb_scene_depth[(__safe_index w3dcgb_u8)i] = w3dcgb_scene_object_depth(&objects[(__safe_index w3dcgb_u8)i]);
i = (w3dcgb_u8)(i + 1);
}
i = 0;
while (i < scene_count)
{
w3dcgb_u8 j;
j = (w3dcgb_u8)(i + 1);
while (j < scene_count)
{
w3dcgb_u8 oi;
w3dcgb_u8 oj;
oi = w3dcgb_scene_order[(__safe_index w3dcgb_u8)i];
oj = w3dcgb_scene_order[(__safe_index w3dcgb_u8)j];
if (w3dcgb_scene_depth[(__safe_index w3dcgb_u8)oj] < w3dcgb_scene_depth[(__safe_index w3dcgb_u8)oi])
{
w3dcgb_scene_order[(__safe_index w3dcgb_u8)i] = oj;
w3dcgb_scene_order[(__safe_index w3dcgb_u8)j] = oi;
}
j = (w3dcgb_u8)(j + 1);
}
i = (w3dcgb_u8)(i + 1);
}
old_color = w3dcgb_line_color;
w3dcgb_clear_occlusion_mask();
w3dcgb_occlusion_active = 0;
i = 0;
while (i < scene_count)
{
Wire3DCGB_Object* obj;
obj = &objects[(__safe_index w3dcgb_u8)w3dcgb_scene_order[(__safe_index w3dcgb_u8)i]];
if ((obj->visible != 0) && (obj->model != 0))
{
if (i == 0) w3dcgb_occlusion_active = 0;
else w3dcgb_occlusion_active = 1;
if (obj->color != 0) Wire3DCGB_SetLineColor(obj->color);
Wire3DCGB_DrawModelScaled(obj->model, obj->x, obj->y, obj->z, (w3dcgb_i8)obj->rx, (w3dcgb_i8)obj->ry, (w3dcgb_i8)obj->rz, obj->scale_q8);
w3dcgb_occlusion_active = 0;
w3dcgb_mark_model_occluder(obj->model);
}
i = (w3dcgb_u8)(i + 1);
}
w3dcgb_occlusion_active = 0;
w3dcgb_line_color = old_color;
}Wire3DCGB_DrawTinyModel2D
Dibuja un marcador de seis píxeles cuya punta y cola indican la dirección.
Sintaxis
void Wire3DCGB_DrawTinyModel2D(w3dcgb_u8 x, w3dcgb_u8 y, w3dcgb_u8 turn, w3dcgb_u8 color);Parámetros
xCoordenada X del centro en píxeles de la ventana gráfica.
yCoordenada Y del centro en píxeles de la ventana gráfica.
turnValor cuyos cinco bits bajos eligen la dirección del pequeño marcador.
colorÍndice de color de dibujo; las paletas de ejemplo usan 1=rojo, 2=azul y 3=verde.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Dibuja un marcador de seis píxeles mediante el trazador de puntos de 128×96, conservando el color de línea. Ignora centros fuera de X=3..124 o Y=3..92. Los cinco bits bajos de turn eligen los desplazamientos de la punta y la cola para izquierda/recto/derecha. No es una transformación 3D general ni despacha al renderizador de pantalla completa.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Preprojected edge arrays, a clipped square, a tiny marker and a projectile.
#include "wire_cgb_example.h"
__prg_rom Wire3DCGB_Edge edges[4]={{0,1},{1,2},{2,3},{3,0}};
__prg_rom s8 vx8[4]={-8,8,8,-8};
__prg_rom s8 vy8[4]={-8,-8,8,8};
__prg_rom s16 vx16[4]={-12,12,12,-12};
__prg_rom s16 vy16[4]={-8,-8,8,8};
__prg_rom u8 mask[1]={5};
Wire3DCGB_Model shape;
void main() {
wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
shape.vertices=0;shape.edges=edges;shape.faces=0;shape.edge_faces=0;
shape.vertex_count=4;shape.edge_count=4;shape.face_count=0;shape.flags=0;
Wire3DCGB_SetLineColor(2);
Wire3DCGB_DrawMaskedModel2D(&shape,vx8,vy8,mask,24,24,1);
Wire3DCGB_DrawEdgeList2D(edges,4,vx8,vy8,64,24,2);
Wire3DCGB_DrawEdgeListClipped2D(edges,4,vx16,vy16,4,4,64,3);
Wire3DCGB_DrawTinyModel2D(104,24,16,3);
result[0]=Wire3DCGB_ProjectAxis48(48,96);
result[1]=Wire3DCGB_ProjectAxis48(-48,96);
Wire3DCGB_DrawFastProjectile(96,64,64,0,1);
result[2]=Wire3DCGB_GetLineColor();
Wire3DCGB_EndFrame();result[7]=0xA55A;
while(1) {}
}Resultado esperado
Dos aristas horizontales rojas, un cuadrado azul, un marco verde recortado, un marcador verde de seis píxeles y un proyectil rojo permiten comparar los formatos de lista.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_lists.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_lists.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:175
kitaqgb/lib/wire3d_cgb.c:8313
void Wire3DCGB_DrawTinyModel2D(w3dcgb_u8 x, w3dcgb_u8 y,
w3dcgb_u8 turn, w3dcgb_u8 color)
{
w3dcgb_u8 nose_x;
w3dcgb_u8 tail_x;
w3dcgb_u8 old_color;
if ((x < 3) || (x > 124) || (y < 3) || (y > (w3dcgb_u8)(WIRE3DCGB_SCREEN_H - 4))) return;
nose_x = x;
tail_x = x;
turn = (w3dcgb_u8)(turn & 31);
if (turn < 12)
{
nose_x = (w3dcgb_u8)(x + 1);
tail_x = (w3dcgb_u8)(x - 1);
}
else if (turn >= 20)
{
nose_x = (w3dcgb_u8)(x - 1);
tail_x = (w3dcgb_u8)(x + 1);
}
old_color = w3dcgb_line_color;
w3dcgb_line_color = (w3dcgb_u8)(color & 3);
w3dcgb_plot_x = nose_x;
w3dcgb_plot_y = (w3dcgb_u8)(y - 2);
w3dcgb_plot_stage_asm();
w3dcgb_plot_x = x;
w3dcgb_plot_y = (w3dcgb_u8)(y - 1);
w3dcgb_plot_stage_asm();
w3dcgb_plot_x = (w3dcgb_u8)(x - 2);
w3dcgb_plot_y = (w3dcgb_u8)(y + 1);
w3dcgb_plot_stage_asm();
w3dcgb_plot_x = (w3dcgb_u8)(x + 2);
w3dcgb_plot_stage_asm();
w3dcgb_plot_x = x;
w3dcgb_plot_y = y;
w3dcgb_plot_stage_asm();
w3dcgb_plot_x = tail_x;
w3dcgb_plot_y = (w3dcgb_u8)(y + 2);
w3dcgb_plot_stage_asm();
w3dcgb_line_color = old_color;
}Wire3DCGB_DrawWhiteBorderFast
Dibuja un borde de un píxel con índice de color 2 alrededor del área de preparación de 128×96.
Sintaxis
void Wire3DCGB_DrawWhiteBorderFast();Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Escribe un borde de un píxel de color 2 alrededor del área de preparación normal, conservando los píxeles interiores y la selección de banco de WRAM. El color visible depende de la paleta. No marca ningún rango modificado; quien use transferencias parciales debe preparar su transferencia.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// A cleared 24-pixel strip and a palette-index-2 border have distinct purposes.
#include "wire_cgb_example.h"
void main() {
u8 y;
wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
Wire3DCGB_SetLineColor(1);
for(y=0;y<96;y++) Wire3DCGB_DrawLine2D(0,y,31,y);
Wire3DCGB_EraseLeftGuard24Fast();
// With this example's palette, color index 2 is blue rather than white.
Wire3DCGB_DrawWhiteBorderFast();
Wire3DCGB_EndFrame(); result[7]=0xA55A;
while(1) {}
}Resultado esperado
Se borran las 24 columnas de la izquierda, queda una franja roja y el borde exterior con índice de color 2 es azul.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_guard.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_guard.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:147
kitaqgb/lib/wire3d_cgb.c:9369
void Wire3DCGB_DrawWhiteBorderFast()
{
w3dcgb_draw_white_border_asm();
}Wire3DCGB_EnableAtomicMaps
Configura la presentación de 128×96 para alternar entre dos mapas del fondo.
Sintaxis
void Wire3DCGB_EnableAtomicMaps();Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Solo al arrancar: reserva ambos mapas BG y replica los tiles del HUD puestos en cola. Activa la alternancia de mapas una vez durante el arranque de 128×96; ignora el modo de pantalla completa o una configuración ya habilitada. Si el LCD está encendido, espera a VBlank, lo apaga, copia ambos bancos de 9800 a 9C00 y asigna a los atributos de cada ventana gráfica los bancos de tiles 0/1, respectivamente. Restaura LCDC con el mapa 9C00 seleccionado y VBK a cero. Quedan reservados ambos mapas BG; los números de tile del HUD en cola se replican.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Reuse both VRAM banks and remove old geometry while presenting sparse frames.
#include "wire_cgb_example.h"
void main() {
wire_results_clear(); Wire3DCGB_Init();
Wire3DCGB_ClearFrameTiles();
Wire3DCGB_EnableAtomicMaps(); wire_colors();
// First frame: red on the left. Fast begin invalidates both bank histories.
Wire3DCGB_BeginFrameFast(); wire_frame(8,8,32,32,1);
Wire3DCGB_EndFrameFast();
// Second frame: blue in the middle, with the old red frame removed.
Wire3DCGB_BeginFrameSparse(); wire_frame(40,40,64,64,2);
Wire3DCGB_EndFrameSparse();
// Third frame: explicitly clearing a stage discards its first green point.
Wire3DCGB_BeginFrameSparse();
Wire3DCGB_SetLineColor(3); Wire3DCGB_DrawPoint2D(4,4);
Wire3DCGB_ClearSparseStageFast();
// The final image contains only this green frame on the right.
wire_frame(80,8,112,32,3);
Wire3DCGB_MarkDirtyRect2D(80,8,112,32);
Wire3DCGB_InvalidateFrameHistory();
Wire3DCGB_EndFrameSparseNow();
result[0]=Wire3DCGB_GetLineColor();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Desaparecen los marcos rojo y azul dibujados antes y solo queda el marco verde final en (80,8)..(112,32), mostrando la transferencia parcial y la gestión del historial.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_sparse.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_sparse.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:144
Startup-only: reserves both BG maps; queued HUD tiles are mirrored.
kitaqgb/lib/wire3d_cgb.c:7912
void Wire3DCGB_EnableAtomicMaps()
{
if ((w3dcgb_full_mode != 0) || (w3dcgb_atomic_maps != 0)) return;
__asm {
w3dam_wait:
LDH_A_MEM 68
CP_IMM 144
JR_C w3dam_wait
LDH_A_MEM 64
PUSH_AF
XOR_A
LDH_MEM_A 64
LDH_MEM_A 79
LD_HL_IMM 0x9800
LD_DE_IMM 0x9C00
LD_B_IMM 4
w3dam_copy_page:
LD_C_IMM 0
w3dam_copy_byte:
LD_A_HL
INC_HL
LD_DE_A
INC_DE
DEC_C
JR_NZ w3dam_copy_byte
DEC_B
JR_NZ w3dam_copy_page
LDH_A_MEM 79
AND_IMM 1
JR_NZ w3dam_attrs
LD_A_IMM 1
LDH_MEM_A 79
LD_HL_IMM 0x9800
LD_DE_IMM 0x9C00
LD_B_IMM 4
JR w3dam_copy_page
w3dam_attrs:
LD_HL_IMM 0x9800
LD_DE_IMM 0x9C00
LD_B_IMM 12
w3dam_row:
LD_C_IMM 16
w3dam_cell:
XOR_A
LDI_HL_A
LD_A_IMM 8
LD_DE_A
INC_DE
DEC_C
JR_NZ w3dam_cell
LD_A_L
ADD_A_IMM 16
LD_L_A
JR_NC w3dam_hl_ready
INC_H
w3dam_hl_ready:
LD_A_E
ADD_A_IMM 16
LD_E_A
JR_NC w3dam_de_ready
INC_D
w3dam_de_ready:
DEC_B
JR_NZ w3dam_row
LD_A_IMM 1
LD_MEM_A w3dcgb_atomic_maps
XOR_A
LDH_MEM_A 79
POP_AF
OR_IMM 8
LDH_MEM_A 64
RET
}
}Wire3DCGB_EnableDoubleSpeed
Cambia la CPU de CGB a doble velocidad.
Sintaxis
void Wire3DCGB_EnableDoubleSpeed();Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
En CGB, termina si KEY1 ya indica doble velocidad; si no, solicita el cambio de velocidad y llama a la función auxiliar STOP. Esta API presupone hardware CGB y no ofrece una alternativa para los modelos monocromos.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// CGB raster paths: a red frame, blue diagonal, green marker and clipped line.
// Build this source together with lib/wire3d_cgb.c in an MBC5 256 KB CGB ROM.
#include "wire3d_cgb.h"
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4D) u8 sample_key1;
__location(0xC110) u16 result[8];
__prg_rom u8 lower_lines[8]={80,56,112,56,112,56,112,80};
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3DCGB_EnableDoubleSpeed();
Wire3DCGB_Init(); // Already at double speed: its internal request is a no-op.
result[2]=(u8)(sample_key1&128);
// Palette writes are performed with the LCD off, after entering VBlank.
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0;
Wire3DCGB_SetPaletteRGB15(WIRE3DCGB_RGB15(0,0,0),WIRE3DCGB_RGB15(31,0,0),WIRE3DCGB_RGB15(0,0,31),WIRE3DCGB_RGB15(0,31,0));
sample_lcdc=0x81;
Wire3DCGB_SetScreenOffset(0,0);
Wire3DCGB_SetCamera(0,0,0,0,0,0);
Wire3DCGB_BeginFrame();
Wire3DCGB_SetLineColor(1);
Wire3DCGB_DrawLine2D(8,8,56,8);
Wire3DCGB_DrawLine2D(56,8,56,40);
Wire3DCGB_DrawLine2D(56,40,8,40);
Wire3DCGB_DrawLine2D(8,40,8,8);
Wire3DCGB_DrawLine2DColor(8,40,56,8,2);
result[0]=Wire3DCGB_GetLineColor(); // Temporary blue restores red.
Wire3DCGB_SetLineColor(3);
Wire3DCGB_DrawPoint2D(64,48);
Wire3DCGB_DrawLineClipped2D(-10,72,140,72,3);
Wire3DCGB_DrawLineList2DColor(lower_lines,2,2);
result[1]=Wire3DCGB_GetLineColor(); // The blue line list restores green.
Wire3DCGB_PutBgTile(18,1,0x80); // Queue the supplied zero glyph outside the viewport.
Wire3DCGB_EndFrame();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Este ejemplo muestra líneas, puntos, borrado y proyección básicos en un solo fotograma. Un marco rojo contiene una diagonal azul, un punto y una línea horizontal verdes, una L azul y un cero verde en la esquina superior derecha.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_raster.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:116
kitaqgb/lib/wire3d_cgb.c:1081
void Wire3DCGB_EnableDoubleSpeed()
{
if ((w3dcgb_reg_key1 & 0x80) != 0) return;
w3dcgb_reg_key1 = 1;
w3dcgb_cgb_speed_switch_asm();
}Wire3DCGB_EndFrame
Transfiere y presenta el fotograma terminado.
Sintaxis
void Wire3DCGB_EndFrame();Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
En modo normal, aplica las escrituras BG en cola, transfiere toda el área de preparación y presenta el banco de tiles terminado. En pantalla completa transfiere y presenta los tiles asignados sin vaciar la cola del HUD. Requiere el LCD encendido y respetar las condiciones de bancos e interrupciones de las funciones de transferencia; puede abarcar varios fotogramas.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Al iniciar sparse en CGB, el primer uso de cada banco de destino (los dos primeros fotogramas) actualiza toda la vista y elimina los mosaicos de inicialización. La medición incluye ese coste. DrawLine2D no registra regiones sparse: use DrawLineClipped2D o llame explícitamente a MarkDirtyRect2D.
Ejemplo de uso
#pragma bank 0
// CGB raster paths: a red frame, blue diagonal, green marker and clipped line.
// Build this source together with lib/wire3d_cgb.c in an MBC5 256 KB CGB ROM.
#include "wire3d_cgb.h"
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4D) u8 sample_key1;
__location(0xC110) u16 result[8];
__prg_rom u8 lower_lines[8]={80,56,112,56,112,56,112,80};
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3DCGB_EnableDoubleSpeed();
Wire3DCGB_Init(); // Already at double speed: its internal request is a no-op.
result[2]=(u8)(sample_key1&128);
// Palette writes are performed with the LCD off, after entering VBlank.
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0;
Wire3DCGB_SetPaletteRGB15(WIRE3DCGB_RGB15(0,0,0),WIRE3DCGB_RGB15(31,0,0),WIRE3DCGB_RGB15(0,0,31),WIRE3DCGB_RGB15(0,31,0));
sample_lcdc=0x81;
Wire3DCGB_SetScreenOffset(0,0);
Wire3DCGB_SetCamera(0,0,0,0,0,0);
Wire3DCGB_BeginFrame();
Wire3DCGB_SetLineColor(1);
Wire3DCGB_DrawLine2D(8,8,56,8);
Wire3DCGB_DrawLine2D(56,8,56,40);
Wire3DCGB_DrawLine2D(56,40,8,40);
Wire3DCGB_DrawLine2D(8,40,8,8);
Wire3DCGB_DrawLine2DColor(8,40,56,8,2);
result[0]=Wire3DCGB_GetLineColor(); // Temporary blue restores red.
Wire3DCGB_SetLineColor(3);
Wire3DCGB_DrawPoint2D(64,48);
Wire3DCGB_DrawLineClipped2D(-10,72,140,72,3);
Wire3DCGB_DrawLineList2DColor(lower_lines,2,2);
result[1]=Wire3DCGB_GetLineColor(); // The blue line list restores green.
Wire3DCGB_PutBgTile(18,1,0x80); // Queue the supplied zero glyph outside the viewport.
Wire3DCGB_EndFrame();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Este ejemplo muestra líneas, puntos, borrado y proyección básicos en un solo fotograma. Un marco rojo contiene una diagonal azul, un punto y una línea horizontal verdes, una L azul y un cero verde en la esquina superior derecha.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_raster.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:189
kitaqgb/lib/wire3d_cgb.c:9881
void Wire3DCGB_EndFrame()
{
if (w3dcgb_full_mode != 0)
{
w3dcgb_full_transfer_asm();
w3dcgb_full_present_asm();
return;
}
if (w3dcgb_bgq_count != 0)
{
w3dcgb_wait_vblank_start();
w3dcgb_flush_bg_queue();
}
w3dcgb_transfer_stage_asm();
w3dcgb_present_stage_asm();
}Wire3DCGB_EndFrameFast
Transfiere y presenta un fotograma completo sin aplicar las escrituras del fondo en cola.
Sintaxis
void Wire3DCGB_EndFrameFast();Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Transfiere y presenta el fotograma completo del modo elegido sin vaciar la cola BG. No consume las escrituras HUD pendientes. Exige las mismas condiciones de LCD, bancos e interrupciones que EndFrame; requiere el entorno de ejecución completo.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Al iniciar sparse en CGB, el primer uso de cada banco de destino (los dos primeros fotogramas) actualiza toda la vista y elimina los mosaicos de inicialización. La medición incluye ese coste. DrawLine2D no registra regiones sparse: use DrawLineClipped2D o llame explícitamente a MarkDirtyRect2D.
Ejemplo de uso
#pragma bank 0
// Reuse both VRAM banks and remove old geometry while presenting sparse frames.
#include "wire_cgb_example.h"
void main() {
wire_results_clear(); Wire3DCGB_Init();
Wire3DCGB_ClearFrameTiles();
Wire3DCGB_EnableAtomicMaps(); wire_colors();
// First frame: red on the left. Fast begin invalidates both bank histories.
Wire3DCGB_BeginFrameFast(); wire_frame(8,8,32,32,1);
Wire3DCGB_EndFrameFast();
// Second frame: blue in the middle, with the old red frame removed.
Wire3DCGB_BeginFrameSparse(); wire_frame(40,40,64,64,2);
Wire3DCGB_EndFrameSparse();
// Third frame: explicitly clearing a stage discards its first green point.
Wire3DCGB_BeginFrameSparse();
Wire3DCGB_SetLineColor(3); Wire3DCGB_DrawPoint2D(4,4);
Wire3DCGB_ClearSparseStageFast();
// The final image contains only this green frame on the right.
wire_frame(80,8,112,32,3);
Wire3DCGB_MarkDirtyRect2D(80,8,112,32);
Wire3DCGB_InvalidateFrameHistory();
Wire3DCGB_EndFrameSparseNow();
result[0]=Wire3DCGB_GetLineColor();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Desaparecen los marcos rojo y azul dibujados antes y solo queda el marco verde final en (80,8)..(112,32), mostrando la transferencia parcial y la gestión del historial.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_sparse.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_sparse.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:190
kitaqgb/lib/wire3d_cgb.c:9902
void Wire3DCGB_EndFrameFast()
{
if (w3dcgb_full_mode != 0)
{
w3dcgb_full_transfer_asm();
w3dcgb_full_present_asm();
return;
}
w3dcgb_transfer_stage_asm();
w3dcgb_present_stage_asm();
}Wire3DCGB_EndFrameSparse
Espera a un nuevo VBlank y transfiere y presenta los rangos parciales necesarios.
Sintaxis
void Wire3DCGB_EndFrameSparse();Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
En modo normal, espera a un nuevo VBlank e invoca EndFrameSparseNow. En pantalla completa usa su transferencia y presentación completas. Requiere el entorno de ejecución completo y el LCD encendido; no se garantiza que termine en un solo fotograma.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Al iniciar sparse en CGB, el primer uso de cada banco de destino (los dos primeros fotogramas) actualiza toda la vista y elimina los mosaicos de inicialización. La medición incluye ese coste. DrawLine2D no registra regiones sparse: use DrawLineClipped2D o llame explícitamente a MarkDirtyRect2D.
Ejemplo de uso
#pragma bank 0
// Reuse both VRAM banks and remove old geometry while presenting sparse frames.
#include "wire_cgb_example.h"
void main() {
wire_results_clear(); Wire3DCGB_Init();
Wire3DCGB_ClearFrameTiles();
Wire3DCGB_EnableAtomicMaps(); wire_colors();
// First frame: red on the left. Fast begin invalidates both bank histories.
Wire3DCGB_BeginFrameFast(); wire_frame(8,8,32,32,1);
Wire3DCGB_EndFrameFast();
// Second frame: blue in the middle, with the old red frame removed.
Wire3DCGB_BeginFrameSparse(); wire_frame(40,40,64,64,2);
Wire3DCGB_EndFrameSparse();
// Third frame: explicitly clearing a stage discards its first green point.
Wire3DCGB_BeginFrameSparse();
Wire3DCGB_SetLineColor(3); Wire3DCGB_DrawPoint2D(4,4);
Wire3DCGB_ClearSparseStageFast();
// The final image contains only this green frame on the right.
wire_frame(80,8,112,32,3);
Wire3DCGB_MarkDirtyRect2D(80,8,112,32);
Wire3DCGB_InvalidateFrameHistory();
Wire3DCGB_EndFrameSparseNow();
result[0]=Wire3DCGB_GetLineColor();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Desaparecen los marcos rojo y azul dibujados antes y solo queda el marco verde final en (80,8)..(112,32), mostrando la transferencia parcial y la gestión del historial.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_sparse.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_sparse.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:191
kitaqgb/lib/wire3d_cgb.c:9917
void Wire3DCGB_EndFrameSparse()
{
if (w3dcgb_full_mode != 0)
{
w3dcgb_full_transfer_asm();
w3dcgb_full_present_asm();
return;
}
w3dcgb_wait_vblank_start();
Wire3DCGB_EndFrameSparseNow();
}Wire3DCGB_EndFrameSparseNow
Envía las escrituras del fondo y los rangos parciales actuales/N−2 sin la espera inicial a un nuevo VBlank.
Sintaxis
void Wire3DCGB_EndFrameSparseNow();Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Aplica las escrituras BG en cola, transfiere el rango parcial de tiles actual/N−2 al banco posterior y lo presenta. Omite la espera inicial a un nuevo VBlank, pero el modo de mapa normal sigue esperando al restaurar el tile vacío del HUD; DMA y la presentación también pueden esperar. El modo de pantalla completa del entorno de ejecución completo usa su propia ruta. El LCD debe estar encendido y SVBK/VBK deben permanecer estables mientras DMA esté activo.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Al iniciar sparse en CGB, el primer uso de cada banco de destino (los dos primeros fotogramas) actualiza toda la vista y elimina los mosaicos de inicialización. La medición incluye ese coste. DrawLine2D no registra regiones sparse: use DrawLineClipped2D o llame explícitamente a MarkDirtyRect2D.
Ejemplo de uso
#pragma bank 0
// Reuse both VRAM banks and remove old geometry while presenting sparse frames.
#include "wire_cgb_example.h"
void main() {
wire_results_clear(); Wire3DCGB_Init();
Wire3DCGB_ClearFrameTiles();
Wire3DCGB_EnableAtomicMaps(); wire_colors();
// First frame: red on the left. Fast begin invalidates both bank histories.
Wire3DCGB_BeginFrameFast(); wire_frame(8,8,32,32,1);
Wire3DCGB_EndFrameFast();
// Second frame: blue in the middle, with the old red frame removed.
Wire3DCGB_BeginFrameSparse(); wire_frame(40,40,64,64,2);
Wire3DCGB_EndFrameSparse();
// Third frame: explicitly clearing a stage discards its first green point.
Wire3DCGB_BeginFrameSparse();
Wire3DCGB_SetLineColor(3); Wire3DCGB_DrawPoint2D(4,4);
Wire3DCGB_ClearSparseStageFast();
// The final image contains only this green frame on the right.
wire_frame(80,8,112,32,3);
Wire3DCGB_MarkDirtyRect2D(80,8,112,32);
Wire3DCGB_InvalidateFrameHistory();
Wire3DCGB_EndFrameSparseNow();
result[0]=Wire3DCGB_GetLineColor();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Desaparecen los marcos rojo y azul dibujados antes y solo queda el marco verde final en (80,8)..(112,32), mostrando la transferencia parcial y la gestión del historial.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_sparse.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_sparse.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:192
kitaqgb/lib/wire3d_cgb.c:9935
void Wire3DCGB_EndFrameSparseNow()
{
#ifndef WIRE3DCGB_MINIMAL_RUNTIME
if (w3dcgb_full_mode != 0)
{
w3dcgb_full_transfer_asm();
w3dcgb_full_present_asm();
return;
}
#endif
/* Atomic mode never writes a displayed tile and does not need a
frame-long VBlank wait before starting an off-screen upload. */
if (w3dcgb_atomic_maps == 0) w3dcgb_restore_hud_blank_tile_asm();
if (w3dcgb_bgq_count != 0) w3dcgb_flush_bg_queue();
w3dcgb_transfer_dirty_tiles();
w3dcgb_present_stage_asm();
}Wire3DCGB_EraseLeftGuard24Fast
Borra las 24 columnas más a la izquierda del área de preparación normal.
Sintaxis
void Wire3DCGB_EraseLeftGuard24Fast();Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Borra las 24 columnas más a la izquierda del área de preparación mediante ASM, conservando la selección de banco. No marca ningún rango modificado; quien use transferencias parciales debe incluir los tiles borrados.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// A cleared 24-pixel strip and a palette-index-2 border have distinct purposes.
#include "wire_cgb_example.h"
void main() {
u8 y;
wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
Wire3DCGB_SetLineColor(1);
for(y=0;y<96;y++) Wire3DCGB_DrawLine2D(0,y,31,y);
Wire3DCGB_EraseLeftGuard24Fast();
// With this example's palette, color index 2 is blue rather than white.
Wire3DCGB_DrawWhiteBorderFast();
Wire3DCGB_EndFrame(); result[7]=0xA55A;
while(1) {}
}Resultado esperado
Se borran las 24 columnas de la izquierda, queda una franja roja y el borde exterior con índice de color 2 es azul.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_guard.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_guard.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:146
kitaqgb/lib/wire3d_cgb.c:9200
void Wire3DCGB_EraseLeftGuard24Fast()
{
w3dcgb_erase_left_guard24_asm();
}Wire3DCGB_EraseModelFaces
Borra los píxeles preparados dentro de las caras frontales proyectadas del modelo.
Sintaxis
void Wire3DCGB_EraseModelFaces(const Wire3DCGB_Model* model, w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 rx, w3dcgb_i8 ry, w3dcgb_i8 rz, w3dcgb_i16 scale_q8);Parámetros
modelModelo que contiene los arrays de vértices, aristas y caras y sus cantidades; las tablas deben permanecer legibles durante la llamada.
xComponente X del punto o del origen del objeto en coordenadas del mundo.
yComponente Y del punto o del origen del objeto en coordenadas del mundo.
zComponente Z del punto o del origen del objeto en coordenadas del mundo.
rxRotación alrededor de X; dieciséis pasos forman una vuelta completa.
ryRotación alrededor de Y; dieciséis pasos forman una vuelta completa.
rzRotación alrededor de Z; dieciséis pasos forman una vuelta completa.
scale_q8Escala con 256 como unidad; los valores no positivos también equivalen a la unidad.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Para un modelo con ocultación de líneas que tenga vértices y caras, transforma como máximo 24 vértices y borra los triángulos orientados hacia delante entre un máximo de 16 caras. Una escala no positiva equivale a la unidad; esta ruta sigue multiplicando a escala unitaria y ejecuta las tres funciones auxiliares de rotación incluso con ángulos cero. Rechaza las caras inválidas o que no pasan la prueba de profundidad. Sustituye la caché de proyección compartida y usa el borrado normal en C del área de preparación, por lo que el código que llama o la asignación debe proporcionar el mapeo correcto de WRAM.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Projected model faces erase a square opening; redraw its outline in green.
#include "wire_cgb_example.h"
#include "wire_cgb_plane.h"
void main() {
u8 y;u8 bank;
wire_results_clear();wire_plane_setup();Wire3DCGB_Init();wire_colors();Wire3DCGB_BeginFrame();
Wire3DCGB_SetLineColor(1);
for(y=8;y<=88;y++) Wire3DCGB_DrawLine2D(24,y,104,y);
bank=sample_svbk;sample_svbk=2;
Wire3DCGB_EraseModelFaces(&plane,0,0,64,0,0,0,256);
sample_svbk=bank;
Wire3DCGB_DrawModelColor(&plane,0,0,64,0,0,0,3);
result[0]=Wire3DCGB_GetLineColor();
Wire3DCGB_EndFrame();result[7]=0xA55A;
while(1) {}
}Resultado esperado
Las caras proyectadas borran una región rellena y permiten distinguir las zonas conservadas de las borradas.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_faces.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_faces.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:132
kitaqgb/lib/wire3d_cgb.c:9033
void Wire3DCGB_EraseModelFaces(const Wire3DCGB_Model* model, w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 rx, w3dcgb_i8 ry, w3dcgb_i8 rz, w3dcgb_i16 scale_q8)
{
w3dcgb_u8 i;
w3dcgb_u8 count;
w3dcgb_u8 face_count;
if (model == 0) return;
if (model->vertices == 0) return;
if (model->faces == 0) return;
if ((model->flags & WIRE3DCGB_MODEL_HIDDEN_LINES) == 0) return;
if (scale_q8 <= 0) scale_q8 = 256;
count = model->vertex_count;
if (count > WIRE3DCGB_MODEL_VERTEX_LIMIT) count = WIRE3DCGB_MODEL_VERTEX_LIMIT;
i = 0;
while (i < count)
{
const Wire3DCGB_Vec3* v;
w3dcgb_i16 vx;
w3dcgb_i16 vy;
w3dcgb_i16 vz;
w3dcgb_u8 sx;
w3dcgb_u8 sy;
v = &model->vertices[(__safe_index w3dcgb_u8)i];
vx = (w3dcgb_i16)((v->x * scale_q8) >> 8);
vy = (w3dcgb_i16)((v->y * scale_q8) >> 8);
vz = (w3dcgb_i16)((v->z * scale_q8) >> 8);
w3dcgb_rotate_y(&vx, &vz, (w3dcgb_i8)ry);
w3dcgb_rotate_x(&vy, &vz, (w3dcgb_i8)rx);
w3dcgb_rotate_z(&vx, &vy, (w3dcgb_i8)rz);
vx = (w3dcgb_i16)(vx + x);
vy = (w3dcgb_i16)(vy + y);
vz = (w3dcgb_i16)(vz + z);
if (w3dcgb_project_world(vx, vy, vz, &sx, &sy))
{
w3dcgb_screen_x[(__safe_index w3dcgb_u8)i] = sx;
w3dcgb_screen_y[(__safe_index w3dcgb_u8)i] = sy;
w3dcgb_screen_visible[(__safe_index w3dcgb_u8)i] = 1;
}
else
{
w3dcgb_screen_visible[(__safe_index w3dcgb_u8)i] = 0;
}
i = (w3dcgb_u8)(i + 1);
}
face_count = model->face_count;
if (face_count > WIRE3DCGB_MODEL_FACE_LIMIT) face_count = WIRE3DCGB_MODEL_FACE_LIMIT;
w3dcgb_build_face_visibility(model, count, face_count);
i = 0;
while (i < face_count)
{
const Wire3DCGB_Face* f;
f = &model->faces[(__safe_index w3dcgb_u8)i];
if (w3dcgb_face_visible[(__safe_index w3dcgb_u8)i] &&
w3dcgb_screen_visible[(__safe_index w3dcgb_u8)f->a] &&
w3dcgb_screen_visible[(__safe_index w3dcgb_u8)f->b] &&
w3dcgb_screen_visible[(__safe_index w3dcgb_u8)f->c])
{
w3dcgb_clear_triangle(
w3dcgb_screen_x[(__safe_index w3dcgb_u8)f->a],
w3dcgb_screen_y[(__safe_index w3dcgb_u8)f->a],
w3dcgb_screen_x[(__safe_index w3dcgb_u8)f->b],
w3dcgb_screen_y[(__safe_index w3dcgb_u8)f->b],
w3dcgb_screen_x[(__safe_index w3dcgb_u8)f->c],
w3dcgb_screen_y[(__safe_index w3dcgb_u8)f->c]);
}
i = (w3dcgb_u8)(i + 1);
}
}Wire3DCGB_ErasePackedSilhouette2D
Borra una silueta empaquetada de ambos planos de color del área de preparación normal.
Sintaxis
void Wire3DCGB_ErasePackedSilhouette2D(const w3dcgb_u8* profile, w3dcgb_u8 count, w3dcgb_i8 y0, w3dcgb_u8 x, w3dcgb_u8 y);Parámetros
profileArray de silueta de un byte por fila; 0xFF omite una fila.
countCantidad de entradas proporcionadas; consulta el límite de procesamiento de cada operación.
y0Desplazamiento con signo desde el centro Y hasta la primera fila de la silueta.
xCoordenada X del centro en píxeles de la ventana gráfica.
yCoordenada Y del centro en píxeles de la ventana gráfica.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Borra hasta 29 filas de silueta empaquetada de ambos planos de bits preparados. El formato, la colocación, el margen de dos píxeles y el recorte coinciden con MarkPackedSilhouette2D; null se ignora. La escritura de tramos en ASM selecciona el banco 2 de WRAM y restaura la selección anterior, pero no marca los tiles modificados. En modo parcial, el código que llama debe incluir los tiles borrados en el rango de transferencia. Esta API trabaja sobre el área de preparación de 128×96.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Colored panels expose triangle, span, rectangle and packed-silhouette erasure.
#include "wire_cgb_example.h"
__prg_rom u8 silhouette[5]={0x73,0x74,0xFF,0x75,0x73};
void main() {
u8 y;
u8 bank;
wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
for(y=8;y<=40;y++) Wire3DCGB_DrawLine2DColor(8,y,40,y,1);
for(y=8;y<=40;y++) Wire3DCGB_DrawLine2DColor(48,y,80,y,2);
for(y=64;y<=72;y++) Wire3DCGB_DrawLine2DColor(88,y,120,y,3);
// The C triangle/rectangle clearers access the stage through the current
// WRAM window. Select bank 2 around them and restore the caller's bank.
bank=sample_svbk; sample_svbk=2;
Wire3DCGB_EraseTriangle2D(12,12,36,12,12,36);
Wire3DCGB_EraseSpan2D(36,40,24);
Wire3DCGB_EraseRect2D(56,16,72,32);
Wire3DCGB_ErasePackedSilhouette2D(silhouette,5,-2,104,68);
sample_svbk=bank;
Wire3DCGB_EndFrame(); result[7]=0xA55A;
while(1) {}
}Resultado esperado
Triángulos, tramos horizontales, rectángulos y siluetas empaquetadas abren huecos negros en paneles rellenos de rojo, azul y verde.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_erase.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_erase.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:153
kitaqgb/lib/wire3d_cgb.c:2038
void Wire3DCGB_ErasePackedSilhouette2D(const w3dcgb_u8* profile, w3dcgb_u8 count,
w3dcgb_i8 y0, w3dcgb_u8 x, w3dcgb_u8 y)
{
w3dcgb_u8 i;
w3dcgb_u8 packed;
w3dcgb_u8 half_width;
w3dcgb_i16 center;
w3dcgb_i16 left;
w3dcgb_i16 right;
w3dcgb_i16 row;
if (profile == 0) return;
if (count > 29) count = 29;
i = 0;
while (i < count)
{
packed = profile[(__safe_index w3dcgb_u8)i];
if (packed != 0xFF)
{
row = (w3dcgb_i16)((w3dcgb_i16)y + (w3dcgb_i16)y0 + (w3dcgb_i16)i);
if ((row >= 0) && (row < WIRE3DCGB_SCREEN_H))
{
center = (w3dcgb_i16)((w3dcgb_i16)x + (w3dcgb_i16)(packed >> 4) - 7);
half_width = (w3dcgb_u8)(packed & 15);
left = (w3dcgb_i16)(center - (w3dcgb_i16)half_width - 2);
right = (w3dcgb_i16)(center + (w3dcgb_i16)half_width + 2);
if ((right >= 0) && (left < WIRE3DCGB_SCREEN_W))
{
if (left < 0) left = 0;
if (right >= WIRE3DCGB_SCREEN_W) right = WIRE3DCGB_SCREEN_W - 1;
w3dcgb_mask_span_y = (w3dcgb_u8)row;
w3dcgb_mask_span_min_x = (w3dcgb_u8)left;
w3dcgb_mask_span_max_x = (w3dcgb_u8)right;
w3dcgb_stage_clear_span_asm();
}
}
}
i = (w3dcgb_u8)(i + 1);
}
}Wire3DCGB_EraseRect2D
Borra un rectángulo del área de preparación normal.
Sintaxis
void Wire3DCGB_EraseRect2D(w3dcgb_u8 x0, w3dcgb_u8 y0, w3dcgb_u8 x1, w3dcgb_u8 y1);Parámetros
x0Extremo X inferior, en píxeles de la ventana gráfica; el orden y el recorte siguen las notas de esta operación.
y0Extremo Y inferior, en píxeles de la ventana gráfica; el orden y el recorte siguen las notas de esta operación.
x1Extremo X superior, en píxeles de la ventana gráfica; el orden y el recorte siguen las notas de esta operación.
y1Extremo Y superior, en píxeles de la ventana gráfica; el orden y el recorte siguen las notas de esta operación.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Ordena los extremos del rectángulo y lo recorta a 128×96. Las franjas izquierdas de altura completa y de 16 o 24 píxeles de ancho usan el borrado ASM que conserva la selección de banco y marca los cambios. Los demás rectángulos se borran por filas en C y requieren que el código que llama proporcione el mapeo WRAM correcto del área de preparación.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Colored panels expose triangle, span, rectangle and packed-silhouette erasure.
#include "wire_cgb_example.h"
__prg_rom u8 silhouette[5]={0x73,0x74,0xFF,0x75,0x73};
void main() {
u8 y;
u8 bank;
wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
for(y=8;y<=40;y++) Wire3DCGB_DrawLine2DColor(8,y,40,y,1);
for(y=8;y<=40;y++) Wire3DCGB_DrawLine2DColor(48,y,80,y,2);
for(y=64;y<=72;y++) Wire3DCGB_DrawLine2DColor(88,y,120,y,3);
// The C triangle/rectangle clearers access the stage through the current
// WRAM window. Select bank 2 around them and restore the caller's bank.
bank=sample_svbk; sample_svbk=2;
Wire3DCGB_EraseTriangle2D(12,12,36,12,12,36);
Wire3DCGB_EraseSpan2D(36,40,24);
Wire3DCGB_EraseRect2D(56,16,72,32);
Wire3DCGB_ErasePackedSilhouette2D(silhouette,5,-2,104,68);
sample_svbk=bank;
Wire3DCGB_EndFrame(); result[7]=0xA55A;
while(1) {}
}Resultado esperado
Triángulos, tramos horizontales, rectángulos y siluetas empaquetadas abren huecos negros en paneles rellenos de rojo, azul y verde.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_erase.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_erase.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:145
kitaqgb/lib/wire3d_cgb.c:9146
void Wire3DCGB_EraseRect2D(w3dcgb_u8 x0, w3dcgb_u8 y0, w3dcgb_u8 x1, w3dcgb_u8 y1)
{
w3dcgb_u8 t;
w3dcgb_u8 y;
if (x0 > x1)
{
t = x0;
x0 = x1;
x1 = t;
}
if (y0 > y1)
{
t = y0;
y0 = y1;
y1 = t;
}
if (x0 >= WIRE3DCGB_SCREEN_W) return;
if (y0 >= WIRE3DCGB_SCREEN_H) return;
if (x1 >= WIRE3DCGB_SCREEN_W) x1 = (w3dcgb_u8)(WIRE3DCGB_SCREEN_W - 1);
if (y1 >= WIRE3DCGB_SCREEN_H) y1 = (w3dcgb_u8)(WIRE3DCGB_SCREEN_H - 1);
if ((x0 == 0) &&
(x1 == 15) &&
(y0 == 0) &&
(y1 == (w3dcgb_u8)(WIRE3DCGB_SCREEN_H - 1)))
{
w3dcgb_erase_left_guard16_asm();
w3dcgb_mark_dirty_rect(0, 0, 15, (w3dcgb_u8)(WIRE3DCGB_SCREEN_H - 1));
return;
}
if ((x0 == 0) &&
(x1 == 23) &&
(y0 == 0) &&
(y1 == (w3dcgb_u8)(WIRE3DCGB_SCREEN_H - 1)))
{
w3dcgb_erase_left_guard24_asm();
w3dcgb_mark_dirty_rect(0, 0, 23, (w3dcgb_u8)(WIRE3DCGB_SCREEN_H - 1));
return;
}
y = y0;
while (y <= y1)
{
w3dcgb_stage_clear_span(y, x0, x1);
if (y == y1) break;
y = (w3dcgb_u8)(y + 1);
}
}Wire3DCGB_EraseSpan2D
Borra un tramo horizontal, guardando y restaurando la selección del banco de WRAM.
Sintaxis
void Wire3DCGB_EraseSpan2D(w3dcgb_u8 y, w3dcgb_u8 x0, w3dcgb_u8 x1);Parámetros
yCoordenada Y en píxeles de la fila que se va a borrar.
x0Extremo X inferior, en píxeles de la ventana gráfica; el orden y el recorte siguen las notas de esta operación.
x1Extremo X superior, en píxeles de la ventana gráfica; el orden y el recorte siguen las notas de esta operación.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Ordena los extremos X, rechaza una fila o un extremo izquierdo fuera de pantalla y limita el extremo derecho a 127. Marca el rango como modificado y usa el borrado de tramos en ASM, que selecciona el banco 2 de WRAM y después restaura la selección anterior.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Colored panels expose triangle, span, rectangle and packed-silhouette erasure.
#include "wire_cgb_example.h"
__prg_rom u8 silhouette[5]={0x73,0x74,0xFF,0x75,0x73};
void main() {
u8 y;
u8 bank;
wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
for(y=8;y<=40;y++) Wire3DCGB_DrawLine2DColor(8,y,40,y,1);
for(y=8;y<=40;y++) Wire3DCGB_DrawLine2DColor(48,y,80,y,2);
for(y=64;y<=72;y++) Wire3DCGB_DrawLine2DColor(88,y,120,y,3);
// The C triangle/rectangle clearers access the stage through the current
// WRAM window. Select bank 2 around them and restore the caller's bank.
bank=sample_svbk; sample_svbk=2;
Wire3DCGB_EraseTriangle2D(12,12,36,12,12,36);
Wire3DCGB_EraseSpan2D(36,40,24);
Wire3DCGB_EraseRect2D(56,16,72,32);
Wire3DCGB_ErasePackedSilhouette2D(silhouette,5,-2,104,68);
sample_svbk=bank;
Wire3DCGB_EndFrame(); result[7]=0xA55A;
while(1) {}
}Resultado esperado
Triángulos, tramos horizontales, rectángulos y siluetas empaquetadas abren huecos negros en paneles rellenos de rojo, azul y verde.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_erase.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_erase.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:134
kitaqgb/lib/wire3d_cgb.c:9123
void Wire3DCGB_EraseSpan2D(w3dcgb_u8 y, w3dcgb_u8 x0, w3dcgb_u8 x1)
{
w3dcgb_u8 tx;
if (x0 > x1)
{
tx = x0;
x0 = x1;
x1 = tx;
}
if ((y >= WIRE3DCGB_SCREEN_H) || (x0 >= WIRE3DCGB_SCREEN_W)) return;
if (x1 >= WIRE3DCGB_SCREEN_W) x1 = WIRE3DCGB_SCREEN_W - 1;
w3dcgb_mark_dirty_rect(x0, y, x1, y);
w3dcgb_mask_span_y = y;
w3dcgb_mask_span_min_x = x0;
w3dcgb_mask_span_max_x = x1;
w3dcgb_stage_clear_span_asm();
}Wire3DCGB_EraseTriangle2D
Borra un triángulo de ambos planos de color del área de preparación normal.
Sintaxis
void Wire3DCGB_EraseTriangle2D(w3dcgb_u8 ax, w3dcgb_u8 ay, w3dcgb_u8 bx, w3dcgb_u8 by, w3dcgb_u8 cx, w3dcgb_u8 cy);Parámetros
axCoordenada X del vértice A en píxeles de la ventana gráfica.
ayCoordenada Y del vértice A en píxeles de la ventana gráfica.
bxCoordenada X del vértice B en píxeles de la ventana gráfica.
byCoordenada Y del vértice B en píxeles de la ventana gráfica.
cxCoordenada X del vértice C en píxeles de la ventana gráfica.
cyCoordenada Y del vértice C en píxeles de la ventana gráfica.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Borra un triángulo mediante el borrado normal en C del área de preparación. Sus tramos recortados marcan como modificados los tiles afectados; el código que llama o la asignación debe proporcionar el mapeo WRAM de dicha área.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Colored panels expose triangle, span, rectangle and packed-silhouette erasure.
#include "wire_cgb_example.h"
__prg_rom u8 silhouette[5]={0x73,0x74,0xFF,0x75,0x73};
void main() {
u8 y;
u8 bank;
wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
for(y=8;y<=40;y++) Wire3DCGB_DrawLine2DColor(8,y,40,y,1);
for(y=8;y<=40;y++) Wire3DCGB_DrawLine2DColor(48,y,80,y,2);
for(y=64;y<=72;y++) Wire3DCGB_DrawLine2DColor(88,y,120,y,3);
// The C triangle/rectangle clearers access the stage through the current
// WRAM window. Select bank 2 around them and restore the caller's bank.
bank=sample_svbk; sample_svbk=2;
Wire3DCGB_EraseTriangle2D(12,12,36,12,12,36);
Wire3DCGB_EraseSpan2D(36,40,24);
Wire3DCGB_EraseRect2D(56,16,72,32);
Wire3DCGB_ErasePackedSilhouette2D(silhouette,5,-2,104,68);
sample_svbk=bank;
Wire3DCGB_EndFrame(); result[7]=0xA55A;
while(1) {}
}Resultado esperado
Triángulos, tramos horizontales, rectángulos y siluetas empaquetadas abren huecos negros en paneles rellenos de rojo, azul y verde.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_erase.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_erase.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:133
kitaqgb/lib/wire3d_cgb.c:9113
void Wire3DCGB_EraseTriangle2D(w3dcgb_u8 ax, w3dcgb_u8 ay, w3dcgb_u8 bx, w3dcgb_u8 by, w3dcgb_u8 cx, w3dcgb_u8 cy)
{
w3dcgb_clear_triangle(ax, ay, bx, by, cx, cy);
}Wire3DCGB_FastMapBegin
Borra los números de tile y los atributos de la ventana gráfica FastMap de 16×12.
Sintaxis
void Wire3DCGB_FastMapBegin();Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Marca FastMap como preparado y borra los números de tile y los atributos de su ventana gráfica de 16×12. Conserva las columnas 16..31 de la copia de trabajo, aunque el volcado copie 32 columnas por fila. Requiere el entorno de ejecución completo y un mapeo WRAM de FastMap estable; no inicializa el hardware ni transfiere el mapa.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// FastMap uses precomputed outline tiles rather than a pixel stage upload.
#include "wire_cgb_example.h"
void main() {
u8 bank;
wire_results_clear(); Wire3DCGB_InitFastMapLite(); wire_colors();
bank=sample_svbk;sample_svbk=2;
Wire3DCGB_FastMapBegin();
Wire3DCGB_FastMapCell(1,1,1,15); // This first red square must disappear.
Wire3DCGB_FastMapFlush();
Wire3DCGB_FastMapBeginTilesOnly();
Wire3DCGB_FastMapCell(13,1,1,1);
Wire3DCGB_FastMapCell(13,1,1,4); // Same-color top and left sides combine.
Wire3DCGB_FastMapRect(4,2,9,7,2,15);
Wire3DCGB_FastMapCell(2,9,3,15);
Wire3DCGB_FastMapFlushTilesOnly();
sample_svbk=bank;result[7]=0xA55A;
while(1) {}
}Resultado esperado
Una esquina roja, un rectángulo azul grande y un marco verde de un tile ilustran las celdas de contorno. Desaparece la celda roja inicial de la esquina superior izquierda, mientras que la actualización exclusiva de tiles conserva los atributos.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_fastmap.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_fastmap.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:160
kitaqgb/lib/wire3d_cgb.c:10137
void Wire3DCGB_FastMapBegin()
{
w3dcgb_fast_map_ready = 1;
w3dcgb_fast_map_clear_rect(0, 0, 16, 12);
}Wire3DCGB_FastMapBeginTilesOnly
Borra solo los números de tile de la ventana gráfica FastMap de 16×12.
Sintaxis
void Wire3DCGB_FastMapBeginTilesOnly();Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Marca FastMap como preparado y borra solo los números de tile de su ventana gráfica de 16×12. Conserva los atributos y las columnas 16..31. Requiere el entorno de ejecución completo y el mapeo WRAM previsto; la inicialización del hardware y la transferencia se realizan aparte.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// FastMap uses precomputed outline tiles rather than a pixel stage upload.
#include "wire_cgb_example.h"
void main() {
u8 bank;
wire_results_clear(); Wire3DCGB_InitFastMapLite(); wire_colors();
bank=sample_svbk;sample_svbk=2;
Wire3DCGB_FastMapBegin();
Wire3DCGB_FastMapCell(1,1,1,15); // This first red square must disappear.
Wire3DCGB_FastMapFlush();
Wire3DCGB_FastMapBeginTilesOnly();
Wire3DCGB_FastMapCell(13,1,1,1);
Wire3DCGB_FastMapCell(13,1,1,4); // Same-color top and left sides combine.
Wire3DCGB_FastMapRect(4,2,9,7,2,15);
Wire3DCGB_FastMapCell(2,9,3,15);
Wire3DCGB_FastMapFlushTilesOnly();
sample_svbk=bank;result[7]=0xA55A;
while(1) {}
}Resultado esperado
Una esquina roja, un rectángulo azul grande y un marco verde de un tile ilustran las celdas de contorno. Desaparece la celda roja inicial de la esquina superior izquierda, mientras que la actualización exclusiva de tiles conserva los atributos.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_fastmap.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_fastmap.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:161
kitaqgb/lib/wire3d_cgb.c:10146
void Wire3DCGB_FastMapBeginTilesOnly()
{
w3dcgb_fast_map_ready = 1;
w3dcgb_fm_x0 = 0;
w3dcgb_fm_y0 = 0;
w3dcgb_fm_count_x = 16;
w3dcgb_fm_count_y = 12;
w3dcgb_fast_map_clear_rect_asm();
}Wire3DCGB_FastMapCell
Añade a una celda del mapa los lados de contorno elegidos entre arriba, abajo, izquierda y derecha.
Sintaxis
void Wire3DCGB_FastMapCell(w3dcgb_u8 tx, w3dcgb_u8 ty, w3dcgb_u8 color, w3dcgb_u8 mask);Parámetros
txPosición X en coordenadas de tile.
tyPosición Y en coordenadas de tile.
colorÍndice de color de dibujo; las paletas de ejemplo usan 1=rojo, 2=azul y 3=verde.
maskMáscara de lados de celda: 1=arriba, 2=abajo, 4=izquierda, 8=derecha.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Añade lados de contorno a una celda: los bits 1/2/4/8 representan arriba/abajo/izquierda/derecha. Combina las máscaras del mismo color; otro color sustituye la máscara anterior. Ignora una máscara cero; el color cero significa MAIN y los superiores a 3 se limitan a 3. Opera sobre la copia de trabajo de 16×12 con mapeo WRAM estable; requiere el entorno de ejecución completo.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// FastMap uses precomputed outline tiles rather than a pixel stage upload.
#include "wire_cgb_example.h"
void main() {
u8 bank;
wire_results_clear(); Wire3DCGB_InitFastMapLite(); wire_colors();
bank=sample_svbk;sample_svbk=2;
Wire3DCGB_FastMapBegin();
Wire3DCGB_FastMapCell(1,1,1,15); // This first red square must disappear.
Wire3DCGB_FastMapFlush();
Wire3DCGB_FastMapBeginTilesOnly();
Wire3DCGB_FastMapCell(13,1,1,1);
Wire3DCGB_FastMapCell(13,1,1,4); // Same-color top and left sides combine.
Wire3DCGB_FastMapRect(4,2,9,7,2,15);
Wire3DCGB_FastMapCell(2,9,3,15);
Wire3DCGB_FastMapFlushTilesOnly();
sample_svbk=bank;result[7]=0xA55A;
while(1) {}
}Resultado esperado
Una esquina roja, un rectángulo azul grande y un marco verde de un tile ilustran las celdas de contorno. Desaparece la celda roja inicial de la esquina superior izquierda, mientras que la actualización exclusiva de tiles conserva los atributos.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_fastmap.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_fastmap.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:162
kitaqgb/lib/wire3d_cgb.c:10160
void Wire3DCGB_FastMapCell(w3dcgb_u8 tx, w3dcgb_u8 ty, w3dcgb_u8 color, w3dcgb_u8 mask)
{
w3dcgb_fast_map_or_cell((w3dcgb_i16)tx, (w3dcgb_i16)ty, color, mask);
}Wire3DCGB_FastMapFlush
Transfiere a VRAM las primeras doce filas completas de números de tile y atributos de la copia de trabajo.
Sintaxis
void Wire3DCGB_FastMapFlush();Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Si el LCD está encendido, espera a un nuevo VBlank y transfiere las primeras doce filas completas de números de tile y atributos al mapa 9800. Con el LCD apagado, procede inmediatamente. Requiere el entorno de ejecución completo, un mapeo WRAM estable y tiempo seguro suficiente para ambas transferencias GDMA inmediatas.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// FastMap uses precomputed outline tiles rather than a pixel stage upload.
#include "wire_cgb_example.h"
void main() {
u8 bank;
wire_results_clear(); Wire3DCGB_InitFastMapLite(); wire_colors();
bank=sample_svbk;sample_svbk=2;
Wire3DCGB_FastMapBegin();
Wire3DCGB_FastMapCell(1,1,1,15); // This first red square must disappear.
Wire3DCGB_FastMapFlush();
Wire3DCGB_FastMapBeginTilesOnly();
Wire3DCGB_FastMapCell(13,1,1,1);
Wire3DCGB_FastMapCell(13,1,1,4); // Same-color top and left sides combine.
Wire3DCGB_FastMapRect(4,2,9,7,2,15);
Wire3DCGB_FastMapCell(2,9,3,15);
Wire3DCGB_FastMapFlushTilesOnly();
sample_svbk=bank;result[7]=0xA55A;
while(1) {}
}Resultado esperado
Una esquina roja, un rectángulo azul grande y un marco verde de un tile ilustran las celdas de contorno. Desaparece la celda roja inicial de la esquina superior izquierda, mientras que la actualización exclusiva de tiles conserva los atributos.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_fastmap.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_fastmap.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:164
kitaqgb/lib/wire3d_cgb.c:10208
void Wire3DCGB_FastMapFlush()
{
w3dcgb_wait_vblank_start();
w3dcgb_fast_map_flush_gdma_asm();
}Wire3DCGB_FastMapFlushTilesOnly
Transfiere solo los números de tile de las primeras doce filas completas del mapa de trabajo.
Sintaxis
void Wire3DCGB_FastMapFlushTilesOnly();Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Si el LCD está encendido, espera a un nuevo VBlank y transfiere solo los números de tile de las primeras doce filas completas al mapa 9800. Conserva los atributos. Requiere el entorno de ejecución completo, un mapeo WRAM estable y un intervalo seguro para GDMA.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// FastMap uses precomputed outline tiles rather than a pixel stage upload.
#include "wire_cgb_example.h"
void main() {
u8 bank;
wire_results_clear(); Wire3DCGB_InitFastMapLite(); wire_colors();
bank=sample_svbk;sample_svbk=2;
Wire3DCGB_FastMapBegin();
Wire3DCGB_FastMapCell(1,1,1,15); // This first red square must disappear.
Wire3DCGB_FastMapFlush();
Wire3DCGB_FastMapBeginTilesOnly();
Wire3DCGB_FastMapCell(13,1,1,1);
Wire3DCGB_FastMapCell(13,1,1,4); // Same-color top and left sides combine.
Wire3DCGB_FastMapRect(4,2,9,7,2,15);
Wire3DCGB_FastMapCell(2,9,3,15);
Wire3DCGB_FastMapFlushTilesOnly();
sample_svbk=bank;result[7]=0xA55A;
while(1) {}
}Resultado esperado
Una esquina roja, un rectángulo azul grande y un marco verde de un tile ilustran las celdas de contorno. Desaparece la celda roja inicial de la esquina superior izquierda, mientras que la actualización exclusiva de tiles conserva los atributos.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_fastmap.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_fastmap.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:165
kitaqgb/lib/wire3d_cgb.c:10217
void Wire3DCGB_FastMapFlushTilesOnly()
{
w3dcgb_wait_vblank_start();
w3dcgb_fast_map_flush_tiles_gdma_asm();
}Wire3DCGB_FastMapRect
Coloca los lados de contorno elegidos alrededor de un rectángulo en coordenadas de tile.
Sintaxis
void Wire3DCGB_FastMapRect(w3dcgb_u8 tx0, w3dcgb_u8 ty0, w3dcgb_u8 tx1, w3dcgb_u8 ty1, w3dcgb_u8 color, w3dcgb_u8 sides);Parámetros
tx0Posición X en coordenadas de tile.
ty0Posición Y en coordenadas de tile.
tx1Posición X en coordenadas de tile.
ty1Posición Y en coordenadas de tile.
colorÍndice de color de dibujo; las paletas de ejemplo usan 1=rojo, 2=azul y 3=verde.
sidesMáscara de lados del rectángulo: 1=arriba, 2=abajo, 4=izquierda, 8=derecha.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Ordena las coordenadas de tile de tipo byte y las recorta a 16×12; después sustituye las celdas de borde elegidas. Los bits 1/2/4/8 representan arriba/abajo/izquierda/derecha. El color cero significa MAIN; los superiores a 3 se limitan a 3. Conserva los atributos y las celdas interiores. Usa al menos dos filas y dos columnas para tener esquinas distintas; las coincidentes se sobrescriben en secuencia. Requiere el entorno de ejecución completo y un mapeo WRAM estable.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// FastMap uses precomputed outline tiles rather than a pixel stage upload.
#include "wire_cgb_example.h"
void main() {
u8 bank;
wire_results_clear(); Wire3DCGB_InitFastMapLite(); wire_colors();
bank=sample_svbk;sample_svbk=2;
Wire3DCGB_FastMapBegin();
Wire3DCGB_FastMapCell(1,1,1,15); // This first red square must disappear.
Wire3DCGB_FastMapFlush();
Wire3DCGB_FastMapBeginTilesOnly();
Wire3DCGB_FastMapCell(13,1,1,1);
Wire3DCGB_FastMapCell(13,1,1,4); // Same-color top and left sides combine.
Wire3DCGB_FastMapRect(4,2,9,7,2,15);
Wire3DCGB_FastMapCell(2,9,3,15);
Wire3DCGB_FastMapFlushTilesOnly();
sample_svbk=bank;result[7]=0xA55A;
while(1) {}
}Resultado esperado
Una esquina roja, un rectángulo azul grande y un marco verde de un tile ilustran las celdas de contorno. Desaparece la celda roja inicial de la esquina superior izquierda, mientras que la actualización exclusiva de tiles conserva los atributos.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_fastmap.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_fastmap.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:163
kitaqgb/lib/wire3d_cgb.c:10170
void Wire3DCGB_FastMapRect(w3dcgb_u8 tx0, w3dcgb_u8 ty0, w3dcgb_u8 tx1, w3dcgb_u8 ty1, w3dcgb_u8 color, w3dcgb_u8 sides)
{
w3dcgb_u8 t;
if (tx0 > tx1)
{
t = tx0;
tx0 = tx1;
tx1 = t;
}
if (ty0 > ty1)
{
t = ty0;
ty0 = ty1;
ty1 = t;
}
if (tx0 >= 16) return;
if (ty0 >= 12) return;
if (tx1 >= 16) tx1 = 15;
if (ty1 >= 12) ty1 = 11;
if (color == 0) color = WIRE3DCGB_COLOR_MAIN;
if (color > 3) color = 3;
w3dcgb_fm_x0 = tx0;
w3dcgb_fm_y0 = ty0;
w3dcgb_fm_x1 = tx1;
w3dcgb_fm_y1 = ty1;
w3dcgb_fm_count_x = (w3dcgb_u8)(tx1 - tx0 + 1);
w3dcgb_fm_count_y = (w3dcgb_u8)(ty1 - ty0 + 1);
w3dcgb_fm_tile_base = (w3dcgb_u8)(W3DCGB_FAST_TILE_BASE + ((color - 1) << 4));
w3dcgb_fm_sides = (w3dcgb_u8)(sides & 15);
w3dcgb_fast_map_rect_asm();
}Wire3DCGB_GetFullScreenOverflow
Informa de una coordenada inválida o del agotamiento de tiles al dibujar a pantalla completa.
Sintaxis
w3dcgb_u8 Wire3DCGB_GetFullScreenOverflow();Valor devuelto
Cero si no hay fallo; uno tras agotar la asignación o encontrar una coordenada inválida.
Condiciones y límites
Devuelve el indicador de fallo del fotograma de pantalla completa: la ruta de líneas rápidas lo activa si se agota la asignación de tiles o una coordenada es inválida. Una vez activado, suprime los píxeles posteriores de la ruta rápida hasta que BeginFrame lo reinicie. No es un indicador general del hardware; la lectura requiere el entorno de ejecución completo.
La asignación en pantalla completa ocurre antes de que la oclusión o el desbordamiento supriman las escrituras de píxeles. Los tiles asignados pueden seguir negros y dibujar tras un fallo aún puede aumentar su cantidad.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// One point per tile exposes the 127-tile limit without relying on text alone.
#include "wire_cgb_example.h"
void main() {
u8 i;
wire_results_clear();
Wire3DCGB_InitFullScreen(); wire_colors();
Wire3DCGB_BeginFrame(); Wire3DCGB_SetLineColor(3);
for(i=0;i<128;i++) Wire3DCGB_DrawPoint2D((i%20)*8+4,(i/20)*8+4);
result[0]=Wire3DCGB_GetFullScreenTileCount();
result[1]=Wire3DCGB_GetFullScreenOverflow();
Wire3DCGB_EndFrame();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
127 puntos rojos ocupan tiles distintos. Intentar una asignación número 128 mantiene la cantidad en 127 y pone overflow a uno.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_capacity.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_capacity.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:194
kitaqgb/lib/wire3d_cgb.c:9965
w3dcgb_u8 Wire3DCGB_GetFullScreenOverflow()
{
return w3dcgb_full_overflow;
}Wire3DCGB_GetFullScreenTileCount
Devuelve la cantidad de tiles de pantalla completa asignados en el fotograma actual.
Sintaxis
w3dcgb_u8 Wire3DCGB_GetFullScreenTileCount();Valor devuelto
Cantidad de tiles asignados, de 0 a 127.
Condiciones y límites
Devuelve la cantidad actual de asignaciones de pantalla completa, hasta 127. No es una cantidad de bytes ni de píxeles visibles o no nulos. Solo está disponible con el entorno de ejecución completo.
La asignación en pantalla completa ocurre antes de que la oclusión o el desbordamiento supriman las escrituras de píxeles. Los tiles asignados pueden seguir negros y dibujar tras un fallo aún puede aumentar su cantidad.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// One point per tile exposes the 127-tile limit without relying on text alone.
#include "wire_cgb_example.h"
void main() {
u8 i;
wire_results_clear();
Wire3DCGB_InitFullScreen(); wire_colors();
Wire3DCGB_BeginFrame(); Wire3DCGB_SetLineColor(3);
for(i=0;i<128;i++) Wire3DCGB_DrawPoint2D((i%20)*8+4,(i/20)*8+4);
result[0]=Wire3DCGB_GetFullScreenTileCount();
result[1]=Wire3DCGB_GetFullScreenOverflow();
Wire3DCGB_EndFrame();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
127 puntos rojos ocupan tiles distintos. Intentar una asignación número 128 mantiene la cantidad en 127 y pone overflow a uno.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_capacity.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_capacity.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:193
kitaqgb/lib/wire3d_cgb.c:9956
w3dcgb_u8 Wire3DCGB_GetFullScreenTileCount()
{
return w3dcgb_full_tile_count;
}Wire3DCGB_GetLineColor
Lee el índice de color de línea guardado actualmente.
Sintaxis
w3dcgb_u8 Wire3DCGB_GetLineColor();Valor devuelto
Valor del color de línea guardado actualmente.
Condiciones y límites
Devuelve el color de línea de dos bits guardado actualmente, sin cambiar el estado de dibujo.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// CGB raster paths: a red frame, blue diagonal, green marker and clipped line.
// Build this source together with lib/wire3d_cgb.c in an MBC5 256 KB CGB ROM.
#include "wire3d_cgb.h"
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4D) u8 sample_key1;
__location(0xC110) u16 result[8];
__prg_rom u8 lower_lines[8]={80,56,112,56,112,56,112,80};
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3DCGB_EnableDoubleSpeed();
Wire3DCGB_Init(); // Already at double speed: its internal request is a no-op.
result[2]=(u8)(sample_key1&128);
// Palette writes are performed with the LCD off, after entering VBlank.
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0;
Wire3DCGB_SetPaletteRGB15(WIRE3DCGB_RGB15(0,0,0),WIRE3DCGB_RGB15(31,0,0),WIRE3DCGB_RGB15(0,0,31),WIRE3DCGB_RGB15(0,31,0));
sample_lcdc=0x81;
Wire3DCGB_SetScreenOffset(0,0);
Wire3DCGB_SetCamera(0,0,0,0,0,0);
Wire3DCGB_BeginFrame();
Wire3DCGB_SetLineColor(1);
Wire3DCGB_DrawLine2D(8,8,56,8);
Wire3DCGB_DrawLine2D(56,8,56,40);
Wire3DCGB_DrawLine2D(56,40,8,40);
Wire3DCGB_DrawLine2D(8,40,8,8);
Wire3DCGB_DrawLine2DColor(8,40,56,8,2);
result[0]=Wire3DCGB_GetLineColor(); // Temporary blue restores red.
Wire3DCGB_SetLineColor(3);
Wire3DCGB_DrawPoint2D(64,48);
Wire3DCGB_DrawLineClipped2D(-10,72,140,72,3);
Wire3DCGB_DrawLineList2DColor(lower_lines,2,2);
result[1]=Wire3DCGB_GetLineColor(); // The blue line list restores green.
Wire3DCGB_PutBgTile(18,1,0x80); // Queue the supplied zero glyph outside the viewport.
Wire3DCGB_EndFrame();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Este ejemplo muestra líneas, puntos, borrado y proyección básicos en un solo fotograma. Un marco rojo contiene una diagonal azul, un punto y una línea horizontal verdes, una L azul y un cero verde en la esquina superior derecha.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_raster.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:120
kitaqgb/lib/wire3d_cgb.c:1147
w3dcgb_u8 Wire3DCGB_GetLineColor()
{
return w3dcgb_line_color;
}Wire3DCGB_Init
Inicializa el renderizador de píxeles de 128×96 para CGB.
Sintaxis
void Wire3DCGB_Init();Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Inicializa el renderizador exclusivo de CGB de 128×96: activa la doble velocidad, apaga el LCD en VBlank, borra ambos bancos de tiles, carga los tiles del HUD y los generados e instala una ventana gráfica de 16×12 ordenada por columnas. Empieza con el banco de tiles vacío 1, desplazamiento cero, paletas BG predeterminadas, color 2 y cámara a cero. Reinicia las colas y borra el área de preparación del banco 2. Llama a BeginFrame antes de dibujar para inicializar la oclusión. La inicialización sustituye globalmente el estado del LCD, los tiles y el mapa.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Al iniciar sparse en CGB, el primer uso de cada banco de destino (los dos primeros fotogramas) actualiza toda la vista y elimina los mosaicos de inicialización. La medición incluye ese coste. DrawLine2D no registra regiones sparse: use DrawLineClipped2D o llame explícitamente a MarkDirtyRect2D.
Ejemplo de uso
#pragma bank 0
// CGB raster paths: a red frame, blue diagonal, green marker and clipped line.
// Build this source together with lib/wire3d_cgb.c in an MBC5 256 KB CGB ROM.
#include "wire3d_cgb.h"
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4D) u8 sample_key1;
__location(0xC110) u16 result[8];
__prg_rom u8 lower_lines[8]={80,56,112,56,112,56,112,80};
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3DCGB_EnableDoubleSpeed();
Wire3DCGB_Init(); // Already at double speed: its internal request is a no-op.
result[2]=(u8)(sample_key1&128);
// Palette writes are performed with the LCD off, after entering VBlank.
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0;
Wire3DCGB_SetPaletteRGB15(WIRE3DCGB_RGB15(0,0,0),WIRE3DCGB_RGB15(31,0,0),WIRE3DCGB_RGB15(0,0,31),WIRE3DCGB_RGB15(0,31,0));
sample_lcdc=0x81;
Wire3DCGB_SetScreenOffset(0,0);
Wire3DCGB_SetCamera(0,0,0,0,0,0);
Wire3DCGB_BeginFrame();
Wire3DCGB_SetLineColor(1);
Wire3DCGB_DrawLine2D(8,8,56,8);
Wire3DCGB_DrawLine2D(56,8,56,40);
Wire3DCGB_DrawLine2D(56,40,8,40);
Wire3DCGB_DrawLine2D(8,40,8,8);
Wire3DCGB_DrawLine2DColor(8,40,56,8,2);
result[0]=Wire3DCGB_GetLineColor(); // Temporary blue restores red.
Wire3DCGB_SetLineColor(3);
Wire3DCGB_DrawPoint2D(64,48);
Wire3DCGB_DrawLineClipped2D(-10,72,140,72,3);
Wire3DCGB_DrawLineList2DColor(lower_lines,2,2);
result[1]=Wire3DCGB_GetLineColor(); // The blue line list restores green.
Wire3DCGB_PutBgTile(18,1,0x80); // Queue the supplied zero glyph outside the viewport.
Wire3DCGB_EndFrame();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Este ejemplo muestra líneas, puntos, borrado y proyección básicos en un solo fotograma. Un marco rojo contiene una diagonal azul, un punto y una línea horizontal verdes, una L azul y un cero verde en la esquina superior derecha.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_raster.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:113
kitaqgb/lib/wire3d_cgb.c:7994
void Wire3DCGB_Init()
{
w3dcgb_u8 row;
w3dcgb_u8 col;
w3dcgb_u8 tid;
w3dcgb_u8 tile_index;
w3dcgb_u16 off;
w3dcgb_full_mode = 0;
w3dcgb_atomic_maps = 0;
Wire3DCGB_EnableDoubleSpeed();
w3dcgb_wait_vblank_start();
w3dcgb_reg_lcdc = 0;
w3dcgb_clear_vram_asm();
w3dcgb_load_hud_tiles();
#ifndef WIRE3DCGB_MINIMAL_RUNTIME
w3dcgb_load_fast_map_tiles();
w3dcgb_load_fast_stamp_tiles();
#endif
w3dcgb_fill_bg_map_asm();
w3dcgb_fill_attr_map_asm();
row = 0;
while (row < W3DCGB_TILE_H)
{
off = (w3dcgb_u16)((w3dcgb_u16)row << 5);
tile_index = row;
col = 0;
while (col < W3DCGB_TILE_W)
{
if (tile_index < 112) tid = (w3dcgb_u8)(0x90 + tile_index);
else tid = (w3dcgb_u8)(tile_index - 112);
w3dcgb_bg_map_9800[(w3dcgb_u16)(off + (w3dcgb_u16)col)] = tid;
tile_index = (w3dcgb_u8)(tile_index + W3DCGB_TILE_H);
col = (w3dcgb_u8)(col + 1);
}
row = (w3dcgb_u8)(row + 1);
}
w3dcgb_select_blank_render_bank_asm();
w3dcgb_reg_scx = 0;
w3dcgb_reg_scy = 0;
w3dcgb_reg_bgp = 0xB4;
Wire3DCGB_SetPaletteRGB15(
WIRE3DCGB_RGB15(0, 0, 2),
WIRE3DCGB_RGB15(10, 20, 31),
WIRE3DCGB_RGB15(31, 31, 31),
WIRE3DCGB_RGB15(31, 14, 4));
w3dcgb_line_color = WIRE3DCGB_COLOR_DEFAULT;
w3dcgb_reg_lcdc = 0x81;
w3dcgb_bgq_count = 0;
w3dcgb_dirty_count = 0;
w3dcgb_prev_dirty_count = 0;
w3dcgb_dirty_min_tile = 0xFF;
w3dcgb_dirty_max_tile = 0;
// Both back banks may contain generated fast-map/stamp tiles. Refresh
// the whole pixel viewport on their first sparse use, including empty rows.
w3dcgb_prev_dirty_min_tile = 0;
w3dcgb_prev_dirty_max_tile = (w3dcgb_u8)(WIRE3DCGB_TILE_COUNT - 1);
w3dcgb_older_dirty_min_tile = 0;
w3dcgb_older_dirty_max_tile = (w3dcgb_u8)(WIRE3DCGB_TILE_COUNT - 1);
w3dcgb_display_tile_bank = 1;
w3dcgb_pending_tile_bank = 1;
Wire3DCGB_SetCamera((w3dcgb_i16)0, (w3dcgb_i16)0, (w3dcgb_i16)0, 0, 0, 0);
w3dcgb_clear_stage_asm();
}Wire3DCGB_InitFastMapLite
Inicializa el renderizado FastMap con tiles de contorno precalculados.
Sintaxis
void Wire3DCGB_InitFastMapLite();Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Inicializa un renderizador de mapas de tiles para CGB con HUD y 48 tiles de contorno precalculados. Borra la VRAM de tiles y los mapas, reinicia desplazamiento, paletas y cámara y selecciona el modo normal. Omite la disposición del mapa para la ventana gráfica habitual de píxeles y los patrones de cubo generados; usa las API FastMap en este modo. Borra el área de preparación del banco 2 y marca como pendiente la preparación del mapa rápido. Requiere compilar con el entorno de ejecución completo.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// FastMap uses precomputed outline tiles rather than a pixel stage upload.
#include "wire_cgb_example.h"
void main() {
u8 bank;
wire_results_clear(); Wire3DCGB_InitFastMapLite(); wire_colors();
bank=sample_svbk;sample_svbk=2;
Wire3DCGB_FastMapBegin();
Wire3DCGB_FastMapCell(1,1,1,15); // This first red square must disappear.
Wire3DCGB_FastMapFlush();
Wire3DCGB_FastMapBeginTilesOnly();
Wire3DCGB_FastMapCell(13,1,1,1);
Wire3DCGB_FastMapCell(13,1,1,4); // Same-color top and left sides combine.
Wire3DCGB_FastMapRect(4,2,9,7,2,15);
Wire3DCGB_FastMapCell(2,9,3,15);
Wire3DCGB_FastMapFlushTilesOnly();
sample_svbk=bank;result[7]=0xA55A;
while(1) {}
}Resultado esperado
Una esquina roja, un rectángulo azul grande y un marco verde de un tile ilustran las celdas de contorno. Desaparece la celda roja inicial de la esquina superior izquierda, mientras que la actualización exclusiva de tiles conserva los atributos.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_fastmap.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_fastmap.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:115
kitaqgb/lib/wire3d_cgb.c:8108
void Wire3DCGB_InitFastMapLite()
{
w3dcgb_atomic_maps = 0;
w3dcgb_full_mode = 0;
Wire3DCGB_EnableDoubleSpeed();
w3dcgb_wait_vblank_start();
w3dcgb_reg_lcdc = 0;
w3dcgb_clear_vram_asm();
w3dcgb_load_hud_tiles();
w3dcgb_load_fast_map_tiles_lite_asm();
w3dcgb_fill_bg_map_asm();
w3dcgb_fill_attr_map_asm();
w3dcgb_reg_scx = 0;
w3dcgb_reg_scy = 0;
w3dcgb_reg_bgp = 0xB4;
Wire3DCGB_SetPaletteRGB15(
WIRE3DCGB_RGB15(0, 0, 2),
WIRE3DCGB_RGB15(10, 20, 31),
WIRE3DCGB_RGB15(31, 31, 31),
WIRE3DCGB_RGB15(31, 14, 4));
w3dcgb_line_color = WIRE3DCGB_COLOR_DEFAULT;
w3dcgb_reg_lcdc = 0x81;
w3dcgb_bgq_count = 0;
w3dcgb_dirty_count = 0;
w3dcgb_prev_dirty_count = 0;
w3dcgb_dirty_min_tile = 0xFF;
w3dcgb_dirty_max_tile = 0;
w3dcgb_prev_dirty_min_tile = 0xFF;
w3dcgb_prev_dirty_max_tile = 0;
w3dcgb_fast_map_ready = 0;
w3dcgb_display_tile_bank = 0;
w3dcgb_pending_tile_bank = 0;
Wire3DCGB_SetCamera((w3dcgb_i16)0, (w3dcgb_i16)0, (w3dcgb_i16)0, 0, 0, 0);
w3dcgb_clear_stage_asm();
}Wire3DCGB_InitFullScreen
Inicializa un renderizador de 160×144 que asigna tiles a medida que dibuja píxeles.
Sintaxis
void Wire3DCGB_InitFullScreen();Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Inicializa el asignador de tiles exclusivo de CGB de 160×144. Borra ambos bancos de tiles y el mapa 9800, configura desplazamiento, paletas, color y cámara, reinicia los contadores de tiles y el estado de búsqueda y tramos y activa el direccionamiento BG sin signo. No carga tiles del HUD. Reserva sus áreas fijas de WRAM para tablas, datos y listas de direcciones y mantén mapeado el mismo banco de WRAM durante todo el renderizado a pantalla completa.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// A large frame demonstrates the 160x144 renderer and its allocated-tile count.
#include "wire_cgb_example.h"
void main() {
wire_results_clear();
Wire3DCGB_InitFullScreen(); wire_colors();
Wire3DCGB_BeginFrame();
Wire3DCGB_SetLineColor(1);
Wire3DCGB_DrawLine2D(8,8,151,8);
Wire3DCGB_DrawLine2D(8,8,8,135);
Wire3DCGB_DrawLine2DColor(8,135,151,135,2);
Wire3DCGB_DrawLine2DColor(151,8,151,135,3);
result[0]=Wire3DCGB_GetFullScreenTileCount();
result[1]=Wire3DCGB_GetFullScreenOverflow();
Wire3DCGB_EndFrameFast();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Un marco grande abarca (8,8)..(151,135): arriba e izquierda en rojo, abajo en azul y derecha en verde. Usa 64 tiles, con overflow a cero.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_full.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_full.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:114
kitaqgb/lib/wire3d_cgb.c:8070
void Wire3DCGB_InitFullScreen()
{
w3dcgb_atomic_maps = 0;
Wire3DCGB_EnableDoubleSpeed();
w3dcgb_wait_vblank_start();
w3dcgb_reg_lcdc = 0;
w3dcgb_clear_vram_asm();
w3dcgb_full_clear_map_asm();
w3dcgb_reg_scx = 0;
w3dcgb_reg_scy = 0;
w3dcgb_reg_bgp = 0xB4;
Wire3DCGB_SetPaletteRGB15(
WIRE3DCGB_RGB15(0, 0, 2),
WIRE3DCGB_RGB15(10, 20, 31),
WIRE3DCGB_RGB15(31, 31, 31),
WIRE3DCGB_RGB15(31, 14, 4));
w3dcgb_line_color = WIRE3DCGB_COLOR_DEFAULT;
w3dcgb_bgq_count = 0;
w3dcgb_dirty_count = 0;
w3dcgb_prev_dirty_count = 0;
w3dcgb_display_tile_bank = 0;
w3dcgb_pending_tile_bank = 0;
w3dcgb_full_tile_count = 0;
w3dcgb_full_prev_tile_count = 0;
w3dcgb_full_overflow = 0;
w3dcgb_full_mode = 1;
Wire3DCGB_SetCamera((w3dcgb_i16)0, (w3dcgb_i16)0, (w3dcgb_i16)0, 0, 0, 0);
w3dcgb_full_begin_asm();
w3dcgb_reg_lcdc = 0x91;
}Wire3DCGB_InvalidateFrameHistory
Amplía el rango de transferencia actual y los dos anteriores a los 192 tiles del modo normal.
Sintaxis
void Wire3DCGB_InvalidateFrameHistory();Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Amplía el rango parcial actual y los dos anteriores a los 192 tiles del modo normal. No borra los píxeles; las transferencias posteriores no pueden confiar en los rangos antiguos.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Al iniciar sparse en CGB, el primer uso de cada banco de destino (los dos primeros fotogramas) actualiza toda la vista y elimina los mosaicos de inicialización. La medición incluye ese coste. DrawLine2D no registra regiones sparse: use DrawLineClipped2D o llame explícitamente a MarkDirtyRect2D.
Ejemplo de uso
#pragma bank 0
// Reuse both VRAM banks and remove old geometry while presenting sparse frames.
#include "wire_cgb_example.h"
void main() {
wire_results_clear(); Wire3DCGB_Init();
Wire3DCGB_ClearFrameTiles();
Wire3DCGB_EnableAtomicMaps(); wire_colors();
// First frame: red on the left. Fast begin invalidates both bank histories.
Wire3DCGB_BeginFrameFast(); wire_frame(8,8,32,32,1);
Wire3DCGB_EndFrameFast();
// Second frame: blue in the middle, with the old red frame removed.
Wire3DCGB_BeginFrameSparse(); wire_frame(40,40,64,64,2);
Wire3DCGB_EndFrameSparse();
// Third frame: explicitly clearing a stage discards its first green point.
Wire3DCGB_BeginFrameSparse();
Wire3DCGB_SetLineColor(3); Wire3DCGB_DrawPoint2D(4,4);
Wire3DCGB_ClearSparseStageFast();
// The final image contains only this green frame on the right.
wire_frame(80,8,112,32,3);
Wire3DCGB_MarkDirtyRect2D(80,8,112,32);
Wire3DCGB_InvalidateFrameHistory();
Wire3DCGB_EndFrameSparseNow();
result[0]=Wire3DCGB_GetLineColor();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Desaparecen los marcos rojo y azul dibujados antes y solo queda el marco verde final en (80,8)..(112,32), mostrando la transferencia parcial y la gestión del historial.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_sparse.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_sparse.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:142
kitaqgb/lib/wire3d_cgb.c:9712
void Wire3DCGB_InvalidateFrameHistory()
{
w3dcgb_dirty_min_tile = 0;
w3dcgb_dirty_max_tile = (w3dcgb_u8)(WIRE3DCGB_TILE_COUNT - 1);
w3dcgb_prev_dirty_min_tile = 0;
w3dcgb_prev_dirty_max_tile = (w3dcgb_u8)(WIRE3DCGB_TILE_COUNT - 1);
w3dcgb_older_dirty_min_tile = 0;
w3dcgb_older_dirty_max_tile = (w3dcgb_u8)(WIRE3DCGB_TILE_COUNT - 1);
}Wire3DCGB_MarkDirtyRect2D
Añade un rectángulo de píxeles al rango que habrá que transferir después.
Sintaxis
void Wire3DCGB_MarkDirtyRect2D(w3dcgb_u8 min_x, w3dcgb_u8 min_y, w3dcgb_u8 max_x, w3dcgb_u8 max_y);Parámetros
min_xExtremo X inferior, en píxeles de la ventana gráfica; el orden y el recorte siguen las notas de esta operación.
min_yExtremo Y inferior, en píxeles de la ventana gráfica; el orden y el recorte siguen las notas de esta operación.
max_xExtremo X superior, en píxeles de la ventana gráfica; el orden y el recorte siguen las notas de esta operación.
max_yExtremo X superior, en píxeles de la ventana gráfica; el orden y el recorte siguen las notas de esta operación.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Marca un rectángulo de píxeles, con extremos incluidos, para transferirlo después sin dibujarlo. Proporciona los extremos en orden; los valores superiores a 127/95 se limitan al borde. Hace seguimiento de los tiles de 128×96, no del asignador de pantalla completa.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Reuse both VRAM banks and remove old geometry while presenting sparse frames.
#include "wire_cgb_example.h"
void main() {
wire_results_clear(); Wire3DCGB_Init();
Wire3DCGB_ClearFrameTiles();
Wire3DCGB_EnableAtomicMaps(); wire_colors();
// First frame: red on the left. Fast begin invalidates both bank histories.
Wire3DCGB_BeginFrameFast(); wire_frame(8,8,32,32,1);
Wire3DCGB_EndFrameFast();
// Second frame: blue in the middle, with the old red frame removed.
Wire3DCGB_BeginFrameSparse(); wire_frame(40,40,64,64,2);
Wire3DCGB_EndFrameSparse();
// Third frame: explicitly clearing a stage discards its first green point.
Wire3DCGB_BeginFrameSparse();
Wire3DCGB_SetLineColor(3); Wire3DCGB_DrawPoint2D(4,4);
Wire3DCGB_ClearSparseStageFast();
// The final image contains only this green frame on the right.
wire_frame(80,8,112,32,3);
Wire3DCGB_MarkDirtyRect2D(80,8,112,32);
Wire3DCGB_InvalidateFrameHistory();
Wire3DCGB_EndFrameSparseNow();
result[0]=Wire3DCGB_GetLineColor();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Desaparecen los marcos rojo y azul dibujados antes y solo queda el marco verde final en (80,8)..(112,32), mostrando la transferencia parcial y la gestión del historial.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_sparse.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_sparse.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:126
kitaqgb/lib/wire3d_cgb.c:1288
void Wire3DCGB_MarkDirtyRect2D(w3dcgb_u8 min_x, w3dcgb_u8 min_y, w3dcgb_u8 max_x, w3dcgb_u8 max_y)
{
w3dcgb_mark_dirty_rect(min_x, min_y, max_x, max_y);
}Wire3DCGB_MarkPackedSilhouette2D
Marca una silueta empaquetada por filas en el mapa de bits de oclusión de 128×96.
Sintaxis
void Wire3DCGB_MarkPackedSilhouette2D(const w3dcgb_u8* profile, w3dcgb_u8 count, w3dcgb_i8 y0, w3dcgb_u8 x, w3dcgb_u8 y);Parámetros
profileArray de silueta de un byte por fila; 0xFF omite una fila.
countCantidad de entradas proporcionadas; consulta el límite de procesamiento de cada operación.
y0Desplazamiento con signo desde el centro Y hasta la primera fila de la silueta.
xCoordenada X del centro en píxeles de la ventana gráfica.
yCoordenada Y del centro en píxeles de la ventana gráfica.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Marca hasta 29 filas de silueta en la máscara de mapa de bits de 128×96. El nibble alto de cada byte empaquetado indica el desplazamiento del centro (nibble−7) y el bajo, la semianchura; 0xFF omite una fila. Coloca las filas en y+y0+i, amplía los tramos dos píxeles y los recorta a la ventana gráfica. profile debe contener count bytes legibles; null se ignora. No actualiza los tramos de pantalla completa ni activa la oclusión.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Red/blue scanlines stop inside masks; green outlines identify the triangle.
#include "wire_cgb_example.h"
__prg_rom u8 silhouette[5]={0x73,0x74,0xFF,0x75,0x73};
void main() {
u8 y;
wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
// Clearing this first test mask must leave the upper-left scanline intact.
Wire3DCGB_MarkTriangle2D(8,8,16,8,8,16);
Wire3DCGB_ClearOcclusionMask();
Wire3DCGB_MarkTriangle2D(32,16,64,16,32,48);
Wire3DCGB_MarkPackedSilhouette2D(silhouette,5,-2,104,32);
Wire3DCGB_SetOcclusionActive(1);
for(y=8;y<=56;y=y+4) Wire3DCGB_DrawLine2DColor(8,y,88,y,1);
for(y=28;y<=36;y++) Wire3DCGB_DrawLine2DColor(92,y,120,y,2);
Wire3DCGB_SetOcclusionActive(0);
Wire3DCGB_DrawLine2DColor(32,16,64,16,3);
Wire3DCGB_DrawLine2DColor(64,16,32,48,3);
Wire3DCGB_DrawLine2DColor(32,48,32,16,3);
Wire3DCGB_EndFrame(); result[7]=0xA55A;
while(1) {}
}Resultado esperado
Un triángulo oculta la parte central de las líneas de barrido rojas; una silueta empaquetada oculta las líneas azules. Los contornos verdes señalan la zona que produce la oclusión.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_mask.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_mask.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:151
kitaqgb/lib/wire3d_cgb.c:1991
void Wire3DCGB_MarkPackedSilhouette2D(const w3dcgb_u8* profile, w3dcgb_u8 count,
w3dcgb_i8 y0, w3dcgb_u8 x, w3dcgb_u8 y)
{
w3dcgb_u8 i;
w3dcgb_u8 packed;
w3dcgb_u8 half_width;
w3dcgb_i16 center;
w3dcgb_i16 left;
w3dcgb_i16 right;
w3dcgb_i16 row;
if (profile == 0) return;
if (count > 29) count = 29;
i = 0;
while (i < count)
{
packed = profile[(__safe_index w3dcgb_u8)i];
if (packed != 0xFF)
{
row = (w3dcgb_i16)((w3dcgb_i16)y + (w3dcgb_i16)y0 + (w3dcgb_i16)i);
if ((row >= 0) && (row < WIRE3DCGB_SCREEN_H))
{
center = (w3dcgb_i16)((w3dcgb_i16)x + (w3dcgb_i16)(packed >> 4) - 7);
half_width = (w3dcgb_u8)(packed & 15);
/* Two-pixel guard covers rasterized endpoints at 22.5-degree views. */
left = (w3dcgb_i16)(center - (w3dcgb_i16)half_width - 2);
right = (w3dcgb_i16)(center + (w3dcgb_i16)half_width + 2);
if ((right >= 0) && (left < WIRE3DCGB_SCREEN_W))
{
if (left < 0) left = 0;
if (right >= WIRE3DCGB_SCREEN_W) right = WIRE3DCGB_SCREEN_W - 1;
w3dcgb_mask_span_y = (w3dcgb_u8)row;
w3dcgb_mask_span_min_x = (w3dcgb_u8)left;
w3dcgb_mask_span_max_x = (w3dcgb_u8)right;
w3dcgb_mask_set_span_asm();
}
}
}
i = (w3dcgb_u8)(i + 1);
}
}Wire3DCGB_MarkTriangle2D
Registra un triángulo como zona que puede ocultar las líneas dibujadas después.
Sintaxis
void Wire3DCGB_MarkTriangle2D(w3dcgb_u8 ax, w3dcgb_u8 ay, w3dcgb_u8 bx, w3dcgb_u8 by, w3dcgb_u8 cx, w3dcgb_u8 cy);Parámetros
axCoordenada X del vértice A en píxeles de la ventana gráfica.
ayCoordenada Y del vértice A en píxeles de la ventana gráfica.
bxCoordenada X del vértice B en píxeles de la ventana gráfica.
byCoordenada Y del vértice B en píxeles de la ventana gráfica.
cxCoordenada X del vértice C en píxeles de la ventana gráfica.
cyCoordenada Y del vértice C en píxeles de la ventana gráfica.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Marca un triángulo en coordenadas de pantalla sin dibujar píxeles ni activar la oclusión. Los vértices deben estar dentro de la ventana gráfica seleccionada. El ASM usado añade un margen de un píxel en X, limitado a 0..127 en modo 128×96 o a 0..159 en modo 160×144. Esta función no recorta triángulos arbitrarios que salgan de los límites.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Red/blue scanlines stop inside masks; green outlines identify the triangle.
#include "wire_cgb_example.h"
__prg_rom u8 silhouette[5]={0x73,0x74,0xFF,0x75,0x73};
void main() {
u8 y;
wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
// Clearing this first test mask must leave the upper-left scanline intact.
Wire3DCGB_MarkTriangle2D(8,8,16,8,8,16);
Wire3DCGB_ClearOcclusionMask();
Wire3DCGB_MarkTriangle2D(32,16,64,16,32,48);
Wire3DCGB_MarkPackedSilhouette2D(silhouette,5,-2,104,32);
Wire3DCGB_SetOcclusionActive(1);
for(y=8;y<=56;y=y+4) Wire3DCGB_DrawLine2DColor(8,y,88,y,1);
for(y=28;y<=36;y++) Wire3DCGB_DrawLine2DColor(92,y,120,y,2);
Wire3DCGB_SetOcclusionActive(0);
Wire3DCGB_DrawLine2DColor(32,16,64,16,3);
Wire3DCGB_DrawLine2DColor(64,16,32,48,3);
Wire3DCGB_DrawLine2DColor(32,48,32,16,3);
Wire3DCGB_EndFrame(); result[7]=0xA55A;
while(1) {}
}Resultado esperado
Un triángulo oculta la parte central de las líneas de barrido rojas; una silueta empaquetada oculta las líneas azules. Los contornos verdes señalan la zona que produce la oclusión.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_mask.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_mask.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:150
kitaqgb/lib/wire3d_cgb.c:1980
void Wire3DCGB_MarkTriangle2D(w3dcgb_u8 ax, w3dcgb_u8 ay, w3dcgb_u8 bx, w3dcgb_u8 by, w3dcgb_u8 cx, w3dcgb_u8 cy)
{
w3dcgb_mark_triangle(ax, ay, bx, by, cx, cy);
}Wire3DCGB_ProjectAxis48
Aproxima un desplazamiento proyectado con una distancia focal de 48.
Sintaxis
w3dcgb_i16 Wire3DCGB_ProjectAxis48(w3dcgb_i16 value, w3dcgb_i16 z);Parámetros
valueComponente de 16 bits con signo que se va a proyectar.
zProfundidad usada para elegir el tamaño o calcular la proyección.
Valor devuelto
Desplazamiento proyectado aproximado de 16 bits con signo.
Condiciones y límites
Aproxima value*48/z sin cámara ni desplazamiento del centro de pantalla. Un Z negativo o muy pequeño pasa a ser 4. Si Z supera 255, desplaza a la derecha la profundidad y la magnitud juntas hasta que la profundidad quepa en un byte; después limita la magnitud a 160. Devuelve un desplazamiento con signo; esta función no rechaza profundidades cercanas ni lejanas.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Preprojected edge arrays, a clipped square, a tiny marker and a projectile.
#include "wire_cgb_example.h"
__prg_rom Wire3DCGB_Edge edges[4]={{0,1},{1,2},{2,3},{3,0}};
__prg_rom s8 vx8[4]={-8,8,8,-8};
__prg_rom s8 vy8[4]={-8,-8,8,8};
__prg_rom s16 vx16[4]={-12,12,12,-12};
__prg_rom s16 vy16[4]={-8,-8,8,8};
__prg_rom u8 mask[1]={5};
Wire3DCGB_Model shape;
void main() {
wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
shape.vertices=0;shape.edges=edges;shape.faces=0;shape.edge_faces=0;
shape.vertex_count=4;shape.edge_count=4;shape.face_count=0;shape.flags=0;
Wire3DCGB_SetLineColor(2);
Wire3DCGB_DrawMaskedModel2D(&shape,vx8,vy8,mask,24,24,1);
Wire3DCGB_DrawEdgeList2D(edges,4,vx8,vy8,64,24,2);
Wire3DCGB_DrawEdgeListClipped2D(edges,4,vx16,vy16,4,4,64,3);
Wire3DCGB_DrawTinyModel2D(104,24,16,3);
result[0]=Wire3DCGB_ProjectAxis48(48,96);
result[1]=Wire3DCGB_ProjectAxis48(-48,96);
Wire3DCGB_DrawFastProjectile(96,64,64,0,1);
result[2]=Wire3DCGB_GetLineColor();
Wire3DCGB_EndFrame();result[7]=0xA55A;
while(1) {}
}Resultado esperado
Dos aristas horizontales rojas, un cuadrado azul, un marco verde recortado, un marcador verde de seis píxeles y un proyectil rojo permiten comparar los formatos de lista.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_lists.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_lists.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:141
kitaqgb/lib/wire3d_cgb.c:9702
w3dcgb_i16 Wire3DCGB_ProjectAxis48(w3dcgb_i16 value, w3dcgb_i16 z)
{
w3dcgb_projection_value = value;
w3dcgb_projection_z = z;
w3dcgb_project_axis48_asm();
return w3dcgb_projection_result;
}Wire3DCGB_ProjectPoint
Proyecta un punto del mundo mediante la cámara a la ventana gráfica de 128×96.
Sintaxis
w3dcgb_u8 Wire3DCGB_ProjectPoint(w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_u8* sx, w3dcgb_u8* sy);Parámetros
xComponente X del punto o del origen del objeto en coordenadas del mundo.
yComponente Y del punto o del origen del objeto en coordenadas del mundo.
zComponente Z del punto o del origen del objeto en coordenadas del mundo.
sxPuntero u8 válido y escribible que recibe la coordenada X proyectada.
syPuntero u8 válido y escribible que recibe la coordenada Y proyectada.
Valor devuelto
Devuelve 1 si la proyección tiene éxito o 0 si se rechaza por profundidad.
Condiciones y límites
Proyecta un punto del mundo mediante la cámara actual a la ventana gráfica de 128×96. Si se rechaza por profundidad, devuelve cero sin cambiar las salidas; si no, escribe coordenadas de tipo byte limitadas a la ventana gráfica. Requiere punteros válidos y escribibles. No es el proyector de pantalla completa de 160×144. No se incluye en compilaciones MINIMAL_RUNTIME.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Four cubes compare unity/half scale and persistent/temporary line colors.
#include "wire_cgb_example.h"
__prg_rom Wire3DCGB_Vec3 vertices[8]={
{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},
{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}
};
__prg_rom Wire3DCGB_Edge edges[12]={
{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},
{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}
};
Wire3DCGB_Model cube;
u8 sx;
u8 sy;
void main() {
wire_results_clear();
cube.vertices=vertices; cube.edges=edges;
cube.faces=0; cube.edge_faces=0;
cube.vertex_count=8; cube.edge_count=12; cube.face_count=0; cube.flags=0;
Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
Wire3DCGB_SetLineColor(1);
Wire3DCGB_DrawModel(&cube,-32,32,96,0,0,0);
Wire3DCGB_DrawModelScaled(&cube,32,32,96,0,0,0,128);
Wire3DCGB_DrawModelColor(&cube,-32,-32,96,0,0,0,2);
Wire3DCGB_DrawModelScaledColor(&cube,32,-32,96,0,0,0,128,3);
result[0]=Wire3DCGB_GetLineColor();
Wire3DCGB_DrawLine3D(0,56,96,0,-56,96);
Wire3DCGB_DrawLine3DColor(-80,0,96,80,0,96,3);
result[1]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
result[2]=sx; result[3]=sy;
// Camera setters affect future projection, leaving the staged cubes intact.
Wire3DCGB_SetCamera(0,0,0,0,4,0);
result[4]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
result[5]=Wire3DCGB_ProjectPointNoRotation(0,0,96,&sx,&sy);
result[6]=sx;
Wire3DCGB_EndFrame(); result[7]=0xA55A;
while(1) {}
}Resultado esperado
Compara modelos a escala unitaria y redimensionados en rojo, azul y verde, además de líneas 3D que se cruzan. Los valores de RAM también comprueban la proyección de cámara y su variante sin rotación.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_models.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:169
kitaqgb/lib/wire3d_cgb.c:589
w3dcgb_u8 Wire3DCGB_ProjectPoint(w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_u8* sx, w3dcgb_u8* sy)
{
return w3dcgb_project_world(x, y, z, sx, sy);
}Wire3DCGB_ProjectPointNoRotation
Proyecta un punto tras restar la posición de cámara, sin rotación de cámara.
Sintaxis
w3dcgb_u8 Wire3DCGB_ProjectPointNoRotation(w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_u8* sx, w3dcgb_u8* sy);Parámetros
xComponente X del punto o del origen del objeto en coordenadas del mundo.
yComponente Y del punto o del origen del objeto en coordenadas del mundo.
zComponente Z del punto o del origen del objeto en coordenadas del mundo.
sxPuntero u8 válido y escribible que recibe la coordenada X proyectada.
syPuntero u8 válido y escribible que recibe la coordenada Y proyectada.
Valor devuelto
Devuelve 1 si la proyección tiene éxito o 0 si se rechaza por profundidad.
Condiciones y límites
Ruta rápida para juegos en los que cabeceo, guiñada y alabeo de la cámara permanecen a cero. Resta la posición de cámara y proyecta a 128×96 ignorando todos sus ángulos. Úsala cuando los tres ángulos sean cero. Rechaza profundidades inválidas sin cambiar los valores apuntados por las salidas; las coordenadas válidas se limitan a la ventana gráfica. No se incluye en compilaciones MINIMAL_RUNTIME.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Four cubes compare unity/half scale and persistent/temporary line colors.
#include "wire_cgb_example.h"
__prg_rom Wire3DCGB_Vec3 vertices[8]={
{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},
{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}
};
__prg_rom Wire3DCGB_Edge edges[12]={
{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},
{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}
};
Wire3DCGB_Model cube;
u8 sx;
u8 sy;
void main() {
wire_results_clear();
cube.vertices=vertices; cube.edges=edges;
cube.faces=0; cube.edge_faces=0;
cube.vertex_count=8; cube.edge_count=12; cube.face_count=0; cube.flags=0;
Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
Wire3DCGB_SetLineColor(1);
Wire3DCGB_DrawModel(&cube,-32,32,96,0,0,0);
Wire3DCGB_DrawModelScaled(&cube,32,32,96,0,0,0,128);
Wire3DCGB_DrawModelColor(&cube,-32,-32,96,0,0,0,2);
Wire3DCGB_DrawModelScaledColor(&cube,32,-32,96,0,0,0,128,3);
result[0]=Wire3DCGB_GetLineColor();
Wire3DCGB_DrawLine3D(0,56,96,0,-56,96);
Wire3DCGB_DrawLine3DColor(-80,0,96,80,0,96,3);
result[1]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
result[2]=sx; result[3]=sy;
// Camera setters affect future projection, leaving the staged cubes intact.
Wire3DCGB_SetCamera(0,0,0,0,4,0);
result[4]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
result[5]=Wire3DCGB_ProjectPointNoRotation(0,0,96,&sx,&sy);
result[6]=sx;
Wire3DCGB_EndFrame(); result[7]=0xA55A;
while(1) {}
}Resultado esperado
Compara modelos a escala unitaria y redimensionados en rojo, azul y verde, además de líneas 3D que se cruzan. Los valores de RAM también comprueban la proyección de cámara y su variante sin rotación.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_models.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:171
Fast path for games whose camera pitch, yaw, and roll stay at zero.
kitaqgb/lib/wire3d_cgb.c:598
w3dcgb_u8 Wire3DCGB_ProjectPointNoRotation(w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z,
w3dcgb_u8* sx, w3dcgb_u8* sy)
{
return w3dcgb_project_camera_space((w3dcgb_i16)(x - w3dcgb_cam_x),
(w3dcgb_i16)(y - w3dcgb_cam_y),
(w3dcgb_i16)(z - w3dcgb_cam_z), sx, sy);
}Wire3DCGB_PutBgTile
Encola un cambio de número de tile del fondo para EndFrame.
Sintaxis
void Wire3DCGB_PutBgTile(w3dcgb_u8 x, w3dcgb_u8 y, w3dcgb_u8 tile);Parámetros
xCoordenada X de tile en el mapa del fondo de 32×32.
yCoordenada Y de tile en el mapa del fondo de 32×32.
tileNúmero de tile de ocho bits para la celda del fondo.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Encola una escritura de número de tile para un mapa BG de 32×32. Ignora coordenadas inválidas y nuevas solicitudes cuando ya hay 48 escrituras pendientes. EndFrame vacía esta cola privada; el modo atomic-map replica las escrituras en ambos mapas BG. No encola atributos.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// CGB raster paths: a red frame, blue diagonal, green marker and clipped line.
// Build this source together with lib/wire3d_cgb.c in an MBC5 256 KB CGB ROM.
#include "wire3d_cgb.h"
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4D) u8 sample_key1;
__location(0xC110) u16 result[8];
__prg_rom u8 lower_lines[8]={80,56,112,56,112,56,112,80};
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3DCGB_EnableDoubleSpeed();
Wire3DCGB_Init(); // Already at double speed: its internal request is a no-op.
result[2]=(u8)(sample_key1&128);
// Palette writes are performed with the LCD off, after entering VBlank.
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0;
Wire3DCGB_SetPaletteRGB15(WIRE3DCGB_RGB15(0,0,0),WIRE3DCGB_RGB15(31,0,0),WIRE3DCGB_RGB15(0,0,31),WIRE3DCGB_RGB15(0,31,0));
sample_lcdc=0x81;
Wire3DCGB_SetScreenOffset(0,0);
Wire3DCGB_SetCamera(0,0,0,0,0,0);
Wire3DCGB_BeginFrame();
Wire3DCGB_SetLineColor(1);
Wire3DCGB_DrawLine2D(8,8,56,8);
Wire3DCGB_DrawLine2D(56,8,56,40);
Wire3DCGB_DrawLine2D(56,40,8,40);
Wire3DCGB_DrawLine2D(8,40,8,8);
Wire3DCGB_DrawLine2DColor(8,40,56,8,2);
result[0]=Wire3DCGB_GetLineColor(); // Temporary blue restores red.
Wire3DCGB_SetLineColor(3);
Wire3DCGB_DrawPoint2D(64,48);
Wire3DCGB_DrawLineClipped2D(-10,72,140,72,3);
Wire3DCGB_DrawLineList2DColor(lower_lines,2,2);
result[1]=Wire3DCGB_GetLineColor(); // The blue line list restores green.
Wire3DCGB_PutBgTile(18,1,0x80); // Queue the supplied zero glyph outside the viewport.
Wire3DCGB_EndFrame();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Este ejemplo muestra líneas, puntos, borrado y proyección básicos en un solo fotograma. Un marco rojo contiene una diagonal azul, un punto y una línea horizontal verdes, una L azul y un cero verde en la esquina superior derecha.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_raster.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:188
kitaqgb/lib/wire3d_cgb.c:1067
void Wire3DCGB_PutBgTile(w3dcgb_u8 x, w3dcgb_u8 y, w3dcgb_u8 tile)
{
if (x >= 32) return;
if (y >= 32) return;
if (w3dcgb_bgq_count >= W3DCGB_BG_QUEUE_LIMIT) return;
w3dcgb_bgq_x[(__safe_index w3dcgb_u8)w3dcgb_bgq_count] = x;
w3dcgb_bgq_y[(__safe_index w3dcgb_u8)w3dcgb_bgq_count] = y;
w3dcgb_bgq_tile[(__safe_index w3dcgb_u8)w3dcgb_bgq_count] = tile;
w3dcgb_bgq_count = (w3dcgb_u8)(w3dcgb_bgq_count + 1);
}WIRE3DCGB_RGB15
Empaqueta los canales rojo, verde y azul de cinco bits en un color CGB de 15 bits.
Sintaxis
#define WIRE3DCGB_RGB15(r5, g5, b5) ((w3dcgb_u16)((w3dcgb_u16)((r5) & 31) | ((w3dcgb_u16)((g5) & 31) << 5) | ((w3dcgb_u16)((b5) & 31) << 10)))Parámetros
r5Canal rojo, 0..31.
g5Canal verde, 0..31.
b5Canal azul, 0..31.
Valor devuelto
Valor RGB15 empaquetado como u16.
Condiciones y límites
Empaqueta los cinco bits bajos de cada canal en RGB15; evalúa cada argumento una sola vez.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// CGB raster paths: a red frame, blue diagonal, green marker and clipped line.
// Build this source together with lib/wire3d_cgb.c in an MBC5 256 KB CGB ROM.
#include "wire3d_cgb.h"
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4D) u8 sample_key1;
__location(0xC110) u16 result[8];
__prg_rom u8 lower_lines[8]={80,56,112,56,112,56,112,80};
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3DCGB_EnableDoubleSpeed();
Wire3DCGB_Init(); // Already at double speed: its internal request is a no-op.
result[2]=(u8)(sample_key1&128);
// Palette writes are performed with the LCD off, after entering VBlank.
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0;
Wire3DCGB_SetPaletteRGB15(WIRE3DCGB_RGB15(0,0,0),WIRE3DCGB_RGB15(31,0,0),WIRE3DCGB_RGB15(0,0,31),WIRE3DCGB_RGB15(0,31,0));
sample_lcdc=0x81;
Wire3DCGB_SetScreenOffset(0,0);
Wire3DCGB_SetCamera(0,0,0,0,0,0);
Wire3DCGB_BeginFrame();
Wire3DCGB_SetLineColor(1);
Wire3DCGB_DrawLine2D(8,8,56,8);
Wire3DCGB_DrawLine2D(56,8,56,40);
Wire3DCGB_DrawLine2D(56,40,8,40);
Wire3DCGB_DrawLine2D(8,40,8,8);
Wire3DCGB_DrawLine2DColor(8,40,56,8,2);
result[0]=Wire3DCGB_GetLineColor(); // Temporary blue restores red.
Wire3DCGB_SetLineColor(3);
Wire3DCGB_DrawPoint2D(64,48);
Wire3DCGB_DrawLineClipped2D(-10,72,140,72,3);
Wire3DCGB_DrawLineList2DColor(lower_lines,2,2);
result[1]=Wire3DCGB_GetLineColor(); // The blue line list restores green.
Wire3DCGB_PutBgTile(18,1,0x80); // Queue the supplied zero glyph outside the viewport.
Wire3DCGB_EndFrame();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Este ejemplo muestra líneas, puntos, borrado y proyección básicos en un solo fotograma. Un marco rojo contiene una diagonal azul, un punto y una línea horizontal verdes, una L azul y un cero verde en la esquina superior derecha.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_raster.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:50
Wire3DCGB_SetCamera
Guarda la posición y la orientación de la cámara para la proyección, con 16 pasos angulares por vuelta.
Sintaxis
void Wire3DCGB_SetCamera(w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 pitch, w3dcgb_i8 yaw, w3dcgb_i8 roll);Parámetros
xComponente X de la cámara en coordenadas del mundo.
yComponente Y de la cámara en coordenadas del mundo.
zComponente Z de la cámara en coordenadas del mundo.
pitchRotación alrededor de X; dieciséis pasos forman una vuelta completa.
yawRotación alrededor de Y; dieciséis pasos forman una vuelta completa.
rollRotación alrededor de Z; dieciséis pasos forman una vuelta completa.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Guarda la posición y los ángulos de la cámara sin cambiar los píxeles existentes. Las funciones auxiliares de rotación usan los cuatro bits bajos del ángulo, es decir, 16 pasos por vuelta. Los desplazamientos de pantalla están en registros LCD independientes que esta llamada no modifica.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Four cubes compare unity/half scale and persistent/temporary line colors.
#include "wire_cgb_example.h"
__prg_rom Wire3DCGB_Vec3 vertices[8]={
{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},
{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}
};
__prg_rom Wire3DCGB_Edge edges[12]={
{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},
{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}
};
Wire3DCGB_Model cube;
u8 sx;
u8 sy;
void main() {
wire_results_clear();
cube.vertices=vertices; cube.edges=edges;
cube.faces=0; cube.edge_faces=0;
cube.vertex_count=8; cube.edge_count=12; cube.face_count=0; cube.flags=0;
Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
Wire3DCGB_SetLineColor(1);
Wire3DCGB_DrawModel(&cube,-32,32,96,0,0,0);
Wire3DCGB_DrawModelScaled(&cube,32,32,96,0,0,0,128);
Wire3DCGB_DrawModelColor(&cube,-32,-32,96,0,0,0,2);
Wire3DCGB_DrawModelScaledColor(&cube,32,-32,96,0,0,0,128,3);
result[0]=Wire3DCGB_GetLineColor();
Wire3DCGB_DrawLine3D(0,56,96,0,-56,96);
Wire3DCGB_DrawLine3DColor(-80,0,96,80,0,96,3);
result[1]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
result[2]=sx; result[3]=sy;
// Camera setters affect future projection, leaving the staged cubes intact.
Wire3DCGB_SetCamera(0,0,0,0,4,0);
result[4]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
result[5]=Wire3DCGB_ProjectPointNoRotation(0,0,96,&sx,&sy);
result[6]=sx;
Wire3DCGB_EndFrame(); result[7]=0xA55A;
while(1) {}
}Resultado esperado
Compara modelos a escala unitaria y redimensionados en rojo, azul y verde, además de líneas 3D que se cruzan. Los valores de RAM también comprueban la proyección de cámara y su variante sin rotación.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_models.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:127
kitaqgb/lib/wire3d_cgb.c:8266
void Wire3DCGB_SetCamera(w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 pitch, w3dcgb_i8 yaw, w3dcgb_i8 roll)
{
w3dcgb_cam_x = x;
w3dcgb_cam_y = y;
w3dcgb_cam_z = z;
w3dcgb_cam_pitch = pitch;
w3dcgb_cam_yaw = yaw;
w3dcgb_cam_roll = roll;
}Wire3DCGB_SetLineColor
Selecciona el índice de color para las líneas que se dibujen a continuación.
Sintaxis
void Wire3DCGB_SetLineColor(w3dcgb_u8 color);Parámetros
colorÍndice de color de dibujo; las paletas de ejemplo usan 1=rojo, 2=azul y 3=verde.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Guarda color & 3. Usa los colores de línea con nombre 1..3: las líneas normales combinan sus planos de bits mediante OR, por lo que los colores se combinan al cruzarse; las líneas rápidas a pantalla completa sustituyen el color del píxel. El color de línea cero se interpreta como 3, no como borrado. El dibujo de puntos en modo normal sí admite por separado el color cero para borrar.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// CGB raster paths: a red frame, blue diagonal, green marker and clipped line.
// Build this source together with lib/wire3d_cgb.c in an MBC5 256 KB CGB ROM.
#include "wire3d_cgb.h"
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4D) u8 sample_key1;
__location(0xC110) u16 result[8];
__prg_rom u8 lower_lines[8]={80,56,112,56,112,56,112,80};
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3DCGB_EnableDoubleSpeed();
Wire3DCGB_Init(); // Already at double speed: its internal request is a no-op.
result[2]=(u8)(sample_key1&128);
// Palette writes are performed with the LCD off, after entering VBlank.
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0;
Wire3DCGB_SetPaletteRGB15(WIRE3DCGB_RGB15(0,0,0),WIRE3DCGB_RGB15(31,0,0),WIRE3DCGB_RGB15(0,0,31),WIRE3DCGB_RGB15(0,31,0));
sample_lcdc=0x81;
Wire3DCGB_SetScreenOffset(0,0);
Wire3DCGB_SetCamera(0,0,0,0,0,0);
Wire3DCGB_BeginFrame();
Wire3DCGB_SetLineColor(1);
Wire3DCGB_DrawLine2D(8,8,56,8);
Wire3DCGB_DrawLine2D(56,8,56,40);
Wire3DCGB_DrawLine2D(56,40,8,40);
Wire3DCGB_DrawLine2D(8,40,8,8);
Wire3DCGB_DrawLine2DColor(8,40,56,8,2);
result[0]=Wire3DCGB_GetLineColor(); // Temporary blue restores red.
Wire3DCGB_SetLineColor(3);
Wire3DCGB_DrawPoint2D(64,48);
Wire3DCGB_DrawLineClipped2D(-10,72,140,72,3);
Wire3DCGB_DrawLineList2DColor(lower_lines,2,2);
result[1]=Wire3DCGB_GetLineColor(); // The blue line list restores green.
Wire3DCGB_PutBgTile(18,1,0x80); // Queue the supplied zero glyph outside the viewport.
Wire3DCGB_EndFrame();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Este ejemplo muestra líneas, puntos, borrado y proyección básicos en un solo fotograma. Un marco rojo contiene una diagonal azul, un punto y una línea horizontal verdes, una L azul y un cero verde en la esquina superior derecha.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_raster.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:119
kitaqgb/lib/wire3d_cgb.c:1140
void Wire3DCGB_SetLineColor(w3dcgb_u8 color)
{
w3dcgb_line_color = (w3dcgb_u8)(color & 3);
}Wire3DCGB_SetOcclusionActive
Activa o desactiva la prueba de oclusión para las líneas posteriores.
Sintaxis
void Wire3DCGB_SetOcclusionActive(w3dcgb_u8 active);Parámetros
activeCero desactiva la prueba de oclusión; cualquier otro valor la activa.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Normaliza active a cero o uno y lo guarda como interruptor de oclusión. No borra máscaras ni marca geometría.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Red/blue scanlines stop inside masks; green outlines identify the triangle.
#include "wire_cgb_example.h"
__prg_rom u8 silhouette[5]={0x73,0x74,0xFF,0x75,0x73};
void main() {
u8 y;
wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
// Clearing this first test mask must leave the upper-left scanline intact.
Wire3DCGB_MarkTriangle2D(8,8,16,8,8,16);
Wire3DCGB_ClearOcclusionMask();
Wire3DCGB_MarkTriangle2D(32,16,64,16,32,48);
Wire3DCGB_MarkPackedSilhouette2D(silhouette,5,-2,104,32);
Wire3DCGB_SetOcclusionActive(1);
for(y=8;y<=56;y=y+4) Wire3DCGB_DrawLine2DColor(8,y,88,y,1);
for(y=28;y<=36;y++) Wire3DCGB_DrawLine2DColor(92,y,120,y,2);
Wire3DCGB_SetOcclusionActive(0);
Wire3DCGB_DrawLine2DColor(32,16,64,16,3);
Wire3DCGB_DrawLine2DColor(64,16,32,48,3);
Wire3DCGB_DrawLine2DColor(32,48,32,16,3);
Wire3DCGB_EndFrame(); result[7]=0xA55A;
while(1) {}
}Resultado esperado
Un triángulo oculta la parte central de las líneas de barrido rojas; una silueta empaquetada oculta las líneas azules. Los contornos verdes señalan la zona que produce la oclusión.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_mask.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_mask.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:149
kitaqgb/lib/wire3d_cgb.c:1970
void Wire3DCGB_SetOcclusionActive(w3dcgb_u8 active)
{
if (active == 0) w3dcgb_occlusion_active = 0;
else w3dcgb_occlusion_active = 1;
}Wire3DCGB_SetPaletteRGB15
Configura los cuatro colores de dibujo y las paletas del fondo que dan color a los patrones.
Sintaxis
void Wire3DCGB_SetPaletteRGB15(w3dcgb_u16 color0, w3dcgb_u16 color1, w3dcgb_u16 color2, w3dcgb_u16 color3);Parámetros
color0Color RGB15 de la entrada 0 de la paleta.
color1Color RGB15 de la entrada 1 de la paleta.
color2Color RGB15 de la entrada 2 de la paleta.
color3Color RGB15 de la entrada 3 de la paleta.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Asigna los cuatro colores RGB15 indicados a la paleta BG 0. Las paletas 1..3 comparten color0 y repiten su respectivo color no nulo en las entradas 1..3, lo que permite recolorear los tiles de patrones monocromos mediante atributos. Llama durante un intervalo válido para acceder a las paletas, normalmente al configurar con el LCD apagado o durante VBlank.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// CGB raster paths: a red frame, blue diagonal, green marker and clipped line.
// Build this source together with lib/wire3d_cgb.c in an MBC5 256 KB CGB ROM.
#include "wire3d_cgb.h"
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4D) u8 sample_key1;
__location(0xC110) u16 result[8];
__prg_rom u8 lower_lines[8]={80,56,112,56,112,56,112,80};
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3DCGB_EnableDoubleSpeed();
Wire3DCGB_Init(); // Already at double speed: its internal request is a no-op.
result[2]=(u8)(sample_key1&128);
// Palette writes are performed with the LCD off, after entering VBlank.
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0;
Wire3DCGB_SetPaletteRGB15(WIRE3DCGB_RGB15(0,0,0),WIRE3DCGB_RGB15(31,0,0),WIRE3DCGB_RGB15(0,0,31),WIRE3DCGB_RGB15(0,31,0));
sample_lcdc=0x81;
Wire3DCGB_SetScreenOffset(0,0);
Wire3DCGB_SetCamera(0,0,0,0,0,0);
Wire3DCGB_BeginFrame();
Wire3DCGB_SetLineColor(1);
Wire3DCGB_DrawLine2D(8,8,56,8);
Wire3DCGB_DrawLine2D(56,8,56,40);
Wire3DCGB_DrawLine2D(56,40,8,40);
Wire3DCGB_DrawLine2D(8,40,8,8);
Wire3DCGB_DrawLine2DColor(8,40,56,8,2);
result[0]=Wire3DCGB_GetLineColor(); // Temporary blue restores red.
Wire3DCGB_SetLineColor(3);
Wire3DCGB_DrawPoint2D(64,48);
Wire3DCGB_DrawLineClipped2D(-10,72,140,72,3);
Wire3DCGB_DrawLineList2DColor(lower_lines,2,2);
result[1]=Wire3DCGB_GetLineColor(); // The blue line list restores green.
Wire3DCGB_PutBgTile(18,1,0x80); // Queue the supplied zero glyph outside the viewport.
Wire3DCGB_EndFrame();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Este ejemplo muestra líneas, puntos, borrado y proyección básicos en un solo fotograma. Un marco rojo contiene una diagonal azul, un punto y una línea horizontal verdes, una L azul y un cero verde en la esquina superior derecha.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_raster.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:118
kitaqgb/lib/wire3d_cgb.c:1112
void Wire3DCGB_SetPaletteRGB15(w3dcgb_u16 color0, w3dcgb_u16 color1, w3dcgb_u16 color2, w3dcgb_u16 color3)
{
w3dcgb_write_bg_color(0, color0);
w3dcgb_write_bg_color(1, color1);
w3dcgb_write_bg_color(2, color2);
w3dcgb_write_bg_color(3, color3);
w3dcgb_write_bg_color(4, color0);
w3dcgb_write_bg_color(5, color1);
w3dcgb_write_bg_color(6, color1);
w3dcgb_write_bg_color(7, color1);
w3dcgb_write_bg_color(8, color0);
w3dcgb_write_bg_color(9, color2);
w3dcgb_write_bg_color(10, color2);
w3dcgb_write_bg_color(11, color2);
w3dcgb_write_bg_color(12, color0);
w3dcgb_write_bg_color(13, color3);
w3dcgb_write_bg_color(14, color3);
w3dcgb_write_bg_color(15, color3);
}Wire3DCGB_SetScreenOffset
Configura directamente los registros de desplazamiento SCX y SCY del LCD.
Sintaxis
void Wire3DCGB_SetScreenOffset(w3dcgb_u8 scx, w3dcgb_u8 scy);Parámetros
scxDesplazamiento en píxeles que se escribe en SCX.
scyDesplazamiento en píxeles que se escribe en SCY.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
Escribe SCX/SCY al instante, sin esperar a VBlank ni cambiar las coordenadas proyectadas. El código que llama decide cuándo es aceptable un cambio visible del desplazamiento.
Solo CGB. El área normal de preparación reserva D300..DEFF en el banco 2 de WRAM. El estado compartido impide la reentrada; no llames a estas rutinas de forma recursiva desde interrupciones. Los ejemplos usan una pila fija y el entorno de ejecución completo.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// CGB raster paths: a red frame, blue diagonal, green marker and clipped line.
// Build this source together with lib/wire3d_cgb.c in an MBC5 256 KB CGB ROM.
#include "wire3d_cgb.h"
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4D) u8 sample_key1;
__location(0xC110) u16 result[8];
__prg_rom u8 lower_lines[8]={80,56,112,56,112,56,112,80};
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3DCGB_EnableDoubleSpeed();
Wire3DCGB_Init(); // Already at double speed: its internal request is a no-op.
result[2]=(u8)(sample_key1&128);
// Palette writes are performed with the LCD off, after entering VBlank.
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0;
Wire3DCGB_SetPaletteRGB15(WIRE3DCGB_RGB15(0,0,0),WIRE3DCGB_RGB15(31,0,0),WIRE3DCGB_RGB15(0,0,31),WIRE3DCGB_RGB15(0,31,0));
sample_lcdc=0x81;
Wire3DCGB_SetScreenOffset(0,0);
Wire3DCGB_SetCamera(0,0,0,0,0,0);
Wire3DCGB_BeginFrame();
Wire3DCGB_SetLineColor(1);
Wire3DCGB_DrawLine2D(8,8,56,8);
Wire3DCGB_DrawLine2D(56,8,56,40);
Wire3DCGB_DrawLine2D(56,40,8,40);
Wire3DCGB_DrawLine2D(8,40,8,8);
Wire3DCGB_DrawLine2DColor(8,40,56,8,2);
result[0]=Wire3DCGB_GetLineColor(); // Temporary blue restores red.
Wire3DCGB_SetLineColor(3);
Wire3DCGB_DrawPoint2D(64,48);
Wire3DCGB_DrawLineClipped2D(-10,72,140,72,3);
Wire3DCGB_DrawLineList2DColor(lower_lines,2,2);
result[1]=Wire3DCGB_GetLineColor(); // The blue line list restores green.
Wire3DCGB_PutBgTile(18,1,0x80); // Queue the supplied zero glyph outside the viewport.
Wire3DCGB_EndFrame();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Este ejemplo muestra líneas, puntos, borrado y proyección básicos en un solo fotograma. Un marco rojo contiene una diagonal azul, un punto y una línea horizontal verdes, una L azul y un cero verde en la esquina superior derecha.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_raster.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_cgb.h:117
kitaqgb/lib/wire3d_cgb.c:1091
void Wire3DCGB_SetScreenOffset(w3dcgb_u8 scx, w3dcgb_u8 scy)
{
w3dcgb_reg_scx = scx;
w3dcgb_reg_scy = scy;
}Tiempos Wire3D, perfiles de 88 filas y relojes independientes
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Una transferencia completa de 88 filas lee 1.408 bytes en DMG y 2.816 en CGB. Reduce los datos un 26,67 % frente a DMG de 120 filas y un 8,33 % frente a 96 filas; no predice el aumento de fps. DMG conserva columnas separadas por 256 bytes; CGB compacta columnas de 11 mosaicos. CGB sigue reservando 3.072 bytes para compatibilidad con pantalla completa.
ProjectCameraPoint proyecta coordenadas de cámara sin restar ni rotar la cámara. Si Z está fuera de 8..255 devuelve 0 sin modificar las salidas. Limita X/Y a ±120; divide los productos de la tabla de profundidad inversa por 32 redondeando hacia abajo con signo y limita el resultado a la pantalla. No realiza recorte geométrico de líneas. ProjectPoint genérico de CGB conserva los límites de rotación ±220 incluso con ángulos cero.
EndFrameNow de DMG omite solo la espera inicial de un nuevo VBlank y procesa la cola BG, los modos de transferencia y el historial dirty. EndFrameSparseNow de CGB también es síncrono. Now aún espera acceso STAT, finalización DMA y presentación segura. Las actualizaciones DMG no son atómicas. El borrado sparse CGB incluye el intervalo actual y el de hace dos imágenes en el banco de destino. Las líneas CGB de bajo nivel requieren marcar dirty.
Al iniciar sparse en CGB, el primer uso de cada banco de destino (los dos primeros fotogramas) actualiza toda la vista y elimina los mosaicos de inicialización. La medición incluye ese coste. DrawLine2D no registra regiones sparse: use DrawLineClipped2D o llame explícitamente a MarkDirtyRect2D.
Los ejemplos usan una caja móvil, un indicador de barras y un BGM de cuatro notas de creación independiente. El movimiento consume ticks transcurridos de audio_vblank; un breve manejador VBlank seguro actualiza el indicador. Nunca llame al renderizador de estado compartido desde una ISR. wire3d_audio_vblank.c coloca la cola de 80 bytes en WRAM fija y las funciones de control en el banco ROM 5. No compile también audio_vblank.c. Los ejemplos CGB usan WIRE3DCGB_STAGE_BANK2_ALLOCATION. Lea la diferencia de ticks de 8 bits antes de 255 imágenes.
La herramienta cuenta marcadores tras completar transferencia y presentación. Mide en dots PPU (4.194.304/s; 70.224/imagen) borrado, proyección, rasterización, transferencia con presentación y esperas externas. Informa media, mediana, intervalo máximo y plazos incumplidos. La transferencia con presentación incluye esperas internas STAT/DMA/VBlank. No compare directamente ciclos CPU CGB a doble velocidad con DMG. La igualdad de fps medio no demuestra que todos los plazos se cumplan. Hardware real sin verificar.
Siete configuraciones originales completaron 48 transferencias cada una: 336 comparaciones stage/VRAM y 84 fotogramas vacíos para comprobar el borrado. Cinco perfiles superaron 25.700 casos límite de proyección. Cinco compilaciones Rust también completaron 48 fotogramas con BGM no nulo. Algunos intervalos superan cuatro fotogramas PPU: el promedio de fps no demuestra ausencia de ralentización. Son pruebas de emulador, sin validación en hardware.
KOKURA ejecutó cada ejemplo original DMG/CGB durante 400 fotogramas; el análisis SARAKURA y la validación estricta pasaron. Cada uno conserva cero errores, una advertencia de PC repetido en la espera y tres observaciones, incluido el riesgo de chasquido DAC/mezclador. No valida fidelidad de audio ni hardware.
Los ejemplos, imágenes y pruebas publicados solo usan geometría, indicadores y patrones de notas creados independientemente. No incluyen ROM comerciales, código extraído, geometría, pantallas, música ni archivos de estado de juegos comerciales.
Resultados de verificación y ejemplos · C / BGM / HUD
| Perfil | fps | Mediana / peor (fotogramas PPU) | Plazos excedidos / 47 |
|---|---|---|---|
clocked_dmg_88_sparse | 13.852 | 4.449 / 4.732 | 35 |
clocked_dmg_96_sparse | 13.186 | 4.669 / 4.891 | 39 |
clocked_dmg_120_sparse | 13.434 | 4.453 / 7.176 | 35 |
clocked_cgb_88_sparse | 15.012 | 4.000 / 5.000 | 28 |
clocked_cgb_96_sparse | 15.092 | 4.000 / 5.000 | 26 |
clocked_cgb_88_full | 12.532 | 5.000 / 6.000 | 41 |
clocked_cgb_96_full | 12.588 | 5.000 / 5.020 | 41 |


Wire3DDMG_ProjectCameraPoint
ProjectCameraPoint proyecta coordenadas de cámara sin restar ni rotar la cámara. Si Z está fuera de 8..255 devuelve 0 sin modificar las salidas. Limita X/Y a ±120; divide los productos de la tabla de profundidad inversa por 32 redondeando hacia abajo con signo y limita el resultado a la pantalla. No realiza recorte geométrico de líneas. ProjectPoint genérico de CGB conserva los límites de rotación ±220 incluso con ángulos cero.
Sintaxis
w3ddmg_u8 Wire3DDMG_ProjectCameraPoint(w3ddmg_i16 x,w3ddmg_i16 y,w3ddmg_i16 z,w3ddmg_u8* sx,w3ddmg_u8* sy);Parámetros
xX/Y/Z de cámara con signo de 16 bits. sx y sy deben ser punteros u8 válidos y escribibles.
yX/Y/Z de cámara con signo de 16 bits. sx y sy deben ser punteros u8 válidos y escribibles.
zX/Y/Z de cámara con signo de 16 bits. sx y sy deben ser punteros u8 válidos y escribibles.
sxX/Y/Z de cámara con signo de 16 bits. sx y sy deben ser punteros u8 válidos y escribibles.
syX/Y/Z de cámara con signo de 16 bits. sx y sy deben ser punteros u8 válidos y escribibles.
Valor devuelto
Devuelve 1 si la proyección tiene éxito o 0 al rechazar la profundidad. El rechazo mantiene sx y sy.
Condiciones y límites
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Los ejemplos usan una caja móvil, un indicador de barras y un BGM de cuatro notas de creación independiente. El movimiento consume ticks transcurridos de audio_vblank; un breve manejador VBlank seguro actualiza el indicador. Nunca llame al renderizador de estado compartido desde una ISR. wire3d_audio_vblank.c coloca la cola de 80 bytes en WRAM fija y las funciones de control en el banco ROM 5. No compile también audio_vblank.c. Los ejemplos CGB usan WIRE3DCGB_STAGE_BANK2_ALLOCATION. Lea la diferencia de ticks de 8 bits antes de 255 imágenes.
La herramienta cuenta marcadores tras completar transferencia y presentación. Mide en dots PPU (4.194.304/s; 70.224/imagen) borrado, proyección, rasterización, transferencia con presentación y esperas externas. Informa media, mediana, intervalo máximo y plazos incumplidos. La transferencia con presentación incluye esperas internas STAT/DMA/VBlank. No compare directamente ciclos CPU CGB a doble velocidad con DMG. La igualdad de fps medio no demuestra que todos los plazos se cumplan. Hardware real sin verificar.
Ejemplo de uso
#define WIRE3D_DMG_HEIGHT 88
#include "wire3d_dmg.h"
void project_one() {
u8 sx; u8 sy;
if (Wire3DDMG_ProjectCameraPoint(-24, 20, 96, &sx, &sy)) {
// Use the projected coordinates in a main-thread drawing routine.
}
}Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Siete configuraciones originales completaron 48 transferencias cada una: 336 comparaciones stage/VRAM y 84 fotogramas vacíos para comprobar el borrado. Cinco perfiles superaron 25.700 casos límite de proyección. Cinco compilaciones Rust también completaron 48 fotogramas con BGM no nulo. Algunos intervalos superan cuatro fotogramas PPU: el promedio de fps no demuestra ausencia de ralentización. Son pruebas de emulador, sin validación en hardware.
Implementación y código fuente
kitaqgb/lib/wire3d_dmg.h:146
Validate depth and project coordinates already in camera space.
kitaqgb/lib/wire3d_dmg.c:720
w3ddmg_u8 Wire3DDMG_ProjectCameraPoint(w3ddmg_i16 x,w3ddmg_i16 y,w3ddmg_i16 z,w3ddmg_u8* sx,w3ddmg_u8* sy)
{
return w3ddmg_project_camera_space(x,y,z,sx,sy);
}Wire3DCGB_ProjectCameraPoint
ProjectCameraPoint proyecta coordenadas de cámara sin restar ni rotar la cámara. Si Z está fuera de 8..255 devuelve 0 sin modificar las salidas. Limita X/Y a ±120; divide los productos de la tabla de profundidad inversa por 32 redondeando hacia abajo con signo y limita el resultado a la pantalla. No realiza recorte geométrico de líneas. ProjectPoint genérico de CGB conserva los límites de rotación ±220 incluso con ángulos cero.
Sintaxis
w3dcgb_u8 Wire3DCGB_ProjectCameraPoint(w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_u8* sx, w3dcgb_u8* sy);Parámetros
xX/Y/Z de cámara con signo de 16 bits. sx y sy deben ser punteros u8 válidos y escribibles.
yX/Y/Z de cámara con signo de 16 bits. sx y sy deben ser punteros u8 válidos y escribibles.
zX/Y/Z de cámara con signo de 16 bits. sx y sy deben ser punteros u8 válidos y escribibles.
sxX/Y/Z de cámara con signo de 16 bits. sx y sy deben ser punteros u8 válidos y escribibles.
syX/Y/Z de cámara con signo de 16 bits. sx y sy deben ser punteros u8 válidos y escribibles.
Valor devuelto
Devuelve 1 si la proyección tiene éxito o 0 al rechazar la profundidad. El rechazo mantiene sx y sy.
Condiciones y límites
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Los ejemplos usan una caja móvil, un indicador de barras y un BGM de cuatro notas de creación independiente. El movimiento consume ticks transcurridos de audio_vblank; un breve manejador VBlank seguro actualiza el indicador. Nunca llame al renderizador de estado compartido desde una ISR. wire3d_audio_vblank.c coloca la cola de 80 bytes en WRAM fija y las funciones de control en el banco ROM 5. No compile también audio_vblank.c. Los ejemplos CGB usan WIRE3DCGB_STAGE_BANK2_ALLOCATION. Lea la diferencia de ticks de 8 bits antes de 255 imágenes.
La herramienta cuenta marcadores tras completar transferencia y presentación. Mide en dots PPU (4.194.304/s; 70.224/imagen) borrado, proyección, rasterización, transferencia con presentación y esperas externas. Informa media, mediana, intervalo máximo y plazos incumplidos. La transferencia con presentación incluye esperas internas STAT/DMA/VBlank. No compare directamente ciclos CPU CGB a doble velocidad con DMG. La igualdad de fps medio no demuestra que todos los plazos se cumplan. Hardware real sin verificar.
Ejemplo de uso
#define WIRE3DCGB_HEIGHT 88
#include "wire3d_cgb.h"
void project_one() {
u8 sx; u8 sy;
if (Wire3DCGB_ProjectCameraPoint(-24, 20, 96, &sx, &sy)) {
// Use the projected coordinates in a main-thread drawing routine.
}
}Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Siete configuraciones originales completaron 48 transferencias cada una: 336 comparaciones stage/VRAM y 84 fotogramas vacíos para comprobar el borrado. Cinco perfiles superaron 25.700 casos límite de proyección. Cinco compilaciones Rust también completaron 48 fotogramas con BGM no nulo. Algunos intervalos superan cuatro fotogramas PPU: el promedio de fps no demuestra ausencia de ralentización. Son pruebas de emulador, sin validación en hardware.
Implementación y código fuente
kitaqgb/lib/wire3d_cgb.h:168
Project camera-space coordinates without subtracting/rotating the camera. Depth 8..255; outputs unchanged on rejection. Shared scratch: no ISR calls.
kitaqgb/lib/wire3d_cgb.c:552
w3dcgb_u8 Wire3DCGB_ProjectCameraPoint(w3dcgb_i16 x,w3dcgb_i16 y,w3dcgb_i16 z,w3dcgb_u8* sx,w3dcgb_u8* sy)
{
return w3dcgb_project_camera_space(x,y,z,sx,sy);
}Wire3DDMG_EndFrameNow
EndFrameNow de DMG omite solo la espera inicial de un nuevo VBlank y procesa la cola BG, los modos de transferencia y el historial dirty. EndFrameSparseNow de CGB también es síncrono. Now aún espera acceso STAT, finalización DMA y presentación segura. Las actualizaciones DMG no son atómicas. El borrado sparse CGB incluye el intervalo actual y el de hace dos imágenes en el banco de destino. Las líneas CGB de bajo nivel requieren marcar dirty.
Sintaxis
void Wire3DDMG_EndFrameNow();Valor devuelto
Sin valor de retorno; vuelve tras completar transferencia y sincronización necesarias.
Condiciones y límites
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Los ejemplos usan una caja móvil, un indicador de barras y un BGM de cuatro notas de creación independiente. El movimiento consume ticks transcurridos de audio_vblank; un breve manejador VBlank seguro actualiza el indicador. Nunca llame al renderizador de estado compartido desde una ISR. wire3d_audio_vblank.c coloca la cola de 80 bytes en WRAM fija y las funciones de control en el banco ROM 5. No compile también audio_vblank.c. Los ejemplos CGB usan WIRE3DCGB_STAGE_BANK2_ALLOCATION. Lea la diferencia de ticks de 8 bits antes de 255 imágenes.
La herramienta cuenta marcadores tras completar transferencia y presentación. Mide en dots PPU (4.194.304/s; 70.224/imagen) borrado, proyección, rasterización, transferencia con presentación y esperas externas. Informa media, mediana, intervalo máximo y plazos incumplidos. La transferencia con presentación incluye esperas internas STAT/DMA/VBlank. No compare directamente ciclos CPU CGB a doble velocidad con DMG. La igualdad de fps medio no demuestra que todos los plazos se cumplan. Hardware real sin verificar.
Ejemplo de uso
#define WIRE3D_DMG_HEIGHT 88
#include "wire3d_dmg.h"
void draw_one() {
Wire3DDMG_BeginFrame();
Wire3DDMG_DrawLine2D(8,8,32,32);
Wire3DDMG_PutBgTile(18,16,128);
Wire3DDMG_EndFrameNow();
}Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.
Resultado esperado
Siete configuraciones originales completaron 48 transferencias cada una: 336 comparaciones stage/VRAM y 84 fotogramas vacíos para comprobar el borrado. Cinco perfiles superaron 25.700 casos límite de proyección. Cinco compilaciones Rust también completaron 48 fotogramas con BGM no nulo. Algunos intervalos superan cuatro fotogramas PPU: el promedio de fps no demuestra ausencia de ralentización. Son pruebas de emulador, sin validación en hardware.
Implementación y código fuente
kitaqgb/lib/wire3d_dmg.h:289
Same queue/gate/history lifecycle, without the initial fresh-VBlank wait. Synchronous STAT-safe upload; not an atomic swap. LCD must remain enabled.
kitaqgb/lib/wire3d_dmg.c:3826
void Wire3DDMG_EndFrameNow()
{
w3ddmg_flush_bg_queue();
if (w3ddmg_aux_transfer_enabled)
{
w3ddmg_transfer_stage_aux_asm();
}
if (w3ddmg_dirty_transfer_enabled)
{
w3ddmg_transfer_dirty_stage();
}
else
{
w3ddmg_transfer_stage_asm();
}
}wire3d_dmg.h — Gráficos de alambre para DMG
Uso de las rutas de renderizado rápido
Para las líneas dentro del área de visualización, la dirección de dibujo y el bit de píxel avanzan de forma incremental, mientras que la cantidad de píxeles restantes y el error se mantienen en registros de CPU. Esto evita calcular las coordenadas de tile por píxel y dibuja píxeles de enlace para unir las diagonales. Con la oclusión activa, cinco puntos de la línea determinan si es necesario dibujarla; las líneas aceptadas usan la misma ruta rápida. Las filas de la máscara se rellenan byte a byte conservando los bits parciales de los bordes. Los rectángulos envolventes de las caras y el descarte por cinco puntos son aproximaciones, no oclusión exacta de triángulos o líneas píxel a píxel. Las rotaciones de 0, 90, 180 y 270 grados limitan las entradas y luego intercambian coordenadas y cambian signos. El rendimiento global también depende de la cantidad de vértices, la longitud de las aristas, la oclusión y las transferencias a VRAM. Mida cada operación por separado del tiempo necesario para completar una imagen visible.
Dibujo de líneas 3D monocromas. Proporciona vértices, aristas y caras del modelo, además de posición, rotación y escala del objeto. Sigue el orden de inicialización, inicio del fotograma, dibujo y transferencia. La física se gestiona aparte. Los ángulos tienen dieciséis pasos por vuelta; la escala 256 equivale a la unidad.
Vec3 contiene x/y/z, Edge los índices de vértice a/b y Face los índices del triángulo a/b/c. Los campos vertices, edges y faces de Model apuntan a esos arrays; cada contador indica su longitud. edge_faces contiene los índices de caras adyacentes f0/f1, con FACE_NONE para una cara ausente. MODEL_HIDDEN_LINES en flags solicita selección de aristas basada en caras. El área proyectada con signo determina la orientación de la cara, por lo que importa el orden de los vértices.
Object guarda una referencia al modelo, posición x/y/z, ángulos rx/ry/rz, scale_q8 y visible. Los objetos pueden compartir un modelo, pero el dibujo no copia tablas ni cambia automáticamente sus bancos ROM. Mantén legibles los datos referenciados durante todo el dibujo. Object de CGB también tiene un índice de color.
El Model de altura 96 también contiene edge_masks y edge_mask_count. Proporciona una tabla RAM de máscaras de aristas de 16 bits seleccionadas por la guiñada del objeto, o pon ambos campos a cero si no se usan.
Wire3DDMG_BeginFrame
Inicia el dibujo de un fotograma y desactiva la prueba de oclusión.
Sintaxis
void Wire3DDMG_BeginFrame();Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 96 void Wire3DDMG_BeginFrame(); Borra los píxeles preparados y la máscara de oclusión y desactiva el filtrado de oclusión. No modifica el fotograma visible de VRAM ni la cola de tiles BG pendientes. WIRE3D_DMG_HEIGHT = 120 void Wire3DDMG_BeginFrame(); Solo desactiva el filtrado de oclusión. El área de preparación suele borrarse durante la transferencia; Init proporciona la primera área limpia. No descarta un fotograma aún no enviado, no borra la máscara ni reinicia las escrituras BG pendientes o las marcas de cambios.
Este ejemplo usa el perfil 128×120; su ventana gráfica empieza en (16,8) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
WIRE3D_DMG_HEIGHT vale 120 de forma predeterminada. Usa wire3d_dmg_96.c para la altura 96. SelectEdgeMask está disponible con altura 96; RotatePoint, DrawIndexedEdges, los controles de habilitación de transferencia y las transferencias directas requieren altura 120.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3DDMG_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
Wire3DDMG_SetCamera(8,0,0,0,0,0);
result[1]=Wire3DDMG_ProjectPoint(0,0,96,&projected_x,&projected_y);
result[2]=projected_x; result[3]=projected_y;
projected_x=91; projected_y=92;
result[4]=Wire3DDMG_ProjectPoint(0,0,7,&projected_x,&projected_y);
result[5]=projected_x; result[6]=projected_y;
Wire3DDMG_SetCamera(0,0,0,0,0,0);
Wire3DDMG_BeginFrame();
Wire3DDMG_DrawLine2D(8,8,56,8);
Wire3DDMG_DrawLine2D(56,8,56,40);
Wire3DDMG_DrawLine2D(56,40,8,40);
Wire3DDMG_DrawLine2D(8,40,8,8);
Wire3DDMG_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
Wire3DDMG_DrawLine3D(-24,-24,96,24,24,96);
// Copy the viewport's top-left frame corner to a separate map cell.
Wire3DDMG_PutBgTile(1,1,160);
Wire3DDMG_EndFrame();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Este ejemplo muestra líneas, puntos, borrado y proyección en un fotograma. Se borra el centro del borde superior del marco de arriba a la izquierda y se proyecta una diagonal cerca del centro. Una proyección rechazada conserva las salidas 91 y 92.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_raster.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_dmg.h:144
Disable occlusion filtering only. Stage clearing normally happens during transfer, and Init supplies the first clean stage. This does not discard an unsubmitted frame, clear the mask, or reset pending BG writes/dirty flags.
kitaqgb/lib/wire3d_dmg.c:3379
void Wire3DDMG_BeginFrame()
{
/* The consuming stage transfer clears D000 as it uploads, so BeginFrame only
resets draw state. Wire3DDMG_Init supplies the first clean buffer. */
w3ddmg_occlusion_active = 0;
}Wire3DDMG_DrawIndexedEdges
Dibuja un modelo de líneas con escala entera a partir de vértices y pares de índices de arista de dos bytes.
Sintaxis
void Wire3DDMG_DrawIndexedEdges(const Wire3DDMG_Vec3* vertices, w3ddmg_u8 vertex_count, const w3ddmg_u8* edges, w3ddmg_u8 edge_count, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 scale);Parámetros
verticesArray de vértices 3D.
vertex_countCantidad de entradas del array de vértices.
edgesÍndices de los vértices de cada arista, en el formato declarado de estructura o de pares de bytes.
edge_countCantidad de aristas.
xComponente X del punto o del origen del objeto en coordenadas del mundo.
yComponente Y del punto o del origen del objeto en coordenadas del mundo.
zComponente Z del punto o del origen del objeto en coordenadas del mundo.
scaleEscala entera; cero se interpreta como uno.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 120 void Wire3DDMG_DrawIndexedEdges(const Wire3DDMG_Vec3* vertices, w3ddmg_u8 vertex_count, const w3ddmg_u8* edges, w3ddmg_u8 edge_count, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 scale); Dibuja aristas indexadas por pares de bytes tras escalado entero y traslación; escala cero significa uno y no hay rotación de objeto ni filtrado de caras. Proyecta hasta 24 vértices. Proporciona como máximo 128 pares de aristas, ya que los desplazamientos de byte vuelven a cero después de 255. Omite ID de vértice inválidos y extremos rechazados por profundidad; ignora arrays null. Los productos y sumas de coordenadas deben poder representarse en s16.
Este ejemplo usa el perfil 128×120; su ventana gráfica empieza en (16,8) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
WIRE3D_DMG_HEIGHT vale 120 de forma predeterminada. Usa wire3d_dmg_96.c para la altura 96. SelectEdgeMask está disponible con altura 96; RotatePoint, DrawIndexedEdges, los controles de habilitación de transferencia y las transferencias directas requieren altura 120.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Upload a main line and an auxiliary block separately; verify source consumption.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3DDMG_Vec3 vertices[2]={{-32,0,0},{32,0,0}};
__prg_rom u8 edge_pairs[2]={0,1};
u8* stage_byte;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3DDMG_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
Wire3DDMG_BeginFrame();
Wire3DDMG_DrawIndexedEdges(vertices,2,edge_pairs,1,-64,104,96,1);
Wire3DDMG_TransferMainNow();
// Direct auxiliary transfer writes a separate tile after the main upload.
for(i=24;i<=31;i++) Wire3DDMG_DrawLine2D(40,i,47,i);
stage_byte=(u8*)0xD518;result[1]=*stage_byte;
Wire3DDMG_TransferAuxNow();result[2]=*stage_byte;
// Do not upload the consumed stage again.
result[7]=0xA55A; while(1) {}
}Resultado esperado
Una línea horizontal proyectada y un bloque auxiliar de 8×8 muestran las transferencias directas; un byte fuente pasa de 255 a 0 al consumirse.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_direct.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_direct.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_dmg.h:253
Draw byte-pair edge indices after integer scaling and translation; scale zero means one, and there is no object rotation or face filtering. Project at most 24 vertices. Supply at most 128 edge pairs because byte offsets wrap after 255. Invalid vertex IDs/depth-rejected endpoints are skipped; null arrays are ignored. Keep coordinate products/sums representable as s16.
kitaqgb/lib/wire3d_dmg.c:4568
void Wire3DDMG_DrawIndexedEdges(const Wire3DDMG_Vec3* vertices, w3ddmg_u8 vertex_count, const w3ddmg_u8* edges, w3ddmg_u8 edge_count, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 scale)
{
w3ddmg_u8 i;
w3ddmg_u8 count;
if (vertices == 0) return;
if (edges == 0) return;
count = vertex_count;
if (count > WIRE3D_DMG_MODEL_VERTEX_LIMIT) count = WIRE3D_DMG_MODEL_VERTEX_LIMIT;
if (scale == 0) scale = 1;
i = 0;
while (i < count)
{
const Wire3DDMG_Vec3* v;
w3ddmg_i16 vx;
w3ddmg_i16 vy;
w3ddmg_i16 vz;
w3ddmg_u8 sx;
w3ddmg_u8 sy;
v = &vertices[(__safe_index w3ddmg_u8)i];
vx = (w3ddmg_i16)(x + (w3ddmg_i16)(v->x * scale));
vy = (w3ddmg_i16)(y + (w3ddmg_i16)(v->y * scale));
vz = (w3ddmg_i16)(z + (w3ddmg_i16)(v->z * scale));
if (w3ddmg_project_world(vx, vy, vz, &sx, &sy))
{
w3ddmg_screen_x[(__safe_index w3ddmg_u8)i] = sx;
w3ddmg_screen_y[(__safe_index w3ddmg_u8)i] = sy;
w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 1;
}
else
{
w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 0;
}
i = (w3ddmg_u8)(i + 1);
}
i = 0;
while (i < edge_count)
{
w3ddmg_u8 a;
w3ddmg_u8 b;
a = edges[(__safe_index w3ddmg_u8)((w3ddmg_u8)(i << 1))];
b = edges[(__safe_index w3ddmg_u8)((w3ddmg_u8)((i << 1) + 1))];
if ((a < count) && (b < count) &&
w3ddmg_screen_visible[(__safe_index w3ddmg_u8)a] &&
w3ddmg_screen_visible[(__safe_index w3ddmg_u8)b])
{
Wire3DDMG_DrawLine2D(
w3ddmg_screen_x[(__safe_index w3ddmg_u8)a],
w3ddmg_screen_y[(__safe_index w3ddmg_u8)a],
w3ddmg_screen_x[(__safe_index w3ddmg_u8)b],
w3ddmg_screen_y[(__safe_index w3ddmg_u8)b]);
}
i = (w3ddmg_u8)(i + 1);
}
}Wire3DDMG_DrawLine2D
Dibuja en el área de preparación una línea de pantalla con conectividad de cuatro vecinos, incluidos los extremos.
Sintaxis
void Wire3DDMG_DrawLine2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by);Parámetros
axCoordenada X del vértice A en píxeles de la ventana gráfica.
ayCoordenada Y del vértice A en píxeles de la ventana gráfica.
bxCoordenada X del vértice B en píxeles de la ventana gráfica.
byCoordenada Y del vértice B en píxeles de la ventana gráfica.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 96 void Wire3DDMG_DrawLine2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by); Dibuja una línea conectada en el área de preparación de 128×96, incluidos los extremos. Durante DrawScene usa el rechazo aproximado de oclusión de cinco muestras; en otros casos dibuja directamente. Proporciona coordenadas de la ventana gráfica. Solo EndFrame actualiza VRAM. WIRE3D_DMG_HEIGHT = 120 void Wire3DDMG_DrawLine2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by); Si está habilitada la transferencia de zonas modificadas, marca el rectángulo envolvente de tiles y dibuja una línea conectada en el área de preparación. El dibujo de escenas puede rechazarla mediante cinco muestras de máscara. Proporciona extremos dentro de la ventana gráfica de 128×120; las comprobaciones de límites de píxel de bajo nivel no recortan geométricamente el segmento.
Este ejemplo usa el perfil 128×120; su ventana gráfica empieza en (16,8) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
WIRE3D_DMG_HEIGHT vale 120 de forma predeterminada. Usa wire3d_dmg_96.c para la altura 96. SelectEdgeMask está disponible con altura 96; RotatePoint, DrawIndexedEdges, los controles de habilitación de transferencia y las transferencias directas requieren altura 120.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3DDMG_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
Wire3DDMG_SetCamera(8,0,0,0,0,0);
result[1]=Wire3DDMG_ProjectPoint(0,0,96,&projected_x,&projected_y);
result[2]=projected_x; result[3]=projected_y;
projected_x=91; projected_y=92;
result[4]=Wire3DDMG_ProjectPoint(0,0,7,&projected_x,&projected_y);
result[5]=projected_x; result[6]=projected_y;
Wire3DDMG_SetCamera(0,0,0,0,0,0);
Wire3DDMG_BeginFrame();
Wire3DDMG_DrawLine2D(8,8,56,8);
Wire3DDMG_DrawLine2D(56,8,56,40);
Wire3DDMG_DrawLine2D(56,40,8,40);
Wire3DDMG_DrawLine2D(8,40,8,8);
Wire3DDMG_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
Wire3DDMG_DrawLine3D(-24,-24,96,24,24,96);
// Copy the viewport's top-left frame corner to a separate map cell.
Wire3DDMG_PutBgTile(1,1,160);
Wire3DDMG_EndFrame();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Este ejemplo muestra líneas, puntos, borrado y proyección en un fotograma. Se borra el centro del borde superior del marco de arriba a la izquierda y se proyecta una diagonal cerca del centro. Una proyección rechazada conserva las salidas 91 y 92.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_raster.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_dmg.h:237
Mark the bounding tile rectangle when dirty transfer is enabled, then draw a connected staged line. Scene drawing may reject it using five mask samples. Supply 128x120 viewport endpoints; low-level pixel bounds checks do not clip the segment geometrically.
kitaqgb/lib/wire3d_dmg.c:3423
void Wire3DDMG_DrawLine2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by)
{
w3ddmg_mark_line_dirty(ax, ay, bx, by);
if (w3ddmg_occlusion_active)
{
w3ddmg_line_stage_masked_c(ax, ay, bx, by);
return;
}
w3ddmg_line_x0 = ax;
w3ddmg_line_y0 = ay;
w3ddmg_line_x1 = bx;
w3ddmg_line_y1 = by;
if (ax < 128 && bx < 128 && ay < WIRE3D_DMG_SCREEN_H && by < WIRE3D_DMG_SCREEN_H)
w3ddmg_line_inside_asm();
else
w3ddmg_line_stage_asm();
}Wire3DDMG_DrawLine3D
Proyecta dos extremos en coordenadas del mundo y dibuja una línea entre ellos.
Sintaxis
void Wire3DDMG_DrawLine3D(w3ddmg_i16 ax, w3ddmg_i16 ay, w3ddmg_i16 az, w3ddmg_i16 bx, w3ddmg_i16 by, w3ddmg_i16 bz);Parámetros
axComponente X del punto inicial en coordenadas del mundo.
ayComponente Y del punto inicial en coordenadas del mundo.
azComponente Z del punto inicial en coordenadas del mundo.
bxComponente X del punto final en coordenadas del mundo.
byComponente Y del punto final en coordenadas del mundo.
bzComponente Z del punto final en coordenadas del mundo.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 96 void Wire3DDMG_DrawLine3D(w3ddmg_i16 ax, w3ddmg_i16 ay, w3ddmg_i16 az, w3ddmg_i16 bx, w3ddmg_i16 by, w3ddmg_i16 bz); Proyecta ambos extremos del mundo y solo dibuja si los dos pasan el rango de profundidad. No calcula intersecciones de segmentos que crucen los planos cercano o lejano; cada extremo proyectado se limita por separado a los bordes de pantalla. WIRE3D_DMG_HEIGHT = 120 void Wire3DDMG_DrawLine3D(w3ddmg_i16 ax, w3ddmg_i16 ay, w3ddmg_i16 az, w3ddmg_i16 bx, w3ddmg_i16 by, w3ddmg_i16 bz); Proyecta ambos extremos del mundo y solo dibuja si los dos pasan el rango de profundidad. No calcula intersecciones de segmentos que crucen los planos cercano o lejano; cada extremo proyectado se limita por separado a los bordes de pantalla.
Este ejemplo usa el perfil 128×120; su ventana gráfica empieza en (16,8) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
WIRE3D_DMG_HEIGHT vale 120 de forma predeterminada. Usa wire3d_dmg_96.c para la altura 96. SelectEdgeMask está disponible con altura 96; RotatePoint, DrawIndexedEdges, los controles de habilitación de transferencia y las transferencias directas requieren altura 120.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3DDMG_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
Wire3DDMG_SetCamera(8,0,0,0,0,0);
result[1]=Wire3DDMG_ProjectPoint(0,0,96,&projected_x,&projected_y);
result[2]=projected_x; result[3]=projected_y;
projected_x=91; projected_y=92;
result[4]=Wire3DDMG_ProjectPoint(0,0,7,&projected_x,&projected_y);
result[5]=projected_x; result[6]=projected_y;
Wire3DDMG_SetCamera(0,0,0,0,0,0);
Wire3DDMG_BeginFrame();
Wire3DDMG_DrawLine2D(8,8,56,8);
Wire3DDMG_DrawLine2D(56,8,56,40);
Wire3DDMG_DrawLine2D(56,40,8,40);
Wire3DDMG_DrawLine2D(8,40,8,8);
Wire3DDMG_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
Wire3DDMG_DrawLine3D(-24,-24,96,24,24,96);
// Copy the viewport's top-left frame corner to a separate map cell.
Wire3DDMG_PutBgTile(1,1,160);
Wire3DDMG_EndFrame();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Este ejemplo muestra líneas, puntos, borrado y proyección en un fotograma. Se borra el centro del borde superior del marco de arriba a la izquierda y se proyecta una diagonal cerca del centro. Una proyección rechazada conserva las salidas 91 y 92.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_raster.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_dmg.h:226
Project both world endpoints and draw only when both pass the depth range. Do not intersect a crossing segment with near/far planes; projected endpoints are independently clamped to the screen edges.
kitaqgb/lib/wire3d_dmg.c:3546
void Wire3DDMG_DrawLine3D(w3ddmg_i16 ax, w3ddmg_i16 ay, w3ddmg_i16 az, w3ddmg_i16 bx, w3ddmg_i16 by, w3ddmg_i16 bz)
{
w3ddmg_u8 sx0;
w3ddmg_u8 sy0;
w3ddmg_u8 sx1;
w3ddmg_u8 sy1;
if (w3ddmg_project_world(ax, ay, az, &sx0, &sy0) == 0) return;
if (w3ddmg_project_world(bx, by, bz, &sx1, &sy1) == 0) return;
Wire3DDMG_DrawLine2D(sx0, sy0, sx1, sy1);
}Wire3DDMG_DrawModel
Dibuja un modelo de vértices y aristas en la posición y con la rotación indicadas, a escala unitaria.
Sintaxis
void Wire3DDMG_DrawModel(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz);Parámetros
modelModelo que contiene los arrays de vértices, aristas y caras y sus cantidades; las tablas deben permanecer legibles durante la llamada.
xComponente X del punto o del origen del objeto en coordenadas del mundo.
yComponente Y del punto o del origen del objeto en coordenadas del mundo.
zComponente Z del punto o del origen del objeto en coordenadas del mundo.
rxRotación alrededor de X; dieciséis pasos forman una vuelta completa.
ryRotación alrededor de Y; dieciséis pasos forman una vuelta completa.
rzRotación alrededor de Z; dieciséis pasos forman una vuelta completa.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 96 void Wire3DDMG_DrawModel(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz); Dibuja un modelo sin cambiar su tamaño mediante DrawModelScaled con escala 256. WIRE3D_DMG_HEIGHT = 120 void Wire3DDMG_DrawModel(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz); Dibuja un modelo sin cambiar su tamaño mediante DrawModelScaled con escala 256.
Este ejemplo usa el perfil 128×120; su ventana gráfica empieza en (16,8) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
WIRE3D_DMG_HEIGHT vale 120 de forma predeterminada. Usa wire3d_dmg_96.c para la altura 96. SelectEdgeMask está disponible con altura 96; RotatePoint, DrawIndexedEdges, los controles de habilitación de transferencia y las transferencias directas requieren altura 120.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Compare direct model scaling with an object-array scene.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3DDMG_Vec3 vertices[8]={{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}};
__prg_rom Wire3DDMG_Edge edges[12]={{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}};
Wire3DDMG_Model cube;
Wire3DDMG_Object objects[2];
s16 px; s16 py; s16 pz;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3DDMG_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
cube.vertices=vertices;cube.edges=edges;cube.faces=0;cube.edge_faces=0;
cube.vertex_count=8;cube.edge_count=12;cube.face_count=0;cube.flags=0;
Wire3DDMG_BeginFrame();
// Upper pair: direct model calls at unity and half scale.
Wire3DDMG_DrawModel(&cube,-32,32,96,0,0,0);
Wire3DDMG_DrawModelScaled(&cube,32,32,96,0,0,0,128);
// Lower pair: the caller owns both object records and the model tables.
for(i=0;i<2;i++) {
objects[i].model=&cube;objects[i].x=-32+(s16)i*64;
objects[i].y=-32;objects[i].z=96;
objects[i].rx=0;objects[i].ry=0;objects[i].rz=0;
objects[i].scale_q8=256-(s16)i*128;objects[i].visible=1;
}
Wire3DDMG_DrawScene(objects,2);
// Numeric checks cover the operation supplied by this viewport profile.
px=16;py=0;pz=0;Wire3DDMG_RotatePoint(&px,&py,&pz,0,4,0);
result[1]=px; result[2]=py; result[3]=pz;
Wire3DDMG_EndFrame(); result[7]=0xA55A;
while(1) {}
}Resultado esperado
Los modelos a escala unitaria y a media escala aparecen sobre una escena de un array de objetos con esas mismas escalas, para mostrar la proyección y el escalado.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_models.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_dmg.h:164
Draw an unscaled model by delegating to DrawModelScaled with scale 256.
kitaqgb/lib/wire3d_dmg.c:3565
void Wire3DDMG_DrawModel(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz)
{
Wire3DDMG_DrawModelScaled(model, x, y, z, rx, ry, rz, 256);
}kitaqgb/lib/wire3d_dmg.c:3563
void Wire3DDMG_DrawModel(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz)
{
Wire3DDMG_DrawModelScaled(model, x, y, z, rx, ry, rz, 256);
}Wire3DDMG_DrawModelScaled
Escala un modelo, lo rota en orden Y/X/Z, traslada y proyecta sus vértices y dibuja las aristas.
Sintaxis
void Wire3DDMG_DrawModelScaled(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz, w3ddmg_i16 scale_q8);Parámetros
modelModelo que contiene los arrays de vértices, aristas y caras y sus cantidades; las tablas deben permanecer legibles durante la llamada.
xComponente X del punto o del origen del objeto en coordenadas del mundo.
yComponente Y del punto o del origen del objeto en coordenadas del mundo.
zComponente Z del punto o del origen del objeto en coordenadas del mundo.
rxRotación alrededor de X; dieciséis pasos forman una vuelta completa.
ryRotación alrededor de Y; dieciséis pasos forman una vuelta completa.
rzRotación alrededor de Z; dieciséis pasos forman una vuelta completa.
scale_q8Escala con 256 como unidad; los valores no positivos también equivalen a la unidad.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 96 void Wire3DDMG_DrawModelScaled(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz, w3ddmg_i16 scale_q8); Escala hasta 24 vértices, los rota en orden Y/X/Z, los traslada y proyecta; después dibuja hasta 16 aristas filtradas por máscaras de guiñada y, opcionalmente, por caras frontales. Una escala no positiva pasa a ser unitaria (256). Ignora punteros null de modelo, vértices o aristas; las tablas referenciadas deben seguir siendo legibles. Mantén productos de escala y traslaciones en el rango de 16 bits con signo. Las aristas que cruzan límites de profundidad se descartan, no se recortan. WIRE3D_DMG_HEIGHT = 120 void Wire3DDMG_DrawModelScaled(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz, w3ddmg_i16 scale_q8); Escala hasta 24 vértices, los rota Y/X/Z, los traslada y proyecta, y recorre todas las entradas de edge_count, un contador de tipo byte, con filtrado opcional por caras adyacentes. El búfer de caras está limitado a 16; las tablas de aristas deben incluir todas las entradas declaradas. Una escala no positiva significa 256. Ignora punteros null de modelo, vértices o aristas. Mantén productos y traslaciones en 16 bits con signo; se descartan las aristas que cruzan límites de profundidad.
Este ejemplo usa el perfil 128×120; su ventana gráfica empieza en (16,8) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
WIRE3D_DMG_HEIGHT vale 120 de forma predeterminada. Usa wire3d_dmg_96.c para la altura 96. SelectEdgeMask está disponible con altura 96; RotatePoint, DrawIndexedEdges, los controles de habilitación de transferencia y las transferencias directas requieren altura 120.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Compare direct model scaling with an object-array scene.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3DDMG_Vec3 vertices[8]={{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}};
__prg_rom Wire3DDMG_Edge edges[12]={{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}};
Wire3DDMG_Model cube;
Wire3DDMG_Object objects[2];
s16 px; s16 py; s16 pz;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3DDMG_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
cube.vertices=vertices;cube.edges=edges;cube.faces=0;cube.edge_faces=0;
cube.vertex_count=8;cube.edge_count=12;cube.face_count=0;cube.flags=0;
Wire3DDMG_BeginFrame();
// Upper pair: direct model calls at unity and half scale.
Wire3DDMG_DrawModel(&cube,-32,32,96,0,0,0);
Wire3DDMG_DrawModelScaled(&cube,32,32,96,0,0,0,128);
// Lower pair: the caller owns both object records and the model tables.
for(i=0;i<2;i++) {
objects[i].model=&cube;objects[i].x=-32+(s16)i*64;
objects[i].y=-32;objects[i].z=96;
objects[i].rx=0;objects[i].ry=0;objects[i].rz=0;
objects[i].scale_q8=256-(s16)i*128;objects[i].visible=1;
}
Wire3DDMG_DrawScene(objects,2);
// Numeric checks cover the operation supplied by this viewport profile.
px=16;py=0;pz=0;Wire3DDMG_RotatePoint(&px,&py,&pz,0,4,0);
result[1]=px; result[2]=py; result[3]=pz;
Wire3DDMG_EndFrame(); result[7]=0xA55A;
while(1) {}
}Resultado esperado
Los modelos a escala unitaria y a media escala aparecen sobre una escena de un array de objetos con esas mismas escalas, para mostrar la proyección y el escalado.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_models.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_dmg.h:170
Scale up to 24 vertices, rotate Y/X/Z, translate and project, then traverse all edge_count entries (a byte count) with optional adjacent-face filtering. Face scratch is capped at 16; edge tables must contain all declared entries. Nonpositive scale means 256. Null model/vertex/edge pointers are ignored. Keep products/translations in signed 16-bit range; depth-crossing edges are dropped.
kitaqgb/lib/wire3d_dmg.c:3710
void Wire3DDMG_DrawModelScaled(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz, w3ddmg_i16 scale_q8)
{
w3ddmg_u8 i;
w3ddmg_u8 count;
w3ddmg_u8 edge_count;
w3ddmg_u8 face_count;
if (model == 0) return;
if (model->vertices == 0) return;
if (model->edges == 0) return;
if (scale_q8 <= 0) scale_q8 = 256;
count = model->vertex_count;
if (count > WIRE3D_DMG_MODEL_VERTEX_LIMIT) count = WIRE3D_DMG_MODEL_VERTEX_LIMIT;
i = 0;
while (i < count)
{
const Wire3DDMG_Vec3* v;
w3ddmg_i16 vx;
w3ddmg_i16 vy;
w3ddmg_i16 vz;
w3ddmg_u8 sx;
w3ddmg_u8 sy;
v = &model->vertices[(__safe_index w3ddmg_u8)i];
vx = (w3ddmg_i16)((v->x * scale_q8) >> 8);
vy = (w3ddmg_i16)((v->y * scale_q8) >> 8);
vz = (w3ddmg_i16)((v->z * scale_q8) >> 8);
w3ddmg_rotate_y(&vx, &vz, ry);
w3ddmg_rotate_x(&vy, &vz, rx);
w3ddmg_rotate_z(&vx, &vy, rz);
vx = (w3ddmg_i16)(vx + x);
vy = (w3ddmg_i16)(vy + y);
vz = (w3ddmg_i16)(vz + z);
if (w3ddmg_project_world(vx, vy, vz, &sx, &sy))
{
w3ddmg_screen_x[(__safe_index w3ddmg_u8)i] = sx;
w3ddmg_screen_y[(__safe_index w3ddmg_u8)i] = sy;
w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 1;
}
else
{
w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 0;
}
i = (w3ddmg_u8)(i + 1);
}
face_count = model->face_count;
if (face_count > WIRE3D_DMG_MODEL_FACE_LIMIT) face_count = WIRE3D_DMG_MODEL_FACE_LIMIT;
if ((model->flags & WIRE3D_DMG_MODEL_HIDDEN_LINES) && (model->faces != 0) && (model->edge_faces != 0))
{
w3ddmg_build_face_visibility(model, count, face_count);
}
edge_count = model->edge_count;
i = 0;
while (i < edge_count)
{
const Wire3DDMG_Edge* e;
e = &model->edges[(__safe_index w3ddmg_u8)i];
if ((e->a < count) && (e->b < count))
{
if (w3ddmg_screen_visible[(__safe_index w3ddmg_u8)e->a] &&
w3ddmg_screen_visible[(__safe_index w3ddmg_u8)e->b] &&
w3ddmg_is_edge_visible(model, i, face_count))
{
Wire3DDMG_DrawLine2D(
w3ddmg_screen_x[(__safe_index w3ddmg_u8)e->a],
w3ddmg_screen_y[(__safe_index w3ddmg_u8)e->a],
w3ddmg_screen_x[(__safe_index w3ddmg_u8)e->b],
w3ddmg_screen_y[(__safe_index w3ddmg_u8)e->b]);
}
}
i = (w3ddmg_u8)(i + 1);
}
}kitaqgb/lib/wire3d_dmg.c:3703
void Wire3DDMG_DrawModelScaled(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz, w3ddmg_i16 scale_q8)
{
w3ddmg_u8 i;
w3ddmg_u8 count;
w3ddmg_u8 edge_count;
w3ddmg_u8 face_count;
if (model == 0) return;
if (model->vertices == 0) return;
if (model->edges == 0) return;
if (scale_q8 <= 0) scale_q8 = 256;
count = model->vertex_count;
if (count > WIRE3D_DMG_MODEL_VERTEX_LIMIT) count = WIRE3D_DMG_MODEL_VERTEX_LIMIT;
i = 0;
while (i < count)
{
const Wire3DDMG_Vec3* v;
w3ddmg_i16 vx;
w3ddmg_i16 vy;
w3ddmg_i16 vz;
w3ddmg_u8 sx;
w3ddmg_u8 sy;
v = &model->vertices[(__safe_index w3ddmg_u8)i];
vx = (w3ddmg_i16)((v->x * scale_q8) >> 8);
vy = (w3ddmg_i16)((v->y * scale_q8) >> 8);
vz = (w3ddmg_i16)((v->z * scale_q8) >> 8);
w3ddmg_rotate_y(&vx, &vz, (w3ddmg_i8)ry);
w3ddmg_rotate_x(&vy, &vz, (w3ddmg_i8)rx);
w3ddmg_rotate_z(&vx, &vy, (w3ddmg_i8)rz);
vx = (w3ddmg_i16)(vx + x);
vy = (w3ddmg_i16)(vy + y);
vz = (w3ddmg_i16)(vz + z);
if (w3ddmg_project_world(vx, vy, vz, &sx, &sy))
{
w3ddmg_screen_x[(__safe_index w3ddmg_u8)i] = sx;
w3ddmg_screen_y[(__safe_index w3ddmg_u8)i] = sy;
w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 1;
}
else
{
w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 0;
}
i = (w3ddmg_u8)(i + 1);
}
face_count = model->face_count;
if (face_count > WIRE3D_DMG_MODEL_FACE_LIMIT) face_count = WIRE3D_DMG_MODEL_FACE_LIMIT;
if ((model->flags & WIRE3D_DMG_MODEL_HIDDEN_LINES) && (model->faces != 0) && (model->edge_faces != 0))
{
w3ddmg_build_face_visibility(model, count, face_count);
}
edge_count = model->edge_count;
if (edge_count > WIRE3D_DMG_MODEL_EDGE_LIMIT) edge_count = WIRE3D_DMG_MODEL_EDGE_LIMIT;
w3ddmg_build_edge_flags(model, edge_count, face_count, rx, ry, rz);
i = 0;
while (i < edge_count)
{
const Wire3DDMG_Edge* e;
e = &model->edges[(__safe_index w3ddmg_u8)i];
if ((e->a < count) && (e->b < count))
{
if (w3ddmg_screen_visible[(__safe_index w3ddmg_u8)e->a] &&
w3ddmg_screen_visible[(__safe_index w3ddmg_u8)e->b] &&
w3ddmg_edge_flags[(__safe_index w3ddmg_u8)i])
{
Wire3DDMG_DrawLine2D(
w3ddmg_screen_x[(__safe_index w3ddmg_u8)e->a],
w3ddmg_screen_y[(__safe_index w3ddmg_u8)e->a],
w3ddmg_screen_x[(__safe_index w3ddmg_u8)e->b],
w3ddmg_screen_y[(__safe_index w3ddmg_u8)e->b]);
}
}
i = (w3ddmg_u8)(i + 1);
}
}Wire3DDMG_DrawScene
Dibuja hasta ocho objetos de cerca a lejos, usando las caras cercanas para ocultar las aristas posteriores.
Sintaxis
void Wire3DDMG_DrawScene(Wire3DDMG_Object* objects, w3ddmg_u8 count);Parámetros
objectsArray de objetos con posiciones, rotaciones, escalas e indicadores de visibilidad.
countCantidad de entradas proporcionadas; consulta el límite de procesamiento de cada operación.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 96 void Wire3DDMG_DrawScene(Wire3DDMG_Object* objects, w3ddmg_u8 count); Procesa como máximo los primeros ocho objetos, ordenados de cerca a lejos por la profundidad de su origen transformado. Dibuja modelos visibles y válidos y marca los rectángulos envolventes de sus caras frontales para rechazar líneas posteriores cuyos puntos de muestreo queden todos ocultos. Aproxima la oclusión entre objetos; no es un búfer de profundidad. Borra su máscara, pero conserva los píxeles ya preparados. Ignora arrays null; los objetos y sus datos deben seguir siendo legibles. WIRE3D_DMG_HEIGHT = 120 void Wire3DDMG_DrawScene(Wire3DDMG_Object* objects, w3ddmg_u8 count); Ordena hasta ocho orígenes de objeto de cerca a lejos por su profundidad de cámara. Dibuja modelos visibles y válidos y marca rectángulos envolventes de caras frontales para los objetos posteriores. La primera posición ordenada omite las pruebas de máscara y la última no añade un nuevo oclusor. Es un rechazo aproximado de líneas, no un búfer de profundidad. Ignora null y entradas vacías; los datos del código que llama y la caché de proyección actual deben ser válidos durante el recorrido.
Este ejemplo usa el perfil 128×120; su ventana gráfica empieza en (16,8) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
WIRE3D_DMG_HEIGHT vale 120 de forma predeterminada. Usa wire3d_dmg_96.c para la altura 96. SelectEdgeMask está disponible con altura 96; RotatePoint, DrawIndexedEdges, los controles de habilitación de transferencia y las transferencias directas requieren altura 120.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Compare direct model scaling with an object-array scene.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3DDMG_Vec3 vertices[8]={{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}};
__prg_rom Wire3DDMG_Edge edges[12]={{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}};
Wire3DDMG_Model cube;
Wire3DDMG_Object objects[2];
s16 px; s16 py; s16 pz;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3DDMG_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
cube.vertices=vertices;cube.edges=edges;cube.faces=0;cube.edge_faces=0;
cube.vertex_count=8;cube.edge_count=12;cube.face_count=0;cube.flags=0;
Wire3DDMG_BeginFrame();
// Upper pair: direct model calls at unity and half scale.
Wire3DDMG_DrawModel(&cube,-32,32,96,0,0,0);
Wire3DDMG_DrawModelScaled(&cube,32,32,96,0,0,0,128);
// Lower pair: the caller owns both object records and the model tables.
for(i=0;i<2;i++) {
objects[i].model=&cube;objects[i].x=-32+(s16)i*64;
objects[i].y=-32;objects[i].z=96;
objects[i].rx=0;objects[i].ry=0;objects[i].rz=0;
objects[i].scale_q8=256-(s16)i*128;objects[i].visible=1;
}
Wire3DDMG_DrawScene(objects,2);
// Numeric checks cover the operation supplied by this viewport profile.
px=16;py=0;pz=0;Wire3DDMG_RotatePoint(&px,&py,&pz,0,4,0);
result[1]=px; result[2]=py; result[3]=pz;
Wire3DDMG_EndFrame(); result[7]=0xA55A;
while(1) {}
}Resultado esperado
Los modelos a escala unitaria y a media escala aparecen sobre una escena de un array de objetos con esas mismas escalas, para mostrar la proyección y el escalado.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_models.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_dmg.h:201
Sort at most eight object origins by camera depth, near to far. Draw visible valid models and mark front-face bounding rectangles for later objects. The first sorted slot bypasses mask tests and the last needs no new occluder. This is coarse line rejection, not a depth buffer. Null/empty input is ignored; caller data and the current projection cache must remain valid during traversal.
kitaqgb/lib/wire3d_dmg.c:3461
void Wire3DDMG_DrawScene(Wire3DDMG_Object* objects, w3ddmg_u8 count)
{
w3ddmg_u8 scene_count;
w3ddmg_u8 i;
if (objects == 0) return;
scene_count = count;
if (scene_count > WIRE3D_DMG_SCENE_OBJECT_LIMIT) scene_count = WIRE3D_DMG_SCENE_OBJECT_LIMIT;
if (scene_count == 0) return;
i = 0;
while (i < scene_count)
{
w3ddmg_scene_order[(__safe_index w3ddmg_u8)i] = i;
w3ddmg_scene_depth[(__safe_index w3ddmg_u8)i] = w3ddmg_scene_object_depth(&objects[(__safe_index w3ddmg_u8)i]);
i = (w3ddmg_u8)(i + 1);
}
i = 0;
while (i < scene_count)
{
w3ddmg_u8 j;
j = (w3ddmg_u8)(i + 1);
while (j < scene_count)
{
w3ddmg_u8 oi;
w3ddmg_u8 oj;
oi = w3ddmg_scene_order[(__safe_index w3ddmg_u8)i];
oj = w3ddmg_scene_order[(__safe_index w3ddmg_u8)j];
if (w3ddmg_scene_depth[(__safe_index w3ddmg_u8)oj] < w3ddmg_scene_depth[(__safe_index w3ddmg_u8)oi])
{
w3ddmg_scene_order[(__safe_index w3ddmg_u8)i] = oj;
w3ddmg_scene_order[(__safe_index w3ddmg_u8)j] = oi;
}
j = (w3ddmg_u8)(j + 1);
}
i = (w3ddmg_u8)(i + 1);
}
w3ddmg_clear_occlusion_mask();
w3ddmg_occlusion_active = 0;
i = 0;
while (i < scene_count)
{
Wire3DDMG_Object* obj;
obj = &objects[(__safe_index w3ddmg_u8)w3ddmg_scene_order[(__safe_index w3ddmg_u8)i]];
if ((obj->visible != 0) && (obj->model != 0))
{
w3ddmg_occlusion_active = i == 0 ? 0 : 1;
Wire3DDMG_DrawModelScaled(obj->model, obj->x, obj->y, obj->z, obj->rx, obj->ry, obj->rz, obj->scale_q8);
if ((w3ddmg_u8)(i + 1) < scene_count)
{
w3ddmg_mark_model_occluder(obj->model);
}
}
i = (w3ddmg_u8)(i + 1);
}
w3ddmg_occlusion_active = 0;
}Wire3DDMG_EndFrame
Envía a VRAM las escrituras del fondo pendientes y el dibujo preparado.
Sintaxis
void Wire3DDMG_EndFrame();Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 96 void Wire3DDMG_EndFrame(); Espera al siguiente VBlank, aplica las escrituras BG pendientes y copia el área de preparación a VRAM consultando los intervalos de acceso. La copia consume los píxeles preparados. La transferencia puede prolongarse más allá de VBlank; no es un intercambio atómico de fotograma. WIRE3D_DMG_HEIGHT = 120 void Wire3DDMG_EndFrame(); Espera al siguiente VBlank y aplica las escrituras BG; después, si está habilitado, consume las franjas auxiliares antes de transferir los tiles modificados o toda el área principal. El solapamiento entre ambas fuentes hace importante ese orden. La consulta de STAT continúa entre intervalos de acceso; la actualización puede no caber en un solo VBlank.
Este ejemplo usa el perfil 128×120; su ventana gráfica empieza en (16,8) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
WIRE3D_DMG_HEIGHT vale 120 de forma predeterminada. Usa wire3d_dmg_96.c para la altura 96. SelectEdgeMask está disponible con altura 96; RotatePoint, DrawIndexedEdges, los controles de habilitación de transferencia y las transferencias directas requieren altura 120.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3DDMG_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
Wire3DDMG_SetCamera(8,0,0,0,0,0);
result[1]=Wire3DDMG_ProjectPoint(0,0,96,&projected_x,&projected_y);
result[2]=projected_x; result[3]=projected_y;
projected_x=91; projected_y=92;
result[4]=Wire3DDMG_ProjectPoint(0,0,7,&projected_x,&projected_y);
result[5]=projected_x; result[6]=projected_y;
Wire3DDMG_SetCamera(0,0,0,0,0,0);
Wire3DDMG_BeginFrame();
Wire3DDMG_DrawLine2D(8,8,56,8);
Wire3DDMG_DrawLine2D(56,8,56,40);
Wire3DDMG_DrawLine2D(56,40,8,40);
Wire3DDMG_DrawLine2D(8,40,8,8);
Wire3DDMG_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
Wire3DDMG_DrawLine3D(-24,-24,96,24,24,96);
// Copy the viewport's top-left frame corner to a separate map cell.
Wire3DDMG_PutBgTile(1,1,160);
Wire3DDMG_EndFrame();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Este ejemplo muestra líneas, puntos, borrado y proyección en un fotograma. Se borra el centro del borde superior del marco de arriba a la izquierda y se proyecta una diagonal cerca del centro. Una proyección rechazada conserva las salidas 91 y 92.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_raster.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_dmg.h:286
Wait for the next VBlank and flush BG writes, then optionally consume the auxiliary strips before uploading either dirty tiles or the entire main stage. Auxiliary/main source overlap makes that ordering significant. STAT polling continues across access windows; the update need not fit one VBlank.
kitaqgb/lib/wire3d_dmg.c:3819
void Wire3DDMG_EndFrame()
{
w3ddmg_wait_vblank_start();
Wire3DDMG_EndFrameNow();
}Wire3DDMG_EraseModelFaces
Proyecta los triángulos frontales del modelo y borra los píxeles preparados de su interior.
Sintaxis
void Wire3DDMG_EraseModelFaces(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz, w3ddmg_i16 scale_q8);Parámetros
modelModelo que contiene los arrays de vértices, aristas y caras y sus cantidades; las tablas deben permanecer legibles durante la llamada.
xComponente X del punto o del origen del objeto en coordenadas del mundo.
yComponente Y del punto o del origen del objeto en coordenadas del mundo.
zComponente Z del punto o del origen del objeto en coordenadas del mundo.
rxRotación alrededor de X; dieciséis pasos forman una vuelta completa.
ryRotación alrededor de Y; dieciséis pasos forman una vuelta completa.
rzRotación alrededor de Z; dieciséis pasos forman una vuelta completa.
scale_q8Escala con 256 como unidad; los valores no positivos también equivalen a la unidad.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 96 void Wire3DDMG_EraseModelFaces(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz, w3ddmg_i16 scale_q8); Proyecta hasta 24 vértices y borra del área de preparación el interior de los triángulos frontales de un modelo con indicadores de líneas ocultas y datos de caras. Una escala no positiva significa 256, la unidad. Examina hasta 16 caras y omite las que cruzan límites de profundidad. También sustituye las cachés de proyección compartidas, pero no actualiza VRAM. WIRE3D_DMG_HEIGHT = 120 void Wire3DDMG_EraseModelFaces(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz, w3ddmg_i16 scale_q8); Proyecta hasta 24 vértices y borra del área de preparación el interior de los triángulos frontales de un modelo con indicadores de líneas ocultas y datos de caras. Una escala no positiva significa 256, la unidad. Examina hasta 16 caras y omite las que cruzan límites de profundidad. También sustituye las cachés de proyección compartidas, pero no actualiza VRAM.
Este ejemplo usa el perfil 128×120; su ventana gráfica empieza en (16,8) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
WIRE3D_DMG_HEIGHT vale 120 de forma predeterminada. Usa wire3d_dmg_96.c para la altura 96. SelectEdgeMask está disponible con altura 96; RotatePoint, DrawIndexedEdges, los controles de habilitación de transferencia y las transferencias directas requieren altura 120.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Erase a screen triangle and a projected model face from separate filled panels.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3DDMG_Vec3 vertices[4]={{-24,-24,0},{24,-24,0},{24,24,0},{-24,24,0}};
__prg_rom Wire3DDMG_Edge edges[4]={{0,1},{1,2},{2,3},{3,0}};
__prg_rom Wire3DDMG_Face faces[2]={{0,2,1},{0,3,2}};
Wire3DDMG_Model plane;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3DDMG_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
plane.vertices=vertices;plane.edges=edges;plane.faces=faces;plane.edge_faces=0;
plane.vertex_count=4;plane.edge_count=4;plane.face_count=2;plane.flags=1;
Wire3DDMG_BeginFrame();
// Separate panels show a direct screen triangle and a projected square face.
for(i=8;i<=32;i++) Wire3DDMG_DrawLine2D(8,i,32,i);
for(i=36;i<=84;i++) Wire3DDMG_DrawLine2D(40,i,88,i);
Wire3DDMG_EraseTriangle2D(12,12,28,12,12,28);
Wire3DDMG_EraseModelFaces(&plane,0,0,64,0,0,0,256);
Wire3DDMG_EndFrame(); result[7]=0xA55A; while(1) {}
}Resultado esperado
Las caras proyectadas borran una región rellena y permiten distinguir las zonas conservadas de las borradas.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_faces.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_faces.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_dmg.h:179
Project up to 24 vertices and erase front-facing triangle interiors from the stage for a model with hidden-line flags and face data. Nonpositive scale means 256 (unity). Up to 16 faces are considered; depth-crossing faces are skipped. This also replaces shared projection caches, but does not update VRAM.
kitaqgb/lib/wire3d_dmg.c:3581
void Wire3DDMG_EraseModelFaces(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz, w3ddmg_i16 scale_q8)
{
w3ddmg_u8 i;
w3ddmg_u8 count;
w3ddmg_u8 face_count;
if (model == 0) return;
if (model->vertices == 0) return;
if (model->faces == 0) return;
if ((model->flags & WIRE3D_DMG_MODEL_HIDDEN_LINES) == 0) return;
if (scale_q8 <= 0) scale_q8 = 256;
count = model->vertex_count;
if (count > WIRE3D_DMG_MODEL_VERTEX_LIMIT) count = WIRE3D_DMG_MODEL_VERTEX_LIMIT;
i = 0;
while (i < count)
{
const Wire3DDMG_Vec3* v;
w3ddmg_i16 vx;
w3ddmg_i16 vy;
w3ddmg_i16 vz;
w3ddmg_u8 sx;
w3ddmg_u8 sy;
v = &model->vertices[(__safe_index w3ddmg_u8)i];
vx = (w3ddmg_i16)((v->x * scale_q8) >> 8);
vy = (w3ddmg_i16)((v->y * scale_q8) >> 8);
vz = (w3ddmg_i16)((v->z * scale_q8) >> 8);
w3ddmg_rotate_y(&vx, &vz, ry);
w3ddmg_rotate_x(&vy, &vz, rx);
w3ddmg_rotate_z(&vx, &vy, rz);
vx = (w3ddmg_i16)(vx + x);
vy = (w3ddmg_i16)(vy + y);
vz = (w3ddmg_i16)(vz + z);
if (w3ddmg_project_world(vx, vy, vz, &sx, &sy))
{
w3ddmg_screen_x[(__safe_index w3ddmg_u8)i] = sx;
w3ddmg_screen_y[(__safe_index w3ddmg_u8)i] = sy;
w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 1;
}
else
{
w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 0;
}
i = (w3ddmg_u8)(i + 1);
}
face_count = model->face_count;
if (face_count > WIRE3D_DMG_MODEL_FACE_LIMIT) face_count = WIRE3D_DMG_MODEL_FACE_LIMIT;
w3ddmg_build_face_visibility(model, count, face_count);
i = 0;
while (i < face_count)
{
const Wire3DDMG_Face* f;
f = &model->faces[(__safe_index w3ddmg_u8)i];
if (w3ddmg_face_visible[(__safe_index w3ddmg_u8)i] &&
w3ddmg_screen_visible[(__safe_index w3ddmg_u8)f->a] &&
w3ddmg_screen_visible[(__safe_index w3ddmg_u8)f->b] &&
w3ddmg_screen_visible[(__safe_index w3ddmg_u8)f->c])
{
w3ddmg_clear_triangle(
w3ddmg_screen_x[(__safe_index w3ddmg_u8)f->a],
w3ddmg_screen_y[(__safe_index w3ddmg_u8)f->a],
w3ddmg_screen_x[(__safe_index w3ddmg_u8)f->b],
w3ddmg_screen_y[(__safe_index w3ddmg_u8)f->b],
w3ddmg_screen_x[(__safe_index w3ddmg_u8)f->c],
w3ddmg_screen_y[(__safe_index w3ddmg_u8)f->c]);
}
i = (w3ddmg_u8)(i + 1);
}
}kitaqgb/lib/wire3d_dmg.c:3579
void Wire3DDMG_EraseModelFaces(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz, w3ddmg_i16 scale_q8)
{
w3ddmg_u8 i;
w3ddmg_u8 count;
w3ddmg_u8 face_count;
if (model == 0) return;
if (model->vertices == 0) return;
if (model->faces == 0) return;
if ((model->flags & WIRE3D_DMG_MODEL_HIDDEN_LINES) == 0) return;
if (scale_q8 <= 0) scale_q8 = 256;
count = model->vertex_count;
if (count > WIRE3D_DMG_MODEL_VERTEX_LIMIT) count = WIRE3D_DMG_MODEL_VERTEX_LIMIT;
i = 0;
while (i < count)
{
const Wire3DDMG_Vec3* v;
w3ddmg_i16 vx;
w3ddmg_i16 vy;
w3ddmg_i16 vz;
w3ddmg_u8 sx;
w3ddmg_u8 sy;
v = &model->vertices[(__safe_index w3ddmg_u8)i];
vx = (w3ddmg_i16)((v->x * scale_q8) >> 8);
vy = (w3ddmg_i16)((v->y * scale_q8) >> 8);
vz = (w3ddmg_i16)((v->z * scale_q8) >> 8);
w3ddmg_rotate_y(&vx, &vz, (w3ddmg_i8)ry);
w3ddmg_rotate_x(&vy, &vz, (w3ddmg_i8)rx);
w3ddmg_rotate_z(&vx, &vy, (w3ddmg_i8)rz);
vx = (w3ddmg_i16)(vx + x);
vy = (w3ddmg_i16)(vy + y);
vz = (w3ddmg_i16)(vz + z);
if (w3ddmg_project_world(vx, vy, vz, &sx, &sy))
{
w3ddmg_screen_x[(__safe_index w3ddmg_u8)i] = sx;
w3ddmg_screen_y[(__safe_index w3ddmg_u8)i] = sy;
w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 1;
}
else
{
w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 0;
}
i = (w3ddmg_u8)(i + 1);
}
face_count = model->face_count;
if (face_count > WIRE3D_DMG_MODEL_FACE_LIMIT) face_count = WIRE3D_DMG_MODEL_FACE_LIMIT;
w3ddmg_build_face_visibility(model, count, face_count);
i = 0;
while (i < face_count)
{
const Wire3DDMG_Face* f;
f = &model->faces[(__safe_index w3ddmg_u8)i];
if (w3ddmg_face_visible[(__safe_index w3ddmg_u8)i] &&
w3ddmg_screen_visible[(__safe_index w3ddmg_u8)f->a] &&
w3ddmg_screen_visible[(__safe_index w3ddmg_u8)f->b] &&
w3ddmg_screen_visible[(__safe_index w3ddmg_u8)f->c])
{
w3ddmg_clear_triangle(
w3ddmg_screen_x[(__safe_index w3ddmg_u8)f->a],
w3ddmg_screen_y[(__safe_index w3ddmg_u8)f->a],
w3ddmg_screen_x[(__safe_index w3ddmg_u8)f->b],
w3ddmg_screen_y[(__safe_index w3ddmg_u8)f->b],
w3ddmg_screen_x[(__safe_index w3ddmg_u8)f->c],
w3ddmg_screen_y[(__safe_index w3ddmg_u8)f->c]);
}
i = (w3ddmg_u8)(i + 1);
}
}Wire3DDMG_EraseSpan2D
Borra un tramo horizontal, con ambos extremos incluidos, de una fila preparada.
Sintaxis
void Wire3DDMG_EraseSpan2D(w3ddmg_u8 y, w3ddmg_u8 x0, w3ddmg_u8 x1);Parámetros
yCoordenada Y en píxeles de la fila que se va a borrar.
x0Extremo X inferior, en píxeles de la ventana gráfica; el orden y el recorte siguen las notas de esta operación.
x1Extremo X superior, en píxeles de la ventana gráfica; el orden y el recorte siguen las notas de esta operación.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 96 void Wire3DDMG_EraseSpan2D(w3ddmg_u8 y, w3ddmg_u8 x0, w3ddmg_u8 x1); Ordena los extremos X y borra el tramo preparado, incluidos ambos extremos. Los dos deben estar en 0..127; un Y inválido se ignora. La rutina no recorta X automáticamente. WIRE3D_DMG_HEIGHT = 120 void Wire3DDMG_EraseSpan2D(w3ddmg_u8 y, w3ddmg_u8 x0, w3ddmg_u8 x1); Ordena los extremos X y borra el tramo preparado, incluidos ambos extremos. Los dos deben estar en 0..127; un Y inválido se ignora. La rutina no recorta X automáticamente.
Este ejemplo usa el perfil 128×120; su ventana gráfica empieza en (16,8) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
WIRE3D_DMG_HEIGHT vale 120 de forma predeterminada. Usa wire3d_dmg_96.c para la altura 96. SelectEdgeMask está disponible con altura 96; RotatePoint, DrawIndexedEdges, los controles de habilitación de transferencia y las transferencias directas requieren altura 120.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3DDMG_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
Wire3DDMG_SetCamera(8,0,0,0,0,0);
result[1]=Wire3DDMG_ProjectPoint(0,0,96,&projected_x,&projected_y);
result[2]=projected_x; result[3]=projected_y;
projected_x=91; projected_y=92;
result[4]=Wire3DDMG_ProjectPoint(0,0,7,&projected_x,&projected_y);
result[5]=projected_x; result[6]=projected_y;
Wire3DDMG_SetCamera(0,0,0,0,0,0);
Wire3DDMG_BeginFrame();
Wire3DDMG_DrawLine2D(8,8,56,8);
Wire3DDMG_DrawLine2D(56,8,56,40);
Wire3DDMG_DrawLine2D(56,40,8,40);
Wire3DDMG_DrawLine2D(8,40,8,8);
Wire3DDMG_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
Wire3DDMG_DrawLine3D(-24,-24,96,24,24,96);
// Copy the viewport's top-left frame corner to a separate map cell.
Wire3DDMG_PutBgTile(1,1,160);
Wire3DDMG_EndFrame();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Este ejemplo muestra líneas, puntos, borrado y proyección en un fotograma. Se borra el centro del borde superior del marco de arriba a la izquierda y se proyecta una diagonal cerca del centro. Una proyección rechazada conserva las salidas 91 y 92.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_raster.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_dmg.h:187
Order the X endpoints and erase the inclusive staged span. Both endpoints must be in 0..127; invalid Y is ignored. The routine does not clip X for you.
kitaqgb/lib/wire3d_dmg.c:3681
void Wire3DDMG_EraseSpan2D(w3ddmg_u8 y, w3ddmg_u8 x0, w3ddmg_u8 x1)
{
w3ddmg_u8 tx;
if (x0 > x1)
{
tx = x0;
x0 = x1;
x1 = tx;
}
w3ddmg_stage_clear_span(y, x0, x1);
}Wire3DDMG_EraseTriangle2D
Borra un triángulo de pantalla del área de preparación mediante tramos horizontales de líneas de barrido.
Sintaxis
void Wire3DDMG_EraseTriangle2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by, w3ddmg_u8 cx, w3ddmg_u8 cy);Parámetros
axCoordenada X del vértice A en píxeles de la ventana gráfica.
ayCoordenada Y del vértice A en píxeles de la ventana gráfica.
bxCoordenada X del vértice B en píxeles de la ventana gráfica.
byCoordenada Y del vértice B en píxeles de la ventana gráfica.
cxCoordenada X del vértice C en píxeles de la ventana gráfica.
cyCoordenada Y del vértice C en píxeles de la ventana gráfica.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 96 void Wire3DDMG_EraseTriangle2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by, w3ddmg_u8 cx, w3ddmg_u8 cy); Borra un triángulo de los píxeles preparados usando intersecciones enteras con líneas de barrido. Proporciona coordenadas de la ventana gráfica. Ignora triángulos degenerados; la máscara de oclusión y VRAM no cambian. WIRE3D_DMG_HEIGHT = 120 void Wire3DDMG_EraseTriangle2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by, w3ddmg_u8 cx, w3ddmg_u8 cy); Borra un triángulo de los píxeles preparados usando intersecciones enteras con líneas de barrido. Proporciona coordenadas de la ventana gráfica. Ignora triángulos degenerados; la máscara de oclusión y VRAM no cambian.
Este ejemplo usa el perfil 128×120; su ventana gráfica empieza en (16,8) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
WIRE3D_DMG_HEIGHT vale 120 de forma predeterminada. Usa wire3d_dmg_96.c para la altura 96. SelectEdgeMask está disponible con altura 96; RotatePoint, DrawIndexedEdges, los controles de habilitación de transferencia y las transferencias directas requieren altura 120.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Erase a screen triangle and a projected model face from separate filled panels.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3DDMG_Vec3 vertices[4]={{-24,-24,0},{24,-24,0},{24,24,0},{-24,24,0}};
__prg_rom Wire3DDMG_Edge edges[4]={{0,1},{1,2},{2,3},{3,0}};
__prg_rom Wire3DDMG_Face faces[2]={{0,2,1},{0,3,2}};
Wire3DDMG_Model plane;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3DDMG_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
plane.vertices=vertices;plane.edges=edges;plane.faces=faces;plane.edge_faces=0;
plane.vertex_count=4;plane.edge_count=4;plane.face_count=2;plane.flags=1;
Wire3DDMG_BeginFrame();
// Separate panels show a direct screen triangle and a projected square face.
for(i=8;i<=32;i++) Wire3DDMG_DrawLine2D(8,i,32,i);
for(i=36;i<=84;i++) Wire3DDMG_DrawLine2D(40,i,88,i);
Wire3DDMG_EraseTriangle2D(12,12,28,12,12,28);
Wire3DDMG_EraseModelFaces(&plane,0,0,64,0,0,0,256);
Wire3DDMG_EndFrame(); result[7]=0xA55A; while(1) {}
}Resultado esperado
Las caras proyectadas borran una región rellena y permiten distinguir las zonas conservadas de las borradas.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_faces.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_faces.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_dmg.h:184
Erase a triangle from staged pixels using integer scanline intersections. Supply viewport coordinates. Degenerate triangles are ignored; the occlusion mask and VRAM are unchanged.
kitaqgb/lib/wire3d_dmg.c:3671
void Wire3DDMG_EraseTriangle2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by, w3ddmg_u8 cx, w3ddmg_u8 cy)
{
w3ddmg_clear_triangle(ax, ay, bx, by, cx, cy);
}Wire3DDMG_Init
Inicializa el LCD, los tiles y el mapa del fondo para una ventana gráfica de alambre monocroma.
Sintaxis
void Wire3DDMG_Init();Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 96 void Wire3DDMG_Init(); Toma el control del LCD: espera a VBlank, lo apaga, borra 6144 bytes de tiles y el mapa BG, instala los tiles del HUD y la ventana gráfica de 128×96 con números de tile con signo, y activa el fondo con desplazamiento cero y BGP=0xB4. Reinicia cámara, cola BG y área de preparación. Reserva 0xD000..0xDFFF para esa área y conserva su mapeo de banco de WRAM. Llama a BeginFrame antes de dibujar para inicializar también la oclusión. WIRE3D_DMG_HEIGHT = 120 void Wire3DDMG_Init(); Toma el control del LCD, borra la VRAM de tiles y el mapa BG e instala una ventana gráfica de 16×15 desde el tile (3,1). Configura desplazamiento (8,0), BGP=0xB4 y la visualización BG. Reinicia cámara, colas, modos de transferencia, ambas tablas de cambios y el área de preparación. Reserva 0xD000..0xDFFF y conserva su mapeo WRAM; el almacenamiento auxiliar comparte esas direcciones. Llama a BeginFrame antes de dibujar para establecer el estado de oclusión.
Este ejemplo usa el perfil 128×120; su ventana gráfica empieza en (16,8) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
WIRE3D_DMG_HEIGHT vale 120 de forma predeterminada. Usa wire3d_dmg_96.c para la altura 96. SelectEdgeMask está disponible con altura 96; RotatePoint, DrawIndexedEdges, los controles de habilitación de transferencia y las transferencias directas requieren altura 120.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3DDMG_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
Wire3DDMG_SetCamera(8,0,0,0,0,0);
result[1]=Wire3DDMG_ProjectPoint(0,0,96,&projected_x,&projected_y);
result[2]=projected_x; result[3]=projected_y;
projected_x=91; projected_y=92;
result[4]=Wire3DDMG_ProjectPoint(0,0,7,&projected_x,&projected_y);
result[5]=projected_x; result[6]=projected_y;
Wire3DDMG_SetCamera(0,0,0,0,0,0);
Wire3DDMG_BeginFrame();
Wire3DDMG_DrawLine2D(8,8,56,8);
Wire3DDMG_DrawLine2D(56,8,56,40);
Wire3DDMG_DrawLine2D(56,40,8,40);
Wire3DDMG_DrawLine2D(8,40,8,8);
Wire3DDMG_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
Wire3DDMG_DrawLine3D(-24,-24,96,24,24,96);
// Copy the viewport's top-left frame corner to a separate map cell.
Wire3DDMG_PutBgTile(1,1,160);
Wire3DDMG_EndFrame();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Este ejemplo muestra líneas, puntos, borrado y proyección en un fotograma. Se borra el centro del borde superior del marco de arriba a la izquierda y se proyecta una diagonal cerca del centro. Una proyección rechazada conserva las salidas 91 y 92.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_raster.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_dmg.h:135
Take over LCD state, clear tile VRAM and the BG map, and install a 16x15 viewport beginning at map tile (3,1). Set scroll (8,0), BGP=0xB4 and BG display. Reset camera, queues, transfer modes, both dirty tables and stage. Reserve 0xD000..0xDFFF and retain its WRAM mapping; auxiliary storage aliases it. Call BeginFrame before drawing to establish occlusion state.
kitaqgb/lib/wire3d_dmg.c:3310
void Wire3DDMG_Init()
{
w3ddmg_u8 row;
w3ddmg_u8 col;
w3ddmg_u8 tid;
w3ddmg_u16 off;
w3ddmg_wait_vblank_start();
w3ddmg_reg_lcdc = 0;
w3ddmg_clear_vram_asm();
w3ddmg_fill_bg_map_asm();
row = 0;
tid = 0x90;
while (row < WIRE3D_DMG_TILE_H)
{
off = (w3ddmg_u16)(0x23 + ((w3ddmg_u16)row << 5));
col = 0;
while (col < WIRE3D_DMG_TILE_W)
{
w3ddmg_bg_map_9800[(w3ddmg_u16)(off + (w3ddmg_u16)col)] = tid;
tid = (w3ddmg_u8)(tid + WIRE3D_DMG_TILE_H);
col = (w3ddmg_u8)(col + 1);
}
row = (w3ddmg_u8)(row + 1);
tid = (w3ddmg_u8)(0x90 + row);
}
w3ddmg_reg_scx = 8;
w3ddmg_reg_scy = 0;
w3ddmg_reg_bgp = 0xB4;
w3ddmg_reg_lcdc = 0x81;
w3ddmg_bgq_count = 0;
w3ddmg_aux_transfer_enabled = 0;
w3ddmg_dirty_transfer_enabled = 0;
Wire3DDMG_SetCamera((w3ddmg_i16)0, (w3ddmg_i16)0, (w3ddmg_i16)0, (w3ddmg_u8)0, (w3ddmg_u8)0, (w3ddmg_u8)0);
w3ddmg_clear_stage_asm();
w3ddmg_clear_stage_aux_asm();
w3ddmg_clear_dirty_tables();
}Wire3DDMG_ProjectPoint
Proyecta un punto del mundo mediante la cámara a coordenadas de la ventana gráfica.
Sintaxis
w3ddmg_u8 Wire3DDMG_ProjectPoint(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8* sx, w3ddmg_u8* sy);Parámetros
xComponente X del punto o del origen del objeto en coordenadas del mundo.
yComponente Y del punto o del origen del objeto en coordenadas del mundo.
zComponente Z del punto o del origen del objeto en coordenadas del mundo.
sxPuntero u8 válido y escribible que recibe la coordenada X proyectada.
syPuntero u8 válido y escribible que recibe la coordenada Y proyectada.
Valor devuelto
Devuelve 1 si la proyección tiene éxito o 0 si se rechaza por profundidad.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 96 w3ddmg_u8 Wire3DDMG_ProjectPoint(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8* sx, w3ddmg_u8* sy); Proyecta un punto del mundo con la cámara actual. Una profundidad rechazada devuelve cero sin cambiar las salidas; si tiene éxito, escribe coordenadas limitadas a 128×96. Los punteros de salida deben ser válidos. Limitar coordenadas a la pantalla no es recorte geométrico. WIRE3D_DMG_HEIGHT = 120 w3ddmg_u8 Wire3DDMG_ProjectPoint(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8* sx, w3ddmg_u8* sy); Proyecta un punto del mundo con la cámara actual. Una profundidad inválida devuelve cero sin cambiar las salidas; si tiene éxito, escribe coordenadas limitadas a 128×120. Ambos punteros de salida deben ser válidos. Las diferencias de coordenadas deben caber en s16.
Este ejemplo usa el perfil 128×120; su ventana gráfica empieza en (16,8) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
WIRE3D_DMG_HEIGHT vale 120 de forma predeterminada. Usa wire3d_dmg_96.c para la altura 96. SelectEdgeMask está disponible con altura 96; RotatePoint, DrawIndexedEdges, los controles de habilitación de transferencia y las transferencias directas requieren altura 120.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3DDMG_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
Wire3DDMG_SetCamera(8,0,0,0,0,0);
result[1]=Wire3DDMG_ProjectPoint(0,0,96,&projected_x,&projected_y);
result[2]=projected_x; result[3]=projected_y;
projected_x=91; projected_y=92;
result[4]=Wire3DDMG_ProjectPoint(0,0,7,&projected_x,&projected_y);
result[5]=projected_x; result[6]=projected_y;
Wire3DDMG_SetCamera(0,0,0,0,0,0);
Wire3DDMG_BeginFrame();
Wire3DDMG_DrawLine2D(8,8,56,8);
Wire3DDMG_DrawLine2D(56,8,56,40);
Wire3DDMG_DrawLine2D(56,40,8,40);
Wire3DDMG_DrawLine2D(8,40,8,8);
Wire3DDMG_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
Wire3DDMG_DrawLine3D(-24,-24,96,24,24,96);
// Copy the viewport's top-left frame corner to a separate map cell.
Wire3DDMG_PutBgTile(1,1,160);
Wire3DDMG_EndFrame();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Este ejemplo muestra líneas, puntos, borrado y proyección en un fotograma. Se borra el centro del borde superior del marco de arriba a la izquierda y se proyecta una diagonal cerca del centro. Una proyección rechazada conserva las salidas 91 y 92.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_raster.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_dmg.h:216
Project a world point with the current camera. Return zero for invalid depth without changing outputs; success writes clamped 128x120 coordinates. Both output pointers must be valid. Coordinate differences must fit s16.
kitaqgb/lib/wire3d_dmg.c:688
w3ddmg_u8 Wire3DDMG_ProjectPoint(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8* sx, w3ddmg_u8* sy)
{
return w3ddmg_project_world(x, y, z, sx, sy);
}Wire3DDMG_PutBgTile
Encola una escritura de número de tile en una celda del mapa del fondo.
Sintaxis
void Wire3DDMG_PutBgTile(w3ddmg_u8 x, w3ddmg_u8 y, w3ddmg_u8 tile);Parámetros
xCoordenada X de tile en el mapa del fondo de 32×32.
yCoordenada Y de tile en el mapa del fondo de 32×32.
tileNúmero de tile de ocho bits para la celda del fondo.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 96 void Wire3DDMG_PutBgTile(w3ddmg_u8 x, w3ddmg_u8 y, w3ddmg_u8 tile); Encola una escritura de tile en el mapa de 32×32 en 0x9800 para EndFrame. Ignora sin aviso las coordenadas inválidas y las solicitudes que superen las 48 escrituras pendientes. Esta cola es independiente de la cola general de la biblioteca vram. WIRE3D_DMG_HEIGHT = 120 void Wire3DDMG_PutBgTile(w3ddmg_u8 x, w3ddmg_u8 y, w3ddmg_u8 tile); Encola una escritura de tile en el mapa de 32×32 en 0x9800 para EndFrame. Ignora sin aviso las coordenadas inválidas y las solicitudes que superen las 48 escrituras pendientes. Esta cola es independiente de la cola general de la biblioteca vram.
Este ejemplo usa el perfil 128×120; su ventana gráfica empieza en (16,8) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
WIRE3D_DMG_HEIGHT vale 120 de forma predeterminada. Usa wire3d_dmg_96.c para la altura 96. SelectEdgeMask está disponible con altura 96; RotatePoint, DrawIndexedEdges, los controles de habilitación de transferencia y las transferencias directas requieren altura 120.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3DDMG_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
Wire3DDMG_SetCamera(8,0,0,0,0,0);
result[1]=Wire3DDMG_ProjectPoint(0,0,96,&projected_x,&projected_y);
result[2]=projected_x; result[3]=projected_y;
projected_x=91; projected_y=92;
result[4]=Wire3DDMG_ProjectPoint(0,0,7,&projected_x,&projected_y);
result[5]=projected_x; result[6]=projected_y;
Wire3DDMG_SetCamera(0,0,0,0,0,0);
Wire3DDMG_BeginFrame();
Wire3DDMG_DrawLine2D(8,8,56,8);
Wire3DDMG_DrawLine2D(56,8,56,40);
Wire3DDMG_DrawLine2D(56,40,8,40);
Wire3DDMG_DrawLine2D(8,40,8,8);
Wire3DDMG_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
Wire3DDMG_DrawLine3D(-24,-24,96,24,24,96);
// Copy the viewport's top-left frame corner to a separate map cell.
Wire3DDMG_PutBgTile(1,1,160);
Wire3DDMG_EndFrame();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Este ejemplo muestra líneas, puntos, borrado y proyección en un fotograma. Se borra el centro del borde superior del marco de arriba a la izquierda y se proyecta una diagonal cerca del centro. Una proyección rechazada conserva las salidas 91 y 92.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_raster.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_dmg.h:258
Queue a tile write to the 32x32 map at 0x9800 for EndFrame. Invalid map coordinates and submissions beyond 48 pending writes are silently ignored. This queue is separate from the general vram library queue.
kitaqgb/lib/wire3d_dmg.c:731
void Wire3DDMG_PutBgTile(w3ddmg_u8 x, w3ddmg_u8 y, w3ddmg_u8 tile)
{
if (x >= 32) return;
if (y >= 32) return;
if (w3ddmg_bgq_count >= WIRE3D_DMG_BG_QUEUE_LIMIT) return;
w3ddmg_bgq_x[(__safe_index w3ddmg_u8)w3ddmg_bgq_count] = x;
w3ddmg_bgq_y[(__safe_index w3ddmg_u8)w3ddmg_bgq_count] = y;
w3ddmg_bgq_tile[(__safe_index w3ddmg_u8)w3ddmg_bgq_count] = tile;
w3ddmg_bgq_count = (w3ddmg_u8)(w3ddmg_bgq_count + 1);
}Wire3DDMG_RotatePoint
Rota un punto en sus propias variables según los ángulos indicados.
Sintaxis
void Wire3DDMG_RotatePoint(w3ddmg_i16* x, w3ddmg_i16* y, w3ddmg_i16* z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz);Parámetros
xPuntero s16 escribible y distinto de los demás para la componente X.
yPuntero s16 escribible y distinto de los demás para la componente Y.
zPuntero s16 escribible y distinto de los demás para la componente Z.
rxRotación alrededor de X; dieciséis pasos forman una vuelta completa.
ryRotación alrededor de Y; dieciséis pasos forman una vuelta completa.
rzRotación alrededor de Z; dieciséis pasos forman una vuelta completa.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 120 void Wire3DDMG_RotatePoint(w3ddmg_i16* x, w3ddmg_i16* y, w3ddmg_i16* z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz); Rota sobre las mismas variables en orden Y/X/Z, con 16 pasos por vuelta. Si algún puntero de componente es null, toda la llamada queda sin efecto; usa punteros distintos. Cada rotación de eje limita sus entradas a ±220.
Este ejemplo usa el perfil 128×120; su ventana gráfica empieza en (16,8) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
WIRE3D_DMG_HEIGHT vale 120 de forma predeterminada. Usa wire3d_dmg_96.c para la altura 96. SelectEdgeMask está disponible con altura 96; RotatePoint, DrawIndexedEdges, los controles de habilitación de transferencia y las transferencias directas requieren altura 120.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Compare direct model scaling with an object-array scene.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3DDMG_Vec3 vertices[8]={{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}};
__prg_rom Wire3DDMG_Edge edges[12]={{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}};
Wire3DDMG_Model cube;
Wire3DDMG_Object objects[2];
s16 px; s16 py; s16 pz;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3DDMG_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
cube.vertices=vertices;cube.edges=edges;cube.faces=0;cube.edge_faces=0;
cube.vertex_count=8;cube.edge_count=12;cube.face_count=0;cube.flags=0;
Wire3DDMG_BeginFrame();
// Upper pair: direct model calls at unity and half scale.
Wire3DDMG_DrawModel(&cube,-32,32,96,0,0,0);
Wire3DDMG_DrawModelScaled(&cube,32,32,96,0,0,0,128);
// Lower pair: the caller owns both object records and the model tables.
for(i=0;i<2;i++) {
objects[i].model=&cube;objects[i].x=-32+(s16)i*64;
objects[i].y=-32;objects[i].z=96;
objects[i].rx=0;objects[i].ry=0;objects[i].rz=0;
objects[i].scale_q8=256-(s16)i*128;objects[i].visible=1;
}
Wire3DDMG_DrawScene(objects,2);
// Numeric checks cover the operation supplied by this viewport profile.
px=16;py=0;pz=0;Wire3DDMG_RotatePoint(&px,&py,&pz,0,4,0);
result[1]=px; result[2]=py; result[3]=pz;
Wire3DDMG_EndFrame(); result[7]=0xA55A;
while(1) {}
}Resultado esperado
Los modelos a escala unitaria y a media escala aparecen sobre una escena de un array de objetos con esas mismas escalas, para mostrar la proyección y el escalado.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_models.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_dmg.h:221
Rotate in place in Y/X/Z order using 16 steps per full turn. A null component pointer makes the whole call a no-op; use distinct pointers. Each axis rotation clamps its inputs to +/-220.
kitaqgb/lib/wire3d_dmg.c:3865
void Wire3DDMG_RotatePoint(w3ddmg_i16* x, w3ddmg_i16* y, w3ddmg_i16* z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz)
{
if (x == 0) return;
if (y == 0) return;
if (z == 0) return;
w3ddmg_rotate_y(x, z, ry);
w3ddmg_rotate_x(y, z, rx);
w3ddmg_rotate_z(x, y, rz);
}Wire3DDMG_SelectEdgeMask
Selecciona una máscara precalculada de visibilidad de aristas según la guiñada del objeto.
Sintaxis
w3ddmg_u16 Wire3DDMG_SelectEdgeMask(const Wire3DDMG_Model* model, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz);Parámetros
modelModelo que contiene los arrays de vértices, aristas y caras y sus cantidades; las tablas deben permanecer legibles durante la llamada.
rxRotación alrededor de X; dieciséis pasos forman una vuelta completa.
ryRotación alrededor de Y; dieciséis pasos forman una vuelta completa.
rzRotación alrededor de Z; dieciséis pasos forman una vuelta completa.
Valor devuelto
Máscara de visibilidad de aristas de 16 bits, o 0xFFFF si no se proporciona una tabla.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 96 w3ddmg_u16 Wire3DDMG_SelectEdgeMask(const Wire3DDMG_Model* model, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz); Selecciona una máscara precalculada con los cuatro bits bajos de la guiñada del objeto; ignora cabeceo, alabeo y orientación de cámara. Usa 16, 8, 4 o 2 sectores; otras cantidades positivas eligen la entrada cero, salvo que las cantidades >=16 usan las primeras 16. Si faltan datos, devuelve 0xFFFF. La tabla de máscaras debe seguir siendo legible con el mapeo actual del puntero de datos.
Este ejemplo usa el perfil 128×96; su ventana gráfica empieza en (0,0) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
WIRE3D_DMG_HEIGHT vale 120 de forma predeterminada. Usa wire3d_dmg_96.c para la altura 96. SelectEdgeMask está disponible con altura 96; RotatePoint, DrawIndexedEdges, los controles de habilitación de transferencia y las transferencias directas requieren altura 120.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Compare direct model scaling with an object-array scene.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3DDMG_Vec3 vertices[8]={{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}};
__prg_rom Wire3DDMG_Edge edges[12]={{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}};
Wire3DDMG_Model cube;
Wire3DDMG_Object objects[2];
u16 masks[2];
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3DDMG_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
cube.vertices=vertices;cube.edges=edges;cube.faces=0;cube.edge_faces=0;
cube.vertex_count=8;cube.edge_count=12;cube.face_count=0;cube.flags=0;
cube.edge_masks=0; cube.edge_mask_count=0;
Wire3DDMG_BeginFrame();
// Upper pair: direct model calls at unity and half scale.
Wire3DDMG_DrawModel(&cube,-32,32,96,0,0,0);
Wire3DDMG_DrawModelScaled(&cube,32,32,96,0,0,0,128);
// Lower pair: the caller owns both object records and the model tables.
for(i=0;i<2;i++) {
objects[i].model=&cube;objects[i].x=-32+(s16)i*64;
objects[i].y=-32;objects[i].z=96;
objects[i].rx=0;objects[i].ry=0;objects[i].rz=0;
objects[i].scale_q8=256-(s16)i*128;objects[i].visible=1;
}
Wire3DDMG_DrawScene(objects,2);
// Numeric checks cover the operation supplied by this viewport profile.
masks[0]=3;masks[1]=12;cube.edge_masks=masks; cube.edge_mask_count=2;
result[1]=Wire3DDMG_SelectEdgeMask(&cube,0,0,0);
result[2]=Wire3DDMG_SelectEdgeMask(&cube,0,8,0);
Wire3DDMG_EndFrame(); result[7]=0xA55A;
while(1) {}
}Resultado esperado
Los modelos a escala unitaria y a media escala aparecen sobre una escena de un array de objetos con esas mismas escalas, para mostrar la proyección y el escalado.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg96_models.c .\kitaqgb\lib\wire3d_dmg_96.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg96_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_dmg.h:207
Select a precomputed mask from the low four bits of object yaw; pitch, roll and camera orientation are ignored. Use 16, 8, 4 or 2 bins; other positive counts select entry zero (counts >=16 use the first 16). Missing data returns 0xFFFF. Keep the mask table readable through the current data-pointer mapping.
kitaqgb/lib/wire3d_dmg.c:1258
w3ddmg_u16 Wire3DDMG_SelectEdgeMask(const Wire3DDMG_Model* model, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz)
{
w3ddmg_u8 count;
w3ddmg_u8 bin;
if (model == 0) return 0xFFFF;
if (model->edge_masks == 0) return 0xFFFF;
count = model->edge_mask_count;
if (count == 0) return 0xFFFF;
(void)rx;
(void)rz;
bin = (w3ddmg_u8)(((w3ddmg_u8)ry) & 15);
if (count >= 16) return model->edge_masks[(__safe_index w3ddmg_u8)bin];
if (count == 8) bin = (w3ddmg_u8)(bin >> 1);
else if (count == 4) bin = (w3ddmg_u8)(bin >> 2);
else if (count == 2) bin = (w3ddmg_u8)(bin >> 3);
else bin = 0;
if (bin >= count) bin = (w3ddmg_u8)(count - 1);
return model->edge_masks[(__safe_index w3ddmg_u8)bin];
}Wire3DDMG_SetAuxTransfer
Elige si EndFrame también transfiere las franjas auxiliares.
Sintaxis
void Wire3DDMG_SetAuxTransfer(w3ddmg_u8 flag);Parámetros
flagCero desactiva la función de transferencia; cualquier otro valor la activa.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 120 void Wire3DDMG_SetAuxTransfer(w3ddmg_u8 flag); Guarda la habilitación de transferencia auxiliar de EndFrame; cualquier valor no nulo la activa. Aquí no copia ni borra datos. Los bytes fuente auxiliares comparten direcciones con el área principal.
Este ejemplo usa el perfil 128×120; su ventana gráfica empieza en (16,8) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
WIRE3D_DMG_HEIGHT vale 120 de forma predeterminada. Usa wire3d_dmg_96.c para la altura 96. SelectEdgeMask está disponible con altura 96; RotatePoint, DrawIndexedEdges, los controles de habilitación de transferencia y las transferencias directas requieren altura 120.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Use the auxiliary-transfer gate to consume an overlapping stage strip.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3DDMG_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
Wire3DDMG_SetDirtyTransfer(1); Wire3DDMG_SetAuxTransfer(1);
Wire3DDMG_BeginFrame();
for(i=24;i<=31;i++) Wire3DDMG_DrawLine2D(40,i,47,i);
// Auxiliary upload consumes this source before the dirty main tile is sent.
Wire3DDMG_EndFrame(); result[7]=0xA55A; while(1) {}
}Resultado esperado
La transferencia auxiliar consume parte del área principal y produce un bloque negro de 8×8 en las coordenadas de pantalla (80,24).
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_aux_gate.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_aux_gate.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_dmg.h:268
Store the EndFrame auxiliary-transfer gate; any nonzero value enables it. No data is copied or cleared here. Auxiliary source bytes alias the main stage.
kitaqgb/lib/wire3d_dmg.c:4639
void Wire3DDMG_SetAuxTransfer(w3ddmg_u8 flag)
{
w3ddmg_aux_transfer_enabled = flag;
}Wire3DDMG_SetCamera
Guarda la posición y la orientación de la cámara para las proyecciones posteriores.
Sintaxis
void Wire3DDMG_SetCamera(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 pitch, w3ddmg_u8 yaw, w3ddmg_u8 roll);Parámetros
xComponente X de la cámara en coordenadas del mundo.
yComponente Y de la cámara en coordenadas del mundo.
zComponente Z de la cámara en coordenadas del mundo.
pitchRotación alrededor de X; dieciséis pasos forman una vuelta completa.
yawRotación alrededor de Y; dieciséis pasos forman una vuelta completa.
rollRotación alrededor de Z; dieciséis pasos forman una vuelta completa.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 96 void Wire3DDMG_SetCamera(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 pitch, w3ddmg_i8 yaw, w3ddmg_i8 roll); Guarda la posición y los ángulos de cámara para dibujos posteriores; una vuelta tiene 16 pasos angulares. No vuelve a proyectar lo ya dibujado ni valida los rangos de entrada. WIRE3D_DMG_HEIGHT = 120 void Wire3DDMG_SetCamera(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 pitch, w3ddmg_u8 yaw, w3ddmg_u8 roll); Guarda la posición y los ángulos de cámara para dibujos posteriores; una vuelta tiene 16 pasos angulares. No vuelve a proyectar lo ya dibujado ni valida los rangos de entrada.
Este ejemplo usa el perfil 128×120; su ventana gráfica empieza en (16,8) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
WIRE3D_DMG_HEIGHT vale 120 de forma predeterminada. Usa wire3d_dmg_96.c para la altura 96. SelectEdgeMask está disponible con altura 96; RotatePoint, DrawIndexedEdges, los controles de habilitación de transferencia y las transferencias directas requieren altura 120.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3DDMG_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
Wire3DDMG_SetCamera(8,0,0,0,0,0);
result[1]=Wire3DDMG_ProjectPoint(0,0,96,&projected_x,&projected_y);
result[2]=projected_x; result[3]=projected_y;
projected_x=91; projected_y=92;
result[4]=Wire3DDMG_ProjectPoint(0,0,7,&projected_x,&projected_y);
result[5]=projected_x; result[6]=projected_y;
Wire3DDMG_SetCamera(0,0,0,0,0,0);
Wire3DDMG_BeginFrame();
Wire3DDMG_DrawLine2D(8,8,56,8);
Wire3DDMG_DrawLine2D(56,8,56,40);
Wire3DDMG_DrawLine2D(56,40,8,40);
Wire3DDMG_DrawLine2D(8,40,8,8);
Wire3DDMG_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
Wire3DDMG_DrawLine3D(-24,-24,96,24,24,96);
// Copy the viewport's top-left frame corner to a separate map cell.
Wire3DDMG_PutBgTile(1,1,160);
Wire3DDMG_EndFrame();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Este ejemplo muestra líneas, puntos, borrado y proyección en un fotograma. Se borra el centro del borde superior del marco de arriba a la izquierda y se proyecta una diagonal cerca del centro. Una proyección rechazada conserva las salidas 91 y 92.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_raster.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_dmg.h:152
Store camera position and angles for later draws; a full turn is 16 angle steps. No existing drawing is reprojected and no input range validation occurs.
kitaqgb/lib/wire3d_dmg.c:3399
void Wire3DDMG_SetCamera(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 pitch, w3ddmg_u8 yaw, w3ddmg_u8 roll)
{
w3ddmg_cam_x = x;
w3ddmg_cam_y = y;
w3ddmg_cam_z = z;
w3ddmg_cam_pitch = pitch;
w3ddmg_cam_yaw = yaw;
w3ddmg_cam_roll = roll;
}kitaqgb/lib/wire3d_dmg.c:3397
void Wire3DDMG_SetCamera(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 pitch, w3ddmg_i8 yaw, w3ddmg_i8 roll)
{
w3ddmg_cam_x = x;
w3ddmg_cam_y = y;
w3ddmg_cam_z = z;
w3ddmg_cam_pitch = pitch;
w3ddmg_cam_yaw = yaw;
w3ddmg_cam_roll = roll;
}Wire3DDMG_SetDirtyTransfer
Selecciona la transferencia de tiles modificados para la ventana gráfica principal de 120 filas.
Sintaxis
void Wire3DDMG_SetDirtyTransfer(w3ddmg_u8 flag);Parámetros
flagCero desactiva la función de transferencia; cualquier otro valor la activa.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 120 void Wire3DDMG_SetDirtyTransfer(w3ddmg_u8 flag); Guarda la habilitación de transferencia de zonas modificadas y borra ambos historiales de cambios y el área principal, aunque el valor no cambie. Conserva VRAM; activarla sobre una imagen anterior puede dejar tiles antiguos sin marcar, así que prepara una imagen inicial limpia.
Este ejemplo usa el perfil 128×120; su ventana gráfica empieza en (16,8) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
WIRE3D_DMG_HEIGHT vale 120 de forma predeterminada. Usa wire3d_dmg_96.c para la altura 96. SelectEdgeMask está disponible con altura 96; RotatePoint, DrawIndexedEdges, los controles de habilitación de transferencia y las transferencias directas requieren altura 120.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Remove the previous frame and upload only the tracked current/previous tiles.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3DDMG_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
Wire3DDMG_SetDirtyTransfer(1); Wire3DDMG_SetAuxTransfer(0);
Wire3DDMG_BeginFrame();
Wire3DDMG_DrawLine2D(8,8,24,8); Wire3DDMG_DrawLine2D(24,8,24,24);
Wire3DDMG_DrawLine2D(24,24,8,24); Wire3DDMG_DrawLine2D(8,24,8,8);
Wire3DDMG_EndFrame();
Wire3DDMG_BeginFrame();
Wire3DDMG_DrawLine2D(80,80,104,80); Wire3DDMG_DrawLine2D(104,80,104,104);
Wire3DDMG_DrawLine2D(104,104,80,104); Wire3DDMG_DrawLine2D(80,104,80,80);
Wire3DDMG_EndFrame(); result[7]=0xA55A; while(1) {}
}Resultado esperado
Desaparece el marco anterior de arriba a la izquierda y solo queda el nuevo en las coordenadas de pantalla (96,88)..(120,112).
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_dirty.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_dirty.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_dmg.h:272
Store the dirty-transfer gate and clear both dirty histories and the main stage, even if the value is unchanged. VRAM is retained; enabling this over an old image can leave unmarked old tiles, so arrange a clean displayed baseline.
kitaqgb/lib/wire3d_dmg.c:4699
void Wire3DDMG_SetDirtyTransfer(w3ddmg_u8 flag)
{
w3ddmg_dirty_transfer_enabled = flag;
w3ddmg_clear_dirty_tables();
w3ddmg_clear_stage_asm();
}Wire3DDMG_SetPalette
Escribe la correspondencia de cuatro tonos en el registro de paleta del fondo monocromo BGP.
Sintaxis
void Wire3DDMG_SetPalette(w3ddmg_u8 bgp);Parámetros
bgpValor del registro BGP con cuatro asignaciones de tono de dos bits.
Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 96 void Wire3DDMG_SetPalette(w3ddmg_u8 bgp); Escribe inmediatamente la codificación directa de la paleta DMG BGP, sin sincronización de fotograma. WIRE3D_DMG_HEIGHT = 120 void Wire3DDMG_SetPalette(w3ddmg_u8 bgp); Escribe inmediatamente la codificación directa de la paleta DMG BGP, sin sincronización de fotograma.
Este ejemplo usa el perfil 128×120; su ventana gráfica empieza en (16,8) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
WIRE3D_DMG_HEIGHT vale 120 de forma predeterminada. Usa wire3d_dmg_96.c para la altura 96. SelectEdgeMask está disponible con altura 96; RotatePoint, DrawIndexedEdges, los controles de habilitación de transferencia y las transferencias directas requieren altura 120.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3DDMG_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
Wire3DDMG_SetCamera(8,0,0,0,0,0);
result[1]=Wire3DDMG_ProjectPoint(0,0,96,&projected_x,&projected_y);
result[2]=projected_x; result[3]=projected_y;
projected_x=91; projected_y=92;
result[4]=Wire3DDMG_ProjectPoint(0,0,7,&projected_x,&projected_y);
result[5]=projected_x; result[6]=projected_y;
Wire3DDMG_SetCamera(0,0,0,0,0,0);
Wire3DDMG_BeginFrame();
Wire3DDMG_DrawLine2D(8,8,56,8);
Wire3DDMG_DrawLine2D(56,8,56,40);
Wire3DDMG_DrawLine2D(56,40,8,40);
Wire3DDMG_DrawLine2D(8,40,8,8);
Wire3DDMG_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
Wire3DDMG_DrawLine3D(-24,-24,96,24,24,96);
// Copy the viewport's top-left frame corner to a separate map cell.
Wire3DDMG_PutBgTile(1,1,160);
Wire3DDMG_EndFrame();
result[7]=0xA55A;
while(1) {}
}Resultado esperado
Este ejemplo muestra líneas, puntos, borrado y proyección en un fotograma. Se borra el centro del borde superior del marco de arriba a la izquierda y se proyecta una diagonal cerca del centro. Una proyección rechazada conserva las salidas 91 y 92.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_raster.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_dmg.h:260
Write the raw DMG BGP palette encoding immediately; no frame synchronization occurs.
kitaqgb/lib/wire3d_dmg.c:746
void Wire3DDMG_SetPalette(w3ddmg_u8 bgp)
{
w3ddmg_reg_bgp = bgp;
}Wire3DDMG_TransferAuxNow
Transfiere inmediatamente seis franjas auxiliares y borra sus bytes fuente.
Sintaxis
void Wire3DDMG_TransferAuxNow();Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 120 void Wire3DDMG_TransferAuxNow(); Transfiere y consume inmediatamente las franjas fuente auxiliares, independientemente de su habilitación. No espera al inicio de VBlank ni actualiza el historial de cambios o la cola BG. La fuente se solapa con el área principal y debe coordinarse con su transferencia.
Este ejemplo usa el perfil 128×120; su ventana gráfica empieza en (16,8) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
WIRE3D_DMG_HEIGHT vale 120 de forma predeterminada. Usa wire3d_dmg_96.c para la altura 96. SelectEdgeMask está disponible con altura 96; RotatePoint, DrawIndexedEdges, los controles de habilitación de transferencia y las transferencias directas requieren altura 120.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Upload a main line and an auxiliary block separately; verify source consumption.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3DDMG_Vec3 vertices[2]={{-32,0,0},{32,0,0}};
__prg_rom u8 edge_pairs[2]={0,1};
u8* stage_byte;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3DDMG_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
Wire3DDMG_BeginFrame();
Wire3DDMG_DrawIndexedEdges(vertices,2,edge_pairs,1,-64,104,96,1);
Wire3DDMG_TransferMainNow();
// Direct auxiliary transfer writes a separate tile after the main upload.
for(i=24;i<=31;i++) Wire3DDMG_DrawLine2D(40,i,47,i);
stage_byte=(u8*)0xD518;result[1]=*stage_byte;
Wire3DDMG_TransferAuxNow();result[2]=*stage_byte;
// Do not upload the consumed stage again.
result[7]=0xA55A; while(1) {}
}Resultado esperado
Una línea horizontal proyectada y un bloque auxiliar de 8×8 muestran las transferencias directas; un byte fuente pasa de 255 a 0 al consumirse.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_direct.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_direct.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_dmg.h:280
Upload and consume auxiliary source strips immediately, independent of the auxiliary gate. No VBlank-start wait or dirty-history/BG-queue update occurs. The source overlaps the main stage and must be coordinated with its upload.
kitaqgb/lib/wire3d_dmg.c:4727
void Wire3DDMG_TransferAuxNow()
{
w3ddmg_transfer_stage_aux_asm();
}Wire3DDMG_TransferMainNow
Transfiere inmediatamente toda el área principal y borra los píxeles fuente consumidos.
Sintaxis
void Wire3DDMG_TransferMainNow();Valor devuelto
No devuelve ningún valor; el estado afectado y la temporización de la pantalla se describen arriba.
Condiciones y límites
WIRE3D_DMG_HEIGHT = 120 void Wire3DDMG_TransferMainNow(); Transfiere y consume inmediatamente toda el área principal, consultando STAT sin esperar al siguiente VBlank. Ignora las habilitaciones de transferencia y conserva los historiales de cambios y la cola de tiles BG; el código que llama coordina el ciclo del fotograma.
Este ejemplo usa el perfil 128×120; su ventana gráfica empieza en (16,8) de la pantalla. Reserva WRAM D000..DFFF y mantén estable su mapeo de banco, también en CGB. El estado compartido no admite reentrada.
WIRE3D_DMG_HEIGHT vale 120 de forma predeterminada. Usa wire3d_dmg_96.c para la altura 96. SelectEdgeMask está disponible con altura 96; RotatePoint, DrawIndexedEdges, los controles de habilitación de transferencia y las transferencias directas requieren altura 120.
WIRE3D_DMG_HEIGHT admite 88, 96 o 120; WIRE3DCGB_HEIGHT admite 88 o 96. Los valores predeterminados siguen siendo DMG 120 y CGB 96. El perfil de 88 filas mide 128×88 y su centro Y=44. Use el mismo ajuste en biblioteca y programa; compile wire3d_dmg_88.c / wire3d_cgb_88.c en lugar de la entrada normal. DMG 88 conserva la estructura de modelos de 96 filas y el límite de 16 aristas. El modo CGB 160×144 no cambia.
Ejemplo de uso
#pragma bank 0
// Upload a main line and an auxiliary block separately; verify source consumption.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3DDMG_Vec3 vertices[2]={{-32,0,0},{32,0,0}};
__prg_rom u8 edge_pairs[2]={0,1};
u8* stage_byte;
void main() {
u8 i;
for(i=0;i<8;i++) result[i]=0;
Wire3DDMG_Init();
// A CGB-compatible ROM also needs CGB palette and tile-map attributes.
if(__cgb_is_cgb()) {
while(sample_ly>=144) {} while(sample_ly<144) {}
sample_lcdc=0; sample_vbk=1;
__vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
for(i=0;i<6;i++) sample_bgpd=0;
sample_lcdc=0x81;
}
Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
result[0]=sample_bgp;
Wire3DDMG_BeginFrame();
Wire3DDMG_DrawIndexedEdges(vertices,2,edge_pairs,1,-64,104,96,1);
Wire3DDMG_TransferMainNow();
// Direct auxiliary transfer writes a separate tile after the main upload.
for(i=24;i<=31;i++) Wire3DDMG_DrawLine2D(40,i,47,i);
stage_byte=(u8*)0xD518;result[1]=*stage_byte;
Wire3DDMG_TransferAuxNow();result[2]=*stage_byte;
// Do not upload the consumed stage again.
result[7]=0xA55A; while(1) {}
}Resultado esperado
Una línea horizontal proyectada y un bloque auxiliar de 8×8 muestran las transferencias directas; un byte fuente pasa de 255 a 0 al consumirse.
Comando de compilación
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_direct.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_direct.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasmImplementación y código fuente
kitaqgb/lib/wire3d_dmg.h:276
Upload and consume the full main stage immediately, polling STAT but not waiting for the next VBlank. Ignore transfer gates and leave dirty histories and BG tile queue unchanged; the caller coordinates the frame lifecycle.
kitaqgb/lib/wire3d_dmg.c:4714
void Wire3DDMG_TransferMainNow()
{
w3ddmg_transfer_stage_asm();
}Estructuras, constantes y cabeceras completas
Consulta estas cabeceras para conocer las macros que no son funciones, las estructuras, los límites de arrays, las enumeraciones y los alias. Reproducen literalmente el código recopilado, incluidos sus comentarios originales.
asset.h — Identificadores de recursos y descriptores de datos
#pragma once
#define ASSET_TYPE_RAW ((u8)0)
#define ASSET_TYPE_TILES ((u8)1)
#define ASSET_TYPE_MAP ((u8)2)
#define ASSET_TYPE_SONG ((u8)3)
// Packed ROM descriptor: type tag, payload bank, bank-window address and byte length.
// The table itself may live in a different bank from the payload.
typedef __packed struct {
u8 type;
u8 bank;
const u8* ptr;
u16 len;
} AssetDesc;
void __farmemcpy(void* dst, u8 bank, const void* src, u16 len);
void __vram_copy(u16 dst, const void* src, u16 len);
// Retain the descriptor table address, bank and count; the table is not copied.
void asset_set_table(u8 bank, const AssetDesc* table, u8 count);
// Copy one descriptor from its ROM bank into caller storage. Return zero for a
// null destination or an out-of-range ID; table validity is the caller's responsibility.
u8 asset_get(u8 asset_id, AssetDesc* out_desc);
// Copy at most max_len bytes using the asset's bank. Success means the ID was
// valid, even when the payload was truncated to fit the supplied limit.
u8 asset_load_raw(u8 asset_id, void* dst, u16 max_len);
// Accept tile/raw descriptors and transfer their bytes to VRAM. This path passes
// the descriptor pointer directly; callers must arrange the correct visible ROM bank.
u8 asset_load_tiles(u8 asset_id, u16 vram_dst);
// Return the descriptor bank, or zero on lookup failure; zero can also be a valid bank.
u8 asset_get_bank(u8 asset_id);
// Return the stored address without switching banks. Use the descriptor bank
// with far-data helpers before dereferencing banked assets; failure returns null.
const u8* asset_get_ptr(u8 asset_id);
// Return the descriptor byte length, or zero if its ID cannot be resolved.
u16 asset_get_len(u8 asset_id);kitaqgb/lib/asset.h
audio.h — Música, efectos de sonido y control de audio
#pragma once
// Shared Game Boy audio driver for KITAQGB projects.
//
// Integration notes:
// - Compile a hardware-register file before audio.c so NR10..NR52 and
// WAVE0..WAVE15 are already declared.
// - Call Audio_Init() once during startup.
// - Call Audio_Update() once per frame, ideally from your VBlank-driven main loop.
// - audio.c is intended to stay in bank 0.
// - Music streams are banked explicitly with Audio_PlayMusic(bank, song).
// - Audio_PlaySFX(sfx, priority) captures the currently visible ROM bank.
// - Audio_PlaySFXBanked(bank, sfx, priority) safely classifies CH1/CH3 data
// after switching to the requested bank, so banked SFX can be started from
// any currently visible ROM bank.
// - GBDAW-Stream v1.2 extends the legacy command set with explicit per-channel
// automation commands that map more directly from GUI and Python tooling.
// Physical APIs and music-stream commands share zero-based CH1..CH4 IDs.
#define AUDIO_CHANNEL_CH1 ((u8)0)
#define AUDIO_CHANNEL_CH2 ((u8)1)
#define AUDIO_CHANNEL_CH3 ((u8)2)
#define AUDIO_CHANNEL_CH4 ((u8)3)
// Music-stream IDs used by NOTE, SET_INST and STOP_CHANNEL.
#define AUDIO_STREAM_CHANNEL_CH1 AUDIO_CHANNEL_CH1
#define AUDIO_STREAM_CHANNEL_CH2 AUDIO_CHANNEL_CH2
#define AUDIO_STREAM_CHANNEL_CH3 AUDIO_CHANNEL_CH3
#define AUDIO_STREAM_CHANNEL_CH4 AUDIO_CHANNEL_CH4
#define AUDIO_PAN_CENTER ((u8)0)
#define AUDIO_PAN_LEFT ((u8)1)
#define AUDIO_PAN_RIGHT ((u8)2)
#define AUDIO_PAN_MUTE ((u8)3)
#define AUDIO_PAN_INHERIT ((u8)0xFF)
#define AUDIO_WAVE_TRIANGLE ((u8)0)
#define AUDIO_WAVE_SAW ((u8)1)
#define AUDIO_WAVE_VOWEL_A ((u8)2)
#define AUDIO_WAVE_VOWEL_I ((u8)3)
#define AUDIO_WAVE_VOWEL_U ((u8)4)
#define AUDIO_WAVE_VOWEL_E ((u8)5)
#define AUDIO_WAVE_VOWEL_O ((u8)6)
#define AUDIO_WAVE_CUSTOM ((u8)7)
#define AUDIO_CH3_LEVEL_MUTE ((u8)0x00)
#define AUDIO_CH3_LEVEL_100 ((u8)0x20)
#define AUDIO_CH3_LEVEL_50 ((u8)0x40)
#define AUDIO_CH3_LEVEL_25 ((u8)0x60)
#define AUDIO_VOLUME_MIN ((u8)0)
#define AUDIO_VOLUME_MAX ((u8)7)
#define AUDIO_NOTE_MAX ((u8)67)
#define AUDIO_CMD_WAIT ((u8)0x00)
#define AUDIO_CMD_NOTE ((u8)0x10)
#define AUDIO_CMD_SET_INST ((u8)0x11)
#define AUDIO_CMD_SET_PAN ((u8)0x12)
#define AUDIO_CMD_SET_SWEEP ((u8)0x13)
#define AUDIO_CMD_SET_WAVE ((u8)0x14)
#define AUDIO_CMD_SET_CH3_CUSTOM_WAVE ((u8)0x15)
#define AUDIO_CMD_SET_CH4_PARAM ((u8)0x16)
#define AUDIO_CMD_SET_MASTER_VOLUME ((u8)0x17)
#define AUDIO_CMD_SET_CH1_DUTY ((u8)0x18)
#define AUDIO_CMD_SET_CH2_DUTY ((u8)0x19)
#define AUDIO_CMD_SET_CH3_LEVEL ((u8)0x1A)
#define AUDIO_CMD_STOP_CHANNEL ((u8)0x20)
#define AUDIO_CMD_LOOP ((u8)0x30)
#define AUDIO_CMD_STOP ((u8)0x40)
#define AUDIO_SFX_CH3_MARKER ((u8)0xFF)
// Enable the APU and reset software streams, instruments, mix and fade state.
// Load the initial triangle wave, then leave every channel silent. Call at startup
// before concurrent interrupt-driven audio service can access these shared fields.
void Audio_Init();
// Advance the master fade first. Unless paused, service both effect streams
// then the optional legacy music decoder. Call once per frame for frame-based timing.
void Audio_Update();
// Retain the bank and song pointer, reset legacy instruments/cursors, and arm
// playback from the beginning. Supply a valid, persistent song; no bytes are copied
// and null is not checked. Existing effect streams remain active.
void __stackcall Audio_PlayMusic(u8 bank, u8 *song);
// Stop legacy music and clear its resume mask, then silence all physical channels.
// Effect pointers remain active and may produce sound on a later update.
void Audio_StopMusic();
// On pause entry, silence hardware while retaining cursors. On resume, retrigger
// eligible legacy CH1, CH2 and CH4 notes; CH3 is not retriggered here. Updates still
// advance master fades while paused, and effect playback resumes on a later update.
void __stackcall Audio_SetPaused(u8 on);
// Capture the currently mapped ROM bank and start an effect with inherited pan.
// Use the explicit-bank API when the pointer belongs to another bank.
void __stackcall Audio_PlaySFX(u8 *sfx, u8 priority);
// Start a banked effect with the channel's base pan, subject to priority arbitration.
void __stackcall Audio_PlaySFXBanked(u8 bank, u8 *sfx, u8 priority);
// Capture the currently mapped ROM bank and request an effect with a pan override.
// Use the explicit-bank API when the pointer belongs to another bank.
void __stackcall Audio_PlaySFXPanned(u8 *sfx, u8 priority, u8 pan);
// Retain a banked effect stream if its priority equals or exceeds the current
// owner's priority, or that slot is empty. A leading CH3 marker selects the wave
// slot and is skipped; other streams use the pulse slot. Paused requests are ignored.
// Keep stream storage valid until completion; acceptance does not trigger a note.
void __stackcall Audio_PlaySFXPannedBanked(u8 bank, u8 *sfx, u8 priority, u8 pan);
// Clear both effect streams and their pan overrides. When not paused, release
// borrowed channels through the configured legacy or VBlank recovery path.
void Audio_StopSfx();
// Stop a physical channel and clear its legacy resume bit. CH1 also clears the
// pulse effect stream; CH3 clears the wave effect stream. This is the legacy
// channel API and does not clear a VBlank driver's independently latched notes.
void __stackcall Audio_StopChannel(u8 ch);
// Set the music-processing gate. This does not silence notes already playing
// or stop the legacy stream cursor from consuming commands.
void __stackcall Audio_SetMusicEnabled(u8 on);
// Enable effect note writes, or disable them and release both effect streams.
// Disabling follows Audio_StopSfx recovery rules rather than silencing all channels.
void __stackcall Audio_SetSfxEnabled(u8 on);
// Clamp both output levels to 0..7, cancel any fade, and write NR50 immediately.
void __stackcall Audio_SetMasterVolume(u8 left, u8 right);
// Move left/right volume toward clamped targets at the requested Audio_Update
// call interval. An interval of zero applies the levels immediately.
void __stackcall Audio_FadeToMasterVolume(u8 left, u8 right, u8 step_frames);
// Cancel further volume steps, retaining the current cached levels and hardware output.
void Audio_CancelMasterVolumeFade();
// Update the base pan for a physical channel and reapply active effect overrides.
// Unknown channel IDs select CH4; unsupported pan values mute the selected channel.
void __stackcall Audio_SetPan(u8 ch, u8 pan);
// Two bits per channel (CH1 in bits 0-1): center, left, right, mute.
// Applies all four positions with one NR51 update for sequencer automation.
void __stackcall Audio_SetPanPacked(u8 packed);
// Install a named preset or the cached custom wave. Unknown IDs are ignored.
// This does not update Audio_Ch3Wave or trigger a new note.
void __stackcall Audio_LoadWave(u8 wave_id);
// Copy 16 packed sample bytes into the persistent custom cache and wave RAM.
// A null pointer is ignored; the source is needed only for this call.
void __stackcall Audio_LoadCustomWave(const u8 *wave16);
// Cache the low two duty bits for the next CH1 note; do not change the active register.
void __stackcall Audio_SetCh1Duty(u8 duty);
// Cache the low two duty bits for the next CH2 note; do not change the active register.
void __stackcall Audio_SetCh2Duty(u8 duty);
// Cache the raw NR32 level encoding for the next CH3 note without writing hardware.
void __stackcall Audio_SetCh3Level(u8 level);
// Cache the raw noise polynomial encoding for the next CH4 note without writing hardware.
void __stackcall Audio_SetCh4Param(u8 param);
// Trigger CH1 with the cached sweep and the supplied raw envelope. Clamp the
// note index; duty values 0, 1 and 3 select their encodings, and all others use 2.
void __stackcall Audio_Ch1NoteOn(u8 note, u8 vol_env, u8 duty2);
// Trigger CH2 with the supplied raw envelope and a clamped note index. Duty
// values 0, 1 and 3 select their encodings; all other values use duty 2.
void __stackcall Audio_Ch2NoteOn(u8 note, u8 vol_env, u8 duty2);
// Clamp the note index, program the raw NR32 output level, and trigger CH3.
// Wave RAM must already contain the desired waveform; this does not load one.
void __stackcall Audio_Ch3NoteOn(u8 note, u8 level);
// Cache the supplied noise parameter, program the raw envelope and polynomial
// registers, then trigger CH4 with the length-enable bit clear.
void __stackcall Audio_Ch4NoteOn(u8 param, u8 vol_env);kitaqgb/lib/audio.h
audio_vblank.h — Reproducción musical mediante la interrupción VBlank
#pragma once
// Fixed-bank VBlank BGM driver.
//
// Stream format:
// delay, ch1_note, ch2_note, ch3_note, ch4_noise_param
// IMMEDIATE, ch1_note, ch2_note, ch3_note, ch4_noise_param
// CONTROL, command, arg0, arg1, arg2
//
// Notes are 0..67. To stay inside the useful CGB register range, C6..G6
// (60..67) alias C5..G5 (48..55) in the fixed pitch table. REST leaves a
// channel unchanged, while STOP silences it. END stops either playback mode.
// LOOP jumps to MusicLoopPoint only in direct-pointer mode; a queue producer
// must expand loops itself. IMMEDIATE is recognized only in queue mode.
// Direct streams treat 0xFB as an ordinary delay, and queues treat 0xFE as one.
#define AUDIO_VBLANK_REST ((u8)0xFF)
#define AUDIO_VBLANK_END ((u8)0xFF)
#define AUDIO_VBLANK_LOOP ((u8)0xFE)
#define AUDIO_VBLANK_STOP ((u8)0xFD)
#define AUDIO_VBLANK_CONTROL ((u8)0xFC)
#define AUDIO_VBLANK_IMMEDIATE ((u8)0xFB)
#define AUDIO_VBLANK_CONTROL_RESET ((u8)0x01)
#define AUDIO_VBLANK_W8 ((u8)15)
#define AUDIO_VBLANK_WQ ((u8)30)
#define AUDIO_VBLANK_WH ((u8)60)
#define AUDIO_VBLANK_QUEUE_RECORDS 16
#define AUDIO_VBLANK_QUEUE_BYTES 80
typedef void (*AudioVBlankFrameHook)();
extern __wram u8 AudioVBlank_MusicPlaying;
extern __wram u8 AudioVBlank_MusicEnabled;
extern __wram u8 AudioVBlank_MusicDelay;
extern __wram u8 *AudioVBlank_MusicStart;
extern __wram u8 *AudioVBlank_MusicPointer;
extern __wram u8 *AudioVBlank_MusicLoopPoint;
extern __wram u8 AudioVBlank_Step;
extern __wram u8 AudioVBlank_Ch2Note;
extern __wram u8 AudioVBlank_Ch1Note;
extern __wram u8 AudioVBlank_Ch3Note;
extern __wram u8 AudioVBlank_Ch2LatchedNote;
extern __wram u8 AudioVBlank_Ch1LatchedNote;
extern __wram u8 AudioVBlank_Ch3LatchedNote;
// Sound effects temporarily own CH1/CH2/CH3. A pending value of 1 means a BGM
// note/stop event was suppressed and must be applied once the effect ends;
// value 2 means release the effect channel without retriggering an old note.
extern __wram u8 AudioVBlank_RestoreCh1Pending;
extern __wram u8 AudioVBlank_RestoreCh3Pending;
extern __wram u8 AudioVBlank_Ch4Param;
extern __wram u8 AudioVBlank_Ch1Envelope;
extern __wram u8 AudioVBlank_Ch2Envelope;
extern __wram u8 AudioVBlank_Ch4Envelope;
extern __wram u8 AudioVBlank_Ch1Duty;
extern __wram u8 AudioVBlank_Ch2Duty;
extern __wram u8 AudioVBlank_Ch1Sweep;
extern __wram u8 AudioVBlank_Ch3Level;
extern __wram u8 AudioVBlank_ControlCommand;
extern __wram u8 AudioVBlank_ControlArg0;
extern __wram u8 AudioVBlank_ControlArg1;
extern __wram u8 AudioVBlank_ControlArg2;
// QueueReset/QueueRefill/QueuePlay provide the foreground producer. The ISR owns
// ReadIndex and decreases Count; use the producer APIs instead of editing the
// indices/count while playback is running. Records contain exactly five bytes.
// MusicPlaying and all enable/pause gates still apply in queue mode.
extern __wram u8 AudioVBlank_QueueMode;
extern __wram u8 AudioVBlank_QueueReadIndex;
extern __wram u8 AudioVBlank_QueueWriteIndex;
extern __wram u8 AudioVBlank_QueueCount;
extern __wram u8 AudioVBlank_QueueUnderruns;
// Queue bytes reside in WRAM bank 1. A producer must select that bank while
// writing and restore the caller bank; publish the record only after all bytes
// are complete. The ISR selects bank 1 itself and restores SVBK before returning.
extern __wramx_bank(1) u8 AudioVBlank_QueueBuffer[AUDIO_VBLANK_QUEUE_BYTES];
// The ISR invokes this hook even when music processing is gated off. It runs
// with SVBK=1 using a direct-address call; keep hook code/data accessible in that
// context and synchronize pointer changes with interrupt execution.
extern __wram AudioVBlankFrameHook AudioVBlank_FrameHook;
// Reset software playback state, queue counters, instruments and the frame hook.
// Call before enabling this ISR; the routine does not mask interrupts or
// initialize the APU registers and cannot synchronize with an active handler.
void AudioVBlank_Init();
// Stop music and select an empty WRAM queue; preserve IE, IME and enable/pause gates.
void AudioVBlank_QueueReset();
// Copy complete records from the currently mapped source; return records accepted.
// Each call attempts at most 16 records and stops when full. Null/zero returns 0.
// Supports ROM and RAM sources, restores SVBK and IE, and never changes IME.
// Single foreground producer only: do not call from an ISR or frame hook.
// LOOP must be expanded by the producer. END occupies a full five-byte record.
u8 __stackcall AudioVBlank_QueueRefill(const u8 *records, u8 count);
// Start/resume queued playback; return 1 on success, 0 for an empty/nonqueue mode.
// Does not enable the interrupt, music gate or clear pause. Queue before starting.
u8 AudioVBlank_QueuePlay();
// Select a directly addressed song and reset its cursors, leaving the playing
// flag unchanged. Song storage must remain accessible to the fixed-bank ISR;
// coordinate this multi-field update with interrupt execution.
void __stackcall AudioVBlank_SetMusic(u8 *song);
// Restart the selected direct song at its beginning, leaving queue mode.
// A null song invokes Stop; this does not enable the music or IRQ gates.
void AudioVBlank_Play();
// Select and restart a directly addressed song. This is not the banked WRAM-queue path.
void __stackcall AudioVBlank_PlayMusic(u8 *song);
// Stop software playback and silence pulse/noise envelopes and the wave DAC.
// Song pointers and the IRQ enable remain unchanged; the routine writes the
// physical channels directly, so coordinate ownership with sound effects.
void AudioVBlank_Stop();
// Gate music processing and clear pending CH1/CH3 recovery on disable.
// No audio register is written here: disabling does not itself silence a note
// already playing or disable the VBlank interrupt.
void __stackcall AudioVBlank_SetEnabled(u8 on);
// Enable the VBlank source in IE and execute EI, enabling CPU interrupts globally.
// Install the correct interrupt vector and initialize driver state first.
void AudioVBlank_EnableIrq();
// Clear only the VBlank bit in IE. Other interrupt sources and current sound remain unchanged.
void AudioVBlank_DisableIrq();
// Recover the borrowed pulse channel (CH1 or CH2) from its latched music event.
// Pending value 2, disabled music, or a non-note latch silences it instead.
// The caller must first establish that the effect has released the channel.
void AudioVBlank_RestoreCh1();
// Recover a latched wave-channel music event after effect release, or disable
// the DAC for a release-only request, disabled music, or a non-note latch.
// The caller owns effect arbitration and clearing the pending flag.
void AudioVBlank_RestoreCh3();
// Request deferred pulse-channel release only when no recovery is pending.
// Preserve value 1, which records a music event suppressed while an effect owned it.
void AudioVBlank_RequestRestoreCh1();
// Request a deferred wave-channel release only if no recovery is pending.
// Preserve value 1, which records a new music event suppressed by the effect.
void AudioVBlank_RequestRestoreCh3();kitaqgb/lib/audio_vblank.h
bank.h — Acceso a código y datos por bancos
#pragma once
// A bank byte accompanies the CPU-visible ROM address; the pointer alone is not a far address.
typedef __packed struct {
u8 bank;
const u8* ptr;
} BankPtr;
extern u8 kq_bank_current;
void __bankswitch(u8 bank);
u8 __farpeek8(u8 bank, const void* addr);
u16 __farpeek16(u8 bank, const void* addr);
void __farmemcpy(void* dst, u8 bank, const void* src, u16 len);
void __farcall_ptr(u8 bank, const void* func);
// Update both the library bank record and the compiler shadow used by far
// reads and calls. Invoke this permanent bank change from fixed-bank code.
void bank_switch(u8 bank);
// Return the last bank recorded by bank_switch; this does not read cartridge hardware.
u8 bank_get_current();
// Read one byte through the compiler intrinsic that accepts an explicit ROM bank.
u8 far_data_read8(u8 bank, const void* addr);
// Read a 16-bit value from the supplied bank and address through the far-read intrinsic.
u16 far_data_read16(u8 bank, const void* addr);
// Copy len bytes from banked ROM into caller-owned writable storage.
void far_data_read(u8 bank, const void* addr, void* dst, u16 len);
// Invoke a no-argument callback in its ROM bank, then restore the caller
// bank. The pointer must identify executable code; no arguments are forwarded.
void far_call(u8 bank, const void* func);
// Store a bank/address pair without accessing ROM; a null output pointer is ignored.
void farptr_make(BankPtr* out, u8 bank, const u8* ptr);
// Read one byte using both components of the bank-qualified pointer.
u8 farptr_read8(BankPtr ptr);
// Read a 16-bit value using both components of the bank-qualified pointer.
u16 farptr_read16(BankPtr ptr);
// Copy len bytes from a bank-qualified pointer; dst must have room for the full copy.
void farptr_read(BankPtr ptr, void* dst, u16 len);kitaqgb/lib/bank.h
camera.h — Coordenadas del mundo y áreas visibles
#pragma once
#include "scroll.h"
// All position, target and bound fields use signed Q8.8 (-128 to just below 128 pixels).
// Pass initialized, non-null storage; world/screen conversion arguments use integer pixels.
typedef struct Camera8_8 {
s16 fx;
s16 fy;
s16 target_fx;
s16 target_fy;
s16 min_fx;
s16 min_fy;
s16 max_fx;
s16 max_fy;
u8 use_target;
u8 use_bounds;
} Camera8_8;
// Zero all position/target/bound fields and disable targeting and bounds.
void Camera_Init(Camera8_8* cam);
// Replace the current Q8.8 position and immediately apply enabled bounds.
void Camera_Set(Camera8_8* cam, s16 fx, s16 fy);
// Store a Q8.8 target and enable subsequent step-toward-target updates.
void Camera_SetTarget(Camera8_8* cam, s16 fx, s16 fy);
// Disable target following without moving the camera or erasing the stored target.
void Camera_ClearTarget(Camera8_8* cam);
// Install ordered Q8.8 bounds, enable them and clamp the current position immediately.
void Camera_SetBounds(Camera8_8* cam, s16 min_fx, s16 min_fy, s16 max_fx, s16 max_fy);
// Disable clamping while retaining the stored bounds and current position.
void Camera_ClearBounds(Camera8_8* cam);
// Add Q8.8 deltas and clamp afterward. Keep the intermediate sums within s16;
// clamping cannot repair arithmetic that already overflowed.
void Camera_Add(Camera8_8* cam, s16 dfx, s16 dfy);
// Move by the signed target delta shifted by 0..7 bits, then apply bounds.
// Quantization can make a small delta produce no movement; only exact equality
// clears targeting, and a target outside the bounds may remain active indefinitely.
void Camera_StepTowardTarget(Camera8_8* cam, u8 shift);
// Discard fractional bits and write the low eight integer bits to background scroll registers.
void Camera_ApplyBg(const Camera8_8* cam);
// Convert the Q8.8 position to byte scroll values and stage them for a later flush.
void Camera_ApplyBgBuffered(const Camera8_8* cam);
// Derive nonnegative camera extents from world minus screen size, then convert
// them to Q8.8 bounds. Extents must fit signed Q8.8; the u16 input type does
// not imply support for arbitrary large worlds.
void Camera_ClampToSize(Camera8_8* cam, u16 world_w_px, u16 world_h_px, u8 screen_w_px, u8 screen_h_px);
// Convert an integer-pixel world X by subtracting the camera's integer X component.
s16 Camera_WorldToScreenX(const Camera8_8* cam, s16 world_x);
// Convert an integer-pixel world Y by subtracting the camera's integer Y component.
s16 Camera_WorldToScreenY(const Camera8_8* cam, s16 world_y);
// Convert integer-pixel screen X back to world X using the camera's integer component.
s16 Camera_ScreenToWorldX(const Camera8_8* cam, s16 screen_x);
// Convert integer-pixel screen Y back to world Y using the camera's integer component.
s16 Camera_ScreenToWorldY(const Camera8_8* cam, s16 screen_y);
// Set the shared camera from integer pixels, converting to the representable Q8.8 range.
void camera_set(s16 x, s16 y);
// Position the shared camera so the world point appears at the requested screen
// anchor. This is an immediate move, not the smoothed target-following path.
void camera_follow_xy(s16 x, s16 y, u8 screen_cx, u8 screen_cy);
// Derive and apply world/screen bounds to the shared convenience camera.
void camera_clamp(u16 world_w_px, u16 world_h_px, u8 screen_w_px, u8 screen_h_px);
// Write the shared camera's current integer position to background scroll registers.
void camera_apply();
// Convert integer-pixel world X using the shared convenience camera.
s16 camera_world_to_screen_x(s16 world_x);
// Convert integer-pixel world Y using the shared convenience camera.
s16 camera_world_to_screen_y(s16 world_y);kitaqgb/lib/camera.h
cgb_palette.h — Paletas de fondo y OBJ de CGB
#pragma once
// High-level CGB palette helpers for KITAQGB.
// Palette writes no-op on DMG; RGB packing works on either hardware model.
// Safe here means CGB hardware gating. Palette data writes still require an accessible
// PPU phase (for example LCD off or a sufficiently short VBlank update).
u8 __cgb_is_cgb();
void __cgb_safe_set_bcps(u8 value);
void __cgb_safe_set_bcpd(u8 value);
void __cgb_safe_set_ocps(u8 value);
void __cgb_safe_set_ocpd(u8 value);
// Mask each component to five bits: red in 0..4, green in 5..9, blue in 10..14.
// These macros wrap oversized components rather than saturating them.
#define CGB_RGB15(r5, g5, b5) ((u16)((u16)((r5) & 31) | ((u16)((g5) & 31) << 5) | ((u16)((b5) & 31) << 10)))
// Pack the red, green and blue components using the public RGB15 macro.
u16 cgb_rgb15(u8 r5, u8 g5, u8 b5);
// Set one background color through the indexed palette wrapper.
void cgb_bg_color(u8 palette_index, u8 color_index, u16 rgb15);
// Set one object color through the indexed palette wrapper.
void cgb_obj_color(u8 palette_index, u8 color_index, u16 rgb15);
// Pack component values and write one background color.
void cgb_bg_rgb(u8 palette_index, u8 color_index, u8 r5, u8 g5, u8 b5);
// Pack component values and write one object color.
void cgb_obj_rgb(u8 palette_index, u8 color_index, u8 r5, u8 g5, u8 b5);
// Write background colors starting at the indexed slot. The range may cross
// palette boundaries and is clamped only at the end of all 32 slots.
void cgb_bg_colors(u8 palette_index, u8 start_color_index, const u16* colors, u8 color_count);
// Write object colors from the indexed slot, potentially crossing into later palettes.
void cgb_obj_colors(u8 palette_index, u8 start_color_index, const u16* colors, u8 color_count);
// Write four consecutive colors for one background palette.
void cgb_bg_palette(u8 palette_index, const u16* colors);
// Write four consecutive colors for one object palette.
void cgb_obj_palette(u8 palette_index, const u16* colors);
// Expose sequential background writes using an absolute color-slot index.
void cgb_bg_colors_raw(u8 start_color_slot, const u16* colors, u8 color_count);
// Expose sequential object writes using an absolute color-slot index.
void cgb_obj_colors_raw(u8 start_color_slot, const u16* colors, u8 color_count);kitaqgb/lib/cgb_palette.h
cgb_tile.h — Números y atributos de tiles de CGB
#pragma once
// Declarations for compiler-intrinsic CGB tile helpers.
// Canonical intrinsic entry points use the "__" prefix.
// Attr writes no-op on DMG. Combined tile+attr writes still write the tile on DMG.
// These helpers emit compiler code; cgb_tile.c has no runtime bodies. Scalar coordinates address 32x32 maps.
// Safe write paths poll VRAM access; LCD-on paths can enable interrupts after writing.
// Use _unsafe/_fast only with caller-managed writable VRAM timing, especially inside an ISR.
// Tile writes use the selected VRAM bank; choose bank zero before combined tile/attribute operations.
#define KQ_CGB_ATTR_PAL_MASK 0x07
#define KQ_CGB_ATTR_BANK1 0x08
#define KQ_CGB_ATTR_XFLIP 0x20
#define KQ_CGB_ATTR_YFLIP 0x40
#define KQ_CGB_ATTR_PRIORITY 0x80
#define KQ_CGB_ATTR_NONE ((u8)0)
#define KQ_CGB_ATTR_PAL(n) ((u8)((n) & KQ_CGB_ATTR_PAL_MASK))
#define KQ_CGB_ATTR_BANK(bank) ((u8)((bank) ? KQ_CGB_ATTR_BANK1 : 0))
#define KQ_CGB_ATTR_XFLIP_IF(enabled) ((u8)((enabled) ? KQ_CGB_ATTR_XFLIP : 0))
#define KQ_CGB_ATTR_YFLIP_IF(enabled) ((u8)((enabled) ? KQ_CGB_ATTR_YFLIP : 0))
#define KQ_CGB_ATTR_PRIORITY_IF(enabled) ((u8)((enabled) ? KQ_CGB_ATTR_PRIORITY : 0))
#define KQ_CGB_ATTR(palette, bank, xflip, yflip, priority) ((u8)(((palette) & KQ_CGB_ATTR_PAL_MASK) | ((bank) ? KQ_CGB_ATTR_BANK1 : 0) | ((xflip) ? KQ_CGB_ATTR_XFLIP : 0) | ((yflip) ? KQ_CGB_ATTR_YFLIP : 0) | ((priority) ? KQ_CGB_ATTR_PRIORITY : 0)))
// Return the compiler/runtime CGB mode test as a byte Boolean.
u8 __cgb_is_cgb();
// Write the VRAM bank selection only on CGB. Safe here means hardware-mode guarded, not PPU-timed.
void __cgb_safe_set_vbk(u8 value);
// Write a tile number to map 9800, waiting for VRAM access when necessary.
void __settile(u8 x, u8 y, u8 tile);
// Write a tile number to map 9800 without waiting for writable VRAM.
void __settile_unsafe(u8 x, u8 y, u8 tile);
// Write at base+32*y+x with VRAM access checks; supply a valid tile-map base.
void __settileat(u16 base, u8 x, u8 y, u8 tile);
// Use an explicit map base without waiting for VRAM access.
void __settileat_unsafe(u16 base, u8 x, u8 y, u8 tile);
// Select the window map from LCDC bit 6, then write a tile with access checks.
void __settilewin(u8 x, u8 y, u8 tile);
// Select the LCDC window map and write without access waits.
void __settilewin_unsafe(u8 x, u8 y, u8 tile);
// Select the background map from LCDC bit 3, then write with access checks.
void __settilebg(u8 x, u8 y, u8 tile);
// Select the LCDC background map and write without access waits.
void __settilebg_unsafe(u8 x, u8 y, u8 tile);
// Copy count sequential bytes to dest using the current VRAM bank and access-checked transfer.
void __settile_bulk(u16 dest, const u8* src, u8 count);
// Copy count sequential bytes to dest without VRAM access waits; retain source-bank visibility.
void __settile_bulk_fast(u16 dest, const u8* src, u8 count);
// Write attributes in bank one at map 9800 on CGB, then leave VBK zero; skip on DMG. Use the access-checked write path.
void __settileattr(u8 x, u8 y, u8 attr);
// Write attributes in bank one at map 9800 on CGB, then leave VBK zero; skip on DMG. No VRAM access waits are inserted.
void __settileattr_unsafe(u8 x, u8 y, u8 attr);
// Write tile and CGB attributes at map 9800; DMG receives only the tile write. Use the access-checked write path.
void __settilecgb(u8 x, u8 y, u8 tile, u8 attr);
// Write tile and CGB attributes at map 9800; DMG receives only the tile write. No VRAM access waits are inserted.
void __settilecgb_unsafe(u8 x, u8 y, u8 tile, u8 attr);
// Write attributes in bank one at the explicit map base on CGB, then leave VBK zero; skip on DMG. Use the access-checked write path.
void __settileatattr(u16 base, u8 x, u8 y, u8 attr);
// Write attributes in bank one at the explicit map base on CGB, then leave VBK zero; skip on DMG. No VRAM access waits are inserted.
void __settileatattr_unsafe(u16 base, u8 x, u8 y, u8 attr);
// Write tile and CGB attributes at the explicit map base; DMG receives only the tile write. Use the access-checked write path.
void __settileatcgb(u16 base, u8 x, u8 y, u8 tile, u8 attr);
// Write tile and CGB attributes at the explicit map base; DMG receives only the tile write. No VRAM access waits are inserted.
void __settileatcgb_unsafe(u16 base, u8 x, u8 y, u8 tile, u8 attr);
// Write attributes in bank one at the LCDC window map on CGB, then leave VBK zero; skip on DMG. Use the access-checked write path.
void __settilewinattr(u8 x, u8 y, u8 attr);
// Write attributes in bank one at the LCDC window map on CGB, then leave VBK zero; skip on DMG. No VRAM access waits are inserted.
void __settilewinattr_unsafe(u8 x, u8 y, u8 attr);
// Write tile and CGB attributes at the LCDC window map; DMG receives only the tile write. Use the access-checked write path.
void __settilewincgb(u8 x, u8 y, u8 tile, u8 attr);
// Write tile and CGB attributes at the LCDC window map; DMG receives only the tile write. No VRAM access waits are inserted.
void __settilewincgb_unsafe(u8 x, u8 y, u8 tile, u8 attr);
// Write attributes in bank one at the LCDC background map on CGB, then leave VBK zero; skip on DMG. Use the access-checked write path.
void __settilebgattr(u8 x, u8 y, u8 attr);
// Write attributes in bank one at the LCDC background map on CGB, then leave VBK zero; skip on DMG. No VRAM access waits are inserted.
void __settilebgattr_unsafe(u8 x, u8 y, u8 attr);
// Write tile and CGB attributes at the LCDC background map; DMG receives only the tile write. Use the access-checked write path.
void __settilebgcgb(u8 x, u8 y, u8 tile, u8 attr);
// Write tile and CGB attributes at the LCDC background map; DMG receives only the tile write. No VRAM access waits are inserted.
void __settilebgcgb_unsafe(u8 x, u8 y, u8 tile, u8 attr);
// Copy count attributes to dest in bank one on CGB, then leave VBK zero; skip on DMG. Transfers use access checks.
void __settileattr_bulk(u16 dest, const u8* src, u8 count);
// Copy count attributes to dest in bank one on CGB, then leave VBK zero; skip on DMG. The caller supplies writable VRAM timing.
void __settileattr_bulk_fast(u16 dest, const u8* src, u8 count);
// Copy tile and attribute streams to dest; DMG receives only tiles. Keep both sources readable. Transfers use access checks.
void __settilecgb_bulk(u16 dest, const u8* tile_src, const u8* attr_src, u8 count);
// Copy tile and attribute streams to dest; DMG receives only tiles. Keep both sources readable. The caller supplies writable VRAM timing.
void __settilecgb_bulk_fast(u16 dest, const u8* tile_src, const u8* attr_src, u8 count);kitaqgb/lib/cgb_tile.h
chain.h — Búferes circulares para el historial de posiciones
#pragma once
typedef __packed struct {
s16 x;
s16 y;
} ChainPoint;
typedef __packed struct {
ChainPoint* points;
u8 capacity;
u8 count;
u8 head;
} Chain;
// Attach caller-owned ring storage and start with no recorded points.
// The storage must remain valid for the lifetime of the chain.
// Use a valid chain pointer and capacity entries of caller-owned storage.
// Capacity at most 128 keeps every head+age sum in the byte range used by the reader.
void chain_init(Chain* chain, ChainPoint* storage, u8 capacity);
// Forget the recorded points without clearing or freeing the backing storage.
void chain_clear(Chain* chain);
// Move the ring head backward and store the newest point. Once full, each push
// replaces the oldest point; zero capacity is a no-op.
void chain_push_head(Chain* chain, s16 x, s16 y);
// Read a point by age, with index zero denoting the newest point. Return zero
// for an invalid request and clear a non-null output first. Keep head + index
// within the 8-bit range: addition is narrowed before the capacity wrap.
u8 chain_get_segment(const Chain* chain, u8 index, ChainPoint* out);
// Return the number of stored points, or zero for a null chain.
u8 chain_get_count(const Chain* chain);
// Return target minus current along the shortest wrapped route.
// Supply size 1..256 and coordinates in 0..size-1; inputs are not normalized.
// Exactly half a field retains the direct displacement sign.
s16 chain_wrap_delta(u8 target, u8 current, u16 size);
// Articulated body: one current pose per joint, including the head at index 0.
// Caller-owned byte arrays keep the inner loop compact on both GB and FC.
// Heading sectors run clockwise: 0=right, 4=down, 8=left, 12=up.
// Coordinates are pixels; each wrapped dimension accepts 1..256 pixels.
typedef __packed struct {
u8* x;
u8* y;
u8* heading;
u8 capacity;
u8 count;
u16 width;
u16 height;
} ChainBody;
// Attach three non-overlapping capacity-byte arrays. Return 1 on success.
// Invalid storage, zero capacity or dimensions outside 1..256 disable the body.
u8 chain_body_init(ChainBody* body, u8* x, u8* y, u8* heading, u8 capacity, u16 width, u16 height);
// Seed count joints in a straight pose behind the head; count includes the head.
// Return 0 without changing the pose if count is zero or exceeds capacity.
// Coordinates wrap to the playfield and headings are masked to 0..15.
u8 chain_body_reset(ChainBody* body, u8 count, u8 head_x, u8 head_y, u8 heading);
// Install the caller's head pose, then pull joints from front to rear.
// Each joint aims four pixels behind its updated predecessor and receives that
// predecessor's OLD heading. Each axis moves 1 pixel, or 2 when error exceeds 4.
// Call once per simulation tick; this does not advance head physics or render.
void chain_body_step(ChainBody* body, u8 head_x, u8 head_y, u8 heading);
// Append a copy of the current tail; later steps separate the new joint.
// Return 1 on growth, or 0 for an empty, disabled or full body.
u8 chain_body_grow(ChainBody* body);
// Remove all joints while retaining caller-owned storage and playfield settings.
void chain_body_clear(ChainBody* body);kitaqgb/lib/chain.h
danmaku.h — Grupos de proyectiles, abanicos, impactos y roces
#pragma once
// Fixed-capacity, allocation-free bullet field for a 160 x 128 play area.
// Positions/velocities are signed Q12.4 / Q4.4; +Y points down.
// Tile ids 0..15 encode the four 4x4 quadrants of an 8x8 tile.
// Reserve those tiles in VRAM, with a 3x3 bullet centered at (2,2)
// in every set quadrant. Other tile ids in the map are decoration.
#define DANMAKU_MAX 96
#define DANMAKU_MAP_BYTES 576
typedef __packed struct {
s16 x;
s16 y;
s8 vx;
s8 vy;
u8 active;
u8 grazed;
} DanmakuBullet;
extern DanmakuBullet dm_bullets[DANMAKU_MAX];
extern __wram __aligned(16) u8 dm_map[DANMAKU_MAP_BYTES];
extern u8 dm_count;
extern u8 dm_peak;
// Per-step hit is a Boolean latch; graze counts newly grazed bullets this step. Spawn/rejection counters wrap at 65536.
extern u8 dm_hit;
extern u8 dm_graze;
extern u8 dm_player_x;
extern u8 dm_player_y;
extern u8 dm_invulnerable;
extern u16 dm_spawned;
extern u16 dm_rejected;
// Reset pool, peak and lifetime counters; player fields and map contents remain caller-owned state.
void danmaku_reset();
// Deactivate the pool while retaining peak/spawn/rejection counters and the RAM map.
void danmaku_clear();
// Use pixel origins inside 160x128 and signed sixteenth-pixel velocities; return one if a slot was allocated.
u8 danmaku_spawn(u8 x, u8 y, s8 vx, s8 vy);
// Attempt a fan using wrapping 32-step angles; count is capped at 96 and speed at 64.
void danmaku_fan(u8 x, u8 y, u8 direction, u8 step, u8 count, u8 speed);
// 32 directions, 0=right, 8=down, 16=left, 24=up. speed in 1/16 px.
// Clear the 32x18 RAM map before drawing the next frame; no transfer is performed.
void danmaku_clear_map();
// Caller fills decoration after clear_map, then calls step to overlay bullets.
// hit and graze are events for this step. Collision uses rendered centers.
void danmaku_step();
// Requires CGB and LCD off or the beginning of VBlank. VBK restored to 0.
// Transfers 18 rows (32-byte stride) to BG map 9800 with 36-block GDMA.
void danmaku_present_now();kitaqgb/lib/danmaku.h
debug.h — Registros y aserciones en RAM
#pragma once
// Use a capacity from 1 through 255; the length counter is a byte.
// Compile every unit with the same override so the array declaration and storage agree.
#ifndef DEBUG_TRACE_MAX
#define DEBUG_TRACE_MAX 32
#endif
// Each packed entry retains a name pointer and two 16-bit values; name text is not copied.
typedef __packed struct {
const u8* name;
u16 value;
u16 frame;
} DebugTraceEntry;
extern DebugTraceEntry kq_debug_trace_log[DEBUG_TRACE_MAX];
extern u8 kq_debug_trace_count;
extern u16 kq_debug_frame;
extern u16 kq_debug_last_assert;
// Reset log length, frame tag and last assertion code; existing entry bytes are not erased.
void debug_init();
// Set the frame tag copied into subsequently recorded entries.
void debug_set_frame(u16 frame);
// Append a named frame marker using 0xFFFF as its value.
void debug_mark_frame(const u8* label);
// Append an unsigned byte value, widened to the log's 16-bit value field.
void debug_trace_u8(const u8* name, u8 value);
// Append a 16-bit value with the current frame tag.
void debug_trace_u16(const u8* name, u16 value);
// Record the assertion code and attempt to append an ASSERT entry. This helper
// does not halt execution, and the code is retained even if the log is full.
void debug_assert_fail(u16 code);
// Return the number of valid entries in the fixed trace buffer.
u8 debug_get_trace_count();
// Expose the internal trace array for inspection; use the count to bound reads.
const DebugTraceEntry* debug_get_trace_log();
// Read the last recorded assertion code, or the zero value installed by initialization.
u16 debug_get_last_assert();
#define KITAQGB_TRACE_U8(name, value) debug_trace_u8((const u8*)(name), (u8)(value))
#define KITAQGB_TRACE_U16(name, value) debug_trace_u16((const u8*)(name), (u16)(value))
#define KITAQGB_TRACE(name, value) debug_trace_u16((const u8*)(name), (u16)(value))
#define KITAQGB_MARK_FRAME(label) debug_mark_frame((const u8*)(label))
#define KITAQGB_ASSERT(cond) do { if (!(cond)) debug_assert_fail((u16)1); } while (0)
#define KITAQGB_ASSERT_CODE(cond, code) do { if (!(cond)) debug_assert_fail((u16)(code)); } while (0)kitaqgb/lib/debug.h
dmg3d.h — Gráficos de alambre monocromos de 128×120 para DMG
// Compatibility names for the shared wire3d_dmg renderer.
// Select the same profile in every translation unit; compile one renderer entry.
#pragma once
#ifndef WIRE3D_DMG_HEIGHT
#define WIRE3D_DMG_HEIGHT 120
#endif
#if WIRE3D_DMG_HEIGHT != 120
#error Incompatible wire3d_dmg profile
#endif
#include "wire3d_dmg.h"
// The aliases below add no calls or storage. Their contracts are documented at the corresponding wire3d_dmg.h declarations.
#define DMG3D_ANGLE_STEPS WIRE3D_DMG_ANGLE_STEPS
#define DMG3D_AUX_COL_BYTES WIRE3D_DMG_AUX_COL_BYTES
#define DMG3D_AUX_ROWS WIRE3D_DMG_AUX_ROWS
#define DMG3D_BG_QUEUE_LIMIT WIRE3D_DMG_BG_QUEUE_LIMIT
#define DMG3D_BeginFrame Wire3DDMG_BeginFrame
#define DMG3D_CENTER_X WIRE3D_DMG_CENTER_X
#define DMG3D_CENTER_Y WIRE3D_DMG_CENTER_Y
#define DMG3D_DrawIndexedEdges Wire3DDMG_DrawIndexedEdges
#define DMG3D_DrawLine2D Wire3DDMG_DrawLine2D
#define DMG3D_DrawLine3D Wire3DDMG_DrawLine3D
#define DMG3D_DrawModel Wire3DDMG_DrawModel
#define DMG3D_DrawModelScaled Wire3DDMG_DrawModelScaled
#define DMG3D_DrawScene Wire3DDMG_DrawScene
#define DMG3D_Edge Wire3DDMG_Edge
#define DMG3D_EdgeFaces Wire3DDMG_EdgeFaces
#define DMG3D_EndFrame Wire3DDMG_EndFrame
#define DMG3D_EraseModelFaces Wire3DDMG_EraseModelFaces
#define DMG3D_EraseSpan2D Wire3DDMG_EraseSpan2D
#define DMG3D_EraseTriangle2D Wire3DDMG_EraseTriangle2D
#define DMG3D_FACE_NONE WIRE3D_DMG_FACE_NONE
#define DMG3D_FAR_Z WIRE3D_DMG_FAR_Z
#define DMG3D_Face Wire3DDMG_Face
#define DMG3D_Init Wire3DDMG_Init
#define DMG3D_MODEL_FACE_LIMIT WIRE3D_DMG_MODEL_FACE_LIMIT
#define DMG3D_MODEL_HIDDEN_LINES WIRE3D_DMG_MODEL_HIDDEN_LINES
#define DMG3D_MODEL_VERTEX_LIMIT WIRE3D_DMG_MODEL_VERTEX_LIMIT
#define DMG3D_Model Wire3DDMG_Model
#define DMG3D_NEAR_Z WIRE3D_DMG_NEAR_Z
#define DMG3D_Object Wire3DDMG_Object
#define DMG3D_PROJECT_LIMIT WIRE3D_DMG_PROJECT_LIMIT
#define DMG3D_ProjectPoint Wire3DDMG_ProjectPoint
#define DMG3D_PutBgTile Wire3DDMG_PutBgTile
#define DMG3D_ROW_BYTES WIRE3D_DMG_ROW_BYTES
#define DMG3D_RotatePoint Wire3DDMG_RotatePoint
#define DMG3D_SCENE_OBJECT_LIMIT WIRE3D_DMG_SCENE_OBJECT_LIMIT
#define DMG3D_SCREEN_H WIRE3D_DMG_SCREEN_H
#define DMG3D_SCREEN_W WIRE3D_DMG_SCREEN_W
#define DMG3D_SetAuxTransfer Wire3DDMG_SetAuxTransfer
#define DMG3D_SetCamera Wire3DDMG_SetCamera
#define DMG3D_SetDirtyTransfer Wire3DDMG_SetDirtyTransfer
#define DMG3D_SetPalette Wire3DDMG_SetPalette
#define DMG3D_TILE_H WIRE3D_DMG_TILE_H
#define DMG3D_TILE_W WIRE3D_DMG_TILE_W
#define DMG3D_TRANSFORM_LIMIT WIRE3D_DMG_TRANSFORM_LIMIT
#define DMG3D_TransferAuxNow Wire3DDMG_TransferAuxNow
#define DMG3D_TransferMainNow Wire3DDMG_TransferMainNow
#define DMG3D_Vec3 Wire3DDMG_Vec3
// The remaining aliases retain internal identifiers for source compatibility; they do not define an independent renderer.
#define DMG3D_abs_i16 w3ddmg_abs_i16
#define DMG3D_angle_index w3ddmg_angle_index
#define DMG3D_aux_transfer_enabled w3ddmg_aux_transfer_enabled
#define DMG3D_bg_map_9800 w3ddmg_bg_map_9800
#define DMG3D_bgq_addr_hi w3ddmg_bgq_addr_hi
#define DMG3D_bgq_addr_lo w3ddmg_bgq_addr_lo
#define DMG3D_bgq_count w3ddmg_bgq_count
#define DMG3D_bgq_tile w3ddmg_bgq_tile
#define DMG3D_bgq_value w3ddmg_bgq_value
#define DMG3D_bgq_x w3ddmg_bgq_x
#define DMG3D_bgq_y w3ddmg_bgq_y
#define DMG3D_bit_mask w3ddmg_bit_mask
#define DMG3D_build_face_visibility w3ddmg_build_face_visibility
#define DMG3D_cam_pitch w3ddmg_cam_pitch
#define DMG3D_cam_roll w3ddmg_cam_roll
#define DMG3D_cam_x w3ddmg_cam_x
#define DMG3D_cam_y w3ddmg_cam_y
#define DMG3D_cam_yaw w3ddmg_cam_yaw
#define DMG3D_cam_z w3ddmg_cam_z
#define DMG3D_clamp_i16 w3ddmg_clamp_i16
#define DMG3D_clamp_screen w3ddmg_clamp_screen
#define DMG3D_clear_dirty_tables w3ddmg_clear_dirty_tables
#define DMG3D_clear_occlusion_mask w3ddmg_clear_occlusion_mask
#define DMG3D_clear_occlusion_mask_asm w3ddmg_clear_occlusion_mask_asm
#define DMG3D_clear_stage_asm w3ddmg_clear_stage_asm
#define DMG3D_clear_stage_aux_asm w3ddmg_clear_stage_aux_asm
#define DMG3D_clear_triangle w3ddmg_clear_triangle
#define DMG3D_clear_vram_asm w3ddmg_clear_vram_asm
#define DMG3D_cos_q6 w3ddmg_cos_q6
#define DMG3D_dirty_dst_hi w3ddmg_dirty_dst_hi
#define DMG3D_dirty_dst_lo w3ddmg_dirty_dst_lo
#define DMG3D_dirty_src_hi w3ddmg_dirty_src_hi
#define DMG3D_dirty_src_lo w3ddmg_dirty_src_lo
#define DMG3D_dirty_tiles w3ddmg_dirty_tiles
#define DMG3D_dirty_transfer_enabled w3ddmg_dirty_transfer_enabled
#define DMG3D_edge_area w3ddmg_edge_area
#define DMG3D_face_visible w3ddmg_face_visible
#define DMG3D_fill_bg_map_asm w3ddmg_fill_bg_map_asm
#define DMG3D_flush_bg_queue w3ddmg_flush_bg_queue
#define DMG3D_i16 w3ddmg_i16
#define DMG3D_i8 w3ddmg_i8
#define DMG3D_inv_depth w3ddmg_inv_depth
#define DMG3D_is_edge_visible w3ddmg_is_edge_visible
#define DMG3D_line_dx w3ddmg_line_dx
#define DMG3D_line_dy w3ddmg_line_dy
#define DMG3D_line_err w3ddmg_line_err
#define DMG3D_line_stage_asm w3ddmg_line_stage_asm
#define DMG3D_line_stage_masked_c w3ddmg_line_stage_masked_c
#define DMG3D_line_sx w3ddmg_line_sx
#define DMG3D_line_sy w3ddmg_line_sy
#define DMG3D_line_x w3ddmg_line_x
#define DMG3D_line_x0 w3ddmg_line_x0
#define DMG3D_line_x1 w3ddmg_line_x1
#define DMG3D_line_y w3ddmg_line_y
#define DMG3D_line_y0 w3ddmg_line_y0
#define DMG3D_line_y1 w3ddmg_line_y1
#define DMG3D_mark_line_dirty w3ddmg_mark_line_dirty
#define DMG3D_mark_model_occluder w3ddmg_mark_model_occluder
#define DMG3D_mark_rect_dirty w3ddmg_mark_rect_dirty
#define DMG3D_mark_tile_dirty w3ddmg_mark_tile_dirty
#define DMG3D_mark_triangle w3ddmg_mark_triangle
#define DMG3D_mask_get w3ddmg_mask_get
#define DMG3D_mask_offset w3ddmg_mask_offset
#define DMG3D_mask_set w3ddmg_mask_set
#define DMG3D_mask_set_span w3ddmg_mask_set_span
#define DMG3D_neg_angle w3ddmg_neg_angle
#define DMG3D_occlusion_active w3ddmg_occlusion_active
#define DMG3D_occlusion_mask w3ddmg_occlusion_mask
#define DMG3D_plot_stage_asm w3ddmg_plot_stage_asm
#define DMG3D_plot_tx w3ddmg_plot_tx
#define DMG3D_plot_x w3ddmg_plot_x
#define DMG3D_plot_y w3ddmg_plot_y
#define DMG3D_prev_dirty_tiles w3ddmg_prev_dirty_tiles
#define DMG3D_project_camera_space w3ddmg_project_camera_space
#define DMG3D_project_world w3ddmg_project_world
#define DMG3D_put_bg_tile_safe_asm w3ddmg_put_bg_tile_safe_asm
#define DMG3D_reg_bgp w3ddmg_reg_bgp
#define DMG3D_reg_lcdc w3ddmg_reg_lcdc
#define DMG3D_reg_ly w3ddmg_reg_ly
#define DMG3D_reg_scx w3ddmg_reg_scx
#define DMG3D_reg_scy w3ddmg_reg_scy
#define DMG3D_rotate_x w3ddmg_rotate_x
#define DMG3D_rotate_y w3ddmg_rotate_y
#define DMG3D_rotate_z w3ddmg_rotate_z
#define DMG3D_scene_depth w3ddmg_scene_depth
#define DMG3D_scene_object_depth w3ddmg_scene_object_depth
#define DMG3D_scene_order w3ddmg_scene_order
#define DMG3D_screen_delta w3ddmg_screen_delta
#define DMG3D_screen_visible w3ddmg_screen_visible
#define DMG3D_screen_x w3ddmg_screen_x
#define DMG3D_screen_y w3ddmg_screen_y
#define DMG3D_sin_q6 w3ddmg_sin_q6
#define DMG3D_stage w3ddmg_stage
#define DMG3D_stage_clear_pixel w3ddmg_stage_clear_pixel
#define DMG3D_stage_clear_span w3ddmg_stage_clear_span
#define DMG3D_transfer_dirty_stage w3ddmg_transfer_dirty_stage
#define DMG3D_transfer_dirty_tile_asm w3ddmg_transfer_dirty_tile_asm
#define DMG3D_transfer_stage_asm w3ddmg_transfer_stage_asm
#define DMG3D_transfer_stage_aux_asm w3ddmg_transfer_stage_aux_asm
#define DMG3D_u16 w3ddmg_u16
#define DMG3D_u8 w3ddmg_u8
#define DMG3D_vram_tiles w3ddmg_vram_tiles
#define DMG3D_wait_vblank_start w3ddmg_wait_vblank_start
#define dmg3d w3ddmg
#define dmg3d_pair_aux_block w3ddmg_pair_aux_block
#define dmg3d_pair_aux_done w3ddmg_pair_aux_done
#define dmg3d_pair_aux_wait_0 w3ddmg_pair_aux_wait_0
#define dmg3d_pair_aux_wait_1 w3ddmg_pair_aux_wait_1
#define dmg3d_pair_aux_wait_10 w3ddmg_pair_aux_wait_10
#define dmg3d_pair_aux_wait_11 w3ddmg_pair_aux_wait_11
#define dmg3d_pair_aux_wait_12 w3ddmg_pair_aux_wait_12
#define dmg3d_pair_aux_wait_13 w3ddmg_pair_aux_wait_13
#define dmg3d_pair_aux_wait_14 w3ddmg_pair_aux_wait_14
#define dmg3d_pair_aux_wait_15 w3ddmg_pair_aux_wait_15
#define dmg3d_pair_aux_wait_16 w3ddmg_pair_aux_wait_16
#define dmg3d_pair_aux_wait_17 w3ddmg_pair_aux_wait_17
#define dmg3d_pair_aux_wait_18 w3ddmg_pair_aux_wait_18
#define dmg3d_pair_aux_wait_19 w3ddmg_pair_aux_wait_19
#define dmg3d_pair_aux_wait_2 w3ddmg_pair_aux_wait_2
#define dmg3d_pair_aux_wait_20 w3ddmg_pair_aux_wait_20
#define dmg3d_pair_aux_wait_21 w3ddmg_pair_aux_wait_21
#define dmg3d_pair_aux_wait_22 w3ddmg_pair_aux_wait_22
#define dmg3d_pair_aux_wait_23 w3ddmg_pair_aux_wait_23
#define dmg3d_pair_aux_wait_24 w3ddmg_pair_aux_wait_24
#define dmg3d_pair_aux_wait_25 w3ddmg_pair_aux_wait_25
#define dmg3d_pair_aux_wait_26 w3ddmg_pair_aux_wait_26
#define dmg3d_pair_aux_wait_27 w3ddmg_pair_aux_wait_27
#define dmg3d_pair_aux_wait_3 w3ddmg_pair_aux_wait_3
#define dmg3d_pair_aux_wait_4 w3ddmg_pair_aux_wait_4
#define dmg3d_pair_aux_wait_5 w3ddmg_pair_aux_wait_5
#define dmg3d_pair_aux_wait_6 w3ddmg_pair_aux_wait_6
#define dmg3d_pair_aux_wait_7 w3ddmg_pair_aux_wait_7
#define dmg3d_pair_aux_wait_8 w3ddmg_pair_aux_wait_8
#define dmg3d_pair_aux_wait_9 w3ddmg_pair_aux_wait_9
#define dmg3d_pair_main_block w3ddmg_pair_main_block
#define dmg3d_pair_main_wait_0 w3ddmg_pair_main_wait_0
#define dmg3d_pair_main_wait_1 w3ddmg_pair_main_wait_1
#define dmg3d_pair_main_wait_10 w3ddmg_pair_main_wait_10
#define dmg3d_pair_main_wait_11 w3ddmg_pair_main_wait_11
#define dmg3d_pair_main_wait_12 w3ddmg_pair_main_wait_12
#define dmg3d_pair_main_wait_13 w3ddmg_pair_main_wait_13
#define dmg3d_pair_main_wait_14 w3ddmg_pair_main_wait_14
#define dmg3d_pair_main_wait_2 w3ddmg_pair_main_wait_2
#define dmg3d_pair_main_wait_3 w3ddmg_pair_main_wait_3
#define dmg3d_pair_main_wait_4 w3ddmg_pair_main_wait_4
#define dmg3d_pair_main_wait_5 w3ddmg_pair_main_wait_5
#define dmg3d_pair_main_wait_6 w3ddmg_pair_main_wait_6
#define dmg3d_pair_main_wait_7 w3ddmg_pair_main_wait_7
#define dmg3d_pair_main_wait_8 w3ddmg_pair_main_wait_8
#define dmg3d_pair_main_wait_9 w3ddmg_pair_main_wait_9
#define dmg3dac_col w3ddmgac_col
#define dmg3dac_enter w3ddmgac_enter
#define dmg3dac_row w3ddmgac_row
#define dmg3dbg_enter w3ddmgbg_enter
#define dmg3dco_enter w3ddmgco_enter
#define dmg3dco_loop w3ddmgco_loop
#define dmg3dco_page w3ddmgco_page
#define dmg3dcs_enter w3ddmgcs_enter
#define dmg3dcs_inner w3ddmgcs_inner
#define dmg3dcs_outer w3ddmgcs_outer
#define dmg3dcv_enter w3ddmgcv_enter
#define dmg3dcv_loop w3ddmgcv_loop
#define dmg3dcv_page w3ddmgcv_page
#define dmg3ddt_enter w3ddmgdt_enter
#define dmg3ddt_loop w3ddmgdt_loop
#define dmg3dfb_enter w3ddmgfb_enter
#define dmg3dfb_loop w3ddmgfb_loop
#define dmg3dfb_page w3ddmgfb_page
#define dmg3dls_branch w3ddmgls_branch
#define dmg3dls_done w3ddmgls_done
#define dmg3dls_enter w3ddmgls_enter
#define dmg3dls_shallow w3ddmgls_shallow
#define dmg3dls_shallow_loop w3ddmgls_shallow_loop
#define dmg3dls_shallow_skip_bridge w3ddmgls_shallow_skip_bridge
#define dmg3dls_steep w3ddmgls_steep
#define dmg3dls_steep_loop w3ddmgls_steep_loop
#define dmg3dls_steep_skip_bridge w3ddmgls_steep_skip_bridge
#define dmg3dls_x_reverse w3ddmgls_x_reverse
#define dmg3dls_y_reverse w3ddmgls_y_reverse
#define dmg3dls_y_start w3ddmgls_y_start
#define dmg3dps_enter w3ddmgps_enter
#define dmg3dps_ret w3ddmgps_retkitaqgb/lib/dmg3d.h
entity.h — Grupos de objetos basados en arrays fijos
#pragma once
// Keep capacity in 1..255: IDs and scan counters are bytes and FF is reserved for failure.
// Use the same definition in every compilation unit.
#ifndef ENTITY_MAX
#define ENTITY_MAX ((u8)16)
#endif
// Position, velocity, state and timer units are game-defined; the pool does not advance them.
// The sprite field is only bookkeeping and does not allocate or release OAM entries.
typedef __packed struct {
u8 active;
u8 type;
s16 x;
s16 y;
s16 vx;
s16 vy;
u8 state;
u8 timer;
u8 sprite;
} Entity;
// An entity callback receives a slot ID, not a persistent object handle.
typedef void (*EntityFn)(u8 id);
// Reset every slot before the game starts using the pool.
void entity_init();
// Returns a reusable slot ID, or 0xFF if no slot is free.
u8 entity_create(u8 type, s16 x, s16 y);
// Release a valid slot without clearing its payload. Reallocation resets the payload;
// a saved pointer or ID must not be treated as a persistent entity identity.
void entity_destroy(u8 id);
// Returns null for an invalid or inactive ID; the returned pointer aliases reusable pool storage.
Entity* entity_get(u8 id);
// Call fn for each slot that is active when the scan reaches it; null is a no-op.
// Callbacks may change the pool, so newly activated later slots can run in this pass.
void entity_update_all(EntityFn fn);
// Use the same active-slot traversal for drawing; the callback supplies all rendering.
void entity_draw_all(EntityFn fn);
// Count occupied slots without changing entity state.
u8 entity_count_active();
// Release every entity and restore deterministic defaults, including the no-sprite sentinel.
void entity_clear_all();kitaqgb/lib/entity.h
fixed.h — Aritmética de punto fijo Q8.8 y rectángulos
#pragma once
// Signed Q8.8 uses 256 units per pixel/value: the range is -128 to 127 + 255/256.
typedef s16 fix8;
#define FIX_ONE ((fix8)256)
#define FIX_HALF ((fix8)128)
typedef __packed struct {
fix8 x;
fix8 y;
} Vec2;
typedef __packed struct {
s16 x;
s16 y;
s16 w;
s16 h;
} KQRect;
// Convert an integer to signed 8.8 fixed point by moving it into the high byte.
// The caller must keep the result within the representable 16-bit range.
fix8 fix_from_int(s16 n);
// Discard the eight fractional bits using a signed right shift.
s16 fix_to_int(fix8 x);
// Approximate 8.8 multiplication by discarding four low bits from each operand
// before multiplying. This trades precision for a smaller intermediate product.
fix8 fix_mul(fix8 a, fix8 b);
// Scale the reduced-precision quotient back to 8.8 and return zero for b == 0.
// Callers must also ensure (b >> 4) is nonzero; the explicit check only tests b.
// The intermediate product must fit the compiler's integer arithmetic.
fix8 fix_div(fix8 a, fix8 b);
// Interpolate toward b using a quantized Q0.8 weight. Both shifts discard low
// bits, so small changes may vanish and a weight of 255 need not reach b.
fix8 fix_lerp(fix8 a, fix8 b, u8 t_q8);
// Return the magnitude in s16. The most-negative s16 has no positive s16
// representation and must be excluded by callers needing a nonnegative result.
s16 kq_abs_s16(s16 v);
// Select the smaller signed value.
s16 kq_min_s16(s16 a, s16 b);
// Select the larger signed value.
s16 kq_max_s16(s16 a, s16 b);
// Clamp to an inclusive interval; callers must provide lo <= hi.
s16 kq_clamp_s16(s16 v, s16 lo, s16 hi);
// Test overlap using exclusive right/bottom edges; touching edges do not collide.
// Require positive dimensions and edge sums that fit s16; zero-sized rectangles
// are not explicitly rejected and may be reported as overlapping.
u8 kq_rect_intersect(KQRect a, KQRect b);
// Test a half-open rectangle: left/top edges are included, right/bottom excluded.
// The coordinate-plus-size sums must remain representable as s16.
u8 kq_point_in_rect(s16 x, s16 y, KQRect r);kitaqgb/lib/fixed.h
input.h — Estado, pulsación, liberación y repetición de botones
#pragma once
#define BTN_RIGHT ((u8)0x01)
#define BTN_LEFT ((u8)0x02)
#define BTN_UP ((u8)0x04)
#define BTN_DOWN ((u8)0x08)
#define BTN_A ((u8)0x10)
#define BTN_B ((u8)0x20)
#define BTN_SELECT ((u8)0x40)
#define BTN_START ((u8)0x80)
// A fresh press pulses immediately. The next pulse occurs DELAY + 1 updates later.
#ifndef INPUT_REPEAT_DELAY
#define INPUT_REPEAT_DELAY ((u8)18)
#endif
// Subsequent pulses are RATE + 1 updates apart; zero repeats on every held update.
#ifndef INPUT_REPEAT_RATE
#define INPUT_REPEAT_RATE ((u8)5)
#endif
extern u8 kq_input_prev_keys;
extern u8 kq_input_keys;
extern u8 kq_input_press_keys;
extern u8 kq_input_release_keys;
extern u8 kq_input_repeat_keys;
u16 __readpadex(u8 prev_keys);
// Clear sampled/edge state and initialize an independent repeat timer for each button.
void input_init();
// Sample input once per game tick and derive press, release and repeat masks.
// Repeat delays are measured in calls to this function, not elapsed wall-clock time.
void input_update();
// Return whether any masked button is currently held.
u8 input_down(u8 mask);
// Return whether any masked button became pressed in the latest sample.
u8 input_pressed(u8 mask);
// Return whether any masked button became released in the latest sample.
u8 input_released(u8 mask);
// Return whether any masked button produced a fresh press or scheduled repeat pulse.
u8 input_repeat(u8 mask);
// Return the complete held-button mask from the latest update.
u8 input_current();
// Return the held-button mask that preceded the latest update.
u8 input_previous();
#define btn_down input_down
#define btn_pressed input_pressed
#define btn_released input_released
#define btn_repeat input_repeatkitaqgb/lib/input.h
link.h — Comunicación serie y paquetes lógicos
#pragma once
// Shared Game Boy serial link library for KITAQGB projects.
//
// Integration notes:
// - Compile a hardware-register file before link.c / link_packet.c so SB, SC,
// IF_REG, and IE_REG are already declared.
// - Call Link_InitMaster() on the clock-source side and Link_InitSlave() on the
// other side.
// - Call Link_Poll() or Link_PollPacket() regularly from the main loop.
// - If you enable serial IRQ mode, call Link_OnSerialIRQ() from your own
// serial interrupt handler at vector 0x0058.
// - The packet layer is intentionally small and one-deep. It works best as a
// master-driven command/response layer. The low-level byte API remains the
// escape hatch for custom protocols.
#define LINK_MODE_SLAVE ((u8)0)
#define LINK_MODE_MASTER ((u8)1)
#define LINK_CLOCK_NORMAL ((u8)0)
#define LINK_CLOCK_FAST ((u8)1)
#define LINK_ERR_NONE ((u8)0)
#define LINK_ERR_BUSY ((u8)1)
#define LINK_ERR_TIMEOUT ((u8)2)
#define LINK_ERR_OVERFLOW ((u8)3)
#define LINK_ERR_PROTOCOL ((u8)4)
#define LINK_ERR_DISCONNECT ((u8)5)
#define LINK_PKT_MAX_PAYLOAD ((u8)24)
#define LINK_RX_QUEUE_SIZE ((u8)8)
#define LINK_TX_QUEUE_SIZE ((u8)8)
#define LINK4_MODE_NONE ((u8)0)
#define LINK4_MODE_HOST ((u8)1)
#define LINK4_MODE_PEER ((u8)2)
#define LINK4_MAX_PLAYERS ((u8)4)
#define LINK4_HOST_SLOT ((u8)0)
#define LINK4_INVALID_SLOT ((u8)0xFF)
// Reset byte queues, packet mailboxes, cooperative-peer state and errors, then
// disable serial transfers and serial IRQ delivery. Existing data is discarded.
void Link_InitCommon();
// Reset link state and select the internal-clock role for subsequent transfers.
void Link_InitMaster();
// Reset link state and select the external-clock role for subsequent transfers.
void Link_InitSlave();
// Enable or disable serial IRQ delivery and clear its pending flag. Enabling
// does not install the handler. Leaving its outer critical section enables CPU interrupts.
void __stackcall Link_SetUseInterrupt(u8 on);
// Select the fast-clock bit for future master transfers; this does not restart
// an active transfer or verify that the hardware supports CGB fast mode.
void __stackcall Link_SetFastClock(u8 on);
// Poll once before returning busy state, so this query may collect a completed byte.
u8 Link_IsBusy();
// Read the ordinary receive-ready flag without polling hardware.
u8 Link_HasByte();
// Return the latest latched error without clearing it.
u8 Link_LastError();
// Clear the error latch without resetting queues or an active transfer.
void Link_ClearError();
// Start one full-duplex byte exchange, or return BUSY without replacing an
// active transfer. Slave mode arms reception and waits for external clocks.
u8 __stackcall Link_BeginTransfer(u8 out);
// Collect a pending transfer only after hardware clears the SC start bit.
void Link_Poll();
// Stop the hardware transfer under interrupt protection. Queued receive bytes
// and packet-layer state remain available; this is not a full protocol reset.
void Link_Cancel();
// Acknowledge serial IRQ and finish a software-busy transfer. Call this from
// the actual serial interrupt handler, not an unrelated interrupt.
void Link_OnSerialIRQ();
// Pop the ordinary receive queue without waiting or polling hardware; null discards a byte.
u8 __stackcall Link_TryReadByte(u8 *out);
// Pop one byte, returning zero when empty. Use Link_TryReadByte when a received
// zero byte must be distinguished from an empty queue.
u8 Link_ReadByte();
// Require an output pointer, poll immediately, then wait at most timeout_frames
// VBlanks for a byte. Zero timeout still performs the initial poll and read.
u8 __stackcall Link_WaitByte(u16 timeout_frames, u8 *out);
// Validate payload size and idle packet state, copy payload bytes into owned
// storage and schedule transmission. Return success means queued, not acknowledged;
// keep polling to progress the exchange and inspect the error latch.
u8 __stackcall Link_SendPacket(const u8 *data, u8 len, u8 cmd);
// Drain received bytes, advance one outgoing exchange and update the retry
// timer. Timeout ticks count calls without progress, not hardware frames; call
// with a controlled cadence and avoid mixing raw reads with packet consumption.
void Link_PollPacket();
// Inspect the shared completed-packet flag without advancing the protocol.
u8 Link_HasPacket();
// Consume the shared packet mailbox and its matching peer flag. Any output
// may be null; a nonnull destination needs room for the received payload because
// there is no destination-capacity argument.
u8 __stackcall Link_ReadPacket(u8 *cmd, u8 *len, u8 *dst);
// Cooperative 4-player adapter helpers.
//
// This layer models the common host-selected adapter pattern:
// - Slot 0 is always the host.
// - The host selects one active peer slot at a time.
// - Packet mailboxes stay one-deep per peer.
// - The original Link_* API remains available for normal 2-player projects.
// Reset as master, validate slot count and select logical peer one. Invalid configuration still discards old link state.
u8 __stackcall Link4_InitHost(u8 slot_count);
// Reset as slave and validate the local nonzero slot and total slot count.
// An invalid configuration still discards the previous link state.
u8 __stackcall Link4_InitPeer(u8 local_slot, u8 slot_count);
// Return the configured cooperative role; this is not a hardware connection probe.
u8 Link4_GetMode();
// Return the configured zero-based local slot.
u8 Link4_GetLocalSlot();
// Return the configured number of logical slots, not a live connection count.
u8 Link4_GetSlotCount();
// Return the current logical destination, or the invalid-slot sentinel when unset.
u8 Link4_GetSelectedPeer();
// Return the peer attributed to the last completed byte transfer.
u8 Link4_GetLastRxPeer();
// Return the peer attributed when the last byte transfer was started.
u8 Link4_GetLastTxPeer();
// Poll completion, then change the logical destination only while byte and
// packet state are idle. A peer can select only the host. No adapter-routing
// command is sent here; the transport must provide the matching physical route.
u8 __stackcall Link4_SelectPeer(u8 peer_slot);
// Select the logical peer and start a byte exchange, returning the first error.
u8 __stackcall Link4_BeginTransferTo(u8 peer_slot, u8 out);
// Inspect a valid peer ring without polling the hardware.
u8 __stackcall Link4_HasByteFrom(u8 peer_slot);
// Pop one byte from the selected peer ring; null output discards it.
u8 __stackcall Link4_TryReadByteFrom(u8 peer_slot, u8 *out);
// Scan remote rings in increasing slot order and return the first available
// byte. Null output pointers are allowed; lower slots have polling priority.
u8 __stackcall Link4_TryReadByteAny(u8 *peer_slot, u8 *out);
// Select a logical peer, then copy and schedule a packet; return the first error.
u8 __stackcall Link4_SendPacketTo(u8 peer_slot, const u8 *data, u8 len, u8 cmd);
// Advance the shared packet engine; this does not poll every logical peer in turn.
void Link4_PollPacket();
// Inspect the one-packet mailbox for a valid remote slot without consuming it.
u8 __stackcall Link4_HasPacketFrom(u8 peer_slot);
// Consume a peer mailbox, copying to optional outputs. A nonnull destination
// needs room for the entire payload. Clear the shared mailbox only when it
// refers to this same peer.
u8 __stackcall Link4_ReadPacketFrom(u8 peer_slot, u8 *cmd, u8 *len, u8 *dst);kitaqgb/lib/link.h
link_dmg07.h — Comunicación DMG-07 con reloj externo
#pragma once
// Polling driver for the physical Nintendo DMG-07 Four Player Adapter.
//
// The adapter supplies every serial clock. LinkDmg07_Poll() must therefore be
// called frequently enough to re-arm the serial port between adapter bytes;
// calling it only once per video frame is not sufficient. Call
// LinkDmg07_TickFrame() exactly once per frame for timeout accounting.
//
// Transmission uses SIZE=1: every adapter packet contains four bytes, one for
// each physical player slot. A console sends its local byte during byte 0 and
// sends zero during bytes 1..3, except while emitting an aligned FF restart
// packet. The adapter broadcasts those four submitted bytes in the following
// packet. The initial broadcast contains undefined adapter data and is
// discarded by this driver.
#define LINK_DMG07_PHASE_PING ((u8)0)
#define LINK_DMG07_PHASE_REQUEST_AA ((u8)1)
#define LINK_DMG07_PHASE_WAIT_CC ((u8)2)
#define LINK_DMG07_PHASE_TRANSFER ((u8)3)
#define LINK_DMG07_MAX_PLAYERS ((u8)4)
#define LINK_DMG07_PACKET_BYTES ((u8)4)
#define LINK_DMG07_SIZE ((u8)1)
// Physical slots here are one-based; do not substitute the zero-based Link4 cooperative slot identifiers.
#define LINK_DMG07_NO_SLOT ((u8)0)
// RATE $10 gives the shortest documented packet period for SIZE=1 while
// retaining the adapter's normal inter-byte pacing. RATE $00 is not used.
#define LINK_DMG07_DEFAULT_RATE ((u8)0x10)
#ifndef LINK_DMG07_TIMEOUT_FRAMES
#define LINK_DMG07_TIMEOUT_FRAMES ((u8)12)
#endif
#define LINK_DMG07_ERR_NONE ((u8)0)
#define LINK_DMG07_ERR_STATE ((u8)1)
#define LINK_DMG07_ERR_NOT_PLAYER1 ((u8)2)
#define LINK_DMG07_ERR_NOT_READY ((u8)3)
#define LINK_DMG07_ERR_TIMEOUT ((u8)4)
#define LINK_DMG07_ERR_PROTOCOL ((u8)5)
#define LINK_DMG07_ERR_OVERFLOW ((u8)6)
#define LINK_DMG07_RESTART_NONE ((u8)0)
#define LINK_DMG07_RESTART_PENDING ((u8)1)
#define LINK_DMG07_RESTART_SENDING ((u8)2)
// Initializes polling-only external-clock operation. A zero RATE is replaced
// with LINK_DMG07_DEFAULT_RATE. This driver disables only the serial IRQ bit.
void __stackcall LinkDmg07_Init(u8 rate);
// Services at most one completed serial byte and immediately re-arms SC=$80.
// Call continuously from the main loop, including between VBlanks.
void LinkDmg07_Poll();
// Advances saturating frame-based silence and handshake timeout counters.
void LinkDmg07_TickFrame();
// Return the discovery, start-handshake or transfer phase without polling.
u8 LinkDmg07_GetPhase();
// Return the one-based player slot, or LINK_DMG07_NO_SLOT before discovery.
u8 LinkDmg07_GetLocalSlot();
// Normalized mask: bit 0 is player 1, ..., bit 3 is player 4.
u8 LinkDmg07_GetConnectedMask();
// Return the last validated raw adapter status byte.
u8 LinkDmg07_GetLastStatus();
// Read the completed-discovery status flag without clearing it.
u8 LinkDmg07_HasPingStatus();
// Clear and report the completed-discovery flag; return zero if no new status exists.
u8 LinkDmg07_ConsumePingStatus();
// Only physical player 1 may request AA AA AA AA. The bytes are aligned to
// the next FE/status/status/status ping packet. All consoles enter transfer
// mode only after receiving four consecutive CC bytes.
u8 LinkDmg07_RequestTransmission();
// Any physical slot may schedule FF FF FF FF at the next four-byte packet
// boundary while remaining in TRANSFER phase. The driver keeps sending aligned
// FF bytes until it sees the adapter's complete all-FF indicator packet, then
// returns to PING. A transfer-phase silence timeout schedules the same recovery
// automatically and preserves the current byte position for clocks that resume.
u8 LinkDmg07_RequestRestart();
// Return whether aligned recovery is absent, pending or sending control traffic.
u8 LinkDmg07_GetRestartState();
// Sets the byte sampled when byte 0 of the next adapter packet is armed.
// Set it before the current packet completes (and before requesting start for
// the first submission). During normal transfer, bytes 1..3 are sent as zero.
void __stackcall LinkDmg07_SetLocalByte(u8 value);
// The first incoming adapter data packet is discarded. Thereafter ReadPacket
// copies four bytes in physical slot order (players 1..4).
u8 LinkDmg07_IsPipelinePrimed();
// Inspect the one-packet receive mailbox without consuming it.
u8 LinkDmg07_HasPacket();
// Consume the latest four-byte packet. A nonnull destination must hold four
// bytes; null discards the packet. Packet storage remains after the flag clears.
u8 __stackcall LinkDmg07_ReadPacket(u8 *dst);
// Read one cached player byte using a one-based slot. Invalid slots return
// zero; the function neither requires readiness nor consumes the packet.
u8 __stackcall LinkDmg07_GetPacketSlot(u8 player_slot);
// SentSequence increments when this console's packet byte is clocked out.
// PacketSequence labels the returned four-byte packet. For a valid packet it
// is one less than SentSequence, making the DMG-07 one-packet delay explicit.
u8 LinkDmg07_GetSentSequence();
// Return the modulo-256 sequence associated with the most recently published packet.
u8 LinkDmg07_GetPacketSequence();
// SilenceFrames is reset by every completed serial byte. TimeoutCount counts
// distinct serial-silence or AA/CC/restart handshake timeouts. DisconnectCount counts
// adapter-silence outages and ping-status membership drops. All saturate.
u8 LinkDmg07_GetSilenceFrames();
// Return the saturating lifetime timeout count, preserved across protocol restarts.
u8 LinkDmg07_GetTimeoutCount();
// Return the saturating count of removed-player and previously-seen-adapter timeout events.
u8 LinkDmg07_GetDisconnectCount();
// Return the saturating protocol/overflow error count. Timeout and request
// validation paths use separate counters or latches and do not increment this value.
u8 LinkDmg07_GetErrorCount();
// Return the latest error latch without clearing counters or restarting the protocol.
u8 LinkDmg07_LastError();
// Clear only the latest error code, preserving counters and protocol state.
void LinkDmg07_ClearError();kitaqgb/lib/link_dmg07.h
physics2d.h — Movimiento y colisiones en 2D
#pragma once
// Position and velocity use caller-selected integer units with one integration
// step per call; no hidden pixel or time conversion occurs. Keep intermediate
// signed arithmetic in range. World/body storage is owned by the caller.
#include "fixed.h"
// Multiply a signed word by a signed byte; divide by 256, truncating toward zero.
s16 __smul16x8(s16 a, s8 b);
// Lightweight deterministic 2D physics for KITAQGB.
// Integer pixels per step are one possible unit convention; inv_mass is Q8.
typedef struct {
s16 x;
s16 y;
s16 vx;
s16 vy;
s16 half_x;
s16 half_y;
s16 inv_mass_q8; // 0 means static body.
s16 restitution_q8; // 0..255 (reserved for future tuning).
u8 active;
} KQBody2D;
typedef struct {
KQBody2D* bodies;
u8 body_count;
s16 gravity_x;
s16 gravity_y;
u8 solver_iterations;
s16 max_speed;
} KQWorld2D;
// Retain the caller-owned body array without initializing its elements.
// Set gravity to (0,32), four contact iterations and a per-axis speed limit of 512.
// A null world is ignored; the array must outlive subsequent world operations.
void kq2d_world_init(KQWorld2D* world, KQBody2D* bodies, u8 body_count);
// Advance active dynamic bodies, then visit each active unordered pair for
// the configured contact passes (zero means one). Static bodies still participate
// as obstacles. The world borrows its array and shares non-reentrant ASM scratch.
// This is discrete integration; fast bodies can pass through thin obstacles.
void kq2d_step(KQWorld2D* world);
// For one active dynamic body, add gravity, clamp each velocity axis and then
// add velocity to position. Null inputs are ignored; no contacts are solved.
// Use a nonnegative speed limit and keep additions in signed 16-bit range.
void kq2d_integrate_body(KQWorld2D* world, KQBody2D* body);
// Test strict overlap of two centered boxes; touching edges return false.
// Both pointers must be valid. Active/mass flags are ignored, and coordinate
// differences and extent sums must fit the signed 16-bit calculations.
u8 kq2d_overlap_aabb(const KQBody2D* a, const KQBody2D* b);
// Initialize an active unit-inverse-mass body at the supplied center and half
// extents, with zero velocity and reserved restitution set to zero. Null is ignored.
void kq2d_body_init(KQBody2D* body, s16 x, s16 y, s16 half_x, s16 half_y);
// Replace the center without altering velocity, extents or activity. Null is ignored.
void kq2d_body_set_pos(KQBody2D* body, s16 x, s16 y);
// Replace velocity without clamping or checking activity/mass. Null is ignored.
void kq2d_body_set_velocity(KQBody2D* body, s16 vx, s16 vy);
// Add gravity and clamp each velocity axis separately for an active dynamic
// body. Null, inactive and static bodies are ignored. Supply a nonnegative limit
// and avoid overflow in the additions before clamping; position is unchanged.
void kq2d_body_apply_gravity(KQBody2D* body, s16 gravity_x, s16 gravity_y, s16 max_speed);
// Scale both velocities through the signed 8-bit coefficient intrinsic.
// Despite the unsigned parameter, values 128..255 become negative coefficients;
// this is not a full-range unsigned Q8 damping helper. Null is ignored.
void kq2d_body_apply_friction(KQBody2D* body, u8 friction_q8);
// Delegate strict rectangle overlap to the fixed-point utility; edge-only
// contact is false. Coordinate-plus-size sums must remain representable as s16.
u8 kq2d_rect_intersect(KQRect a, KQRect b);
// Delegate the half-open point test: include left/top and exclude right/bottom.
// Coordinate-plus-size sums must remain representable as s16.
u8 kq2d_point_in_rect(s16 x, s16 y, KQRect r);
// Opt-in surface solver. Velocities/threshold/kick share the caller's units.
// Normal must be unit length in Q8; coefficients are 0..255.
typedef struct {
s16 nx_q8;
s16 ny_q8;
s16 vx;
s16 vy;
s16 bounce_threshold;
s16 kick;
u8 restitution_q8;
u8 friction_q8;
} KQSurface2D;
// Truncates toward zero, including negative values; coefficient is -256..256.
s16 kq2d_scale_q8(s16 value, s16 coefficient);
// Conservative circular bound, with a shared Q8 scale for both components.
// Quantizes toward zero; very small limits relative to input may yield zero.
// Components and positive max_speed must be <= 16383 in magnitude.
void kq2d_body_limit_speed(KQBody2D* body, s16 max_speed);
// Kinematic surface response; returns incoming normal speed, or zero if separating.
// Caller resolves penetration separately. Relative components must fit +/-8191.
s16 kq2d_body_resolve_surface(KQBody2D* body, const KQSurface2D* surface);
// Linear crossing time in Q8 (0..256); positive separation is outside.
// Returns 0 for initial overlap, 256 for no crossing. Gaps must fit +/-8191.
u16 kq2d_surface_toi_q8(s16 start_gap, s16 end_gap);kitaqgb/lib/physics2d.h
physics2d_circle.h — Física de círculos
#pragma once
// Deterministic 2D circle physics for KITAQGB.
// Intended for top-down ball games such as billiards, air hockey, and marbles.
// Use consistent caller-selected units for centers, radii and per-step velocity.
// The implementation uses 16-bit arithmetic: reduced squared-distance sums and
// weight products must fit their types. Reduction to byte-sized components alone
// is insufficient to guarantee this. Body storage remains caller-owned.
typedef struct {
s16 x;
s16 y;
s16 vx;
s16 vy;
s16 radius;
s16 inv_mass_q8; // 0 means static body.
u8 restitution_q8; // 0..255, higher means bouncier.
u8 friction_q8; // 0..255, higher removes more tangential motion.
u8 active;
} KQCircleBody2D;
typedef struct {
KQCircleBody2D* bodies;
u8 body_count;
s16 gravity_x;
s16 gravity_y;
u8 solver_iterations;
s16 max_speed;
u8 linear_damping_q8; // 255 is almost no damping, lower values damp faster.
u8 use_bounds;
s16 min_x;
s16 min_y;
s16 max_x;
s16 max_y;
u8 wall_restitution_q8;
u8 wall_friction_q8;
} KQCircleWorld2D;
// Retain a caller-owned array without initializing bodies. Set zero gravity,
// four contact passes, per-axis limit 768 and damping 252/256; bounds start disabled.
// A null world is ignored. Keep the array alive for subsequent steps.
void kq2dc_world_init(KQCircleWorld2D* world, KQCircleBody2D* bodies, u8 body_count);
// Store and enable bounds without validating their order or fitting bodies
// immediately. Supply extents large enough for body diameters. Null is ignored.
void kq2dc_set_bounds(KQCircleWorld2D* world, s16 min_x, s16 min_y, s16 max_x, s16 max_y);
// Integrate active dynamic bodies, apply bounds, solve contacts, then damp
// velocity and snap components in -1..1 to zero. Zero solver iterations means one.
// Pairs with both velocities zero are skipped, so resting overlaps can remain.
// Bounds can reposition static bodies; null world/array inputs are ignored.
void kq2dc_step(KQCircleWorld2D* world);
// Compare a reduced integer center distance with the reduced radius sum.
// Valid pointers and positive radii are required; activity and mass are ignored.
// This approximate test requires representable differences, radius sums and
// squared-distance sum. Touching at the computed distance returns false.
u8 kq2dc_overlap_circle(const KQCircleBody2D* a, const KQCircleBody2D* b);kitaqgb/lib/physics2d_circle.h
physics3d.h — Física de cajas AABB en 3D
#pragma once
// Lightweight deterministic 3D physics for KITAQGB.
// AABB contacts, acceleration, mass-weighted bounce, and impact state flags.
// The game owns break decisions: the solver records impact speeds but never
// sets this flag or deactivates a body based on break_speed. Positions, extents,
// velocities and acceleration use consistent caller-selected per-step units.
#define KQ3D_BODY_BROKEN ((u8)0x01)
typedef struct {
s16 x;
s16 y;
s16 z;
s16 vx;
s16 vy;
s16 vz;
s16 ax;
s16 ay;
s16 az;
s16 half_x;
s16 half_y;
s16 half_z;
s16 mass_q8; // 256 means mass 1.0.
s16 inv_mass_q8; // 0 means static body.
s16 restitution_q8; // 256 means perfectly elastic.
s16 break_speed; // Reserved for game-side impact thresholds.
s16 last_impact_speed;
u8 active;
u8 flags;
} KQBody3D;
typedef struct {
KQBody3D* bodies;
u8 body_count;
s16 gravity_x;
s16 gravity_y;
s16 gravity_z;
u8 solver_iterations;
s16 max_speed;
} KQWorld3D;
// Borrow the body array without initializing it. Set gravity (0,24,0), four
// contact passes and a per-axis speed limit of 512. Null world is ignored;
// the caller retains ownership and must keep the array alive.
void kq3d_world_init(KQWorld3D* world, KQBody3D* bodies, u8 body_count);
// Initialize an active centered box with zero velocity/acceleration,
// restitution 224, cleared impact/flags and mass set through the weight helper.
// The caller supplies valid half extents. Null body is ignored.
void kq3d_body_init(KQBody3D* body, s16 x, s16 y, s16 z, s16 half_x, s16 half_y, s16 half_z, s16 mass_q8);
// Store the requested mass; nonpositive mass makes the body static.
// For positive mass compute inverse weight as max(1,32767/max(mass,64)).
// The stored mass retains the original input; this is a relative solver weight,
// not an exact Q8 reciprocal. Null body is ignored.
void kq3d_body_set_mass(KQBody3D* body, s16 mass_q8);
// Integrate active dynamic bodies and reset their impact values, then solve
// each active unordered pair for the configured passes (zero means one).
// Static bodies retain previous impact maxima until the game clears them.
// Acceleration persists; flags and break thresholds remain game-owned.
// This discrete solver shares non-reentrant ASM scratch and can miss fast crossings.
void kq3d_step(KQWorld3D* world);
// Reset impact for one active dynamic body, add gravity and persistent body
// acceleration, clamp velocity per axis and advance position. Static/inactive
// bodies retain impact state. Null inputs are ignored; no contacts are solved.
// Use a nonnegative speed limit and avoid overflow before clamping.
void kq3d_integrate_body(KQWorld3D* world, KQBody3D* body);
// Test strict overlap on all three axes; face-only contact returns false.
// Valid pointers are required and flags are ignored. Center differences and
// extent sums must fit the signed 16-bit magnitude calculations.
u8 kq3d_overlap_aabb(const KQBody3D* a, const KQBody3D* b);
// Sum three signed products, shifting each by eight bits before addition.
// Coefficients are signed bytes scaled by 1/256; the 16-bit sum is not saturated.
s16 kq3d_dot_q8_8(s16 x, s16 y, s16 z, s8 ax, s8 ay, s8 az);kitaqgb/lib/physics3d.h
raster.h — Tablas de desplazamiento por franjas y líneas de barrido
#pragma once
#include "scroll.h"
// Keep wrapper capacity consistent with the compiler split-table capacity; wrapper checks do not enlarge it.
#define KQ_RASTER_MAX_BANDS 8
#define KQ_RASTER_OK 0
#define KQ_RASTER_FULL 1
#define KQ_RASTER_BAD_LY 2
#define KQ_RASTER_UNSORTED 3
#define KQ_RASTER_BAD_RANGE 4
#define KQ_RASTER_BG KQ_SCROLL_SPLIT_USE_BG
#define KQ_RASTER_WIN KQ_SCROLL_SPLIT_USE_WIN
#define KQ_RASTER_WIN_SHOW KQ_SCROLL_SPLIT_WIN_SHOW
#define KQ_RASTER_WIN_HIDE KQ_SCROLL_SPLIT_WIN_HIDE
#define KQ_RASTER_BG_COLOR0 KQ_SCROLL_SPLIT_BG_COLOR0
#define KQ_RASTER_FLAG_MASK 0x1F
#define KQ_RASTER_LINE_FLAT 0
#define KQ_RASTER_LINE_X_TITLE 1
#define KQ_RASTER_LINE_TRAVEL_GATE 2
// Caller-owned wave state. Initialize it before use and keep it non-null for every LineX operation.
// frame_counter measures RunFrame calls, not an independent hardware clock.
typedef struct RasterLineX {
u8 profile;
u8 base_x;
u8 phase;
u8 phase_step;
u8 frame_divider;
u8 frame_counter;
} RasterLineX;
// Stop split scheduling, empty the shared table and clear error/count state.
void Raster_Init();
// Stop splits immediately and clear bookkeeping. Build and commit a new table to restart.
void Raster_Clear();
// Commit an empty split table so no raster bands remain active.
void Raster_Disable();
// Read the number of bands currently recorded by this wrapper.
u8 Raster_GetCount();
// Read the last stored status without clearing it.
u8 Raster_GetLastError();
// Append a validated background-scroll band and advance the monotonic-LY
// bookkeeping. A successful append clears the previous error.
u8 Raster_Push(u8 ly, u8 scx, u8 scy);
// Append a validated extended band after masking flags to supported operations.
u8 Raster_PushEx(u8 ly, u8 scx, u8 scy, u8 wx, u8 wy, u8 flags);
// Enable window updates and pass hardware WX/WY values without coordinate conversion.
u8 Raster_PushWindowRaw(u8 ly, u8 wx, u8 wy, u8 flags);
// Convert screen X to hardware WX by adding seven, then queue a window band.
// The byte addition wraps if callers supply an excessive X coordinate.
u8 Raster_PushWindowScreen(u8 ly, u8 screen_x, u8 screen_y, u8 flags);
// Queue both background and window updates, converting window screen X to WX.
u8 Raster_PushBgWindowScreen(u8 ly, u8 scx, u8 scy, u8 screen_x, u8 screen_y, u8 flags);
// Pack a 15-bit color into the extended band's two scroll-byte fields and select
// the color-zero operation, which interprets those fields as color data.
u8 Raster_PushBgColor0(u8 ly, u16 rgb15);
// Publish pending splits and return the stored status. This commits even if an
// earlier append failed; callers should inspect errors while building the table.
u8 Raster_Commit();
// Validate the HUD height, then replace pending splits with a fixed top band
// and scrolling playfield. The new table still requires an explicit commit.
u8 Raster_BuildHudTop(u8 hud_height, u8 camera_x, u8 camera_y);
// Build a scrolling upper playfield and fixed bottom HUD after validating the split.
u8 Raster_BuildHudBottom(u8 hud_y, u8 camera_x, u8 camera_y);
// Build two horizontal-scroll bands sharing one vertical scroll value.
u8 Raster_BuildParallax2(u8 split_y, u8 far_scx, u8 near_scx, u8 scy);
// Build three horizontal-scroll bands at ordered visible split lines. Invalid
// parameters leave the previous pending table intact and set the error status.
u8 Raster_BuildParallax3(u8 y1, u8 y2, u8 scx0, u8 scx1, u8 scx2, u8 scy);
// Initialize a scanline-wave state with phase zero and one phase step per frame.
void Raster_LineXInit(RasterLineX* effect, u8 profile, u8 base_x);
// Change the wave profile and restart its phase/divider counter.
void Raster_LineXSetProfile(RasterLineX* effect, u8 profile);
// Configure the phase increment and frame interval; clamp a zero interval to one.
void Raster_LineXSetSpeed(RasterLineX* effect, u8 phase_step, u8 frame_divider);
// Set the byte phase directly without resetting the frame-divider counter.
void Raster_LineXSetPhase(RasterLineX* effect, u8 phase);
// Look up the selected periodic profile at LY + phase and add base X modulo
// 256. An unknown profile returns the unmodified base X.
u8 Raster_LineXGetOffset(const RasterLineX* effect, u8 ly);
// Render all 144 visible lines with one SCX write per line, then advance phase.
// This foreground renderer masks interrupts during the visible frame. Do game
// and audio work between calls; do not combine it with a STAT raster driver.
// Returns without changing the effect when the LCD is off.
void Raster_LineXRunFrame(RasterLineX* effect);kitaqgb/lib/raster.h
rpg.h — Números aleatorios, texto, mapas, guardado y servicios RPG/ADV/SLG
#pragma once
// The application supplies frame/cursor/font tiles at these indices; these constants do not load graphics.
#ifndef TEXT_TILE_FILL
#define TEXT_TILE_FILL ((u8)0)
#endif
#ifndef TEXT_TILE_FRAME_TL
#define TEXT_TILE_FRAME_TL ((u8)1)
#endif
#ifndef TEXT_TILE_FRAME_TR
#define TEXT_TILE_FRAME_TR ((u8)2)
#endif
#ifndef TEXT_TILE_FRAME_BL
#define TEXT_TILE_FRAME_BL ((u8)3)
#endif
#ifndef TEXT_TILE_FRAME_BR
#define TEXT_TILE_FRAME_BR ((u8)4)
#endif
#ifndef TEXT_TILE_FRAME_H
#define TEXT_TILE_FRAME_H ((u8)5)
#endif
#ifndef TEXT_TILE_FRAME_V
#define TEXT_TILE_FRAME_V ((u8)6)
#endif
#ifndef TEXT_TILE_CURSOR
#define TEXT_TILE_CURSOR ((u8)7)
#endif
#ifndef TEXT_TILE_PAGE_WAIT
#define TEXT_TILE_PAGE_WAIT ((u8)8)
#endif
#ifndef TEXT_DIGIT_BASE
#define TEXT_DIGIT_BASE ((u8)'0')
#endif
#define TEXT_CTRL_END ((u8)0x00)
#define TEXT_CTRL_NEWLINE ((u8)0x0A)
#define TEXT_CTRL_WAIT ((u8)0x01)
#define TEXT_CTRL_PAGE_WAIT ((u8)0x02)
#define PAD_KEY_RIGHT ((u8)0x01)
#define PAD_KEY_LEFT ((u8)0x02)
#define PAD_KEY_UP ((u8)0x04)
#define PAD_KEY_DOWN ((u8)0x08)
#define PAD_KEY_A ((u8)0x10)
#define PAD_KEY_B ((u8)0x20)
#define PAD_KEY_SELECT ((u8)0x40)
#define PAD_KEY_START ((u8)0x80)
// Default layout: four 512-byte slots, each with a six-byte header and at most 506 payload bytes.
#define SAVE_SLOT_COUNT ((u8)4)
#define SAVE_SLOT_SIZE ((u16)512)
#define SAVE_MAGIC0 ((u8)0x4B)
#define SAVE_MAGIC1 ((u8)0x51)
#define SAVE_VERSION ((u8)1)
#define SAVE_OK ((u8)1)
#define SAVE_ERR ((u8)0)
// A bank byte plus a CPU-visible address forms this data reference; it does not switch banks by itself.
typedef __packed struct {
u8 bank;
const u8* ptr;
} far_ptr_t;
typedef __packed struct {
u8 x;
u8 y;
u8 w;
u8 h;
const u8* const* items;
u8 count;
u8 cursor;
} menu_t;
typedef __packed struct {
u8 id;
u8 qty;
const u8* name;
} item_t;
// Packed nine-byte ordinary-map descriptor. Tile IDs use bank_tiles; collision bits and event bytes
// use the descriptor bank. Width/height are tile cells, with row-major data.
typedef __packed struct {
u8 width;
u8 height;
u8 bank_tiles;
const u8* tiles;
const u8* collision_bits;
const void* events;
} map_t;
// One 2x2 metatile: four tile IDs plus collision, palette metadata and event ID.
// The map drawing routine uses tile IDs only; it does not apply palette attributes.
typedef __packed struct {
u8 tile_tl;
u8 tile_tr;
u8 tile_bl;
u8 tile_br;
u8 collision;
u8 palette;
u8 event;
} metatile_t;
// Metatile dimensions count 2x2 cells. bank_tiles=0 means use the descriptor bank;
// nonzero bank_tiles supplies both ID-array and definition-table reads.
typedef __packed struct {
u8 width;
u8 height;
u8 bank_tiles;
const u8* metatile_ids;
const metatile_t* metatiles;
} metatile_map_t;
typedef __packed struct {
u8 x;
u8 y;
u8 w;
u8 h;
const u8* const* items;
u8 count;
u8 cursor;
u8 prev_keys;
u8 selected;
u8 cancelled;
} menu_state_t;
typedef __packed struct {
u8 x;
u8 y;
u8 hp;
u8 move;
u8 atk_min;
u8 atk_max;
u8 team;
u8 acted;
} unit_t;
void __wait_vblank();
u16 __readpadex(u8 prev_keys);
u16 __getbgmapbase();
void __memset(void* dst, u8 value, u16 count);
void __memcpy(void* dst, const void* src, u16 count);
void __settile(u8 x, u8 y, u8 tile);
void __settilebg(u8 x, u8 y, u8 tile);
void __settileat(u16 base, u8 x, u8 y, u8 tile);
void __vram_memcpy(u16 dst, const void* src, u16 len);
void __vram_memset(u16 dst, u8 value, u16 len);
void __far_memcpy(void* dst, u8 bank, const void* src, u16 len);
u8 __rng8();
void __rng_seed(u16 seed);
void __scroll_bg_set(u8 scx, u8 scy);
void __settile_xy(u8 x, u8 y, u8 tile);
void __settile_rect(u8 x, u8 y, u8 w, u8 h, u8 tile);
void __settile_row(u8 x, u8 y, const u8* src, u8 len);
void __settile_col(u8 x, u8 y, const u8* src, u8 len);
void __fill_tilemap(u16 base, u8 tile, u16 count);
void __settilemap_rect(u16 base, u8 x, u8 y, u8 w, u8 h, const u8* src);
void __vram_copy(u16 dst, const void* src, u16 len);
void __vram_fill(u16 dst, u8 value, u16 len);
void __vram_copy_hblank(u16 dst, const void* src, u16 len);
void __vram_copy_dma(u16 dst, const void* src, u16 len);
u8 __farpeek8(u8 bank, const void* addr);
u16 __farpeek16(u8 bank, const void* addr);
void __farmemcpy(void* dst, u8 bank, const void* src, u16 len);
// The current GB backend evaluates/discards these arguments but emits no indirect call.
void __farcall_ptr(u8 bank, const void* func);
#define far_read8(p) __farpeek8((p).bank, (p).ptr)
#define far_read16(p) __farpeek16((p).bank, (p).ptr)
#define far_read_block(dst, p, len) __farmemcpy((dst), (p).bank, (p).ptr, (len))
void __memcpy_small(void* dst, const void* src, u8 len);
void __memset_small(void* dst, u8 value, u8 len);
void __copy16(void* dst, const void* src);
void __copy32(void* dst, const void* src);
u16 __tile_addr(u16 base, u8 x, u8 y);
u16 __map_index(u8 x, u8 y, u8 width);
u8 __xy_in_rect(u8 x, u8 y, u8 rx, u8 ry, u8 rw, u8 rh);
u8 __manhattan(u8 x1, u8 y1, u8 x2, u8 y2);
u8 __bit_test(const u8* p, u16 bit_index);
void __bit_set(u8* p, u16 bit_index);
void __bit_clear(u8* p, u16 bit_index);
void __bit_toggle(u8* p, u16 bit_index);
// Compiler intrinsic, separate from the RAM rle_decode helpers below; it is not a bounded-stream API.
u16 __rle_decode_vram(u16 dst, u8 bank, const void* src);
// Advance the compiler-provided pseudorandom generator and return one byte.
u8 rng8();
// Consume two generator bytes in high-byte/low-byte order to form a 16-bit value.
u16 rng16();
// Reduce a random byte modulo max; zero returns zero without consuming randomness.
// Modulo reduction is biased unless max divides the generator range.
u8 rand_range(u8 max);
// Select an index from cumulative byte weights using a 16-bit random draw.
// A zero total, including an empty list, returns zero; callers must distinguish
// that case from a valid index. Modulo reduction can introduce a small bias.
u8 weighted_choice(const u8* weights, u8 count);
// Replace the generator seed so subsequent calls can reproduce a sequence.
void rng_seed(u16 seed);
// Alias the byte generator; this consumes one generator step.
u8 rng_next8();
// Alias the two-step 16-bit generator.
u16 rng_next16();
// Alias rand_range and return a value in [0,max), or zero when max is zero.
u8 rng_range(u8 max);
// Return false for zero and true for values at least 100. Intermediate values
// use the modulo-based range generator, so percentages are approximate.
u8 rng_chance(u8 percent);
// Set the tile-space window, reset its cursor and redraw it immediately.
// Opening does not reset the existing character speed or load font tiles.
void text_open(u8 x, u8 y, u8 w, u8 h);
// Erase the open window with the fill tile and disable windowed character output.
void text_close();
// Decode an END-terminated stream of tile bytes and newline/wait/page controls.
// WAIT consumes a following frame-count byte. The source must remain readable
// through blocking waits; the routine does not validate stream length.
void text_print(const u8* str);
// Decode the same text controls while fetching each byte from the specified
// ROM bank. The pointer advances within that bank; it does not roll into the next bank.
void text_print_far(u8 bank, const u8* str);
// Redraw choices and block for edge-triggered navigation: UP/DOWN wrap, A
// accepts, and B returns 0xFF. Zero choices also returns 0xFF. Choice strings
// use raw tile bytes, and the caller must fit them inside the available rows.
u8 text_choice(const u8* const* choices, u8 count);
// Set VBlank waits per windowed character; zero prints without character delays.
void text_set_speed(u8 speed);
// Open and redraw a window using the same tile-space arguments as text_open.
void text_window(u8 x, u8 y, u8 w, u8 h);
// Fill the supplied tile rectangle without changing the active text window or cursor.
void text_clear_rect(u8 x, u8 y, u8 w, u8 h);
// Draw a zero-terminated tile string at absolute tile coordinates, without
// window clipping, control codes or the windowed printing delay.
void text_print_xy(u8 x, u8 y, const u8* str);
// Print an unsigned byte in decimal using only the required number of cells.
void text_print_u8(u8 x, u8 y, u8 value);
// Print an unsigned word in decimal using only the required number of cells.
void text_print_u16(u8 x, u8 y, u16 value);
// Print a minus tile for negative values, followed by the unsigned magnitude.
// Positive values use the unsigned decimal path; no plus sign is emitted.
void text_print_s16(u8 x, u8 y, s16 value);
// Replace the active script and clear wait, choice and saved-return state.
void script_run(u8 bank, const u8* script);
// Execute commands until an output/choice yields (0), a wait yields (1), or
// execution ends (2). Control/flag commands continue within the same call, so
// a script loop without a yielding command can block the game loop indefinitely.
u8 script_step();
// Set the number of subsequent script_step calls to spend waiting. Frame-based
// timing requires the application to call script_step once per frame.
void script_wait_frames(u8 n);
// Run a blocking menu loop with wraparound up/down selection, A to accept
// and B to cancel. Return 0xFF for an empty menu or cancellation. Item strings
// and menu dimensions must fit the visible tile area.
u8 menu_run(const menu_t* menu);
// Open a two-choice dialog and return the text-choice result (YES first, NO second).
u8 menu_yesno();
// Run a blocking item menu, drawing names and two-digit quantities. Return
// the selected index or 0xFF on empty input/B; this does not consume an item.
u8 menu_inventory(const item_t* items, u8 count);
// Initialize a nonblocking menu state that borrows the item pointer table.
// Selection starts unset (0xFF), and the cancellation flag starts clear.
void menu_init_state(menu_state_t* state, u8 x, u8 y, u8 w, u8 h, const u8* const* items, u8 count);
// Draw the current menu and cursor without waiting or sampling input. The
// caller schedules suitable display timing and keeps item text within bounds.
void menu_draw(menu_state_t* state);
// Sample new button presses and update cursor/selection state without drawing.
// Selected and cancelled results remain latched; a B press in the same update
// as A clears selection and leaves cancellation set.
void menu_update(menu_state_t* state);
// Read the latched selection without clearing it; null state returns 0xFF.
u8 menu_get_selected(menu_state_t* state);
// Read the latched cancellation flag; null state returns false.
u8 menu_was_cancelled(menu_state_t* state);
// Load the nine-byte ordinary-map descriptor and draw up to 20 by 18 tiles
// from its top-left corner. Drawing does not upload tile graphics or clear
// background cells beyond smaller map dimensions.
void map_load(u8 bank, const map_t* map);
// Use metatile collision when that mode is active; otherwise read one packed
// collision bit. Missing maps/out-of-range cells block movement, but a valid
// ordinary map without a collision array is entirely passable.
u8 map_is_blocked(u8 x, u8 y);
// Report whether an event exists at the cell. Ordinary maps expose a Boolean
// byte-presence test; metatile maps reduce their event ID to a Boolean here.
u8 map_trigger_at(u8 x, u8 y);
// Center an ordinary-map tile coordinate within a 20-by-18 viewport and clamp
// the scroll origin to its edges. This adjusts scroll registers only; it does
// not stream newly exposed map rows into VRAM.
void camera_center(u8 x, u8 y);
// Select metatile mode, copy its descriptor and draw the initial viewport
// with the camera at cell (0,0).
void map_load_metatile(u8 bank, const metatile_map_t* map);
// Draw a 10-by-9 metatile viewport as 20-by-18 individual background tiles.
// Out-of-range cells use definition zero; palette attributes are not written.
// Remember the camera and clear the dirty flag after the full redraw.
void map_draw_visible(u8 camera_tx, u8 camera_ty);
// Read a row-major metatile ID, returning ID zero for inactive or out-of-range
// lookups. Callers must provide a usable definition for metatile zero.
u8 map_get_metatile(u8 tx, u8 ty);
// Return the selected definition's palette byte. An out-of-range coordinate
// uses the metatile-zero fallback; this function does not write CGB attributes.
u8 map_get_attr(u8 tx, u8 ty);
// Treat out-of-range metatile cells as solid; otherwise inspect the definition
// collision flag. In ordinary-map mode, delegate to its packed collision bits.
u8 map_is_solid(u8 tx, u8 ty);
// Return a metatile event ID, or the ordinary-map Boolean trigger result.
// Missing/out-of-range metatile cells have no event.
u8 map_get_event(u8 tx, u8 ty);
// Mark the viewport for a full redraw when a valid metatile cell changes.
// The coordinate is validated but no per-cell dirty list is retained.
void map_mark_dirty(u8 tx, u8 ty);
// Redraw the remembered metatile viewport only when the shared dirty flag is set.
void map_flush_dirty();
// Validate slot and payload length, write payload bytes, then write the header
// and checksum. Return one after completing the writes; interruption can leave
// a partially replaced slot, so this is not transactional save storage.
u8 save_write(u8 slot, const void* data, u16 len);
// Require matching magic/version, exact requested length and a valid checksum
// before copying data into the destination. Validation failure leaves the
// destination unchanged. An invalid slot returns before touching RAM control;
// validation failures after enabling RAM disable it before returning zero.
u8 save_read(u8 slot, void* data, u16 len);
// Validate a slot's header, payload bounds and checksum without copying the
// payload out. A nonzero result means the stored record passes these checks.
u8 save_exists(u8 slot);
// Initialize the expected RAM access state and leave cartridge RAM disabled.
// Existing slot contents are preserved.
void save_init();
// Alias the checked save_read operation.
u8 save_load(u8 slot, void* data, u16 len);
// Alias save_exists, including its header and checksum validation.
u8 save_check(u8 slot);
// Zero the complete selected slot, including header and payload; invalid slot
// IDs are ignored. Cartridge RAM is disabled when clearing finishes.
void save_clear(u8 slot);
// Build movement costs, then convert reachable cells to one and unreachable
// 0xFF cells to zero. The caller provides one output byte per current-map cell
// and a valid unit origin; path-search workspace limits also apply.
u8 unit_move_range(unit_t* u, u8* out_mask);
// Mark cells whose Manhattan distance falls within the inclusive attack range.
// This geometric mask does not test obstacles, line of sight or other units.
u8 unit_attack_range(unit_t* u, u8* out_mask);
// A unit can act only while HP is nonzero and its acted flag is clear.
// The unit pointer must refer to a valid record.
u8 unit_can_act(const unit_t* u);
// Find a shortest cardinal path with BFS and write direction codes 0=up,
// 1=right, 2=down, 3=left. Return its byte length, or zero for failure or an
// already-reached goal. The caller supplies max_len output bytes and respects
// the shared workspace/distance limits; excessive paths are not truncated.
u8 path_find_bfs(u8 sx, u8 sy, u8 gx, u8 gy, u8* out_path, u8 max_len);
// Flood cardinal neighbors at unit cost, stopping expansion at the movement
// limit and rejecting blocked destinations. Initialize output to 0xFF only
// after validating the map and origin; invalid input leaves output unchanged.
void range_fill_move(u8 sx, u8 sy, u8 move, u8* out_costmap);
// Read a bit from the flag array. Callers must keep id below 2048.
u8 flag_get(u16 id);
// Set a flag bit without disturbing adjacent flags; id must be below 2048.
void flag_set(u16 id);
// Clear a flag bit; id must be below 2048.
void flag_clear(u16 id);
// Read a quest-state byte; quest_id must be below 64.
u8 quest_state(u8 quest_id);
// Replace a quest-state byte without validating its game-specific meaning.
// The caller must keep quest_id below 64.
void quest_set_state(u8 quest_id, u8 state);
// Expand count/value byte pairs until a zero count terminates the stream.
// The caller must provide a valid terminator and sufficient destination storage;
// there are no source or destination bounds parameters. Return the 16-bit byte count.
u16 rle_decode(void* dst, const void* src);
// Decode the same count/value format using bank-qualified reads for every source
// byte. Keep the encoded stream within the supplied bank/address mapping and
// provide enough destination space; a zero count ends the stream.
u16 rle_decode_far(void* dst, u8 bank, const void* src);
// Return the active map width in its own cell units, or zero when no map is loaded.
u8 map_current_width();
// Return the active map height in its own cell units, or zero when no map is loaded.
u8 map_current_height();kitaqgb/lib/rpg.h
scene.h — Registro, cambio y actualización de escenas
#pragma once
typedef void (*SceneFunc)();
// Callbacks may be null. Keep the table and non-null targets readable for its lifetime.
// These plain function pointers do not carry a ROM bank number.
typedef __packed struct {
SceneFunc enter;
SceneFunc update;
SceneFunc draw;
SceneFunc exit;
} SceneDef;
// Attach the caller-owned scene table and clear current-scene state without invoking callbacks.
void scene_init(const SceneDef* scenes, u8 count);
// Replace the table by resetting scene state; this does not call the old scene's exit handler.
void scene_set_table(const SceneDef* scenes, u8 count);
// Ignore invalid IDs; otherwise exit the current scene and enter the requested one.
// Selecting the current ID still performs exit/enter. Callbacks run synchronously.
void scene_change(u8 scene_id);
// Clear the change flag before calling the active scene's update handler, so a
// transition made during that handler is visible afterward.
void scene_update();
// Call the active scene's draw handler if one exists; no current scene is a no-op.
void scene_draw();
// Return the stored scene ID; zero is also returned before the first transition.
u8 scene_get_current();
// Read the transition flag, which is cleared at the start of an active scene update.
u8 scene_was_changed();kitaqgb/lib/scene.h
scroll.h — Desplazamiento del fondo, la ventana y las zonas divididas
#pragma once
// Flags select operations in a raster split; raw window X includes the hardware +7 offset.
#define KQ_SCROLL_SPLIT_USE_BG 0x01
#define KQ_SCROLL_SPLIT_USE_WIN 0x02
#define KQ_SCROLL_SPLIT_WIN_SHOW 0x04
#define KQ_SCROLL_SPLIT_WIN_HIDE 0x08
#define KQ_SCROLL_SPLIT_BG_COLOR0 0x10
void __scroll_bg_set(u8 scx, u8 scy);
void __scroll_bg_x_set(u8 scx);
void __scroll_bg_y_set(u8 scy);
u8 __scroll_bg_x_get();
u8 __scroll_bg_y_get();
void __scroll_win_set(u8 wx, u8 wy);
void __scroll_win_x_set(u8 wx);
void __scroll_win_y_set(u8 wy);
u8 __scroll_win_x_get();
u8 __scroll_win_y_get();
void __scroll_bg_set_buffered(u8 scx, u8 scy);
void __scroll_bg_x_set_buffered(u8 scx);
void __scroll_bg_y_set_buffered(u8 scy);
void __scroll_win_set_buffered(u8 wx, u8 wy);
void __scroll_win_x_set_buffered(u8 wx);
void __scroll_win_y_set_buffered(u8 wy);
void __scroll_flush();
void __scroll_split_reset();
void __scroll_split_push(u8 ly, u8 scx, u8 scy);
void __scroll_split_push_ex(u8 ly, u8 scx, u8 scy, u8 wx, u8 wy, u8 flags);
void __scroll_split_commit();
void __scroll_win_show();
void __scroll_win_hide();
void __scroll_bg_add(s8 dx, s8 dy);
void __scroll_win_add(s8 dx, s8 dy);
// Reset background scroll to zero and place the window at screen origin
// using hardware WX=7 and WY=0.
void Scroll_Init();
// Write both hardware background-scroll bytes immediately.
void Scroll_SetBg(u8 scx, u8 scy);
// Write horizontal background scroll while leaving vertical scroll unchanged.
void Scroll_SetBgX(u8 scx);
// Write vertical background scroll while leaving horizontal scroll unchanged.
void Scroll_SetBgY(u8 scy);
// Read the tracked current background X; this is not a direct SCX register read.
u8 Scroll_GetBgX();
// Read the tracked current background Y; pending and raster-only values are excluded.
u8 Scroll_GetBgY();
// Write raw hardware WX/WY values; callers add seven to a screen-space window X.
void Scroll_SetWindow(u8 wx, u8 wy);
// Write raw hardware WX without converting a screen-space X coordinate.
void Scroll_SetWindowX(u8 wx);
// Write the window Y coordinate through the intrinsic.
void Scroll_SetWindowY(u8 wy);
// Read tracked current WX, including its seven-pixel offset; not a live hardware read.
u8 Scroll_GetWindowX();
// Read tracked current WY; pending and raster-only values are excluded.
u8 Scroll_GetWindowY();
// Stage background-scroll values in the intrinsic buffer for a later flush.
void Scroll_SetBgBuffered(u8 scx, u8 scy);
// Stage raw window-coordinate values for a later flush.
void Scroll_SetWindowBuffered(u8 wx, u8 wy);
// Apply the buffered scroll/window state through the compiler runtime.
void Scroll_Flush();
// Apply signed deltas to the byte-sized background-scroll coordinates.
void Scroll_BgAdd(s8 dx, s8 dy);
// Apply signed deltas to the byte-sized hardware window coordinates.
void Scroll_WindowAdd(s8 dx, s8 dy);
// Request window visibility through the compiler intrinsic.
void Scroll_WindowShow();
// Request that the window be hidden through the compiler intrinsic.
void Scroll_WindowHide();
// Clear the pending split table before building a new raster configuration.
void Scroll_SplitReset();
// Append a background-scroll split directly. Use Raster_Push when caller-side
// scanline ordering and capacity validation are desired.
void Scroll_SplitPush(u8 ly, u8 scx, u8 scy);
// Append an extended split with raw background/window fields and operation flags.
void Scroll_SplitPushEx(u8 ly, u8 scx, u8 scy, u8 wx, u8 wy, u8 flags);
// Reuse the two background-scroll fields to carry the low/high RGB15 bytes
// for a split whose operation flag selects background color zero.
void Scroll_SplitPushBgColor0(u8 ly, u16 rgb15);
// Publish the pending split configuration through the compiler runtime.
void Scroll_SplitCommit();kitaqgb/lib/scroll.h
slg.h — Tableros, listas de jugadas y deshacer
#pragma once
// A row-major byte board. Storage is borrowed; cell values and coordinates have game-defined meaning.
typedef __packed struct {
u8 width;
u8 height;
u8* cells;
} SLGBoard;
typedef __packed struct {
u8 x;
u8 y;
u8 value;
} SLGMove;
typedef __packed struct {
SLGMove* items;
u8 count;
u8 capacity;
} SLGMoveList;
// Undo records are retained cell values only; popping one does not apply it to a board.
typedef __packed struct {
SLGMove* items;
u8 count;
u8 capacity;
} SLGUndoStack;
// Attach width * height bytes of caller-owned cell storage without clearing it.
void slg_board_init(SLGBoard* board, u8 width, u8 height, u8* cells);
// Fill every cell with value; a null board is ignored. A valid board must own
// enough accessible cell storage for its declared dimensions.
void slg_board_clear(SLGBoard* board, u8 value);
// Return zero for a null board or out-of-range coordinate; otherwise read the
// cell. Zero therefore cannot distinguish an invalid lookup from an empty cell.
u8 slg_board_get(const SLGBoard* board, u8 x, u8 y);
// Write a cell only when the board and coordinate are valid.
void slg_board_set(SLGBoard* board, u8 x, u8 y, u8 value);
// Attach caller-owned move storage and reset the list length.
void slg_move_list_init(SLGMoveList* list, SLGMove* items, u8 capacity);
// Forget the moves without erasing their storage; a null list is ignored.
void slg_move_list_clear(SLGMoveList* list);
// Append coordinates and a value to the bounded move list. Return zero on a
// null/full list without replacing any existing move.
u8 slg_move_list_push(SLGMoveList* list, u8 x, u8 y, u8 value);
// Attach caller-owned undo records and initialize an empty stack.
void slg_undo_init(SLGUndoStack* stack, SLGMove* items, u8 capacity);
// Record a cell's previous value for later undo. Return zero if the stack is
// null or full; this function does not change the board itself.
u8 slg_undo_push(SLGUndoStack* stack, u8 x, u8 y, u8 old_value);
// Remove the newest undo record and optionally copy it out. A null output
// still discards the record; a null or empty stack returns zero.
u8 slg_undo_pop(SLGUndoStack* stack, SLGMove* out_move);kitaqgb/lib/slg.h
sprite.h — Reserva y posición de OBJ, metasprites y animación
#pragma once
// Keep the default 40 for the standard DMA path. Hardware always transfers 160 bytes,
// even if this array is shortened; a custom layout must provide valid bytes for that full transfer.
#ifndef SPRITE_MAX
#define SPRITE_MAX 40
#endif
#define SPRITE_FLAG_PAL1 ((u8)0x10)
#define SPRITE_FLAG_XFLIP ((u8)0x20)
#define SPRITE_FLAG_YFLIP ((u8)0x40)
#define SPRITE_FLAG_PRIORITY ((u8)0x80)
// Packed hardware order is Y, X, tile, flags; screen coordinates need the GB OAM offsets.
typedef __packed struct {
u8 y;
u8 x;
u8 tile;
u8 flags;
} SpriteOamEntry;
extern __wram __aligned(256) SpriteOamEntry kq_sprite_oam[SPRITE_MAX];
extern u8 kq_sprite_active[SPRITE_MAX];
extern u8 kq_sprite_used;
extern u8 kq_sprite_height;
// Signed pixel displacements from a common origin; final byte coordinates wrap rather than clip.
typedef __packed struct {
s8 dx;
s8 dy;
u8 tile;
u8 flags;
} MetaSpritePart;
// Initialize frame/ticks within their configured ranges. This animation selects consecutive tile IDs;
// it does not change sprite size or automatically step by two tiles in 8x16 mode.
typedef __packed struct {
u8 first_tile;
u8 frame_count;
u8 frame;
u8 ticks;
u8 ticks_per_frame;
} SpriteAnim;
void __wait_vblank();
void __oam_dma(u16 src_ptr);
// Clear allocation and shadow OAM state and reset the DMA-stub installation flag.
// The default height is eight pixels; the hardware display mode is configured elsewhere.
void sprite_init();
// Claim the first free slot, hide it, and return its ID; return 0xFF when full.
// Previously stored tile/flag bytes are retained until the caller replaces them.
u8 sprite_alloc();
// Release an allocated valid slot and hide it. Repeated frees do not decrement the count.
void sprite_free(u8 id);
// Convert screen coordinates to OAM coordinates by adding X=8 and Y=16.
// The byte additions wrap; this updates shadow storage even for an unallocated slot.
void sprite_set_pos(u8 id, u8 x, u8 y);
// Set a valid shadow slot's tile byte; allocation and hardware transfer are separate.
void sprite_set_tile(u8 id, u8 tile);
// Replace a valid shadow slot's complete hardware attribute byte.
void sprite_set_flags(u8 id, u8 flags);
// Move a valid shadow slot off screen without freeing it.
void sprite_hide(u8 id);
// Install the HRAM stub lazily and execute OAM DMA with interrupts disabled.
// This routine does not wait for VBlank and always enables interrupts afterward;
// it does not restore the caller's previous interrupt-enable state.
void sprite_flush_oam_now();
// Wait for VBlank, then transfer shadow OAM using the immediate DMA routine.
void sprite_flush_oam();
// Return the number of active slots, including slots activated by metasprite_draw.
// Hidden allocated slots remain active until sprite_free releases them.
u8 sprite_count_used();
// Report whether the software overlap estimate exceeds ten sprites on a scanline.
u8 sprite_warn_scanline_overflow();
// Estimate the largest overlap of active, non-hidden shadow sprites across
// visible scanlines using the configured sprite height. This is a software
// overlap count, not a rendered-pixel or hardware-priority simulation.
u8 sprite_max_scanline_count();
// Place consecutive parts, counting each newly activated slot once. Existing
// active slots are overwritten without increasing the allocation count. Return
// the number written; an invalid first slot or zero count writes nothing.
u8 metasprite_draw(u8 first_id, u8 x, u8 y, const MetaSpritePart* parts, u8 count);
// Advance animation ticks/frame with wrapping frame selection and return the
// resulting tile. Zero ticks-per-frame freezes animation; null state returns zero.
u8 anim_update(SpriteAnim* anim);kitaqgb/lib/sprite.h
sprite_order.h — Selección de sprites por prioridad y rotación
#pragma once
// Copyright (c) 2026 DAISUKE OBA. MIT License.
// Hardware-compatible layout without requiring the sprite allocator or its
// global storage. Cast a sprite.h shadow buffer to this type when combining
// the libraries; both layouts contain exactly Y, X, tile and flags bytes.
typedef __packed struct {
u8 y;
u8 x;
u8 tile;
u8 flags;
} SpriteOrderOamEntry;
#define SPRITE_ORDER_LEVELS 4
#define SPRITE_ORDER_OAM_COUNT 40
// One submitted, visible sprite. Attributes retain their hardware meaning;
// priority 0..3 controls OAM selection order, not the BG-over-OBJ flag.
typedef __packed struct {
SpriteOrderOamEntry oam;
u8 priority;
} SpriteOrderItem;
// Caller-owned foreground state. Capacity is 1..255 items; count includes only
// accepted submissions. Rebuild the same logical submission list each frame so
// phase rotation distributes selection among equal-priority sprites.
typedef struct {
SpriteOrderItem* items;
u8 capacity;
u8 count;
u8 height;
u8 phase;
} SpriteOrder;
// Bind writable item storage and select the hardware sprite height (8 or 16).
// Return 1 on success. Invalid storage, zero capacity or another height returns
// 0 and leaves a non-null state disabled. A null state returns 0 without writes.
u8 sprite_order_init(SpriteOrder* order, SpriteOrderItem* items, u8 capacity, u8 height);
// Discard this frame's submissions while preserving storage, height and phase.
// A null state is ignored. Call once before submitting the next frame's sprites.
void sprite_order_begin(SpriteOrder* order);
// Submit one sprite at signed, top-left SCREEN pixel coordinates. Preserve the
// tile and attribute bytes; use priority 0 (first) through 3 (last). Fully
// off-screen sprites, invalid priorities, disabled state and full storage return
// 0 without consuming a slot. Partly visible sprites are accepted. Return 1 on
// acceptance. Hardware 8x16 mode still ignores the tile index's low bit.
u8 sprite_order_push(SpriteOrder* order, s16 x, s16 y, u8 tile, u8 flags, u8 priority);
// Write a complete 160-byte shadow OAM: ascending priority, then cyclic order
// within each priority. Clamp limit to 40, return the number emitted and zero
// all unused entries (including Y) so they cannot consume scanline slots.
// Advance phase once for a nonempty valid queue, even when limit is zero.
// Empty queues reset phase to zero. Null/disabled/corrupt state or null output
// returns 0 without modifying output or phase.
// Output must provide 40 entries and must not overlap item/state storage.
// This only writes RAM. Build in foreground, then transfer during VBlank.
// DMG overlap priority also depends on X: this cannot override that hardware
// rule. OAM order chooses the first ten sprites per scanline on both DMG/CGB.
// It neither updates sprite_alloc's bookkeeping nor performs OAM DMA.
u8 sprite_order_build(SpriteOrder* order, SpriteOrderOamEntry* output, u8 limit);kitaqgb/lib/sprite_order.h
system.h — Arranque, contadores de fotogramas, esperas e interrupciones
#pragma once
// This callback runs in the caller of system_wait_vblank, not as an installed ISR.
// Its plain pointer has no ROM bank component; keep the target callable in that mapping.
typedef void (*SystemCallback)();
extern u16 kq_system_frame;
void __wait_vblank();
// Reset the software frame counter and remove any registered callback.
void system_init();
// Wait for VBlank, count this wrapper call, then invoke the callback synchronously.
// The counter wraps at 16 bits and is not an independent hardware frame clock.
void system_wait_vblank();
// Replace the callback used by system_wait_vblank; null disables the callback.
void system_set_vblank_callback(SystemCallback callback);
// Read the software count of completed system_wait_vblank calls.
u16 system_get_frame();
// Return the low byte of the software frame counter for wrapping 8-bit timing.
u8 system_get_frame8();
// Enable CPU interrupts and return using the inline-assembly function body.
void system_enable_interrupts();
// Disable CPU interrupts and return; callers must explicitly re-enable them later.
void system_disable_interrupts();
#define gb_init system_init
#define gb_wait_vblank system_wait_vblank
#define gb_set_vblank_callback system_set_vblank_callback
#define gb_frame_count system_get_frame
#define gb_enable_interrupts system_enable_interrupts
#define gb_disable_interrupts system_disable_interruptskitaqgb/lib/system.h
vram.h — Actualizaciones de VRAM en cola y transferencias
#pragma once
// Keep this capacity in 1..255 in all units; counts and capacity/free return values are bytes.
#ifndef VRAM_QUEUE_MAX
#define VRAM_QUEUE_MAX 32
#endif
#define VRAM_CMD_BG_TILE ((u8)1)
#define VRAM_CMD_BG_RECT ((u8)2)
#define VRAM_CMD_BG_BLOCK ((u8)3)
#define VRAM_CMD_MEMCPY ((u8)4)
#define VRAM_CMD_MEMSET ((u8)5)
// A command owns metadata only. src is a retained near pointer with no bank number or copied payload.
typedef __packed struct {
u8 kind;
u8 x;
u8 y;
u8 w;
u8 h;
u8 value;
u16 dst;
const u8* src;
u16 len;
} VramCommand;
extern VramCommand kq_vram_queue[VRAM_QUEUE_MAX];
extern u8 kq_vram_queue_used;
extern u8 kq_vram_queue_overflowed;
void __wait_vblank();
void __settile_xy(u8 x, u8 y, u8 tile);
void __settile_rect(u8 x, u8 y, u8 w, u8 h, u8 tile);
void __settilemap_rect(u16 base, u8 x, u8 y, u8 w, u8 h, const u8* src);
void __vram_copy(u16 dst, const void* src, u16 len);
void __vram_fill(u16 dst, u8 value, u16 len);
// Start with an empty command queue and a clear overflow flag.
void vram_init();
// Discard pending commands and clear the latched overflow flag without writing VRAM.
void vram_clear_queue();
// Queue a single background tile write; return zero if no command slot is available.
u8 vram_queue_bg_tile(u8 x, u8 y, u8 tile);
// Provide the short alias for a queued background tile write.
u8 vram_queue_tile(u8 x, u8 y, u8 tile);
// Queue a rectangle filled with one tile value; coordinates and dimensions are in tiles.
u8 vram_queue_bg_rect(u8 x, u8 y, u8 w, u8 h, u8 tile);
// Queue a tile-map rectangle while retaining src rather than copying its bytes.
// Keep the source data and its ROM bank accessible until the queue is flushed.
u8 vram_queue_bg_block(u16 base, u8 x, u8 y, u8 w, u8 h, const u8* src);
// Queue a byte transfer and retain the source pointer. The source must remain
// valid and visible until flush; len is measured in bytes, not tiles.
u8 vram_queue_memcpy(u16 dst, const void* src, u16 len);
// Alias the queued byte-copy operation; this does not convert a tile count to bytes.
u8 vram_queue_tiles(u16 dst, const void* src, u16 len);
// Queue a byte fill and return zero if the command queue is full.
u8 vram_queue_memset(u16 dst, u8 value, u16 len);
// Execute pending commands in insertion order without waiting for VBlank here.
// The caller must arrange suitable VRAM access timing and a sufficient transfer budget.
// Only the used count is cleared; overflow stays latched until an explicit reset.
void vram_flush_now();
// Wait for VBlank before executing the queue. Waiting once does not itself limit
// the queued workload to the available VBlank duration.
void vram_flush();
// Return the number of queued commands, not the number of transfer bytes.
u8 vram_get_queue_used();
// Return the total number of command slots, independent of queue usage.
// This is command-buffer capacity, not free space in hardware VRAM.
u8 vram_get_queue_capacity();
// Return the remaining command-slot capacity.
u8 vram_get_queue_free();
// Read the overflow latch without clearing it.
u8 vram_get_overflowed();kitaqgb/lib/vram.h
wire3d.h — Gráficos de alambre para DMG
// Compatibility names for the shared wire3d_dmg renderer.
// Select the same profile in every translation unit; compile one renderer entry.
#pragma once
#ifndef WIRE3D_DMG_HEIGHT
#define WIRE3D_DMG_HEIGHT 96
#endif
#if WIRE3D_DMG_HEIGHT != 96
#error Incompatible wire3d_dmg profile
#endif
#include "wire3d_dmg.h"
#define W3D_BG_QUEUE_LIMIT WIRE3D_DMG_BG_QUEUE_LIMIT
#define W3D_CENTER_X WIRE3D_DMG_CENTER_X
#define W3D_CENTER_Y WIRE3D_DMG_CENTER_Y
#define W3D_FAR_Z WIRE3D_DMG_FAR_Z
#define W3D_HUD_TILE_BASE WIRE3D_DMG_HUD_TILE_BASE
#define W3D_HUD_TILE_BLANK WIRE3D_DMG_HUD_TILE_BLANK
#define W3D_HUD_TILE_COUNT WIRE3D_DMG_HUD_TILE_COUNT
#define W3D_NEAR_Z WIRE3D_DMG_NEAR_Z
#define W3D_PROJECT_LIMIT WIRE3D_DMG_PROJECT_LIMIT
#define W3D_ROW_BYTES WIRE3D_DMG_ROW_BYTES
#define W3D_TILE_H WIRE3D_DMG_TILE_H
#define W3D_TILE_W WIRE3D_DMG_TILE_W
#define W3D_TRANSFORM_LIMIT WIRE3D_DMG_TRANSFORM_LIMIT
#define WIRE3D_EDGE_MASK_BINS_16 WIRE3D_DMG_EDGE_MASK_BINS_16
#define WIRE3D_FACE_NONE WIRE3D_DMG_FACE_NONE
#define WIRE3D_MODEL_EDGE_LIMIT WIRE3D_DMG_MODEL_EDGE_LIMIT
#define WIRE3D_MODEL_FACE_LIMIT WIRE3D_DMG_MODEL_FACE_LIMIT
#define WIRE3D_MODEL_HIDDEN_LINES WIRE3D_DMG_MODEL_HIDDEN_LINES
#define WIRE3D_MODEL_VERTEX_LIMIT WIRE3D_DMG_MODEL_VERTEX_LIMIT
#define WIRE3D_SCENE_OBJECT_LIMIT WIRE3D_DMG_SCENE_OBJECT_LIMIT
#define WIRE3D_SCREEN_H WIRE3D_DMG_SCREEN_H
#define WIRE3D_SCREEN_W WIRE3D_DMG_SCREEN_W
#define Wire3D_BeginFrame Wire3DDMG_BeginFrame
#define Wire3D_DrawLine2D Wire3DDMG_DrawLine2D
#define Wire3D_DrawLine3D Wire3DDMG_DrawLine3D
#define Wire3D_DrawModel Wire3DDMG_DrawModel
#define Wire3D_DrawModelScaled Wire3DDMG_DrawModelScaled
#define Wire3D_DrawScene Wire3DDMG_DrawScene
#define Wire3D_Edge Wire3DDMG_Edge
#define Wire3D_EdgeFaces Wire3DDMG_EdgeFaces
#define Wire3D_EndFrame Wire3DDMG_EndFrame
#define Wire3D_EraseModelFaces Wire3DDMG_EraseModelFaces
#define Wire3D_EraseSpan2D Wire3DDMG_EraseSpan2D
#define Wire3D_EraseTriangle2D Wire3DDMG_EraseTriangle2D
#define Wire3D_Face Wire3DDMG_Face
#define Wire3D_Init Wire3DDMG_Init
#define Wire3D_Model Wire3DDMG_Model
#define Wire3D_Object Wire3DDMG_Object
#define Wire3D_ProjectPoint Wire3DDMG_ProjectPoint
#define Wire3D_PutBgTile Wire3DDMG_PutBgTile
#define Wire3D_SelectEdgeMask Wire3DDMG_SelectEdgeMask
#define Wire3D_SetCamera Wire3DDMG_SetCamera
#define Wire3D_SetPalette Wire3DDMG_SetPalette
#define Wire3D_Vec3 Wire3DDMG_Vec3
#define w3d_abs_i16 w3ddmg_abs_i16
#define w3d_bg_map_9800 w3ddmg_bg_map_9800
#define w3d_bgq_addr_hi w3ddmg_bgq_addr_hi
#define w3d_bgq_addr_lo w3ddmg_bgq_addr_lo
#define w3d_bgq_count w3ddmg_bgq_count
#define w3d_bgq_tile w3ddmg_bgq_tile
#define w3d_bgq_value w3ddmg_bgq_value
#define w3d_bgq_x w3ddmg_bgq_x
#define w3d_bgq_y w3ddmg_bgq_y
#define w3d_bit_mask w3ddmg_bit_mask
#define w3d_build_edge_flags w3ddmg_build_edge_flags
#define w3d_build_face_visibility w3ddmg_build_face_visibility
#define w3d_cam_pitch w3ddmg_cam_pitch
#define w3d_cam_roll w3ddmg_cam_roll
#define w3d_cam_x w3ddmg_cam_x
#define w3d_cam_y w3ddmg_cam_y
#define w3d_cam_yaw w3ddmg_cam_yaw
#define w3d_cam_z w3ddmg_cam_z
#define w3d_clamp_i16 w3ddmg_clamp_i16
#define w3d_clamp_screen w3ddmg_clamp_screen
#define w3d_clear_occlusion_mask w3ddmg_clear_occlusion_mask
#define w3d_clear_occlusion_mask_asm w3ddmg_clear_occlusion_mask_asm
#define w3d_clear_stage_asm w3ddmg_clear_stage_asm
#define w3d_clear_triangle w3ddmg_clear_triangle
#define w3d_clear_vram_asm w3ddmg_clear_vram_asm
#define w3d_cos_q6 w3ddmg_cos_q6
#define w3d_edge_area w3ddmg_edge_area
#define w3d_edge_flags w3ddmg_edge_flags
#define w3d_face_visible w3ddmg_face_visible
#define w3d_fill_bg_map_asm w3ddmg_fill_bg_map_asm
#define w3d_flush_bg_queue w3ddmg_flush_bg_queue
#define w3d_hud_tiles w3ddmg_hud_tiles
#define w3d_i16 w3ddmg_i16
#define w3d_i8 w3ddmg_i8
#define w3d_inv_depth w3ddmg_inv_depth
#define w3d_is_edge_visible w3ddmg_is_edge_visible
#define w3d_line_dx w3ddmg_line_dx
#define w3d_line_dy w3ddmg_line_dy
#define w3d_line_err w3ddmg_line_err
#define w3d_line_stage_asm w3ddmg_line_stage_asm
#define w3d_line_stage_masked_c w3ddmg_line_stage_masked_c
#define w3d_line_sx w3ddmg_line_sx
#define w3d_line_sy w3ddmg_line_sy
#define w3d_line_x w3ddmg_line_x
#define w3d_line_x0 w3ddmg_line_x0
#define w3d_line_x1 w3ddmg_line_x1
#define w3d_line_y w3ddmg_line_y
#define w3d_line_y0 w3ddmg_line_y0
#define w3d_line_y1 w3ddmg_line_y1
#define w3d_load_hud_tiles w3ddmg_load_hud_tiles
#define w3d_mark_model_occluder w3ddmg_mark_model_occluder
#define w3d_mark_triangle w3ddmg_mark_triangle
#define w3d_mask_get w3ddmg_mask_get
#define w3d_mask_offset w3ddmg_mask_offset
#define w3d_mask_set w3ddmg_mask_set
#define w3d_mask_set_span w3ddmg_mask_set_span
#define w3d_neg_angle w3ddmg_neg_angle
#define w3d_occlusion_active w3ddmg_occlusion_active
#define w3d_occlusion_mask w3ddmg_occlusion_mask
#define w3d_pair_block w3ddmg_pair_block
#define w3d_pair_wait_0 w3ddmg_pair_wait_0
#define w3d_pair_wait_1 w3ddmg_pair_wait_1
#define w3d_pair_wait_10 w3ddmg_pair_wait_10
#define w3d_pair_wait_11 w3ddmg_pair_wait_11
#define w3d_pair_wait_12 w3ddmg_pair_wait_12
#define w3d_pair_wait_13 w3ddmg_pair_wait_13
#define w3d_pair_wait_14 w3ddmg_pair_wait_14
#define w3d_pair_wait_15 w3ddmg_pair_wait_15
#define w3d_pair_wait_2 w3ddmg_pair_wait_2
#define w3d_pair_wait_3 w3ddmg_pair_wait_3
#define w3d_pair_wait_4 w3ddmg_pair_wait_4
#define w3d_pair_wait_5 w3ddmg_pair_wait_5
#define w3d_pair_wait_6 w3ddmg_pair_wait_6
#define w3d_pair_wait_7 w3ddmg_pair_wait_7
#define w3d_pair_wait_8 w3ddmg_pair_wait_8
#define w3d_pair_wait_9 w3ddmg_pair_wait_9
#define w3d_plot_stage_asm w3ddmg_plot_stage_asm
#define w3d_plot_tx w3ddmg_plot_tx
#define w3d_plot_x w3ddmg_plot_x
#define w3d_plot_y w3ddmg_plot_y
#define w3d_project_camera_space w3ddmg_project_camera_space
#define w3d_project_world w3ddmg_project_world
#define w3d_put_bg_tile_safe_asm w3ddmg_put_bg_tile_safe_asm
#define w3d_reg_bgp w3ddmg_reg_bgp
#define w3d_reg_lcdc w3ddmg_reg_lcdc
#define w3d_reg_ly w3ddmg_reg_ly
#define w3d_reg_scx w3ddmg_reg_scx
#define w3d_reg_scy w3ddmg_reg_scy
#define w3d_rotate_x w3ddmg_rotate_x
#define w3d_rotate_y w3ddmg_rotate_y
#define w3d_rotate_z w3ddmg_rotate_z
#define w3d_scene_depth w3ddmg_scene_depth
#define w3d_scene_object_depth w3ddmg_scene_object_depth
#define w3d_scene_order w3ddmg_scene_order
#define w3d_screen_delta w3ddmg_screen_delta
#define w3d_screen_visible w3ddmg_screen_visible
#define w3d_screen_x w3ddmg_screen_x
#define w3d_screen_y w3ddmg_screen_y
#define w3d_sin_q6 w3ddmg_sin_q6
#define w3d_stage w3ddmg_stage
#define w3d_stage_clear_pixel w3ddmg_stage_clear_pixel
#define w3d_stage_clear_span w3ddmg_stage_clear_span
#define w3d_transfer_stage_asm w3ddmg_transfer_stage_asm
#define w3d_u16 w3ddmg_u16
#define w3d_u8 w3ddmg_u8
#define w3d_vram_tiles w3ddmg_vram_tiles
#define w3d_wait_vblank_start w3ddmg_wait_vblank_start
#define w3dbg_enter w3ddmgbg_enter
#define w3dco_enter w3ddmgco_enter
#define w3dco_loop w3ddmgco_loop
#define w3dco_page w3ddmgco_page
#define w3dcs_enter w3ddmgcs_enter
#define w3dcs_inner w3ddmgcs_inner
#define w3dcs_outer w3ddmgcs_outer
#define w3dcv_enter w3ddmgcv_enter
#define w3dcv_loop w3ddmgcv_loop
#define w3dcv_page w3ddmgcv_page
#define w3dfb_enter w3ddmgfb_enter
#define w3dfb_loop w3ddmgfb_loop
#define w3dfb_page w3ddmgfb_page
#define w3dls_branch w3ddmgls_branch
#define w3dls_done w3ddmgls_done
#define w3dls_enter w3ddmgls_enter
#define w3dls_shallow w3ddmgls_shallow
#define w3dls_shallow_loop w3ddmgls_shallow_loop
#define w3dls_shallow_skip_bridge w3ddmgls_shallow_skip_bridge
#define w3dls_steep w3ddmgls_steep
#define w3dls_steep_loop w3ddmgls_steep_loop
#define w3dls_steep_skip_bridge w3ddmgls_steep_skip_bridge
#define w3dls_x_reverse w3ddmgls_x_reverse
#define w3dls_y_reverse w3ddmgls_y_reverse
#define w3dls_y_start w3ddmgls_y_start
#define w3dps_enter w3ddmgps_enter
#define w3dps_ret w3ddmgps_retkitaqgb/lib/wire3d.h
wire3d_cgb.h — Gráficos de alambre en color para CGB
#pragma once
#ifndef KITAQGB_WIRE3D_CGB_H
#define KITAQGB_WIRE3D_CGB_H
#define WIRE3DCGB_SCREEN_W 128
#ifndef WIRE3DCGB_HEIGHT
#define WIRE3DCGB_HEIGHT 96
#endif
#if WIRE3DCGB_HEIGHT != 88 && WIRE3DCGB_HEIGHT != 96
#error WIRE3DCGB_HEIGHT must be 88 or 96
#endif
#define WIRE3DCGB_SCREEN_H WIRE3DCGB_HEIGHT
#if WIRE3DCGB_HEIGHT == 88
#define WIRE3DCGB_TILE_ROWS 11
#define WIRE3DCGB_TILE_COUNT 176
#define WIRE3DCGB_COLUMN_BYTES 176
#define WIRE3DCGB_NEG_COLUMN_BYTES 0xFF50
#define WIRE3DCGB_STAGE_RIGHT 0xDD50
#define WIRE3DCGB_STAGE_BOTTOM 0xD3AE
#define WIRE3DCGB_SECOND_DMA 0xAF
#else
#define WIRE3DCGB_TILE_ROWS 12
#define WIRE3DCGB_TILE_COUNT 192
#define WIRE3DCGB_COLUMN_BYTES 192
#define WIRE3DCGB_NEG_COLUMN_BYTES 0xFF40
#define WIRE3DCGB_STAGE_RIGHT 0xDE40
#define WIRE3DCGB_STAGE_BOTTOM 0xD3BE
#define WIRE3DCGB_SECOND_DMA 0xBF
#endif
// Reserve 3072 bytes in either profile for full-screen compatibility.
#define WIRE3DCGB_UPLOAD_BYTES (WIRE3DCGB_TILE_COUNT * 16)
#define WIRE3DCGB_FULL_SCREEN_W 160
#define WIRE3DCGB_FULL_SCREEN_H 144
#define WIRE3DCGB_FULL_TILE_LIMIT 127
#define WIRE3DCGB_STAGE_BASE 0xD300
#define WIRE3DCGB_STAGE_WRAM_BANK 2
#define WIRE3DCGB_STAGE_BYTES 3072
#define WIRE3DCGB_MODEL_VERTEX_LIMIT 24
#define WIRE3DCGB_MODEL_FACE_LIMIT 16
#define WIRE3DCGB_MODEL_EDGE_LIMIT 64
#define WIRE3DCGB_SCENE_OBJECT_LIMIT 8
#define WIRE3DCGB_FACE_NONE 255
#define WIRE3DCGB_MODEL_HIDDEN_LINES 1
#define WIRE3DCGB_COLOR_LOW 1
#define WIRE3DCGB_COLOR_MAIN 2
#define WIRE3DCGB_COLOR_HIGH 3
#define WIRE3DCGB_COLOR_DEFAULT WIRE3DCGB_COLOR_MAIN
#define WIRE3DCGB_RGB15(r5, g5, b5) ((w3dcgb_u16)((w3dcgb_u16)((r5) & 31) | ((w3dcgb_u16)((g5) & 31) << 5) | ((w3dcgb_u16)((b5) & 31) << 10)))
typedef s8 w3dcgb_i8;
typedef s16 w3dcgb_i16;
typedef u8 w3dcgb_u8;
typedef u16 w3dcgb_u16;
typedef struct {
w3dcgb_i16 x;
w3dcgb_i16 y;
w3dcgb_i16 z;
} Wire3DCGB_Vec3;
typedef struct {
w3dcgb_u8 a;
w3dcgb_u8 b;
} Wire3DCGB_Edge;
typedef struct {
w3dcgb_u8 a;
w3dcgb_u8 b;
w3dcgb_u8 c;
} Wire3DCGB_Face;
typedef struct {
w3dcgb_u8 f0;
w3dcgb_u8 f1;
} Wire3DCGB_EdgeFaces;
typedef struct {
const Wire3DCGB_Vec3* vertices;
const Wire3DCGB_Edge* edges;
const Wire3DCGB_Face* faces;
const Wire3DCGB_EdgeFaces* edge_faces;
w3dcgb_u8 vertex_count;
w3dcgb_u8 edge_count;
w3dcgb_u8 face_count;
w3dcgb_u8 flags;
} Wire3DCGB_Model;
typedef struct {
const Wire3DCGB_Model* model;
w3dcgb_i16 x;
w3dcgb_i16 y;
w3dcgb_i16 z;
w3dcgb_i8 rx;
w3dcgb_i8 ry;
w3dcgb_i8 rz;
w3dcgb_i16 scale_q8;
w3dcgb_u8 visible;
w3dcgb_u8 color;
} Wire3DCGB_Object;
typedef struct {
w3dcgb_i16 x;
w3dcgb_i16 y;
w3dcgb_i16 z;
w3dcgb_i8 rx;
w3dcgb_i8 ry;
w3dcgb_i8 rz;
w3dcgb_u8 color;
} Wire3DCGB_FastCube;
void Wire3DCGB_Init();
void Wire3DCGB_InitFullScreen();
void Wire3DCGB_InitFastMapLite();
void Wire3DCGB_EnableDoubleSpeed();
void Wire3DCGB_SetScreenOffset(w3dcgb_u8 scx, w3dcgb_u8 scy);
void Wire3DCGB_SetPaletteRGB15(w3dcgb_u16 color0, w3dcgb_u16 color1, w3dcgb_u16 color2, w3dcgb_u16 color3);
void Wire3DCGB_SetLineColor(w3dcgb_u8 color);
w3dcgb_u8 Wire3DCGB_GetLineColor();
void Wire3DCGB_ClearFrameTiles();
void Wire3DCGB_BeginFrame();
void Wire3DCGB_BeginFrameFast();
void Wire3DCGB_BeginFrameSparse();
void Wire3DCGB_ClearSparseStageFast();
void Wire3DCGB_MarkDirtyRect2D(w3dcgb_u8 min_x, w3dcgb_u8 min_y, w3dcgb_u8 max_x, w3dcgb_u8 max_y);
void Wire3DCGB_SetCamera(w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 pitch, w3dcgb_i8 yaw, w3dcgb_i8 roll);
void Wire3DCGB_DrawModel(const Wire3DCGB_Model* model, w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 rx, w3dcgb_i8 ry, w3dcgb_i8 rz);
void Wire3DCGB_DrawModelScaled(const Wire3DCGB_Model* model, w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 rx, w3dcgb_i8 ry, w3dcgb_i8 rz, w3dcgb_i16 scale_q8);
void Wire3DCGB_DrawModelColor(const Wire3DCGB_Model* model, w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 rx, w3dcgb_i8 ry, w3dcgb_i8 rz, w3dcgb_u8 color);
void Wire3DCGB_DrawModelScaledColor(const Wire3DCGB_Model* model, w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 rx, w3dcgb_i8 ry, w3dcgb_i8 rz, w3dcgb_i16 scale_q8, w3dcgb_u8 color);
void Wire3DCGB_EraseModelFaces(const Wire3DCGB_Model* model, w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 rx, w3dcgb_i8 ry, w3dcgb_i8 rz, w3dcgb_i16 scale_q8);
void Wire3DCGB_EraseTriangle2D(w3dcgb_u8 ax, w3dcgb_u8 ay, w3dcgb_u8 bx, w3dcgb_u8 by, w3dcgb_u8 cx, w3dcgb_u8 cy);
void Wire3DCGB_EraseSpan2D(w3dcgb_u8 y, w3dcgb_u8 x0, w3dcgb_u8 x1);
/* Signed endpoints, clipped before conversion to the rasterizer's u8 ABI. */
void Wire3DCGB_DrawLineClipped2D(w3dcgb_i16 x0, w3dcgb_i16 y0,
w3dcgb_i16 x1, w3dcgb_i16 y1, w3dcgb_u8 color);
void Wire3DCGB_DrawEdgeListClipped2D(const Wire3DCGB_Edge* edges, w3dcgb_u8 edge_count,
const w3dcgb_i16* vx, const w3dcgb_i16* vy, w3dcgb_u8 vertex_count,
w3dcgb_i16 cx, w3dcgb_i16 cy, w3dcgb_u8 color);
w3dcgb_i16 Wire3DCGB_ProjectAxis48(w3dcgb_i16 value, w3dcgb_i16 z);
void Wire3DCGB_InvalidateFrameHistory();
/* Startup-only: reserves both BG maps; queued HUD tiles are mirrored. */
void Wire3DCGB_EnableAtomicMaps();
void Wire3DCGB_EraseRect2D(w3dcgb_u8 x0, w3dcgb_u8 y0, w3dcgb_u8 x1, w3dcgb_u8 y1);
void Wire3DCGB_EraseLeftGuard24Fast();
void Wire3DCGB_DrawWhiteBorderFast();
void Wire3DCGB_ClearOcclusionMask();
void Wire3DCGB_SetOcclusionActive(w3dcgb_u8 active);
void Wire3DCGB_MarkTriangle2D(w3dcgb_u8 ax, w3dcgb_u8 ay, w3dcgb_u8 bx, w3dcgb_u8 by, w3dcgb_u8 cx, w3dcgb_u8 cy);
void Wire3DCGB_MarkPackedSilhouette2D(const w3dcgb_u8* profile, w3dcgb_u8 count,
w3dcgb_i8 y0, w3dcgb_u8 x, w3dcgb_u8 y);
void Wire3DCGB_ErasePackedSilhouette2D(const w3dcgb_u8* profile, w3dcgb_u8 count,
w3dcgb_i8 y0, w3dcgb_u8 x, w3dcgb_u8 y);
void Wire3DCGB_DrawScene(Wire3DCGB_Object* objects, w3dcgb_u8 count);
void Wire3DCGB_DrawFastCubes(Wire3DCGB_FastCube* cubes, w3dcgb_u8 count, w3dcgb_u8 hidden_enabled, w3dcgb_u8 selected);
void Wire3DCGB_DrawFastStatus(w3dcgb_u8 hidden_enabled, w3dcgb_u8 selected);
void Wire3DCGB_DrawFastCubeFrame(Wire3DCGB_FastCube* cubes, w3dcgb_u8 count, w3dcgb_u8 hidden_enabled, w3dcgb_u8 selected);
void Wire3DCGB_DrawFastProjectile(w3dcgb_u8 x, w3dcgb_u8 y, w3dcgb_i16 z, w3dcgb_u8 phase, w3dcgb_u8 color);
void Wire3DCGB_FastMapBegin();
void Wire3DCGB_FastMapBeginTilesOnly();
void Wire3DCGB_FastMapCell(w3dcgb_u8 tx, w3dcgb_u8 ty, w3dcgb_u8 color, w3dcgb_u8 mask);
void Wire3DCGB_FastMapRect(w3dcgb_u8 tx0, w3dcgb_u8 ty0, w3dcgb_u8 tx1, w3dcgb_u8 ty1, w3dcgb_u8 color, w3dcgb_u8 sides);
void Wire3DCGB_FastMapFlush();
void Wire3DCGB_FastMapFlushTilesOnly();
// Project camera-space coordinates without subtracting/rotating the camera.
// Depth 8..255; outputs unchanged on rejection. Shared scratch: no ISR calls.
w3dcgb_u8 Wire3DCGB_ProjectCameraPoint(w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_u8* sx, w3dcgb_u8* sy);
w3dcgb_u8 Wire3DCGB_ProjectPoint(w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_u8* sx, w3dcgb_u8* sy);
/* Fast path for games whose camera pitch, yaw, and roll stay at zero. */
w3dcgb_u8 Wire3DCGB_ProjectPointNoRotation(w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_u8* sx, w3dcgb_u8* sy);
void Wire3DCGB_DrawLine3D(w3dcgb_i16 ax, w3dcgb_i16 ay, w3dcgb_i16 az, w3dcgb_i16 bx, w3dcgb_i16 by, w3dcgb_i16 bz);
void Wire3DCGB_DrawLine3DColor(w3dcgb_i16 ax, w3dcgb_i16 ay, w3dcgb_i16 az, w3dcgb_i16 bx, w3dcgb_i16 by, w3dcgb_i16 bz, w3dcgb_u8 color);
void Wire3DCGB_DrawPoint2D(w3dcgb_u8 x, w3dcgb_u8 y);
void Wire3DCGB_DrawTinyModel2D(w3dcgb_u8 x, w3dcgb_u8 y,
w3dcgb_u8 turn, w3dcgb_u8 color);
void Wire3DCGB_DrawLine2D(w3dcgb_u8 ax, w3dcgb_u8 ay, w3dcgb_u8 bx, w3dcgb_u8 by);
void Wire3DCGB_DrawLine2DColor(w3dcgb_u8 ax, w3dcgb_u8 ay, w3dcgb_u8 bx, w3dcgb_u8 by, w3dcgb_u8 color);
void Wire3DCGB_DrawMaskedModel2D(const Wire3DCGB_Model* model,
const w3dcgb_i8* vertex_x, const w3dcgb_i8* vertex_y,
const w3dcgb_u8* edge_mask,
w3dcgb_u8 x, w3dcgb_u8 y, w3dcgb_u8 color);
void Wire3DCGB_DrawEdgeList2D(const Wire3DCGB_Edge* edges, w3dcgb_u8 edge_count,
const w3dcgb_i8* vertex_x, const w3dcgb_i8* vertex_y,
w3dcgb_u8 x, w3dcgb_u8 y, w3dcgb_u8 color);
void Wire3DCGB_DrawLineList2DColor(const w3dcgb_u8* line_xy,
w3dcgb_u8 line_count, w3dcgb_u8 color);
void Wire3DCGB_PutBgTile(w3dcgb_u8 x, w3dcgb_u8 y, w3dcgb_u8 tile);
void Wire3DCGB_EndFrame();
void Wire3DCGB_EndFrameFast();
void Wire3DCGB_EndFrameSparse();
void Wire3DCGB_EndFrameSparseNow();
w3dcgb_u8 Wire3DCGB_GetFullScreenTileCount();
w3dcgb_u8 Wire3DCGB_GetFullScreenOverflow();
#endifkitaqgb/lib/wire3d_cgb.h
wire3d_dmg.h — Gráficos de alambre para DMG
#pragma once
// Select the viewport at build time before including this header or source.
// Default: 128x120 with consuming uploads and optional dirty/auxiliary transfer.
// Heights 88 and 96 retain the HUD and yaw-mask profile with BeginFrame clearing.
#ifndef WIRE3D_DMG_HEIGHT
#define WIRE3D_DMG_HEIGHT 120
#endif
#if WIRE3D_DMG_HEIGHT != 88 && WIRE3D_DMG_HEIGHT != 96 && WIRE3D_DMG_HEIGHT != 120
#error WIRE3D_DMG_HEIGHT must be 88, 96 or 120
#endif
#ifndef KITAQGB_WIRE3D_DMG_H
#define KITAQGB_WIRE3D_DMG_H
#if WIRE3D_DMG_HEIGHT != 120
// Monochrome 128x88/96 wireframe renderer with global, non-reentrant state.
// It takes over LCD tile data/map and reserves WRAM 0xD000..0xDFFF for staging.
// Angles wrap every 16 steps; scale 256 is unity. Scene occlusion is a coarse
// face-bounding-box/five-line-sample heuristic, not per-pixel depth testing.
#else
// Monochrome 128x120 staged renderer with global non-reentrant state.
// Reserve WRAM 0xD000..0xDFFF and the renderer's tile/map VRAM regions.
// BeginFrame does not clear pixels: uploads consume the stage. Auxiliary source
// strips alias the main stage, and dirty transfer relies on current/previous flags.
#endif
#define WIRE3D_DMG_SCREEN_W 128
#if WIRE3D_DMG_HEIGHT != 120
#define WIRE3D_DMG_SCREEN_H WIRE3D_DMG_HEIGHT
#else
#define WIRE3D_DMG_SCREEN_H 120
#endif
#define WIRE3D_DMG_MODEL_VERTEX_LIMIT 24
#if WIRE3D_DMG_HEIGHT != 120
#define WIRE3D_DMG_MODEL_EDGE_LIMIT 16
#endif
#define WIRE3D_DMG_MODEL_FACE_LIMIT 16
#define WIRE3D_DMG_SCENE_OBJECT_LIMIT 8
#define WIRE3D_DMG_FACE_NONE 255
#define WIRE3D_DMG_MODEL_HIDDEN_LINES 1
#if WIRE3D_DMG_HEIGHT != 120
#define WIRE3D_DMG_EDGE_MASK_BINS_16 16
#else
#define WIRE3D_DMG_ANGLE_STEPS 16
#endif
typedef s8 w3ddmg_i8;
typedef s16 w3ddmg_i16;
typedef u8 w3ddmg_u8;
typedef u16 w3ddmg_u16;
typedef struct {
w3ddmg_i16 x;
w3ddmg_i16 y;
w3ddmg_i16 z;
} Wire3DDMG_Vec3;
typedef struct {
w3ddmg_u8 a;
w3ddmg_u8 b;
} Wire3DDMG_Edge;
typedef struct {
w3ddmg_u8 a;
w3ddmg_u8 b;
w3ddmg_u8 c;
} Wire3DDMG_Face;
typedef struct {
w3ddmg_u8 f0;
w3ddmg_u8 f1;
} Wire3DDMG_EdgeFaces;
#if WIRE3D_DMG_HEIGHT != 120
// Model tables are borrowed for drawing, never copied or bank-switched.
// Counts are capped at 24 vertices, 16 edges and 16 faces; each supplied table
// must contain the referenced entries. Triangle winding with positive projected
// area is front-facing. FACE_NONE denotes a missing adjacent face.
#else
// Model tables are borrowed and must remain readable in the active bank.
// At most 24 vertices and 16 faces are processed; the model edge count is not
// limited to 16. Supply all declared edge and adjacency entries. Positive
// projected triangle area is front-facing; FACE_NONE means missing adjacency.
#endif
typedef struct {
const Wire3DDMG_Vec3* vertices;
const Wire3DDMG_Edge* edges;
const Wire3DDMG_Face* faces;
const Wire3DDMG_EdgeFaces* edge_faces;
#if WIRE3D_DMG_HEIGHT != 120
/* Keep edge mask tables in RAM for pointer-indirect access on current KITAQGB. */
const w3ddmg_u16* edge_masks;
#endif
w3ddmg_u8 vertex_count;
w3ddmg_u8 edge_count;
w3ddmg_u8 face_count;
#if WIRE3D_DMG_HEIGHT != 120
w3ddmg_u8 edge_mask_count;
#endif
w3ddmg_u8 flags;
} Wire3DDMG_Model;
typedef struct {
const Wire3DDMG_Model* model;
w3ddmg_i16 x;
w3ddmg_i16 y;
w3ddmg_i16 z;
#if WIRE3D_DMG_HEIGHT != 120
w3ddmg_i8 rx;
w3ddmg_i8 ry;
w3ddmg_i8 rz;
#else
w3ddmg_u8 rx;
w3ddmg_u8 ry;
w3ddmg_u8 rz;
#endif
w3ddmg_i16 scale_q8;
w3ddmg_u8 visible;
} Wire3DDMG_Object;
#if WIRE3D_DMG_HEIGHT != 120
// Take over the LCD: wait for VBlank, switch it off, clear 6144 tile bytes and
// the BG map, install HUD tiles and the 128x96 signed-tile viewport, then enable
// BG display with scroll zero and BGP=0xB4. Reset camera, BG queue and stage.
// Reserve 0xD000..0xDFFF for staging and retain its WRAM bank mapping.
// Call BeginFrame before drawing to initialize the occlusion state as well.
#else
// Take over LCD state, clear tile VRAM and the BG map, and install a 16x15
// viewport beginning at map tile (3,1). Set scroll (8,0), BGP=0xB4 and BG display.
// Reset camera, queues, transfer modes, both dirty tables and stage. Reserve
// 0xD000..0xDFFF and retain its WRAM mapping; auxiliary storage aliases it.
// Call BeginFrame before drawing to establish occlusion state.
#endif
void Wire3DDMG_Init();
#if WIRE3D_DMG_HEIGHT != 120
// Clear staged pixels and occlusion mask and disable occlusion filtering.
// This leaves the displayed VRAM frame and pending BG tile queue unchanged.
#else
// Disable occlusion filtering only. Stage clearing normally happens during
// transfer, and Init supplies the first clean stage. This does not discard an
// unsubmitted frame, clear the mask, or reset pending BG writes/dirty flags.
#endif
void Wire3DDMG_BeginFrame();
/* Validate depth and project coordinates already in camera space. */
w3ddmg_u8 Wire3DDMG_ProjectCameraPoint(w3ddmg_i16 x,w3ddmg_i16 y,w3ddmg_i16 z,w3ddmg_u8* sx,w3ddmg_u8* sy);
// Store camera position and angles for later draws; a full turn is 16 angle
// steps. No existing drawing is reprojected and no input range validation occurs.
#if WIRE3D_DMG_HEIGHT != 120
void Wire3DDMG_SetCamera(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 pitch, w3ddmg_i8 yaw, w3ddmg_i8 roll);
#else
void Wire3DDMG_SetCamera(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 pitch, w3ddmg_u8 yaw, w3ddmg_u8 roll);
#endif
// Draw an unscaled model by delegating to DrawModelScaled with scale 256.
#if WIRE3D_DMG_HEIGHT != 120
void Wire3DDMG_DrawModel(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz);
// Scale, rotate in Y/X/Z order, translate and project at most 24 vertices;
// then draw up to 16 edges filtered by yaw masks and optional front-facing faces.
// Nonpositive scale becomes unity (256). Null model/vertex/edge pointers are
// ignored; referenced tables must remain readable. Keep scale products and
// translations in signed 16-bit range. Depth-crossing edges are dropped, not clipped.
void Wire3DDMG_DrawModelScaled(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz, w3ddmg_i16 scale_q8);
#else
void Wire3DDMG_DrawModel(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz);
// Scale up to 24 vertices, rotate Y/X/Z, translate and project, then traverse
// all edge_count entries (a byte count) with optional adjacent-face filtering.
// Face scratch is capped at 16; edge tables must contain all declared entries.
// Nonpositive scale means 256. Null model/vertex/edge pointers are ignored.
// Keep products/translations in signed 16-bit range; depth-crossing edges are dropped.
void Wire3DDMG_DrawModelScaled(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz, w3ddmg_i16 scale_q8);
#endif
// Project up to 24 vertices and erase front-facing triangle interiors from
// the stage for a model with hidden-line flags and face data. Nonpositive scale
// means 256 (unity). Up to 16 faces are considered; depth-crossing faces are
// skipped. This also replaces shared projection caches, but does not update VRAM.
#if WIRE3D_DMG_HEIGHT != 120
void Wire3DDMG_EraseModelFaces(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz, w3ddmg_i16 scale_q8);
#else
void Wire3DDMG_EraseModelFaces(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz, w3ddmg_i16 scale_q8);
#endif
// Erase a triangle from staged pixels using integer scanline intersections.
// Supply viewport coordinates. Degenerate triangles are ignored; the occlusion
// mask and VRAM are unchanged.
void Wire3DDMG_EraseTriangle2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by, w3ddmg_u8 cx, w3ddmg_u8 cy);
// Order the X endpoints and erase the inclusive staged span. Both endpoints
// must be in 0..127; invalid Y is ignored. The routine does not clip X for you.
void Wire3DDMG_EraseSpan2D(w3ddmg_u8 y, w3ddmg_u8 x0, w3ddmg_u8 x1);
#if WIRE3D_DMG_HEIGHT != 120
// Process at most the first eight objects, sorted near to far by transformed
// origin depth. Draw visible valid models, then mark their front-face bounding
// rectangles to reject fully sampled later lines. This approximates inter-object
// occlusion, not a depth buffer. It clears its mask but retains existing staged
// pixels. Null arrays are ignored; objects and their data must remain readable.
#else
// Sort at most eight object origins by camera depth, near to far. Draw visible
// valid models and mark front-face bounding rectangles for later objects. The
// first sorted slot bypasses mask tests and the last needs no new occluder.
// This is coarse line rejection, not a depth buffer. Null/empty input is ignored;
// caller data and the current projection cache must remain valid during traversal.
#endif
void Wire3DDMG_DrawScene(Wire3DDMG_Object* objects, w3ddmg_u8 count);
#if WIRE3D_DMG_HEIGHT != 120
// Select a precomputed mask from the low four bits of object yaw; pitch,
// roll and camera orientation are ignored. Use 16, 8, 4 or 2 bins; other positive
// counts select entry zero (counts >=16 use the first 16). Missing data returns
// 0xFFFF. Keep the mask table readable through the current data-pointer mapping.
w3ddmg_u16 Wire3DDMG_SelectEdgeMask(const Wire3DDMG_Model* model, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz);
// Project a world point with the current camera. Return zero for rejected
// depth, leaving outputs unchanged; success writes clamped coordinates for the selected height.
// Output pointers must be valid. Screen clamping is not geometric clipping.
#else
// Project a world point with the current camera. Return zero for invalid
// depth without changing outputs; success writes clamped 128x120 coordinates.
// Both output pointers must be valid. Coordinate differences must fit s16.
#endif
w3ddmg_u8 Wire3DDMG_ProjectPoint(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8* sx, w3ddmg_u8* sy);
#if WIRE3D_DMG_HEIGHT == 120
// Rotate in place in Y/X/Z order using 16 steps per full turn. A null
// component pointer makes the whole call a no-op; use distinct pointers.
// Each axis rotation clamps its inputs to +/-220.
void Wire3DDMG_RotatePoint(w3ddmg_i16* x, w3ddmg_i16* y, w3ddmg_i16* z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz);
#endif
// Project both world endpoints and draw only when both pass the depth range.
// Do not intersect a crossing segment with near/far planes; projected endpoints
// are independently clamped to the screen edges.
void Wire3DDMG_DrawLine3D(w3ddmg_i16 ax, w3ddmg_i16 ay, w3ddmg_i16 az, w3ddmg_i16 bx, w3ddmg_i16 by, w3ddmg_i16 bz);
#if WIRE3D_DMG_HEIGHT != 120
// Draw a connected line into the 128x96 stage, including endpoints. During
// DrawScene, use the coarse five-sample occlusion rejection; otherwise draw directly.
// Supply viewport coordinates. VRAM is updated only by EndFrame.
#else
// Mark the bounding tile rectangle when dirty transfer is enabled, then draw
// a connected staged line. Scene drawing may reject it using five mask samples.
// Supply 128x120 viewport endpoints; low-level pixel bounds checks do not clip
// the segment geometrically.
#endif
void Wire3DDMG_DrawLine2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by);
#if WIRE3D_DMG_HEIGHT == 120
// Draw a wireframe rectangle directly into the staged bitplane. Endpoints are
// inclusive screen pixels in 0..127 x 0..119; both horizontal and vertical
// edges are written with byte masks and only touched tiles are uploaded.
void Wire3DDMG_DrawRect2D(w3ddmg_u8 x0, w3ddmg_u8 y0, w3ddmg_u8 x1, w3ddmg_u8 y1);
#endif
// Draw the canonical 12 edges of an 8-vertex projected box in one call.
// Vertex order is near-face corners 0..3, then far-face corners 4..7.
void Wire3DDMG_DrawBoxEdges2D(const w3ddmg_u8* sx, const w3ddmg_u8* sy);
#if WIRE3D_DMG_HEIGHT == 120
// Draw byte-pair edge indices after integer scaling and translation; scale
// zero means one, and there is no object rotation or face filtering. Project at
// most 24 vertices. Supply at most 128 edge pairs because byte offsets wrap
// after 255. Invalid vertex IDs/depth-rejected endpoints are skipped; null arrays
// are ignored. Keep coordinate products/sums representable as s16.
void Wire3DDMG_DrawIndexedEdges(const Wire3DDMG_Vec3* vertices, w3ddmg_u8 vertex_count, const w3ddmg_u8* edges, w3ddmg_u8 edge_count, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 scale);
#endif
// Queue a tile write to the 32x32 map at 0x9800 for EndFrame. Invalid map
// coordinates and submissions beyond 48 pending writes are silently ignored.
// This queue is separate from the general vram library queue.
void Wire3DDMG_PutBgTile(w3ddmg_u8 x, w3ddmg_u8 y, w3ddmg_u8 tile);
// Write the raw DMG BGP palette encoding immediately; no frame synchronization occurs.
void Wire3DDMG_SetPalette(w3ddmg_u8 bgp);
#if WIRE3D_DMG_HEIGHT != 120
// Wait for the next VBlank, flush pending BG map writes, then copy the stage
// to VRAM while polling access windows. Copying consumes the staged pixels.
// The transfer may extend beyond VBlank; this is not an atomic frame swap.
#else
// Store the EndFrame auxiliary-transfer gate; any nonzero value enables it.
// No data is copied or cleared here. Auxiliary source bytes alias the main stage.
void Wire3DDMG_SetAuxTransfer(w3ddmg_u8 flag);
// Store the dirty-transfer gate and clear both dirty histories and the main
// stage, even if the value is unchanged. VRAM is retained; enabling this over an
// old image can leave unmarked old tiles, so arrange a clean displayed baseline.
void Wire3DDMG_SetDirtyTransfer(w3ddmg_u8 flag);
// Upload and consume the full main stage immediately, polling STAT but not
// waiting for the next VBlank. Ignore transfer gates and leave dirty histories
// and BG tile queue unchanged; the caller coordinates the frame lifecycle.
void Wire3DDMG_TransferMainNow();
// Upload and consume auxiliary source strips immediately, independent of the
// auxiliary gate. No VBlank-start wait or dirty-history/BG-queue update occurs.
// The source overlaps the main stage and must be coordinated with its upload.
void Wire3DDMG_TransferAuxNow();
// Wait for the next VBlank and flush BG writes, then optionally consume the
// auxiliary strips before uploading either dirty tiles or the entire main stage.
// Auxiliary/main source overlap makes that ordering significant. STAT polling
// continues across access windows; the update need not fit one VBlank.
#endif
void Wire3DDMG_EndFrame();
// Same queue/gate/history lifecycle, without the initial fresh-VBlank wait.
// Synchronous STAT-safe upload; not an atomic swap. LCD must remain enabled.
void Wire3DDMG_EndFrameNow();
#endif
#if WIRE3D_DMG_HEIGHT == 120
#endifkitaqgb/lib/wire3d_dmg.h
zx0.h —
#pragma once
// Copyright (c) 2026 DAISUKE OBA. MIT License.
// ZX0-compatible forward v2 streams; format designed by Einar Saukas.
#define ZX0_OK 0
#define ZX0_BAD_ARGUMENT 1
#define ZX0_TRUNCATED 2
#define ZX0_BAD_STREAM 3
#define ZX0_OUTPUT_FULL 4
#define ZX0_DISPLAY_ACTIVE 5
// Shared last-call status. These foreground routines are not reentrant.
extern u8 zx0_error;
// Return decoded bytes, or zero on error (possibly after partial writes).
// Source and output must not overlap or cross their current CPU bank windows.
// Capacity and packed_size are byte counts. No prefix/backward/v1 streams.
u16 zx0_decompress(void* dst, u16 capacity, const void* src, u16 packed_size);
// Decode a KQA1 raw/RLE/ZX0 asset produced with --format=auto.
// Empty raw assets return zero with zx0_error==ZX0_OK.
u16 asset_decompress(void* dst, u16 capacity, const void* src, u16 packed_size);
// Decode directly into the selected GB VRAM bank ($8000..$9FFF), with LCD off.
// Preserve LCDC, VBK and interrupt state. Output must fit before $A000.
u16 zx0_decompress_vram(u16 vram_addr, const void* src, u16 packed_size);kitaqgb/lib/zx0.h







