KITAQ SISTEMA DE DESARROLLO
MANUAL DE USO 2026.09

SERIE KITAQ • EDICIÓN DE REFERENCIA

BIBLIOTECA KITAQGB

Herramientas para crear un juego

Desde tu primera línea hasta la ejecución, la observación y la repetición de pruebas.
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.

KITAQGB · SHA-256 · KITAQFC · SHA-256

Cambios y verificación de la biblioteca local, 2026-10-03

Las fuentes de C:/kitaqgb_project/lib se compararon con la revisión pública 2de7f4b. Las fechas por sí solas no determinan qué versión es más reciente. La versión local añade funciones; la pública contiene otras adiciones y correcciones. Esta sección describe las fuentes locales guardadas por separado de las pruebas existentes de la API pública.

physics2d.c conserva la API de contacto y añade implementaciones con caché de contacto y límite de velocidad mediante KQ2D_CACHE_SURFACE. Reserve el banco ROM 13 al activarlo. Definir KQ2D_EXTERNAL_SCALE_Q8, KQ2D_EXTERNAL_REST_COMPONENT o KQ2D_EXTERNAL_SURFACE exige proporcionar la implementación correspondiente. Los 8.872 casos siguientes usan la ruta predeterminada sin estas definiciones.

KQ3D_BODY_SPHERE=0x04 selecciona contactos esfera–caja. El radio es half_x. kq3d_overlap_sphere_aabb(sphere, box) incluye la tangencia y devuelve 0 para punteros NULL o radios no positivos. No existe un solucionador específico esfera–esfera. Mantenga diferencias, productos y sumas de cuadrados dentro de sus rangos de 16 bits.

Un body activo con KQ3D_BODY_KINEMATIC=0x02 actualiza velocidad y posición X/Y en kq3d_step incluso con masa inversa cero. La posición y velocidad Z no cambian. Los contactos no desplazan un body de masa inversa cero. kq3d_integrate_body sigue omitiendo los bodies estáticos. break_speed y KQ3D_BODY_BROKEN no provocan destrucción automática.

El bank_switch local escribe kq_bank_current y la dirección 0x2000. A diferencia de la ruta pública __bankswitch, no actualiza el seguimiento de banco del compilador. Cambie desde el banco fijo; use __bankswitch si también debe mantener el estado de restauración.

Los cgb_bg_color/cgb_obj_color locales y sus envoltorios RGB de un color no activan el incremento automático del índice. La ejecución CGB confirmó que el byte bajo de 0x1234 se sobrescribe con 0x12. Use la corrección pública o una API colors con matrices. En DMG no se escribe.

El metasprite_draw local amplía el contador a first_id+count solo al terminar. Un retorno anticipado en el límite de 40 sprites no lo actualiza. Con first_id=39 y count=2, devuelve 1, la ranura 39 está activa y el contador vale 0. La versión pública actualiza el contador al procesar cada ranura.

La versión local ofrece vram_get_queue_used y vram_get_queue_free, pero carece del vram_get_queue_capacity público. La capacidad es VRAM_QUEUE_MAX, 32 de forma predeterminada. Un comando produce used=1 y free=31.

wire3d_dmg.h declara DrawRect2D solo en el perfil de 96 líneas. DrawBoxEdges2D se declara en ambos perfiles; DrawIndexedEdges solo en el de 120 líneas. Seleccione una fuente acorde con el perfil. El dibujo de estas funciones no se volvió a verificar aquí. No se encontró implementación de DrawRect2D ni DrawBoxEdges2D en las fuentes lib guardadas. Son solo declaraciones; llamarlas requiere una implementación aparte.

El audio_vblank local no incluye los AudioVBlank_QueueReset/QueueRefill/QueuePlay públicos ni audio_vblank_queue.inc. ZX0 también es exclusivo de la versión pública. Estas adiciones no forman parte de las funciones locales declaradas verificadas.

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

KQ3D_BODY_SPHERE=0x04 selecciona contactos esfera–caja. El radio es half_x. kq3d_overlap_sphere_aabb(sphere, box) incluye la tangencia y devuelve 0 para punteros NULL o radios no positivos. No existe un solucionador específico esfera–esfera. Mantenga diferencias, productos y sumas de cuadrados dentro de sus rangos de 16 bits.

physics3d.c / physics3d.h

Verificación ejecutada

Ruta 2D predeterminada: 8.872 casos superados con la API C de KOKURA y selección automática de hardware. Se comprobaron límite de velocidad, contactos, multiplicación Q8 con signo e instante de impacto. No fueron ejecuciones separadas con DMG/CGB explícitos.

Límites físicos: 19 casos en DMG y CGB, 38 ejecuciones superadas. Las pruebas separadas de extensión 3D y reproducción de sprites/VRAM/paleta coincidieron con lo esperado en ambos modos. Paleta y sprites reproducen defectos; no confirman un funcionamiento correcto.

Son pruebas de emulador de ROM generadas por el compilador C#. No demuestran equivalencia Rust, hardware físico, audio, dibujo ni corrección de todas las API. Las imágenes y pruebas existentes siguen siendo resultados históricos ligados a sus huellas de fuentes.

Huellas de fuentes, entradas, valores esperados y observados, pasos de reproducción · evidence.tar.gz · verify_rom_cases.py · verify_surface.py

1. Utilizar la biblioteca

La biblioteca reúne código C reutilizable basado en las funciones intrínsecas __ de KITAQGB. Abarca desde el control de pantalla hasta física, gráficos 3D y comunicaciones.

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

Cada entrada de API incluye la declaración, la cabecera, la implementación y un ejemplo de uso. Los fragmentos muestran cómo pasar argumentos; el programa que llama debe preparar los búferes y objetos necesarios. La sección de programas completos contiene ejemplos que se pueden compilar directamente como ROM.

2. Organizar un fotograma del juego

system_init inicializa la gestión de fotogramas. system_wait_vblank espera y aumenta el contador de fotogramas del programa. En GB, esa función de espera invoca la función de retorno de VBlank de forma cooperativa: registrarla no instala un manejador de interrupción de hardware.

  1. Actualiza la entrada una vez.
  2. Calcula el movimiento, las colisiones y el estado del juego.
  3. Prepara las órdenes de dibujo y la OAM.
  4. Aplica las actualizaciones durante VBlank.
  5. Haz avanzar la música según el controlador elegido.

Si combinas operaciones que esperan, como vram_flush y sprite_flush_oam, una sola actualización del juego puede terminar esperando dos fotogramas. Si ya has realizado la espera, puede convenir la variante _now, siempre que respetes sus requisitos de acceso al hardware.

3. Entrada y repetición de botones

input_down(mask) comprueba si un botón sigue pulsado; input_pressed(mask), si acaba de pulsarse; e input_released(mask), si acaba de soltarse. input_repeat(mask) ofrece la repetición habitual de los menús. Estos estados se actualizan con input_update(). Llamarla varias veces en un mismo fotograma puede borrar la detección de una pulsación nueva.

BotonesMáscaras
Derecha, izquierda, arriba, abajo0x01 / 0x02 / 0x04 / 0x08
A, B, SELECT, START0x10 / 0x20 / 0x40 / 0x80

gb_input.c cuenta las pulsaciones de A. Comprueba que mantenerlo pulsado no aumenta continuamente el contador. Después sustituye input_pressed por input_down para observar la diferencia.

4. Fondos, texto y VRAM

vram_queue_bg_tile encola un tile, vram_queue_bg_rect un rectángulo y vram_queue_bg_block una transferencia desde un array. Comprueba los valores devueltos y vram_get_overflowed() para detectar si se ha agotado la capacidad. Si una operación conserva un puntero al origen, mantén los datos sin modificar, la memoria válida y su banco accesible hasta que termine la transferencia.

vram_get_queue_capacity() devuelve el número total de entradas de la cola de comandos (32 por defecto), vram_get_queue_free() indica cuántas quedan libres y vram_get_queue_used() cuántas están ocupadas. Cada operación encolada ocupa una entrada, independientemente de la cantidad de datos que transfiera. Estas funciones consultan la cola de transferencias, no el espacio libre de la VRAM física.

text.c y menu.c implementan los servicios de texto, selección y ventanas declarados en rpg.h. La correspondencia entre texto y tiles debe coincidir con la fuente cargada en VRAM. No tiene por qué ser la misma que utiliza la función auxiliar m_text de este manual.

5. Sprites y animación

Empieza con sprite_init, sprite_alloc, sprite_set_tile y sprite_set_pos. GB admite 40 sprites en total y 10 por línea de barrido. Ten en cuenta tanto el número total como su concentración en una misma línea horizontal. sprite_warn_scanline_overflow y sprite_max_scanline_count ayudan a examinar la distribución.

MetaSpritePart describe posiciones relativas de objetos OBJ. SpriteAnim define los tiles de cada paso de la animación y sus intervalos. Las partes que dibuja metasprite_draw deben corresponder a las entradas OBJ reservadas. La A de gb_sprite.c muestra cómo utilizar el tile de una letra como sprite.

6. Color, desplazamiento, efectos por línea y cámaras

Los componentes RGB de cgb_bg_rgb y cgb_obj_rgb van de 0 a 31, no de 0 a 255. CGB_RGB15 los empaqueta en un valor de 16 bits. Las funciones de alto nivel para paletas CGB están diseñadas para no realizar ninguna operación en DMG.

Scroll_SetBg sitúa el fondo y Scroll_SetWindow la ventana. El módulo de cámara obtiene el área visible a partir de las coordenadas del mundo. No mezcles las unidades de punto fijo de la cámara con los píxeles enteros de pantalla.

raster.c genera tablas de desplazamiento por franjas y distorsión horizontal por línea. Las operaciones Scroll_SplitCommit utilizan los vectores VBlank/STAT. Si la música y el desplazamiento necesitan el mismo vector, coordínalos mediante un despachador común; dos manejadores independientes no pueden ocuparlo simultáneamente.

7. Música y efectos de sonido

Compila primero audio_hwregs_gb.c, después audio.c y por último el código del juego. No dupliques las definiciones de los registros NR10–NR52 si el juego ya las aporta. Tras Audio_Init, lo habitual es llamar a Audio_Update una vez por fotograma.

Audio_PlayMusic(bank,song) especifica expresamente el banco de la música. Audio_PlaySFXBanked reproduce un efecto situado en otro banco. Las prioridades resuelven la competencia entre efectos que utilizan los mismos canales físicos. GB dispone de cuatro: CH1, CH2, CH3 y CH4.

Los comandos del flujo musical AUDIO_CMD_NOTE, AUDIO_CMD_SET_INST y AUDIO_CMD_STOP_CHANNEL comparten los ID de canal de la API normal: 0=CH1, 1=CH2, 2=CH3, 3=CH4. CH1 es pulso con barrido, CH2 pulso, CH3 forma de onda y CH4 ruido. La cabecera define AUDIO_NOTE_MAX=67.

El flujo básico de efectos de CH1 lee pares de nota y volumen por fotograma y termina con la nota 0. CH3 emplea otro marcador y otro formato. Consulta gb_sound.c. Los fundidos avanzan durante Audio_Update; si dejas de actualizar, el fundido también se detiene.

8. Música mediante la interrupción VBlank

audio_vblank.c utiliza un formato de reproducción independiente. Los registros temporizados contienen cinco bytes: delay, ch1_note, ch2_note, ch3_note, ch4_noise_param. El controlador lee canciones direccionables directamente o consume una cola en WRAM. Usa AudioVBlank_QueueReset para inicializar el modo de cola, AudioVBlank_QueueRefill para suministrar registros completos de cinco bytes y AudioVBlank_QueuePlay para iniciar la reproducción. La cola debe rellenarse desde un único productor en primer plano. LOOP solo se reconoce en los flujos directos e IMMEDIATE solo en el modo de cola. Los flujos normales de audio.c no pueden pasarse sin modificar.

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

El parche modifica el vector VBlank en 0x0040 y actualiza la suma de comprobación. Aplícalo únicamente a una ROM preparada para este controlador. Revisa los posibles conflictos con manejadores VBlank propios y con el desplazamiento dividido. Compilar correctamente no demuestra que la música se oiga: grábala con KOKURA y comprueba que avance.

9. Punto fijo, física y 3D

En la aritmética Q8.8 de fixed.h, 256 representa 1,0 y 128 representa 0,5. gb_fixed.c muestra fix_from_int, fix_mul y fix_to_int. Define los rangos de valores antes de programar los cálculos para evitar desbordamientos.

physics2d trabaja con rectángulos, physics2d_circle con círculos y physics3d con AABB tridimensionales. Prepara e inicializa los arreglos de mundo y cuerpos, configura la velocidad o la gravedad y ejecuta un paso. Usa unidades coherentes para la posición y la velocidad por paso; la biblioteca no convierte automáticamente a píxeles. El ejemplo circular emplea posición 40 y velocidad 2. Una masa inversa nula indica un cuerpo estático. Consulta en las cabeceras la representación de cada coeficiente y los límites de los cálculos intermedios. En particular, la función kq2d_body_apply_friction convierte su coeficiente a un byte con signo: 128–255 pasan a ser valores negativos, no factores de amortiguación Q8 sin signo. gb_circle.c muestra un paso completo.

wire3d_dmg es una biblioteca de renderizado alámbrico monocromo para Game Boy. Compila wire3d_dmg_96.c para una vista de 128 × 96 o wire3d_dmg.c para 128 × 120, y utiliza las funciones Wire3DDMG_*. wire3d y dmg3d también ofrecen puntos de entrada para los perfiles de 96 y 120 líneas, respectivamente. Compila un solo punto de entrada por programa. wire3d_cgb es el renderizador dedicado al color. Reserva expresamente la RAM, la VRAM y las zonas de pantalla de cada renderizador. Los dos renderizadores monocromos descartan las aristas que cruzan los límites de profundidad, en lugar de recortarlas. La ocultación entre objetos se aproxima mediante rectángulos que encierran las caras y cinco muestras por línea; no es una prueba de profundidad por píxel. La versión CGB utiliza doble velocidad y DMA, y requiere --cgb=cgb_only.

Wire3DDMG_BeginFrame (WIRE3D_DMG_HEIGHT=96) borra el búfer de dibujo. Wire3DDMG_BeginFrame (WIRE3D_DMG_HEIGHT=120) solo reinicia el estado de ocultación: DMG3D consume y borra los datos al transferirlos a VRAM. La transferencia de tiles modificados incluye los del fotograma anterior para borrar los píxeles antiguos. La transferencia auxiliar comparte parte del búfer principal; no dispone de uno independiente. Organiza la secuencia de cada fotograma según el renderizador elegido.

Para las líneas de CGB, utiliza los colores 1, 2 y 3. El modo normal de 128 × 96 combina los bits de color: al superponer los colores 1 y 2 se obtiene el color 3. El color 0 no borra una línea. Limpia el fotograma o usa las funciones de borrado específicas. En el modo normal, Wire3DCGB_DrawLine2D y el dibujo de modelos no registran la región que debe transferirse. Para dibujar líneas y registrar esa región, usa Wire3DCGB_DrawLineClipped2D; para incluir toda el área de dibujo en la siguiente transferencia parcial, llama a Wire3DCGB_InvalidateFrameHistory.

El modo de 160 × 144 asigna como máximo 127 teselas por fotograma. Si el trazador rápido no puede asignar una tesela o recibe una coordenada fuera de pantalla, Wire3DCGB_GetFullScreenOverflow() devuelve un valor distinto de cero y se suspenden las escrituras de píxeles hasta inicializar el siguiente fotograma. Mantén los vértices dentro del área seleccionada. El margen derecho de la máscara triangular llega como máximo a X=127 en el modo de 128 × 96 y a X=159 en pantalla completa. Respeta la configuración de bancos WRAM indicada en cada API, especialmente al usar pantalla completa o FastMap.

10. Escenas, grupos de objetos y patrones de proyectiles

scene gestiona estados como título, partida y pausa; entity proporciona un pool de objetos de capacidad fija; chain ofrece seguimiento articulado e historial de posiciones. Usa ChainBody para mover una serpiente o cuerda articulada. Comprueba los valores de fallo de asignación, como 0xFF, antes de usar el puntero devuelto por entity_get.

danmaku proporciona grupos de proyectiles en punto fijo, generación direccional y en abanico, impactos y roces. Su composición sobre el fondo CGB evita el límite habitual de objetos OBJ, pero siguen existiendo límites de tiempo por fotograma y de ancho de banda para actualizar el fondo. Mide el tiempo de procesamiento en lugar de fijarte únicamente en el número de proyectiles.

11. RPG, aventuras, estrategia y partidas guardadas

rpg.h reúne declaraciones de números aleatorios, indicadores, misiones, compresión, texto, menús, scripts, mapas, guardado y búsqueda de rutas. Las implementaciones se reparten entre archivos como rng.c, flags.c, rle.c y text.c. Utiliza el diccionario para escoger las unidades necesarias.

Un valor fijo de rng_seed genera una secuencia reproducible para las pruebas. Comprueba si cada función de rango incluye su límite superior. flag_get y flag_set trabajan sobre conjuntos de bits. save.c utiliza un esquema de acceso a SRAM de tipo MBC5: la capacidad de RAM de la cabecera de la ROM debe corresponder al área de guardado del juego.

Los servicios de tablero, listas de jugadas y deshacer de slg.h, así como la búsqueda de rutas de slg_path.c, son independientes de las reglas y la evaluación propias de cada juego. La anchura, la altura y los arrays de trabajo deben respetar tanto los límites de la biblioteca como los de cada argumento.

12. Comunicaciones

link.c implementa transferencias de bytes por el puerto serie; link_packet.c añade una capa opcional de paquetes. Enlaza primero link_hwregs_gb.c. Los modos de sondeo e interrupción requieren llamadas distintas. Para usar interrupciones, el juego debe conectar el vector 0x0058.

Las operaciones lógicas Link4_* y las operaciones LinkDmg07_* del adaptador físico Nintendo DMG-07 son sistemas distintos. DMG-07 utiliza un reloj externo: llama con frecuencia a LinkDmg07_Poll y una vez por fotograma a LinkDmg07_TickFrame. Sondear solo una vez por fotograma puede resultar demasiado lento. En los trabajos pair/dmg07 de KOKURA, prueba por separado la conexión, el inicio, la desconexión y la reconexión.

13. Bancos, recursos y depuración

BankPtr combina un número de banco con un puntero. far_data_read copia recursos de otro banco a RAM. El módulo de recursos relaciona identificadores con descriptores; el juego sigue siendo responsable de la vigencia de los datos, los bancos y los tamaños.

debug_trace_u8 y debug_trace_u16 registran valores en RAM; debug_assert_fail registra un código de diagnóstico. No son llamadas a printf que impriman en la consola del PC. Examina los registros mediante las herramientas de observación de memoria del emulador. gb_debug.c registra HP=42.

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.

Mostrar el juego de caracteres incluido: 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.
Ejemplo en pantalla: 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

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


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

Su primer texto en pantalla: La pantalla muestra HELLO WORLD y 042. El cero inicial corresponde al formato decimal de tres dígitos.
Ejemplo en pantalla: 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

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


// Initialize the display/font, write HELLO WORLD and a three-digit 042,
// then wait for frames so the result remains visible.
void main() {
    m_init();
    m_text(2,3,"HELLO");
    m_text(2,5,"HELLO WORLD");
    m_number(42);
    while (1) { m_wait();  }
}
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.

Calcular con un valor intermedio más amplio: 030 representa el resultado calculado, 30.
Ejemplo en pantalla: 030 representa el resultado calculado, 30.

Descargar código fuente / Estado de la verificación

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


// Widen before adding 200 + 100, divide the 16-bit sum, and display 30.
// The cast demonstrates avoiding an 8-bit intermediate result.
void main() {
    m_init();
    m_text(2,3,"ARITHMETIC");
    u16 sum;
    sum = (u16)200 + 100;
    m_number((u8)(sum / 10));
    while (1) { m_wait();  }
}
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.

Bifurcaciones y bucles: 042 es el resultado final de estos bucles y bifurcaciones.
Ejemplo en pantalla: 042 es el resultado final de estos bucles y bifurcaciones.

Descargar código fuente / Estado de la verificación

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


// Exercise loop control and a final branch, then display the selected value 42.
void main() {
    m_init();
    m_text(2,3,"CONTROL");
    u8 i; u8 sum; sum=0;
    for (i=0;i<8;i++) { if (i==3) continue; sum=(u8)(sum+i); }
    while (sum<30) { sum++; }
    do { sum++; } while (sum<32);
    switch (sum) { case 32: sum=42; break; default: sum=0; break; }
    m_number(sum);
    while (1) { m_wait();  }
}
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.
Ejemplo en pantalla: 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.

Descargar código fuente / Estado de la verificación

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

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

Banderas de bits y copia de búfer: el primer byte de destino se muestra como 010; el bit 3 aporta 8 y el bit 1 aporta 2.
Ejemplo en pantalla: 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

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

// Clear the source bytes, set bits 3 and 1, copy the buffer, and display 8 + 2 = 10.
void main() {
    m_init();
    m_text(2,3,"BITS MEMORY");
    u8 data[4]; u8 copy[4];
    __memset(data,0,4); __bit_set(data,3); __bit_toggle(data,1);
    __memcpy(copy,data,4); m_number(copy[0]);
    while (1) { m_wait();  }
}
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.

Contar nuevas pulsaciones de un botón: 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.
Ejemplo en pantalla: 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

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

Multiplicar valores de punto fijo Q8.8: 012 significa 3 × 4 = 12. Es el entero convertido, no el valor interno escalado por 256.
Ejemplo en pantalla: 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

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

// Convert 3 and 4 to Q8.8, multiply them, convert the result back to an
// integer, and display 12.
void main() {
    m_init();
    m_text(2,3,"FIXED");
    fix8 a; fix8 b; a=fix_from_int(3); b=fix_from_int(4);
    m_number((u8)fix_to_int(fix_mul(a,b)));
    while (1) { m_wait();  }
}
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.

Asignar desde un pool fijo de objetos: 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.
Ejemplo en pantalla: 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

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

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

Registrar un valor de diagnóstico en RAM: 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.
Ejemplo en pantalla: 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

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

// Record HP = 42 with frame tag 1 and display the number of trace entries.
// The trace buffer contains the value; the screen displays the count, not HP.
void main() {
    m_init();
    m_text(2,3,"DEBUG");
    debug_init(); debug_set_frame(1); debug_trace_u8("HP",42);
    m_number(debug_get_trace_count());
    while (1) { m_wait();  }
}
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.

Guardar un historial de posiciones: 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.
Ejemplo en pantalla: 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

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

Leer el contador de fotogramas de la biblioteca: 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.
Ejemplo en pantalla: 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

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

// Reset the library frame count, perform two counted waits, and display 2.
// Subsequent m_wait calls leave that library counter unchanged.
void main() {
    m_init();
    m_text(2,3,"SYSTEM");
    system_init(); system_wait_vblank(); system_wait_vblank();
    m_number(system_get_frame8());
    while (1) { m_wait();  }
}
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.

Seleccionar el ID de la escena actual: 001 es el ID actual devuelto por scene_get_current. El ejemplo no registra callbacks de escena ni dibujo de transiciones.
Ejemplo en pantalla: 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

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

Convertir coordenadas del mundo en coordenadas de pantalla: 052 menos 010 da el valor mostrado, 042. Es un cálculo de coordenadas; no desplaza el fondo.
Ejemplo en pantalla: 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

powershell
.\kitaqgb\kitaqgb.exe kitaqgb/lib/scroll.c kitaqgb/lib/camera.c kitaq-docs/samples/gb_camera.c -I kitaqgb/lib -I kitaq-docs/samples -o out/gb_camera.gb --profile=dev --rst-disable --stack-bank=fixed
c
// Convert world coordinates to screen coordinates.
// Expected: 042: world x=52 minus camera x=10
#include "gb_common.h"
#include "camera.h"
Camera8_8 cam;
// Set the camera X coordinate to 10 pixels in Q8.8 (10 * 256), then subtract
// it from world X = 52 to display screen X = 42.
void main() {
    m_init();
    m_text(2,3,"CAMERA");
    Camera_Init(&cam); Camera_Set(&cam,2560,0);
    m_number((u8)Camera_WorldToScreenX(&cam,52));
    while (1) { m_wait();  }
}
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.
Ejemplo en pantalla: el último byte, out[2], se muestra como 042. Los tres bytes descomprimidos deben contener 42.

Descargar código fuente / Estado de la verificación

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

Leer y escribir una casilla del tablero: 042 es el valor leído de nuevo. El programa no dibuja el tablero de 4×4.
Ejemplo en pantalla: 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

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

Avanzar una caja un paso de física: 042 es la coordenada X resultante, medida en píxeles enteros en este ejemplo. No se dibuja una caja ni una animación continua.
Ejemplo en pantalla: 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

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

Leer datos de ROM con un argumento de banco: El segundo byte de destino se muestra como 042. Este ejemplo lee ROM fija; no demuestra una transferencia entre distintos bancos conmutables.
Ejemplo en pantalla: 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

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

Cargar datos por ID de recurso: El segundo byte se muestra como 042. Esto demuestra la búsqueda y copia de recursos, no el renderizado de imágenes.
Ejemplo en pantalla: 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

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

Asignar un proyectil: 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.
Ejemplo en pantalla: 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

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

// Reset the bullet pool, spawn one bullet and display the active count.
// This numeric example does not install the background bullet compositor.
void main() {
    m_init();
    m_text(2,3,"DANMAKU");
    danmaku_reset(); danmaku_spawn(40,40,16,0);
    m_number(dm_count);
    while (1) { m_wait();  }
}
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.

Configurar una paleta de fondo de CGB: Ejecútelo en modo CGB para ver texto violeta y 042 sobre blanco. La salida monocroma de DMG no permite comprobar estos colores.
Ejemplo en pantalla: 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

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

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

Desplazar el fondo horizontalmente: 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.
Ejemplo en pantalla: 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

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

Encolar una actualización de tile: Busque un único 4 en la coordenada de tile del fondo (3,8). Es una actualización de tile, no un contador numérico.
Ejemplo en pantalla: 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

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

// Queue font tile 52 (the digit 4) at tile coordinate (3,8), then wait for
// VBlank and execute the queued transfer.
void main() {
    m_init();
    m_text(2,3,"VRAM QUEUE");
    vram_init();
    vram_queue_bg_tile(3,8,52); vram_flush();
    while (1) { m_wait();  }
}
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.

Mostrar un sprite mediante DMA de OAM: aparece una letra A inmóvil en la posición indicada para el sprite. En un juego, compruebe si falló la asignación antes de utilizar el ID devuelto.
Ejemplo en pantalla: 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

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

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

Generar un valor aleatorio reproducible: 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.
Ejemplo en pantalla: 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

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

// Seed the generator with 1234 and display one value in [0,10).
// Restarting with the same seed reproduces the sequence.
void main() {
    m_init();
    m_text(2,3,"RNG");
    rng_seed(1234); m_number(rng_range(10));
    while (1) { m_wait();  }
}
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.

Guardar una bandera de estado del juego: 001 significa que el indicador 12 es verdadero. El ejemplo opera sobre indicadores en RAM y no los conserva al apagar y encender.
Ejemplo en pantalla: 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

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

// Clear and set flag 12, then display its Boolean value. This does not write
// a save file or demonstrate persistence across power cycles.
void main() {
    m_init();
    m_text(2,3,"FLAGS");
    flag_clear(12); flag_set(12); m_number(flag_get(12));
    while (1) { m_wait();  }
}
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.

Avanzar un círculo un paso de física: 042 es la coordenada X entera resultante. El ejemplo no dibuja un contorno circular ni una animación de colisión.
Ejemplo en pantalla: 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

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

Procesar un efecto de sonido en cada fotograma: 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.
Ejemplo en pantalla: 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

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

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 --decompress
zx0_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

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

Parámetros

dst

Inicio de la RAM de destino escribible; no debe ser null. Expresa la capacidad en bytes, no en elementos del array.

capacity

Cantidad 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.

src

Inicio de los datos comprimidos legibles mediante el mapeo de banco actual. No debe ser null.

packed_size

Cantidad 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.

Formato ZX0 — Einar Saukas

Ejemplo de uso

c
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.

zx0_decompress: DMG — 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.
DMG — 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.
zx0_decompress: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/zx0.h:15

Notas de la declaración (original)
Return decoded bytes, or zero on error (possibly after partial writes).
Source and output must not overlap or cross their current CPU bank windows.
Capacity and packed_size are byte counts. No prefix/backward/v1 streams.

kitaqgb/lib/zx0.c:52

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

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

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

Parámetros

dst

Inicio de la RAM de destino escribible; no debe ser null. Expresa la capacidad en bytes, no en elementos del array.

capacity

Cantidad 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.

src

Inicio de los datos comprimidos legibles mediante el mapeo de banco actual. No debe ser null.

packed_size

Cantidad 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.

Formato ZX0 — Einar Saukas

Ejemplo de uso

c
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.

asset_decompress: DMG — 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.
DMG — 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.
asset_decompress: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/zx0.h:18

Notas de la declaración (original)
Decode a KQA1 raw/RLE/ZX0 asset produced with --format=auto.
Empty raw assets return zero with zx0_error==ZX0_OK.

kitaqgb/lib/zx0.c:95

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

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

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

Parámetros

vram_addr

Dirección inicial de VRAM, 0x8000..0x9FFF. La salida queda limitada por el final de VRAM en 0xA000. En CGB, selecciona VBK antes de llamar.

src

Inicio de los datos comprimidos legibles mediante el mapeo de banco actual. No debe ser null.

packed_size

Cantidad 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.

Formato ZX0 — Einar Saukas

Ejemplo de uso

c
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.

zx0_decompress_vram: DMG — 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.
DMG — 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.
zx0_decompress_vram: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/zx0.h:21

Notas de la declaración (original)
Decode directly into the selected GB VRAM bank ($8000..$9FFF), with LCD off.
Preserve LCDC, VBK and interrupt state. Output must fit before $A000.

kitaqgb/lib/zx0.c:132

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

asset.h — 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

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

Parámetros

asset_id

Índice del recurso, empezando por cero. Debe cumplir asset_id < count en la tabla registrada.

out_desc

Espacio 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

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

Este fragmento 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.

asset_get: DMG
DMG
asset_get: CGB
CGB

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/asset.h:24

Notas de la declaración (original)
Copy one descriptor from its ROM bank into caller storage. Return zero for a
null destination or an out-of-range ID; table validity is the caller's responsibility.

kitaqgb/lib/asset.c:18

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

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

c
u8 asset_get_bank(u8 asset_id);

Parámetros

asset_id

Índice del recurso, empezando por cero. Debe cumplir asset_id < count en 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

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

Este fragmento 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.

asset_get_bank: DMG
DMG
asset_get_bank: CGB
CGB

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/asset.h:32

Notas de la declaración (original)
Return the descriptor bank, or zero on lookup failure; zero can also be a valid bank.

kitaqgb/lib/asset.c:51

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

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

c
u16 asset_get_len(u8 asset_id);

Parámetros

asset_id

Índice del recurso, empezando por cero. Debe cumplir asset_id < count en 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

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

Este fragmento 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.

asset_get_len: DMG
DMG
asset_get_len: CGB
CGB

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/asset.h:37

Notas de la declaración (original)
Return the descriptor byte length, or zero if its ID cannot be resolved.

kitaqgb/lib/asset.c:68

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

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

c
const u8* asset_get_ptr(u8 asset_id);

Parámetros

asset_id

Índice del recurso, empezando por cero. Debe cumplir asset_id < count en 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

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

Este fragmento 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.

asset_get_ptr: DMG
DMG
asset_get_ptr: CGB
CGB

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/asset.h:35

Notas de la declaración (original)
Return the stored address without switching banks. Use the descriptor bank
with far-data helpers before dereferencing banked assets; failure returns null.

kitaqgb/lib/asset.c:60

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

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

c
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 < count en la tabla registrada.

dst

Destino 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_len

Má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

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

Este fragmento 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.

asset_load_raw: DMG
DMG
asset_load_raw: CGB
CGB

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/asset.h:27

Notas de la declaración (original)
Copy at most max_len bytes using the asset's bank. Success means the ID was
valid, even when the payload was truncated to fit the supplied limit.

kitaqgb/lib/asset.c:28

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

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

c
u8 asset_load_tiles(u8 asset_id, u16 vram_dst);

Parámetros

asset_id

Índice del recurso, empezando por cero. Debe cumplir asset_id < count en la tabla registrada.

vram_dst

Dirección de byte en VRAM, entre $8000 y $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

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

Este fragmento 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.

asset_load_tiles: DMG
DMG
asset_load_tiles: CGB
CGB

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/asset.h:30

Notas de la declaración (original)
Accept tile/raw descriptors and transfer their bytes to VRAM. This path passes
the descriptor pointer directly; callers must arrange the correct visible ROM bank.

kitaqgb/lib/asset.c:41

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

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

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

Parámetros

bank

Banco de ROM de la tabla de descriptores, expresado en 8 bits; no es el banco de los datos.

table

Puntero cercano a count entradas AssetDesc consecutivas. Los count * 6 bytes deben seguir siendo legibles en el banco de la tabla mientras esté registrada.

count

Nú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

c
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.

asset_set_table: DMG
DMG
asset_set_table: CGB
CGB

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/asset.h:21

Notas de la declaración (original)
Retain the descriptor table address, bank and count; the table is not copied.

kitaqgb/lib/asset.c:9

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

audio.h — 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

c
void Audio_CancelMasterVolumeFade();

Valor devuelto

Sin valor de retorno. Modifica registros de sonido o el estado del controlador.

Ejemplo de uso

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

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.

Audio_CancelMasterVolumeFade: DMG
DMG
Audio_CancelMasterVolumeFade: CGB
CGB
DMG — Audio grabado
CGB — Audio grabado

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/audio.h:125

Notas de la declaración (original)
Cancel further volume steps, retaining the current cached levels and hardware output.

kitaqgb/lib/audio.c:548

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

Configura barrido, ciclo de trabajo, envolvente y altura de CH1, y dispara el pulso.

Sintaxis

c
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_env

Codificació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.

duty2

Ciclo 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

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

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.

Audio_Ch1NoteOn: DMG
DMG
Audio_Ch1NoteOn: CGB
CGB
DMG — Audio grabado
CGB — Audio grabado

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/audio.h:151

Notas de la declaración (original)
Trigger CH1 with the cached sweep and the supplied raw envelope. Clamp the
note index; duty values 0, 1 and 3 select their encodings, and all others use 2.

kitaqgb/lib/audio.c:132

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

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

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

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

Configura ciclo de trabajo, envolvente y altura de CH2, y dispara el pulso.

Sintaxis

c
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_env

Codificació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.

duty2

Ciclo 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

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

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.

Audio_Ch2NoteOn: DMG
DMG
Audio_Ch2NoteOn: CGB
CGB
DMG — Audio grabado
CGB — Audio grabado

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/audio.h:154

Notas de la declaración (original)
Trigger CH2 with the supplied raw envelope and a clamped note index. Duty
values 0, 1 and 3 select their encodings; all other values use duty 2.

kitaqgb/lib/audio.c:666

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

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

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

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

Dispara la onda CH3 cargada con la altura y el nivel NR32 solicitados.

Sintaxis

c
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.

level

Codificació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

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

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.

Audio_Ch3NoteOn: DMG
DMG
Audio_Ch3NoteOn: CGB
CGB
DMG — Audio grabado
CGB — Audio grabado

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/audio.h:157

Notas de la declaración (original)
Clamp the note index, program the raw NR32 output level, and trigger CH3.
Wave RAM must already contain the desired waveform; this does not load one.

kitaqgb/lib/audio.c:115

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

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

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

Guarda los parámetros de ruido, configura los registros de envolvente y contador polinómico, y dispara CH4.

Sintaxis

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

Parámetros

param

NR43 bruto: bits 7..4 para desplazamiento del reloj, bit 3 para LFSR corto y bits 2..0 para código divisor.

vol_env

Codificació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

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

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.

Audio_Ch4NoteOn: DMG
DMG
Audio_Ch4NoteOn: CGB
CGB
DMG — Audio grabado
CGB — Audio grabado

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/audio.h:160

Notas de la declaración (original)
Cache the supplied noise parameter, program the raw envelope and polynomial
registers, then trigger CH4 with the length-enable bit clear.

kitaqgb/lib/audio.c:688

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

Mueve cada nivel de salida un paso hacia el objetivo al intervalo solicitado.

Sintaxis

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

Parámetros

left

Nivel maestro izquierdo, de 0 a 7; los valores mayores se limitan a 7. Cero no es silencio total.

right

Nivel maestro derecho, de 0 a 7; los valores mayores se limitan a 7.

step_frames

Nú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

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

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.

Audio_FadeToMasterVolume: DMG
DMG
Audio_FadeToMasterVolume: CGB
CGB
DMG — Audio grabado
CGB — Audio grabado

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/audio.h:123

Notas de la declaración (original)
Move left/right volume toward clamped targets at the requested Audio_Update
call interval. An interval of zero applies the levels immediately.

kitaqgb/lib/audio.c:528

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

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

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

Activa la APU, inicializa música, efectos, pausa, mezcla y onda, y deja todos los canales en silencio.

Sintaxis

c
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

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

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.

Audio_Init: DMG
DMG
Audio_Init: CGB
CGB
DMG — Audio grabado
CGB — Audio grabado

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/audio.h:76

Notas de la declaración (original)
Enable the APU and reset software streams, instruments, mix and fade state.
Load the initial triangle wave, then leave every channel silent. Call at startup
before concurrent interrupt-driven audio service can access these shared fields.

kitaqgb/lib/audio.c:864

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

    Audio_SetMasterVolume(AUDIO_VOLUME_MAX, AUDIO_VOLUME_MAX);
    Audio_SilenceAll();

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

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

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

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

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

Copia dieciséis bytes a la caché de onda personalizada y a la RAM de onda CH3.

Sintaxis

c
void __stackcall Audio_LoadCustomWave(const u8 *wave16);

Parámetros

wave16

Diecisé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

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

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.

Audio_LoadCustomWave: DMG
DMG
Audio_LoadCustomWave: CGB
CGB
DMG — Audio grabado
CGB — Audio grabado

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/audio.h:138

Notas de la declaración (original)
Copy 16 packed sample bytes into the persistent custom cache and wave RAM.
A null pointer is ignored; the source is needed only for this call.

kitaqgb/lib/audio.c:614

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

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

    Audio_ApplyWaveBytes(Audio_CustomWave);
}
Audio_LoadWave

Instala una onda predefinida o personalizada en caché en la RAM de onda CH3.

Sintaxis

c
void __stackcall Audio_LoadWave(u8 wave_id);

Parámetros

wave_id

ID 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

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

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.

Audio_LoadWave: DMG
DMG
Audio_LoadWave: CGB
CGB
DMG — Audio grabado
CGB — Audio grabado

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/audio.h:135

Notas de la declaración (original)
Install a named preset or the cached custom wave. Unknown IDs are ignored.
This does not update Audio_Ch3Wave or trigger a new note.

kitaqgb/lib/audio.c:631

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

Prepara la canción del banco indicado desde el principio y reinicia instrumentos, panorama y delay.

Sintaxis

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

Parámetros

bank

Banco ROM que contiene el flujo; debe coincidir con su ubicación.

song

Direcció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

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

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.

Audio_PlayMusic: DMG
DMG
Audio_PlayMusic: CGB
CGB
DMG — Audio grabado
CGB — Audio grabado

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/audio.h:83

Notas de la declaración (original)
Retain the bank and song pointer, reset legacy instruments/cursors, and arm
playback from the beginning. Supply a valid, persistent song; no bytes are copied
and null is not checked. Existing effect streams remain active.

kitaqgb/lib/audio.c:924

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

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

    Audio_PlayingMusic = 1;
}
Audio_PlaySFX

Captura el banco ROM actual y solicita un efecto que hereda el panorama base.

Sintaxis

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

Parámetros

sfx

Inicio del flujo de bytes del efecto. Consulta las notas para los formatos de pulsos y CH3.

priority

Prioridad 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

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

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.

Audio_PlaySFX: DMG
DMG
Audio_PlaySFX: CGB
CGB
DMG — Audio grabado
CGB — Audio grabado

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/audio.h:93

Notas de la declaración (original)
Capture the currently mapped ROM bank and start an effect with inherited pan.
Use the explicit-bank API when the pointer belongs to another bank.

kitaqgb/lib/audio.c:1085

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

Identifica el tipo de efecto en el banco de origen explícito y solicita reproducirlo con el panorama base.

Sintaxis

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

Parámetros

bank

Banco ROM que contiene el flujo; debe coincidir con su ubicación.

sfx

Inicio del flujo de bytes del efecto. Consulta las notas para los formatos de pulsos y CH3.

priority

Prioridad 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

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

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.

Audio_PlaySFXBanked: DMG
DMG
Audio_PlaySFXBanked: CGB
CGB
DMG — Audio grabado
CGB — Audio grabado

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/audio.h:95

Notas de la declaración (original)
Start a banked effect with the channel's base pan, subject to priority arbitration.

kitaqgb/lib/audio.c:1078

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

Captura el banco ROM actual y solicita un efecto con panorama específico.

Sintaxis

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

Parámetros

sfx

Inicio del flujo de bytes del efecto. Consulta las notas para los formatos de pulsos y CH3.

priority

Prioridad de 0 a 255. Gana el valor mayor; uno igual también puede sustituir al efecto actual.

pan

0=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

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

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.

Audio_PlaySFXPanned: DMG
DMG
Audio_PlaySFXPanned: CGB
CGB
DMG — Audio grabado
CGB — Audio grabado

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/audio.h:98

Notas de la declaración (original)
Capture the currently mapped ROM bank and request an effect with a pan override.
Use the explicit-bank API when the pointer belongs to another bank.

kitaqgb/lib/audio.c:1091

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

Adquiere una ranura de efecto de pulsos o CH3 con banco, prioridad y panorama explícitos.

Sintaxis

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

Parámetros

bank

Banco ROM que contiene el flujo; debe coincidir con su ubicación.

sfx

Inicio del flujo de bytes del efecto. Consulta las notas para los formatos de pulsos y CH3.

priority

Prioridad de 0 a 255. Gana el valor mayor; uno igual también puede sustituir al efecto actual.

pan

0=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

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

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.

Audio_PlaySFXPannedBanked: DMG
DMG
Audio_PlaySFXPannedBanked: CGB
CGB
DMG — Audio grabado
CGB — Audio grabado

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/audio.h:103

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

kitaqgb/lib/audio.c:1041

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

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

Guarda el índice de ciclo de trabajo de la próxima nota CH1.

Sintaxis

c
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

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

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.

Audio_SetCh1Duty: DMG
DMG
Audio_SetCh1Duty: CGB
CGB
DMG — Audio grabado
CGB — Audio grabado

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/audio.h:141

Notas de la declaración (original)
Cache the low two duty bits for the next CH1 note; do not change the active register.

kitaqgb/lib/audio.c:644

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

Guarda el índice de ciclo de trabajo de la próxima nota CH2.

Sintaxis

c
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

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

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.

Audio_SetCh2Duty: DMG
DMG
Audio_SetCh2Duty: CGB
CGB
DMG — Audio grabado
CGB — Audio grabado

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/audio.h:143

Notas de la declaración (original)
Cache the low two duty bits for the next CH2 note; do not change the active register.

kitaqgb/lib/audio.c:649

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

Guarda el nivel de salida NR32 de la próxima nota CH3.

Sintaxis

c
void __stackcall Audio_SetCh3Level(u8 level);

Parámetros

level

Codificació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

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

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.

Audio_SetCh3Level: DMG
DMG
Audio_SetCh3Level: CGB
CGB
DMG — Audio grabado
CGB — Audio grabado

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/audio.h:145

Notas de la declaración (original)
Cache the raw NR32 level encoding for the next CH3 note without writing hardware.

kitaqgb/lib/audio.c:654

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

Guarda los parámetros de ruido NR43 de la próxima nota CH4.

Sintaxis

c
void __stackcall Audio_SetCh4Param(u8 param);

Parámetros

param

NR43 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

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

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.

Audio_SetCh4Param: DMG
DMG
Audio_SetCh4Param: CGB
CGB
DMG — Audio grabado
CGB — Audio grabado

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/audio.h:147

Notas de la declaración (original)
Cache the raw noise polynomial encoding for the next CH4 note without writing hardware.

kitaqgb/lib/audio.c:659

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

Limita los niveles maestros izquierdo/derecho a 0..7, los escribe de inmediato y cancela el fundido activo.

Sintaxis

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

Parámetros

left

Nivel maestro izquierdo, de 0 a 7; los valores mayores se limitan a 7. Cero no es silencio total.

right

Nivel 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

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

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.

Audio_SetMasterVolume: DMG
DMG
Audio_SetMasterVolume: CGB
CGB
DMG — Audio grabado
CGB — Audio grabado

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/audio.h:120

Notas de la declaración (original)
Clamp both output levels to 0..7, cancel any fade, and write NR50 immediately.

kitaqgb/lib/audio.c:515

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

Controla si el decodificador musical normal escribe notas nuevas.

Sintaxis

c
void __stackcall Audio_SetMusicEnabled(u8 on);

Parámetros

on

Cero 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

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

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.

Audio_SetMusicEnabled: DMG
DMG
Audio_SetMusicEnabled: CGB
CGB
DMG — Audio grabado
CGB — Audio grabado

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/audio.h:114

Notas de la declaración (original)
Set the music-processing gate. This does not silence notes already playing
or stop the legacy stream cursor from consuming commands.

kitaqgb/lib/audio.c:498

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

Cambia el panorama base de una voz física y vuelve a aplicar los panoramas específicos de los efectos activos.

Sintaxis

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

Parámetros

ch

ID de canal: 0=CH1, 1=CH2, 2=CH3, 3=CH4. Las API directas y los flujos musicales usan los mismos ID.

pan

0=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

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

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.

Audio_SetPan: DMG
DMG
Audio_SetPan: CGB
CGB
DMG — Audio grabado
CGB — Audio grabado

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/audio.h:129

Notas de la declaración (original)
Update the base pan for a physical channel and reapply active effect overrides.
Unknown channel IDs select CH4; unsupported pan values mute the selected channel.

kitaqgb/lib/audio.c:558

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

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

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

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

    Audio_UpdateNR51();
}
Audio_SetPanPacked

Extrae cuatro panoramas base de un byte y actualiza NR51 una vez.

Sintaxis

c
void __stackcall Audio_SetPanPacked(u8 packed);

Parámetros

packed

Dos 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

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

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.

Audio_SetPanPacked: DMG
DMG
Audio_SetPanPacked: CGB
CGB
DMG — Audio grabado
CGB — Audio grabado

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/audio.h:132

Notas de la declaración (original)
Two bits per channel (CH1 in bits 0-1): center, left, right, mute.
Applies all four positions with one NR51 update for sequencer automation.

kitaqgb/lib/audio.c:589

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

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

c
void __stackcall Audio_SetPaused(u8 on);

Parámetros

on

Cero 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

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

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.

Audio_SetPaused: DMG
DMG
Audio_SetPaused: CGB
CGB
DMG — Audio grabado
CGB — Audio grabado

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/audio.h:90

Notas de la declaración (original)
On pause entry, silence hardware while retaining cursors. On resume, retrigger
eligible legacy CH1, CH2 and CH4 notes; CH3 is not retriggered here. Updates still
advance master fades while paused, and effect playback resumes on a later update.

kitaqgb/lib/audio.c:1010

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

Permite o bloquea las escrituras de notas de efectos; deshabilitar también libera sus ranuras.

Sintaxis

c
void __stackcall Audio_SetSfxEnabled(u8 on);

Parámetros

on

Cero 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

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

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.

Audio_SetSfxEnabled: DMG
DMG
Audio_SetSfxEnabled: CGB
CGB
DMG — Audio grabado
CGB — Audio grabado

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/audio.h:117

Notas de la declaración (original)
Enable effect note writes, or disable them and release both effect streams.
Disabling follows Audio_StopSfx recovery rules rather than silencing all channels.

kitaqgb/lib/audio.c:505

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

Detiene una voz física y elimina su nota musical de la máscara de reanudación.

Sintaxis

c
void __stackcall Audio_StopChannel(u8 ch);

Parámetros

ch

ID 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

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

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.

Audio_StopChannel: DMG
DMG
Audio_StopChannel: CGB
CGB
DMG — Audio grabado
CGB — Audio grabado

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/audio.h:110

Notas de la declaración (original)
Stop a physical channel and clear its legacy resume bit. CH1 also clears the
pulse effect stream; CH3 clears the wave effect stream. This is the legacy
channel API and does not clear a VBlank driver's independently latched notes.

kitaqgb/lib/audio.c:981

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

Borra la reproducción de canción y su máscara de reanudación, y silencia inmediatamente las cuatro voces.

Sintaxis

c
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

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

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.

Audio_StopMusic: DMG
DMG
Audio_StopMusic: CGB
CGB
DMG — Audio grabado
CGB — Audio grabado

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/audio.h:86

Notas de la declaración (original)
Stop legacy music and clear its resume mask, then silence all physical channels.
Effect pointers remain active and may produce sound on a later update.

kitaqgb/lib/audio.c:952

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

Borra ambos flujos de efectos y sus panoramas específicos, y libera los canales prestados.

Sintaxis

c
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

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

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.

Audio_StopSfx: DMG
DMG
Audio_StopSfx: CGB
CGB
DMG — Audio grabado
CGB — Audio grabado

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/audio.h:106

Notas de la declaración (original)
Clear both effect streams and their pan overrides. When not paused, release
borrowed channels through the configured legacy or VBlank recovery path.

kitaqgb/lib/audio.c:960

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

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

Avanza una vez el fundido de volumen; salvo en pausa, procesa después efectos y música, en ese orden.

Sintaxis

c
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

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

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.

Audio_Update: DMG
DMG
Audio_Update: CGB
CGB
DMG — Audio grabado
CGB — Audio grabado

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/audio.h:79

Notas de la declaración (original)
Advance the master fade first. Unless paused, service both effect streams
then the optional legacy music decoder. Call once per frame for frame-based timing.

kitaqgb/lib/audio.c:849

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

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

audio_vblank.h — 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

c
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

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

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.

AudioVBlank_DisableIrq: DMG
DMG
AudioVBlank_DisableIrq: CGB
CGB
DMG — Audio grabado
CGB — Audio grabado

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/audio_vblank.h:118

Notas de la declaración (original)
Clear only the VBlank bit in IE. Other interrupt sources and current sound remain unchanged.

kitaqgb/lib/audio_vblank_control.inc:129

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

Activa el bit VBlank de IE y ejecuta EI para habilitar globalmente las interrupciones de CPU.

Sintaxis

c
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

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

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.

AudioVBlank_EnableIrq: DMG
DMG
AudioVBlank_EnableIrq: CGB
CGB
DMG — Audio grabado
CGB — Audio grabado

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/audio_vblank.h:116

Notas de la declaración (original)
Enable the VBlank source in IE and execute EI, enabling CPU interrupts globally.
Install the correct interrupt vector and initialize driver state first.

kitaqgb/lib/audio_vblank_control.inc:122

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

Inicializa el estado musical VBlank, la cola, los instrumentos y el hook. No inicializa la APU ni bloquea interrupciones.

Sintaxis

c
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

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

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.

AudioVBlank_Init: DMG
DMG
AudioVBlank_Init: CGB
CGB
DMG — Audio grabado
CGB — Audio grabado

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/audio_vblank.h:85

Notas de la declaración (original)
Reset software playback state, queue counters, instruments and the frame hook.
Call before enabling this ISR; the routine does not mask interrupts or
initialize the APU registers and cannot synchronize with an active handler.

kitaqgb/lib/audio_vblank_control.inc:6

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

Reinicia la canción seleccionada desde el principio y sale del modo cola. Una canción NULL detiene la reproducción.

Sintaxis

c
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

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

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.

AudioVBlank_Play: DMG
DMG
AudioVBlank_Play: CGB
CGB
DMG — Audio grabado
CGB — Audio grabado

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/audio_vblank.h:103

Notas de la declaración (original)
Restart the selected direct song at its beginning, leaving queue mode.
A null song invokes Stop; this does not enable the music or IRQ gates.

kitaqgb/lib/audio_vblank_control.inc:58

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

Selecciona una canción de lectura directa y prepara su reproducción desde el principio.

Sintaxis

c
void __stackcall AudioVBlank_PlayMusic(u8 *song);

Parámetros

song

Direcció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

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

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.

AudioVBlank_PlayMusic: DMG
DMG
AudioVBlank_PlayMusic: CGB
CGB
DMG — Audio grabado
CGB — Audio grabado

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/audio_vblank.h:105

Notas de la declaración (original)
Select and restart a directly addressed song. This is not the banked WRAM-queue path.

kitaqgb/lib/audio_vblank_control.inc:73

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

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

c
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

c
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.

AudioVBlank_QueuePlay: DMG
DMG
AudioVBlank_QueuePlay: CGB
CGB
DMG — Audio grabado
CGB — Audio grabado

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/audio_vblank.h:96

Notas de la declaración (original)
Start/resume queued playback; return 1 on success, 0 for an empty/nonqueue mode.
Does not enable the interrupt, music gate or clear pause. Queue before starting.

kitaqgb/lib/audio_vblank_queue.inc:112

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

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

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

Parámetros

records

Matriz 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.

count

Nú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

c
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.

AudioVBlank_QueueRefill: DMG
DMG
AudioVBlank_QueueRefill: CGB
CGB
DMG — Audio grabado
CGB — Audio grabado

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/audio_vblank.h:93

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

kitaqgb/lib/audio_vblank_queue.inc:93

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

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

c
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

c
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.

AudioVBlank_QueueReset: DMG
DMG
AudioVBlank_QueueReset: CGB
CGB
DMG — Audio grabado
CGB — Audio grabado

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/audio_vblank.h:87

Notas de la declaración (original)
Stop music and select an empty WRAM queue; preserve IE, IME and enable/pause gates.

kitaqgb/lib/audio_vblank_queue.inc:76

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

Establece la solicitud 2 de solo liberación de pulso si no hay nada pendiente, conservando una solicitud de recuperación 1 existente.

Sintaxis

c
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

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

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.

AudioVBlank_RequestRestoreCh1: DMG
DMG
AudioVBlank_RequestRestoreCh1: CGB
CGB
DMG — Audio grabado
CGB — Audio grabado

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/audio_vblank.h:129

Notas de la declaración (original)
Request deferred pulse-channel release only when no recovery is pending.
Preserve value 1, which records a music event suppressed while an effect owned it.

kitaqgb/lib/audio_vblank.c:908

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

Establece la solicitud 2 de solo liberación de onda si no hay nada pendiente, conservando una solicitud de recuperación 1 existente.

Sintaxis

c
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

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

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.

AudioVBlank_RequestRestoreCh3: DMG
DMG
AudioVBlank_RequestRestoreCh3: CGB
CGB
DMG — Audio grabado
CGB — Audio grabado

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/audio_vblank.h:132

Notas de la declaración (original)
Request a deferred wave-channel release only if no recovery is pending.
Preserve value 1, which records a new music event suppressed by the effect.

kitaqgb/lib/audio_vblank.c:916

c
void AudioVBlank_RequestRestoreCh3()
{
    if (AudioVBlank_RestoreCh3Pending == 0)
        AudioVBlank_RestoreCh3Pending = 2;
}
AudioVBlank_RestoreCh1

Restaura una nota musical retenida en la voz de pulsos prestada al efecto (CH1 o CH2), o la libera en silencio.

Sintaxis

c
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

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

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.

AudioVBlank_RestoreCh1: DMG
DMG
AudioVBlank_RestoreCh1: CGB
CGB
DMG — Audio grabado
CGB — Audio grabado

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/audio_vblank.h:122

Notas de la declaración (original)
Recover the borrowed pulse channel (CH1 or CH2) from its latched music event.
Pending value 2, disabled music, or a non-note latch silences it instead.
The caller must first establish that the effect has released the channel.

kitaqgb/lib/audio_vblank.c:769

c
void AudioVBlank_RestoreCh1()
{
    __asm {
        LD_A_MEM Audio_EffectUsesCh2
        OR_A
        JR_NZ audiovb_restore_ch2
        LD_A_MEM AudioVBlank_RestoreCh1Pending
        CP_IMM 2
        JR_Z audiovb_restore_ch1_off
        LD_A_MEM AudioVBlank_MusicPlaying
        OR_A
        JR_Z audiovb_restore_ch1_off
        LD_A_MEM AudioVBlank_MusicEnabled
        OR_A
        JR_Z audiovb_restore_ch1_off
        LD_A_MEM Audio_MusicEnabled
        OR_A
        JR_Z audiovb_restore_ch1_off
        LD_A_MEM AudioVBlank_Ch1LatchedNote
        CP_IMM 0x44
        JR_NC audiovb_restore_ch1_off
        LD_C_A
        LD_A_MEM AudioVBlank_Ch1Sweep
        LDH_MEM_A 0x10
        LD_A_MEM AudioVBlank_Ch1Duty
        LDH_MEM_A 0x11
        LD_A_MEM AudioVBlank_Ch1Envelope
        LDH_MEM_A 0x12
        LD_A_C
        LD_E_A
        LD_D_IMM 0
        LD_HL_IMM AudioVBlank_FreqLo
        ADD_HL_DE
        LD_A_HL
        LDH_MEM_A 0x13
        LD_HL_IMM AudioVBlank_FreqHi
        ADD_HL_DE
        LD_A_HL
        OR_IMM 0x80
        LDH_MEM_A 0x14
        JR audiovb_restore_ch1_done
audiovb_restore_ch1_off:
        XOR_A
        LDH_MEM_A 0x12
audiovb_restore_ch1_done:
        JR audiovb_restore_square_done

audiovb_restore_ch2:
        LD_A_MEM AudioVBlank_RestoreCh1Pending
        CP_IMM 2
        JR_Z audiovb_restore_ch2_off
        LD_A_MEM AudioVBlank_MusicPlaying
        OR_A
        JR_Z audiovb_restore_ch2_off
        LD_A_MEM AudioVBlank_MusicEnabled
        OR_A
        JR_Z audiovb_restore_ch2_off
        LD_A_MEM Audio_MusicEnabled
        OR_A
        JR_Z audiovb_restore_ch2_off
        LD_A_MEM AudioVBlank_Ch2LatchedNote
        CP_IMM 0x44
        JR_NC audiovb_restore_ch2_off
        LD_C_A
        LD_A_MEM AudioVBlank_Ch2Duty
        LDH_MEM_A 0x16
        LD_A_MEM AudioVBlank_Ch2Envelope
        LDH_MEM_A 0x17
        LD_A_C
        LD_E_A
        LD_D_IMM 0
        LD_HL_IMM AudioVBlank_FreqLo
        ADD_HL_DE
        LD_A_HL
        LDH_MEM_A 0x18
        LD_HL_IMM AudioVBlank_FreqHi
        ADD_HL_DE
        LD_A_HL
        OR_IMM 0x80
        LDH_MEM_A 0x19
        JR audiovb_restore_square_done
audiovb_restore_ch2_off:
        XOR_A
        LDH_MEM_A 0x17
audiovb_restore_square_done:
    }
}
AudioVBlank_RestoreCh3

Restaura la nota retenida de CH3 tras liberar el efecto, o deshabilita su DAC.

Sintaxis

c
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

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

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.

AudioVBlank_RestoreCh3: DMG
DMG
AudioVBlank_RestoreCh3: CGB
CGB
DMG — Audio grabado
CGB — Audio grabado

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/audio_vblank.h:126

Notas de la declaración (original)
Recover a latched wave-channel music event after effect release, or disable
the DAC for a release-only request, disabled music, or a non-note latch.
The caller owns effect arbitration and clearing the pending flag.

kitaqgb/lib/audio_vblank.c:860

c
void AudioVBlank_RestoreCh3()
{
    __asm {
        LD_A_MEM AudioVBlank_RestoreCh3Pending
        CP_IMM 2
        JR_Z audiovb_restore_ch3_off
        LD_A_MEM AudioVBlank_MusicPlaying
        OR_A
        JR_Z audiovb_restore_ch3_off
        LD_A_MEM AudioVBlank_MusicEnabled
        OR_A
        JR_Z audiovb_restore_ch3_off
        LD_A_MEM Audio_MusicEnabled
        OR_A
        JR_Z audiovb_restore_ch3_off
        LD_A_MEM AudioVBlank_Ch3LatchedNote
        CP_IMM 0x44
        JR_NC audiovb_restore_ch3_off
        LD_C_A
        LD_A_IMM 0x80
        LDH_MEM_A 0x1A
        XOR_A
        LDH_MEM_A 0x1B
        LD_A_MEM AudioVBlank_Ch3Level
        LDH_MEM_A 0x1C
        LD_A_C
        LD_E_A
        LD_D_IMM 0
        LD_HL_IMM AudioVBlank_FreqLo
        ADD_HL_DE
        LD_A_HL
        LDH_MEM_A 0x1D
        LD_HL_IMM AudioVBlank_FreqHi
        ADD_HL_DE
        LD_A_HL
        OR_IMM 0x80
        LDH_MEM_A 0x1E
        JR audiovb_restore_ch3_done
audiovb_restore_ch3_off:
        XOR_A
        LDH_MEM_A 0x1A
audiovb_restore_ch3_done:
    }
}
AudioVBlank_SetEnabled

Permite o bloquea la música VBlank y borra las solicitudes de recuperación al deshabilitarla. El sonido actual e IRQ no cambian.

Sintaxis

c
void __stackcall AudioVBlank_SetEnabled(u8 on);

Parámetros

on

Cero 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

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

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.

AudioVBlank_SetEnabled: DMG
DMG
AudioVBlank_SetEnabled: CGB
CGB
DMG — Audio grabado
CGB — Audio grabado

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/audio_vblank.h:113

Notas de la declaración (original)
Gate music processing and clear pending CH1/CH3 recovery on disable.
No audio register is written here: disabling does not itself silence a note
already playing or disable the VBlank interrupt.

kitaqgb/lib/audio_vblank_control.inc:109

c
void __stackcall AudioVBlank_SetEnabled(u8 on)
{
    if (on != 0) AudioVBlank_MusicEnabled = 1;
    else {
        AudioVBlank_MusicEnabled = 0;
        // Do not carry a stale SFX-recovery request into a later song.
        AudioVBlank_RestoreCh1Pending = 0;
        AudioVBlank_RestoreCh3Pending = 0;
    }
}
AudioVBlank_SetMusic

Selecciona una canción de lectura directa y reinicia sus cursores sin cambiar la bandera de reproducción.

Sintaxis

c
void __stackcall AudioVBlank_SetMusic(u8 *song);

Parámetros

song

Direcció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

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

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.

AudioVBlank_SetMusic: DMG
DMG
AudioVBlank_SetMusic: CGB
CGB
DMG — Audio grabado
CGB — Audio grabado

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/audio_vblank.h:100

Notas de la declaración (original)
Select a directly addressed song and reset its cursors, leaving the playing
flag unchanged. Song storage must remain accessible to the fixed-bank ISR;
coordinate this multi-field update with interrupt execution.

kitaqgb/lib/audio_vblank_control.inc:46

c
void __stackcall AudioVBlank_SetMusic(u8 *song)
{
    AudioVBlank_MusicStart = song;
    AudioVBlank_MusicPointer = song;
    AudioVBlank_MusicLoopPoint = song;
    AudioVBlank_MusicDelay = 0;
    AudioVBlank_Step = 0;
    AudioVBlank_QueueMode = 0;
}
AudioVBlank_Stop

Borra los estados de reproducción, delay y recuperación, y silencia inmediatamente pulsos, ruido y onda. IRQ sigue habilitado.

Sintaxis

c
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

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

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.

AudioVBlank_Stop: DMG
DMG
AudioVBlank_Stop: CGB
CGB
DMG — Audio grabado
CGB — Audio grabado

Programa de ejemplo completo

Comando de compilación

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

kitaqgb/lib/audio_vblank.h:109

Notas de la declaración (original)
Stop software playback and silence pulse/noise envelopes and the wave DAC.
Song pointers and the IRQ enable remain unchanged; the routine writes the
physical channels directly, so coordinate ownership with sound effects.

kitaqgb/lib/audio_vblank_control.inc:82

c
void AudioVBlank_Stop()
{
    AudioVBlank_MusicPlaying = 0;
    AudioVBlank_MusicDelay = 0;
    AudioVBlank_Step = 0;
    AudioVBlank_Ch2Note = AUDIO_VBLANK_REST;
    AudioVBlank_Ch1Note = AUDIO_VBLANK_REST;
    AudioVBlank_Ch3Note = AUDIO_VBLANK_REST;
    AudioVBlank_Ch2LatchedNote = AUDIO_VBLANK_STOP;
    AudioVBlank_Ch1LatchedNote = AUDIO_VBLANK_STOP;
    AudioVBlank_Ch3LatchedNote = AUDIO_VBLANK_STOP;
    AudioVBlank_RestoreCh1Pending = 0;
    AudioVBlank_RestoreCh3Pending = 0;
    AudioVBlank_Ch4Param = AUDIO_VBLANK_REST;
    __asm {
        XOR_A
        LDH_MEM_A 0x12
        LDH_MEM_A 0x17
        LDH_MEM_A 0x1C
        LDH_MEM_A 0x1A
        LDH_MEM_A 0x21
    }
}

bank.h — 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

c
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

c
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.

bank_get_current: DMG
DMG
bank_get_current: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\banked_data_calls.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\banked_data_calls.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/bank.h:21

Notas de la declaración (original)
Return the last bank recorded by bank_switch; this does not read cartridge hardware.

kitaqgb/lib/bank.c:15

c
u8 bank_get_current()
{
    return kq_bank_current;
}
bank_switch

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

c
void bank_switch(u8 bank);

Parámetros

bank

Nú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

c
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.

bank_switch: DMG
DMG
bank_switch: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\banked_data_calls.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\banked_data_calls.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/bank.h:19

Notas de la declaración (original)
Update both the library bank record and the compiler shadow used by far
reads and calls. Invoke this permanent bank change from fixed-bank code.

kitaqgb/lib/bank.c:8

c
void bank_switch(u8 bank)
{
    kq_bank_current = bank;
    __bankswitch(bank);
}
far_call

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

c
void far_call(u8 bank, const void* func);

Parámetros

bank

Nú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.

func

Direcció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

c
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.

far_call: DMG
DMG
far_call: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\banked_data_calls.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\banked_data_calls.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/bank.h:30

Notas de la declaración (original)
Invoke a no-argument callback in its ROM bank, then restore the caller
bank. The pointer must identify executable code; no arguments are forwarded.

kitaqgb/lib/bank.c:40

c
void far_call(u8 bank, const void* func)
{
    __farcall_ptr(bank, func);
}
far_data_read

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

c
void far_data_read(u8 bank, const void* addr, void* dst, u16 len);

Parámetros

bank

Nú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.

addr

Puntero cercano a bytes legibles del banco de ROM seleccionado. No incluye el número de banco.

dst

Destino 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.

len

Cantidad 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

c
far_data_read(3,payload,buffer,4); // Copy into four writable RAM bytes.
bank_expect(buffer[0]==0xD3 && buffer[1]==0x7A && buffer[2]==0x5C && buffer[3]==0x96,7);

Este fragmento 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.

far_data_read: DMG
DMG
far_data_read: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\banked_data_calls.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\banked_data_calls.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/bank.h:27

Notas de la declaración (original)
Copy len bytes from banked ROM into caller-owned writable storage.

kitaqgb/lib/bank.c:33

c
void far_data_read(u8 bank, const void* addr, void* dst, u16 len)
{
    __farmemcpy(dst, bank, addr, len);
}
far_data_read16

Lee dos bytes consecutivos mediante __farpeek16 y forma una palabra little-endian. El primer byte ocupa los ocho bits bajos.

Sintaxis

c
u16 far_data_read16(u8 bank, const void* addr);

Parámetros

bank

Nú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.

addr

Puntero 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

c
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.

far_data_read16: DMG
DMG
far_data_read16: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\banked_data_calls.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\banked_data_calls.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/bank.h:25

Notas de la declaración (original)
Read a 16-bit value from the supplied bank and address through the far-read intrinsic.

kitaqgb/lib/bank.c:27

c
u16 far_data_read16(u8 bank, const void* addr)
{
    return __farpeek16(bank, addr);
}
far_data_read8

Lee un byte del banco ROM y la dirección indicados mediante __farpeek8; restaura el banco anterior y devuelve el valor.

Sintaxis

c
u8 far_data_read8(u8 bank, const void* addr);

Parámetros

bank

Nú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.

addr

Puntero 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

c
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.

far_data_read8: DMG
DMG
far_data_read8: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\banked_data_calls.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\banked_data_calls.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/bank.h:23

Notas de la declaración (original)
Read one byte through the compiler intrinsic that accepts an explicit ROM bank.

kitaqgb/lib/bank.c:21

c
u8 far_data_read8(u8 bank, const void* addr)
{
    return __farpeek8(bank, addr);
}
farptr_make

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

c
void farptr_make(BankPtr* out, u8 bank, const u8* ptr);

Parámetros

out

Puntero a espacio escribible para un BankPtr de tres bytes. Si out es nulo, no se escribe nada.

bank

Nú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.

ptr

Direcció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

c
farptr_make(&pointer,3,payload+1); // Store a bank and address; do not read ROM.
bank_expect(pointer.bank==3 && pointer.ptr==payload+1,8);
farptr_make(0,1,home1); // A null destination is ignored.

Este fragmento 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.

farptr_make: DMG
DMG
farptr_make: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\banked_data_calls.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\banked_data_calls.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/bank.h:32

Notas de la declaración (original)
Store a bank/address pair without accessing ROM; a null output pointer is ignored.

kitaqgb/lib/bank.c:46

c
void farptr_make(BankPtr* out, u8 bank, const u8* ptr)
{
    if (out == 0) return;
    out->bank = bank;
    out->ptr = ptr;
}
farptr_read

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

c
void farptr_read(BankPtr ptr, void* dst, u16 len);

Parámetros

ptr

Un valor BankPtr con los campos bank y ptr. Pasa el descriptor, no su dirección. El descriptor del llamador no se modifica.

dst

Destino 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.

len

Cantidad 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

c
farptr_read(pointer,buffer,3);
bank_expect(buffer[0]==0x7A && buffer[1]==0x5C && buffer[2]==0x96,11);
bank_expect(pointer.bank==3 && pointer.ptr==payload+1,23);

Este fragmento 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.

farptr_read: DMG
DMG
farptr_read: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\banked_data_calls.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\banked_data_calls.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/bank.h:38

Notas de la declaración (original)
Copy len bytes from a bank-qualified pointer; dst must have room for the full copy.

kitaqgb/lib/bank.c:66

c
void farptr_read(BankPtr ptr, void* dst, u16 len)
{
    __farmemcpy(dst, ptr.bank, ptr.ptr, len);
}
farptr_read16

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

c
u16 farptr_read16(BankPtr ptr);

Parámetros

ptr

Un 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

c
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.

farptr_read16: DMG
DMG
farptr_read16: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\banked_data_calls.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\banked_data_calls.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/bank.h:36

Notas de la declaración (original)
Read a 16-bit value using both components of the bank-qualified pointer.

kitaqgb/lib/bank.c:60

c
u16 farptr_read16(BankPtr ptr)
{
    return __farpeek16(ptr.bank, ptr.ptr);
}
farptr_read8

Lee un byte usando ambos campos de un BankPtr pasado por valor. El descriptor aporta el banco que un puntero cercano no contiene.

Sintaxis

c
u8 farptr_read8(BankPtr ptr);

Parámetros

ptr

Un 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

c
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.

farptr_read8: DMG
DMG
farptr_read8: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\banked_data_calls.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\banked_data_calls.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/bank.h:34

Notas de la declaración (original)
Read one byte using both components of the bank-qualified pointer.

kitaqgb/lib/bank.c:54

c
u8 farptr_read8(BankPtr ptr)
{
    return __farpeek8(ptr.bank, ptr.ptr);
}

camera.h — 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

c
void Camera_Add(Camera8_8* cam, s16 dfx, s16 dfy);

Parámetros

cam

Puntero válido a un Camera8_8 inicializado y propiedad del código que llama.

dfx

Desplazamiento Q8.8 con signo; 256 equivale a un píxel.

dfy

Desplazamiento 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

c
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).

Camera_Add: DMG
DMG
Camera_Add: CGB
CGB

Programa de ejemplo completo

Comando de compilación

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

Ejemplo de uso

c
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.

Camera_Add: DMG
DMG
Camera_Add: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/camera.h:34

Notas de la declaración (original)
Add Q8.8 deltas and clamp afterward. Keep the intermediate sums within s16;
clamping cannot repair arithmetic that already overflowed.

kitaqgb/lib/camera.c:79

c
void Camera_Add(Camera8_8* cam, s16 dfx, s16 dfy)
{
    cam->fx += dfx;
    cam->fy += dfy;
    Camera_ApplyBounds(cam);
}
camera_apply

Aplica de inmediato la posición actual de la cámara compartida al desplazamiento del fondo.

Sintaxis

c
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

c
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).

camera_apply: DMG
DMG
camera_apply: CGB
CGB

Programa de ejemplo completo

Comando de compilación

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

Ejemplo de uso

c
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.

camera_apply: DMG
DMG
camera_apply: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/camera.h:64

Notas de la declaración (original)
Write the shared camera's current integer position to background scroll registers.

kitaqgb/lib/camera.c:179

c
void camera_apply()
{
    Camera_ApplyBg(&camera_default);
}
Camera_ApplyBg

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

c
void Camera_ApplyBg(const Camera8_8* cam);

Parámetros

cam

Puntero válido a un Camera8_8 inicializado 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

c
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).

Camera_ApplyBg: DMG
DMG
Camera_ApplyBg: CGB
CGB

Programa de ejemplo completo

Comando de compilación

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

Ejemplo de uso

c
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.

Camera_ApplyBg: DMG
DMG
Camera_ApplyBg: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/camera.h:40

Notas de la declaración (original)
Discard fractional bits and write the low eight integer bits to background scroll registers.

kitaqgb/lib/camera.c:109

c
void Camera_ApplyBg(const Camera8_8* cam)
{
    __scroll_bg_set((u8)(cam->fx >> 8), (u8)(cam->fy >> 8));
}
Camera_ApplyBgBuffered

Redondea hacia abajo la posición de la cámara a píxeles enteros y la deja pendiente como desplazamiento del fondo.

Sintaxis

c
void Camera_ApplyBgBuffered(const Camera8_8* cam);

Parámetros

cam

Puntero válido a un Camera8_8 inicializado 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

c
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).

Camera_ApplyBgBuffered: DMG
DMG
Camera_ApplyBgBuffered: CGB
CGB

Programa de ejemplo completo

Comando de compilación

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

Ejemplo de uso

c
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.

Camera_ApplyBgBuffered: DMG
DMG
Camera_ApplyBgBuffered: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/camera.h:42

Notas de la declaración (original)
Convert the Q8.8 position to byte scroll values and stage them for a later flush.

kitaqgb/lib/camera.c:115

c
void Camera_ApplyBgBuffered(const Camera8_8* cam)
{
    __scroll_bg_set_buffered((u8)(cam->fx >> 8), (u8)(cam->fy >> 8));
}
camera_clamp

Aplica a la cámara compartida los límites obtenidos al restar la pantalla del mundo.

Sintaxis

c
void camera_clamp(u16 world_w_px, u16 world_h_px, u8 screen_w_px, u8 screen_h_px);

Parámetros

world_w_px

Dimensión del mundo en píxeles enteros; la diferencia positiva respecto a la pantalla debe quedar entre 0 y 127.

world_h_px

Dimensión del mundo en píxeles enteros; la diferencia positiva respecto a la pantalla debe quedar entre 0 y 127.

screen_w_px

Tamañ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_px

Tamañ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

c
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).

camera_clamp: DMG
DMG
camera_clamp: CGB
CGB

Programa de ejemplo completo

Comando de compilación

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

Ejemplo de uso

c
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.

camera_clamp: DMG
DMG
camera_clamp: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/camera.h:62

Notas de la declaración (original)
Derive and apply world/screen bounds to the shared convenience camera.

kitaqgb/lib/camera.c:173

c
void camera_clamp(u16 world_w_px, u16 world_h_px, u8 screen_w_px, u8 screen_h_px)
{
    Camera_ClampToSize(&camera_default, world_w_px, world_h_px, screen_w_px, screen_h_px);
}
Camera_ClampToSize

Resta las dimensiones de la pantalla a las del mundo y establece los límites no negativos resultantes para la cámara.

Sintaxis

c
void Camera_ClampToSize(Camera8_8* cam, u16 world_w_px, u16 world_h_px, u8 screen_w_px, u8 screen_h_px);

Parámetros

cam

Puntero válido a un Camera8_8 inicializado y propiedad del código que llama.

world_w_px

Dimensión del mundo en píxeles enteros; la diferencia positiva respecto a la pantalla debe quedar entre 0 y 127.

world_h_px

Dimensión del mundo en píxeles enteros; la diferencia positiva respecto a la pantalla debe quedar entre 0 y 127.

screen_w_px

Tamañ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_px

Tamañ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

c
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).

Camera_ClampToSize: DMG
DMG
Camera_ClampToSize: CGB
CGB

Programa de ejemplo completo

Comando de compilación

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

Ejemplo de uso

c
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.

Camera_ClampToSize: DMG
DMG
Camera_ClampToSize: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/camera.h:46

Notas de la declaración (original)
Derive nonnegative camera extents from world minus screen size, then convert
them to Q8.8 bounds. Extents must fit signed Q8.8; the u16 input type does
not imply support for arbitrary large worlds.

kitaqgb/lib/camera.c:123

c
void Camera_ClampToSize(Camera8_8* cam, u16 world_w_px, u16 world_h_px, u8 screen_w_px, u8 screen_h_px)
{
    s16 max_x = 0;
    s16 max_y = 0;

    if (world_w_px > screen_w_px) max_x = (s16)((u16)(world_w_px - screen_w_px) << 8);
    if (world_h_px > screen_h_px) max_y = (s16)((u16)(world_h_px - screen_h_px) << 8);
    Camera_SetBounds(cam, (s16)0, (s16)0, max_x, max_y);
}
Camera_ClearBounds

Desactiva los límites sin cambiar la posición, el objetivo ni los límites guardados.

Sintaxis

c
void Camera_ClearBounds(Camera8_8* cam);

Parámetros

cam

Puntero válido a un Camera8_8 inicializado 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

c
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).

Camera_ClearBounds: DMG
DMG
Camera_ClearBounds: CGB
CGB

Programa de ejemplo completo

Comando de compilación

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

Ejemplo de uso

c
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.

Camera_ClearBounds: DMG
DMG
Camera_ClearBounds: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/camera.h:31

Notas de la declaración (original)
Disable clamping while retaining the stored bounds and current position.

kitaqgb/lib/camera.c:72

c
void Camera_ClearBounds(Camera8_8* cam)
{
    cam->use_bounds = 0;
}
Camera_ClearTarget

Desactiva el seguimiento conservando la posición actual y el objetivo guardado.

Sintaxis

c
void Camera_ClearTarget(Camera8_8* cam);

Parámetros

cam

Puntero válido a un Camera8_8 inicializado 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

c
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).

Camera_ClearTarget: DMG
DMG
Camera_ClearTarget: CGB
CGB

Programa de ejemplo completo

Comando de compilación

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

Ejemplo de uso

c
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.

Camera_ClearTarget: DMG
DMG
Camera_ClearTarget: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/camera.h:27

Notas de la declaración (original)
Disable target following without moving the camera or erasing the stored target.

kitaqgb/lib/camera.c:55

c
void Camera_ClearTarget(Camera8_8* cam)
{
    cam->use_target = 0;
}
camera_follow_xy

Mueve de inmediato la cámara compartida para que un punto del mundo aparezca en el punto de anclaje indicado en pantalla.

Sintaxis

c
void camera_follow_xy(s16 x, s16 y, u8 screen_cx, u8 screen_cy);

Parámetros

x

Coordenada X del mundo en píxeles enteros; el resultado y la diferencia intermedia deben caber en s16.

y

Coordenada Y del mundo en píxeles enteros; el resultado y la diferencia intermedia deben caber en s16.

screen_cx

Coordenada del punto de anclaje en pantalla en píxeles enteros, de 0 a 255.

screen_cy

Coordenada 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

c
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).

camera_follow_xy: DMG
DMG
camera_follow_xy: CGB
CGB

Programa de ejemplo completo

Comando de compilación

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

Ejemplo de uso

c
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.

camera_follow_xy: DMG
DMG
camera_follow_xy: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/camera.h:60

Notas de la declaración (original)
Position the shared camera so the world point appears at the requested screen
anchor. This is an immediate move, not the smoothed target-following path.

kitaqgb/lib/camera.c:165

c
void camera_follow_xy(s16 x, s16 y, u8 screen_cx, u8 screen_cy)
{
    s16 cx = (s16)(x - screen_cx);
    s16 cy = (s16)(y - screen_cy);
    Camera_Set(&camera_default, (s16)(cx << 8), (s16)(cy << 8));
}
Camera_Init

Pone a cero la posición, el objetivo y los límites, y desactiva el seguimiento y la limitación al rango.

Sintaxis

c
void Camera_Init(Camera8_8* cam);

Parámetros

cam

Camera8_8 accesible 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

c
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).

Camera_Init: DMG
DMG
Camera_Init: CGB
CGB

Programa de ejemplo completo

Comando de compilación

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

Ejemplo de uso

c
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.

Camera_Init: DMG
DMG
Camera_Init: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/camera.h:21

Notas de la declaración (original)
Zero all position/target/bound fields and disable targeting and bounds.

kitaqgb/lib/camera.c:24

c
void Camera_Init(Camera8_8* cam)
{
    cam->fx = 0;
    cam->fy = 0;
    cam->target_fx = 0;
    cam->target_fy = 0;
    cam->min_fx = 0;
    cam->min_fy = 0;
    cam->max_fx = 0;
    cam->max_fy = 0;
    cam->use_target = 0;
    cam->use_bounds = 0;
}
Camera_ScreenToWorldX

Suma la parte entera de X de la cámara a la X entera de pantalla para obtener la X del mundo.

Sintaxis

c
s16 Camera_ScreenToWorldX(const Camera8_8* cam, s16 screen_x);

Parámetros

cam

Puntero válido a un Camera8_8 inicializado y propiedad del código que llama.

screen_x

Coordenada 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

c
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).

Camera_ScreenToWorldX: DMG
DMG
Camera_ScreenToWorldX: CGB
CGB

Programa de ejemplo completo

Comando de compilación

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

Ejemplo de uso

c
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.

Camera_ScreenToWorldX: DMG
DMG
Camera_ScreenToWorldX: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/camera.h:52

Notas de la declaración (original)
Convert integer-pixel screen X back to world X using the camera's integer component.

kitaqgb/lib/camera.c:146

c
s16 Camera_ScreenToWorldX(const Camera8_8* cam, s16 screen_x)
{
    return (s16)(screen_x + (cam->fx >> 8));
}
Camera_ScreenToWorldY

Suma la parte entera de Y de la cámara a la Y entera de pantalla para obtener la Y del mundo.

Sintaxis

c
s16 Camera_ScreenToWorldY(const Camera8_8* cam, s16 screen_y);

Parámetros

cam

Puntero válido a un Camera8_8 inicializado y propiedad del código que llama.

screen_y

Coordenada 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

c
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).

Camera_ScreenToWorldY: DMG
DMG
Camera_ScreenToWorldY: CGB
CGB

Programa de ejemplo completo

Comando de compilación

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

Ejemplo de uso

c
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.

Camera_ScreenToWorldY: DMG
DMG
Camera_ScreenToWorldY: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/camera.h:54

Notas de la declaración (original)
Convert integer-pixel screen Y back to world Y using the camera's integer component.

kitaqgb/lib/camera.c:152

c
s16 Camera_ScreenToWorldY(const Camera8_8* cam, s16 screen_y)
{
    return (s16)(screen_y + (cam->fy >> 8));
}
Camera_Set

Sustituye la posición actual de la cámara y la ajusta inmediatamente a los límites que estén activados.

Sintaxis

c
void Camera_Set(Camera8_8* cam, s16 fx, s16 fy);

Parámetros

cam

Puntero válido a un Camera8_8 inicializado y propiedad del código que llama.

fx

Coordenada X. Coordenada Q8.8 con signo: 256 equivale a un píxel; el rango va de −128 a 127+255/256 píxeles.

fy

Coordenada 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

c
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).

Camera_Set: DMG
DMG
Camera_Set: CGB
CGB

Programa de ejemplo completo

Comando de compilación

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

Ejemplo de uso

c
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.

Camera_Set: DMG
DMG
Camera_Set: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/camera.h:23

Notas de la declaración (original)
Replace the current Q8.8 position and immediately apply enabled bounds.

kitaqgb/lib/camera.c:39

c
void Camera_Set(Camera8_8* cam, s16 fx, s16 fy)
{
    cam->fx = fx;
    cam->fy = fy;
    Camera_ApplyBounds(cam);
}
camera_set

Mueve la cámara compartida con coordenadas de píxeles enteros y aplica sus límites activados.

Sintaxis

c
void camera_set(s16 x, s16 y);

Parámetros

x

Coordenada X del mundo en píxeles enteros; el resultado y la diferencia intermedia deben caber en s16.

y

Coordenada 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

c
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).

camera_set: DMG
DMG
camera_set: CGB
CGB

Programa de ejemplo completo

Comando de compilación

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

Ejemplo de uso

c
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.

camera_set: DMG
DMG
camera_set: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/camera.h:57

Notas de la declaración (original)
Set the shared camera from integer pixels, converting to the representable Q8.8 range.

kitaqgb/lib/camera.c:158

c
void camera_set(s16 x, s16 y)
{
    Camera_Set(&camera_default, (s16)(x << 8), (s16)(y << 8));
}
Camera_SetBounds

Establece las coordenadas mínimas y máximas, activa los límites y ajusta de inmediato la posición actual.

Sintaxis

c
void Camera_SetBounds(Camera8_8* cam, s16 min_fx, s16 min_fy, s16 max_fx, s16 max_fy);

Parámetros

cam

Puntero válido a un Camera8_8 inicializado y propiedad del código que llama.

min_fx

Coordenada 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_fy

Coordenada 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_fx

Coordenada 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_fy

Coordenada 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

c
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).

Camera_SetBounds: DMG
DMG
Camera_SetBounds: CGB
CGB

Programa de ejemplo completo

Comando de compilación

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

Ejemplo de uso

c
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.

Camera_SetBounds: DMG
DMG
Camera_SetBounds: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/camera.h:29

Notas de la declaración (original)
Install ordered Q8.8 bounds, enable them and clamp the current position immediately.

kitaqgb/lib/camera.c:61

c
void Camera_SetBounds(Camera8_8* cam, s16 min_fx, s16 min_fy, s16 max_fx, s16 max_fy)
{
    cam->min_fx = min_fx;
    cam->min_fy = min_fy;
    cam->max_fx = max_fx;
    cam->max_fy = max_fy;
    cam->use_bounds = 1;
    Camera_ApplyBounds(cam);
}
Camera_SetTarget

Guarda un objetivo y activa el seguimiento sin mover la posición actual.

Sintaxis

c
void Camera_SetTarget(Camera8_8* cam, s16 fx, s16 fy);

Parámetros

cam

Puntero válido a un Camera8_8 inicializado y propiedad del código que llama.

fx

Coordenada X. Coordenada Q8.8 con signo: 256 equivale a un píxel; el rango va de −128 a 127+255/256 píxeles.

fy

Coordenada 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

c
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).

Camera_SetTarget: DMG
DMG
Camera_SetTarget: CGB
CGB

Programa de ejemplo completo

Comando de compilación

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

Ejemplo de uso

c
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.

Camera_SetTarget: DMG
DMG
Camera_SetTarget: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/camera.h:25

Notas de la declaración (original)
Store a Q8.8 target and enable subsequent step-toward-target updates.

kitaqgb/lib/camera.c:47

c
void Camera_SetTarget(Camera8_8* cam, s16 fx, s16 fy)
{
    cam->target_fx = fx;
    cam->target_fy = fy;
    cam->use_target = 1;
}
Camera_StepTowardTarget

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

c
void Camera_StepTowardTarget(Camera8_8* cam, u8 shift);

Parámetros

cam

Puntero válido a un Camera8_8 inicializado y propiedad del código que llama.

shift

Exponente 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

c
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).

Camera_StepTowardTarget: DMG
DMG
Camera_StepTowardTarget: CGB
CGB

Programa de ejemplo completo

Comando de compilación

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

Ejemplo de uso

c
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.

Camera_StepTowardTarget: DMG
DMG
Camera_StepTowardTarget: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/camera.h:38

Notas de la declaración (original)
Move by the signed target delta shifted by 0..7 bits, then apply bounds.
Quantization can make a small delta produce no movement; only exact equality
clears targeting, and a target outside the bounds may remain active indefinitely.

kitaqgb/lib/camera.c:89

c
void Camera_StepTowardTarget(Camera8_8* cam, u8 shift)
{
    s16 dx;
    s16 dy;

    if (cam->use_target == 0) return;
    if (shift > 7) shift = 7;

    // Keep target-minus-position differences within s16 as well as the individual positions.
    dx = cam->target_fx - cam->fx;
    dy = cam->target_fy - cam->fy;

    if (dx != 0) cam->fx += (dx >> shift);
    if (dy != 0) cam->fy += (dy >> shift);

    if (cam->fx == cam->target_fx && cam->fy == cam->target_fy) cam->use_target = 0;
    Camera_ApplyBounds(cam);
}
camera_world_to_screen_x

Convierte la X del mundo en X de pantalla restando la parte entera de X de la cámara compartida.

Sintaxis

c
s16 camera_world_to_screen_x(s16 world_x);

Parámetros

world_x

Coordenada 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

c
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).

camera_world_to_screen_x: DMG
DMG
camera_world_to_screen_x: CGB
CGB

Programa de ejemplo completo

Comando de compilación

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

Ejemplo de uso

c
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.

camera_world_to_screen_x: DMG
DMG
camera_world_to_screen_x: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/camera.h:66

Notas de la declaración (original)
Convert integer-pixel world X using the shared convenience camera.

kitaqgb/lib/camera.c:185

c
s16 camera_world_to_screen_x(s16 world_x)
{
    return Camera_WorldToScreenX(&camera_default, world_x);
}
camera_world_to_screen_y

Convierte la Y del mundo en Y de pantalla restando la parte entera de Y de la cámara compartida.

Sintaxis

c
s16 camera_world_to_screen_y(s16 world_y);

Parámetros

world_y

Coordenada 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

c
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).

camera_world_to_screen_y: DMG
DMG
camera_world_to_screen_y: CGB
CGB

Programa de ejemplo completo

Comando de compilación

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

Ejemplo de uso

c
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.

camera_world_to_screen_y: DMG
DMG
camera_world_to_screen_y: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/camera.h:68

Notas de la declaración (original)
Convert integer-pixel world Y using the shared convenience camera.

kitaqgb/lib/camera.c:191

c
s16 camera_world_to_screen_y(s16 world_y)
{
    return Camera_WorldToScreenY(&camera_default, world_y);
}
Camera_WorldToScreenX

Resta la parte entera de X de la cámara a una coordenada X entera del mundo para obtener la X en pantalla.

Sintaxis

c
s16 Camera_WorldToScreenX(const Camera8_8* cam, s16 world_x);

Parámetros

cam

Puntero válido a un Camera8_8 inicializado y propiedad del código que llama.

world_x

Coordenada 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

c
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).

Camera_WorldToScreenX: DMG
DMG
Camera_WorldToScreenX: CGB
CGB

Programa de ejemplo completo

Comando de compilación

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

Ejemplo de uso

c
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.

Camera_WorldToScreenX: DMG
DMG
Camera_WorldToScreenX: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/camera.h:48

Notas de la declaración (original)
Convert an integer-pixel world X by subtracting the camera's integer X component.

kitaqgb/lib/camera.c:134

c
s16 Camera_WorldToScreenX(const Camera8_8* cam, s16 world_x)
{
    return (s16)(world_x - (cam->fx >> 8));
}
Camera_WorldToScreenY

Resta la parte entera de Y de la cámara a una coordenada Y entera del mundo para obtener la Y en pantalla.

Sintaxis

c
s16 Camera_WorldToScreenY(const Camera8_8* cam, s16 world_y);

Parámetros

cam

Puntero válido a un Camera8_8 inicializado y propiedad del código que llama.

world_y

Coordenada 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

c
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).

Camera_WorldToScreenY: DMG
DMG
Camera_WorldToScreenY: CGB
CGB

Programa de ejemplo completo

Comando de compilación

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

Ejemplo de uso

c
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.

Camera_WorldToScreenY: DMG
DMG
Camera_WorldToScreenY: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/camera.h:50

Notas de la declaración (original)
Convert an integer-pixel world Y by subtracting the camera's integer Y component.

kitaqgb/lib/camera.c:140

c
s16 Camera_WorldToScreenY(const Camera8_8* cam, s16 world_y)
{
    return (s16)(world_y - (cam->fy >> 8));
}

cgb_palette.h — 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

c
void cgb_bg_color(u8 palette_index, u8 color_index, u16 rgb15);

Parámetros

palette_index

Nú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).

rgb15

Color 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. Usa CGB_RGB15 o cgb_rgb15 para 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

c
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.

cgb_bg_color: --cgb=cgb / DMG
--cgb=cgb / DMG
cgb_bg_color: --cgb=cgb / CGB
--cgb=cgb / CGB
cgb_bg_color: --cgb=dmg / DMG
--cgb=dmg / DMG
cgb_bg_color: --cgb=cgb_only / CGB
--cgb=cgb_only / CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/cgb_palette.h:22

Notas de la declaración (original)
Set one background color through the indexed palette wrapper.

kitaqgb/lib/cgb_palette.c:110

c
void cgb_bg_color(u8 palette_index, u8 color_index, u16 rgb15)
{
    cgb__write_color_bg_raw(cgb__palette_color_slot(palette_index, color_index), rgb15);
}
cgb_bg_colors

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

c
void cgb_bg_colors(u8 palette_index, u8 start_color_index, const u16* colors, u8 color_count);

Parámetros

palette_index

Nú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).

colors

const 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_count

Cantidad de palabras de color, no de bytes, como u8 (0–255). Cero no hace nada. Se limita a 32 - 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

c
cgb_bg_colors(3,2,tail_green,2); // Two color words; color 3 becomes green.
expect_color(0,14,0); expect_color(0,15,992);

Este fragmento 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.

cgb_bg_colors: --cgb=cgb / DMG
--cgb=cgb / DMG
cgb_bg_colors: --cgb=cgb / CGB
--cgb=cgb / CGB
cgb_bg_colors: --cgb=dmg / DMG
--cgb=dmg / DMG
cgb_bg_colors: --cgb=cgb_only / CGB
--cgb=cgb_only / CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/cgb_palette.h:32

Notas de la declaración (original)
Write background colors starting at the indexed slot. The range may cross
palette boundaries and is clamped only at the end of all 32 slots.

kitaqgb/lib/cgb_palette.c:135

c
void cgb_bg_colors(u8 palette_index, u8 start_color_index, const u16* colors, u8 color_count)
{
    cgb__write_colors_bg_raw(cgb__palette_color_slot(palette_index, start_color_index), colors, color_count);
}
cgb_bg_colors_raw

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

c
void cgb_bg_colors_raw(u8 start_color_slot, const u16* colors, u8 color_count);

Parámetros

start_color_slot

Posición absoluta de color, 0–31; se normaliza con & 31 antes de limitar la longitud. Posición = paleta × 4 + color. No es un desplazamiento en bytes.

colors

const 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_count

Cantidad de palabras de color, no de bytes, como u8 (0–255). Cero no hace nada. Se limita a 32 - 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

c
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.

cgb_bg_colors_raw: --cgb=cgb / DMG
--cgb=cgb / DMG
cgb_bg_colors_raw: --cgb=cgb / CGB
--cgb=cgb / CGB
cgb_bg_colors_raw: --cgb=dmg / DMG
--cgb=dmg / DMG
cgb_bg_colors_raw: --cgb=cgb_only / CGB
--cgb=cgb_only / CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/cgb_palette.h:42

Notas de la declaración (original)
Expose sequential background writes using an absolute color-slot index.

kitaqgb/lib/cgb_palette.c:159

c
void cgb_bg_colors_raw(u8 start_color_slot, const u16* colors, u8 color_count)
{
    cgb__write_colors_bg_raw(start_color_slot, colors, color_count);
}
cgb_bg_palette

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

c
void cgb_bg_palette(u8 palette_index, const u16* colors);

Parámetros

palette_index

Número de paleta, 0–7; solo usa los tres bits bajos (& 7).

colors

const 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

c
cgb_bg_palette(4,red_palette); // Exactly four color words for BG palette 4.
expect_color(0,16,32767); expect_color(0,19,31);

Este fragmento 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.

cgb_bg_palette: --cgb=cgb / DMG
--cgb=cgb / DMG
cgb_bg_palette: --cgb=cgb / CGB
--cgb=cgb / CGB
cgb_bg_palette: --cgb=dmg / DMG
--cgb=dmg / DMG
cgb_bg_palette: --cgb=cgb_only / CGB
--cgb=cgb_only / CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/cgb_palette.h:37

Notas de la declaración (original)
Write four consecutive colors for one background palette.

kitaqgb/lib/cgb_palette.c:147

c
void cgb_bg_palette(u8 palette_index, const u16* colors)
{
    cgb_bg_colors(palette_index, 0, colors, 4);
}
cgb_bg_rgb

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

c
void cgb_bg_rgb(u8 palette_index, u8 color_index, u8 r5, u8 g5, u8 b5);

Parámetros

palette_index

Nú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, b5

Componentes 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

c
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.

cgb_bg_rgb: --cgb=cgb / DMG
--cgb=cgb / DMG
cgb_bg_rgb: --cgb=cgb / CGB
--cgb=cgb / CGB
cgb_bg_rgb: --cgb=dmg / DMG
--cgb=dmg / DMG
cgb_bg_rgb: --cgb=cgb_only / CGB
--cgb=cgb_only / CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/cgb_palette.h:26

Notas de la declaración (original)
Pack component values and write one background color.

kitaqgb/lib/cgb_palette.c:122

c
void cgb_bg_rgb(u8 palette_index, u8 color_index, u8 r5, u8 g5, u8 b5)
{
    cgb_bg_color(palette_index, color_index, cgb_rgb15(r5, g5, b5));
}
cgb_obj_color

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

c
void cgb_obj_color(u8 palette_index, u8 color_index, u16 rgb15);

Parámetros

palette_index

Nú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).

rgb15

Color 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. Usa CGB_RGB15 o cgb_rgb15 para 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

c
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.

cgb_obj_color: --cgb=cgb / DMG
--cgb=cgb / DMG
cgb_obj_color: --cgb=cgb / CGB
--cgb=cgb / CGB
cgb_obj_color: --cgb=dmg / DMG
--cgb=dmg / DMG
cgb_obj_color: --cgb=cgb_only / CGB
--cgb=cgb_only / CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/cgb_palette.h:24

Notas de la declaración (original)
Set one object color through the indexed palette wrapper.

kitaqgb/lib/cgb_palette.c:116

c
void cgb_obj_color(u8 palette_index, u8 color_index, u16 rgb15)
{
    cgb__write_color_obj_raw(cgb__palette_color_slot(palette_index, color_index), rgb15);
}
cgb_obj_colors

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

c
void cgb_obj_colors(u8 palette_index, u8 start_color_index, const u16* colors, u8 color_count);

Parámetros

palette_index

Nú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).

colors

const 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_count

Cantidad de palabras de color, no de bytes, como u8 (0–255). Cero no hace nada. Se limita a 32 - 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

c
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.

cgb_obj_colors: --cgb=cgb / DMG
--cgb=cgb / DMG
cgb_obj_colors: --cgb=cgb / CGB
--cgb=cgb / CGB
cgb_obj_colors: --cgb=dmg / DMG
--cgb=dmg / DMG
cgb_obj_colors: --cgb=cgb_only / CGB
--cgb=cgb_only / CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/cgb_palette.h:34

Notas de la declaración (original)
Write object colors from the indexed slot, potentially crossing into later palettes.

kitaqgb/lib/cgb_palette.c:141

c
void cgb_obj_colors(u8 palette_index, u8 start_color_index, const u16* colors, u8 color_count)
{
    cgb__write_colors_obj_raw(cgb__palette_color_slot(palette_index, start_color_index), colors, color_count);
}
cgb_obj_colors_raw

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

c
void cgb_obj_colors_raw(u8 start_color_slot, const u16* colors, u8 color_count);

Parámetros

start_color_slot

Posición absoluta de color, 0–31; se normaliza con & 31 antes de limitar la longitud. Posición = paleta × 4 + color. No es un desplazamiento en bytes.

colors

const 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_count

Cantidad de palabras de color, no de bytes, como u8 (0–255). Cero no hace nada. Se limita a 32 - 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

c
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.

cgb_obj_colors_raw: --cgb=cgb / DMG
--cgb=cgb / DMG
cgb_obj_colors_raw: --cgb=cgb / CGB
--cgb=cgb / CGB
cgb_obj_colors_raw: --cgb=dmg / DMG
--cgb=dmg / DMG
cgb_obj_colors_raw: --cgb=cgb_only / CGB
--cgb=cgb_only / CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/cgb_palette.h:44

Notas de la declaración (original)
Expose sequential object writes using an absolute color-slot index.

kitaqgb/lib/cgb_palette.c:165

c
void cgb_obj_colors_raw(u8 start_color_slot, const u16* colors, u8 color_count)
{
    cgb__write_colors_obj_raw(start_color_slot, colors, color_count);
}
cgb_obj_palette

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

c
void cgb_obj_palette(u8 palette_index, const u16* colors);

Parámetros

palette_index

Número de paleta, 0–7; solo usa los tres bits bajos (& 7).

colors

const 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

c
cgb_obj_palette(4,blue_palette); // Exactly four words; OBJ color zero is transparent on screen.
expect_color(1,16,32767); expect_color(1,19,31744);

Este fragmento 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.

cgb_obj_palette: --cgb=cgb / DMG
--cgb=cgb / DMG
cgb_obj_palette: --cgb=cgb / CGB
--cgb=cgb / CGB
cgb_obj_palette: --cgb=dmg / DMG
--cgb=dmg / DMG
cgb_obj_palette: --cgb=cgb_only / CGB
--cgb=cgb_only / CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/cgb_palette.h:39

Notas de la declaración (original)
Write four consecutive colors for one object palette.

kitaqgb/lib/cgb_palette.c:153

c
void cgb_obj_palette(u8 palette_index, const u16* colors)
{
    cgb_obj_colors(palette_index, 0, colors, 4);
}
cgb_obj_rgb

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

c
void cgb_obj_rgb(u8 palette_index, u8 color_index, u8 r5, u8 g5, u8 b5);

Parámetros

palette_index

Nú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, b5

Componentes 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

c
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.

cgb_obj_rgb: --cgb=cgb / DMG
--cgb=cgb / DMG
cgb_obj_rgb: --cgb=cgb / CGB
--cgb=cgb / CGB
cgb_obj_rgb: --cgb=dmg / DMG
--cgb=dmg / DMG
cgb_obj_rgb: --cgb=cgb_only / CGB
--cgb=cgb_only / CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/cgb_palette.h:28

Notas de la declaración (original)
Pack component values and write one object color.

kitaqgb/lib/cgb_palette.c:128

c
void cgb_obj_rgb(u8 palette_index, u8 color_index, u8 r5, u8 g5, u8 b5)
{
    cgb_obj_color(palette_index, color_index, cgb_rgb15(r5, g5, b5));
}
CGB_RGB15

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

c
#define CGB_RGB15(r5, g5, b5) ((u16)((u16)((r5) & 31) | ((u16)((g5) & 31) << 5) | ((u16)((b5) & 31) << 10)))

Parámetros

r5, g5, b5

Componentes 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

c
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.

CGB_RGB15: --cgb=cgb / DMG
--cgb=cgb / DMG
CGB_RGB15: --cgb=cgb / CGB
--cgb=cgb / CGB
CGB_RGB15: --cgb=dmg / DMG
--cgb=dmg / DMG
CGB_RGB15: --cgb=cgb_only / CGB
--cgb=cgb_only / CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementació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

c
u16 cgb_rgb15(u8 r5, u8 g5, u8 b5);

Parámetros

r5, g5, b5

Componentes 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

c
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.

cgb_rgb15: --cgb=cgb / DMG
--cgb=cgb / DMG
cgb_rgb15: --cgb=cgb / CGB
--cgb=cgb / CGB
cgb_rgb15: --cgb=dmg / DMG
--cgb=dmg / DMG
cgb_rgb15: --cgb=cgb_only / CGB
--cgb=cgb_only / CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/cgb_palette.h:19

Notas de la declaración (original)
Pack the red, green and blue components using the public RGB15 macro.

kitaqgb/lib/cgb_palette.c:104

c
u16 cgb_rgb15(u8 r5, u8 g5, u8 b5)
{
    return CGB_RGB15(r5, g5, b5);
}

cgb_tile.h — 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

c
#define KQ_CGB_ATTR(palette, bank, xflip, yflip, priority) ((u8)(((palette) & KQ_CGB_ATTR_PAL_MASK) | ((bank) ? KQ_CGB_ATTR_BANK1 : 0) | ((xflip) ? KQ_CGB_ATTR_XFLIP : 0) | ((yflip) ? KQ_CGB_ATTR_YFLIP : 0) | ((priority) ? KQ_CGB_ATTR_PRIORITY : 0)))

Parámetros

palette

Número de paleta, 0–7; solo usa los tres bits bajos (& 7).

bank, xflip, yflip, priority

Cero 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

c
attr=KQ_CGB_ATTR(10,0,2,2,0); // Palette 2, bank 0, both reflections: 0x62.
if (attr!=98 || KQ_CGB_ATTR(10,2,3,4,5)!=234) failures++;
cell(10,11,1,attr);

Este fragmento 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.

KQ_CGB_ATTR: --cgb=cgb / DMG
--cgb=cgb / DMG
KQ_CGB_ATTR: --cgb=cgb / CGB
--cgb=cgb / CGB
KQ_CGB_ATTR: --cgb=dmg / DMG
--cgb=dmg / DMG
KQ_CGB_ATTR: --cgb=cgb_only / CGB
--cgb=cgb_only / CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementació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

c
#define KQ_CGB_ATTR_BANK(bank) ((u8)((bank) ? KQ_CGB_ATTR_BANK1 : 0))

Parámetros

bank

Cero 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

c
attr=(u8)(2|KQ_CGB_ATTR_BANK(enabled)); // Any nonzero value selects tile-data bank 1.
if (attr!=10) failures++;
cell(4,11,1,attr); // Blue hollow square, unlike the bank-0 triangle.

Este fragmento 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.

KQ_CGB_ATTR_BANK: --cgb=cgb / DMG
--cgb=cgb / DMG
KQ_CGB_ATTR_BANK: --cgb=cgb / CGB
--cgb=cgb / CGB
KQ_CGB_ATTR_BANK: --cgb=dmg / DMG
--cgb=dmg / DMG
KQ_CGB_ATTR_BANK: --cgb=cgb_only / CGB
--cgb=cgb_only / CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementació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

c
#define KQ_CGB_ATTR_PAL(n) ((u8)((n) & KQ_CGB_ATTR_PAL_MASK))

Parámetros

n

Nú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

c
attr=KQ_CGB_ATTR_PAL(9); // 9 & 7 = palette 1, red in this BG example.
if (attr!=1) failures++;
cell(2,11,1,attr);

Este fragmento 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.

KQ_CGB_ATTR_PAL: --cgb=cgb / DMG
--cgb=cgb / DMG
KQ_CGB_ATTR_PAL: --cgb=cgb / CGB
--cgb=cgb / CGB
KQ_CGB_ATTR_PAL: --cgb=dmg / DMG
--cgb=dmg / DMG
KQ_CGB_ATTR_PAL: --cgb=cgb_only / CGB
--cgb=cgb_only / CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementació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

c
#define KQ_CGB_ATTR_PRIORITY_IF(enabled) ((u8)((enabled) ? KQ_CGB_ATTR_PRIORITY : 0))

Parámetros

enabled

Cero 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

c
attr=(u8)(3|KQ_CGB_ATTR_PRIORITY_IF(enabled)); // Keep nonzero BG pixels in front of sprites.
if (attr!=131) failures++;
cell(12,11,1,attr);
sprite(7,96,88,2,3); // Red full tile behind the green priority triangle.

Este fragmento 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.

KQ_CGB_ATTR_PRIORITY_IF: --cgb=cgb / DMG
--cgb=cgb / DMG
KQ_CGB_ATTR_PRIORITY_IF: --cgb=cgb / CGB
--cgb=cgb / CGB
KQ_CGB_ATTR_PRIORITY_IF: --cgb=dmg / DMG
--cgb=dmg / DMG
KQ_CGB_ATTR_PRIORITY_IF: --cgb=cgb_only / CGB
--cgb=cgb_only / CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementació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

c
#define KQ_CGB_ATTR_XFLIP_IF(enabled) ((u8)((enabled) ? KQ_CGB_ATTR_XFLIP : 0))

Parámetros

enabled

Cero 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

c
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.

KQ_CGB_ATTR_XFLIP_IF: --cgb=cgb / DMG
--cgb=cgb / DMG
KQ_CGB_ATTR_XFLIP_IF: --cgb=cgb / CGB
--cgb=cgb / CGB
KQ_CGB_ATTR_XFLIP_IF: --cgb=dmg / DMG
--cgb=dmg / DMG
KQ_CGB_ATTR_XFLIP_IF: --cgb=cgb_only / CGB
--cgb=cgb_only / CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementació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

c
#define KQ_CGB_ATTR_YFLIP_IF(enabled) ((u8)((enabled) ? KQ_CGB_ATTR_YFLIP : 0))

Parámetros

enabled

Cero 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

c
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.

KQ_CGB_ATTR_YFLIP_IF: --cgb=cgb / DMG
--cgb=cgb / DMG
KQ_CGB_ATTR_YFLIP_IF: --cgb=cgb / CGB
--cgb=cgb / CGB
KQ_CGB_ATTR_YFLIP_IF: --cgb=dmg / DMG
--cgb=dmg / DMG
KQ_CGB_ATTR_YFLIP_IF: --cgb=cgb_only / CGB
--cgb=cgb_only / CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\cgb_palette_attributes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\cgb_palette_attributes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementació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

c
s16 chain_wrap_delta(u8 target, u8 current, u16 size);

Parámetros

target

Coordenada objetivo, de 0 a size−1.

current

Coordenada actual, de 0 a size−1.

size

Longitud 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

c
distances[0]=chain_wrap_delta(1,159,160);   // +2: cross the right edge.
    distances[1]=chain_wrap_delta(159,1,160);   // -2: cross the left edge.
    distances[2]=chain_wrap_delta(80,0,160);    // +80: keep the direct sign.
    distances[3]=chain_wrap_delta(0,80,160);    // -80: same-length routes.
    distances[4]=chain_wrap_delta(0,0,1);       // 0: the only valid position.

Este fragmento 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.

chain_wrap_delta: DMG
DMG
chain_wrap_delta: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\chain_wrap.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\chain_wrap.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/chain.h:35

Notas de la declaración (original)
Return target minus current along the shortest wrapped route.
Supply size 1..256 and coordinates in 0..size-1; inputs are not normalized.
Exactly half a field retains the direct displacement sign.

kitaqgb/lib/chain.c:98

c
s16 chain_wrap_delta(u8 target, u8 current, u16 size)
{
    s16 delta;
    s16 half;
    delta = (s16)((s16)target - (s16)current);
    half = (s16)(size >> 1);
    // At exactly half a field, retain the sign of the direct displacement.
    if (delta > half) delta = (s16)(delta - (s16)size);
    else if (delta < (s16)(0 - half)) delta = (s16)(delta + (s16)size);
    return delta;
}
chain_body_init

Asocia tres arrays de articulaciones del código que llama y pone el número a cero, sin reservar memoria.

Sintaxis

c
u8 chain_body_init(ChainBody* body, u8* x, u8* y, u8* heading, u8 capacity, u16 width, u16 height);

Parámetros

body

ChainBody de destino; se ignora null. Salvo al inicializar, pasa un estado inicializado.

x

Array de coordenadas X de las articulaciones.

y

Array de coordenadas Y de las articulaciones.

heading

Array de direcciones de las articulaciones.

capacity

Longitud reservada del array, de 1 a 255.

width

Ancho del campo con bordes conectados, de 1 a 256.

height

Alto 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

c
chain_body_init(&body,joint_x,joint_y,joint_heading,8,160,144);
    // Eight caller-owned slots, including the head, on a wrapped 160x144 field.

Este fragmento 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.

chain_body_init: DMG — 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.
DMG — 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.
chain_body_init: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\chain_body.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\chain_body.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/chain.h:53

Notas de la declaración (original)
Attach three non-overlapping capacity-byte arrays. Return 1 on success.
Invalid storage, zero capacity or dimensions outside 1..256 disable the body.

kitaqgb/lib/chain.c:119

c
u8 chain_body_init(ChainBody* body, u8* x, u8* y, u8* heading, u8 capacity, u16 width, u16 height)
{
    if (body == 0) return 0;
    body->x = x;
    body->y = y;
    body->heading = heading;
    body->count = 0;
    body->capacity = 0;
    body->width = width;
    body->height = height;
    if (x == 0 || y == 0 || heading == 0 || capacity == 0) return 0;
    if (width == 0 || width > 256 || height == 0 || height > 256) return 0;
    body->capacity = capacity;
    return 1;
}
chain_body_reset

Construye una postura inicial recta colocando articulaciones detrás de la cabeza indicada.

Sintaxis

c
u8 chain_body_reset(ChainBody* body, u8 count, u8 head_x, u8 head_y, u8 heading);

Parámetros

body

ChainBody de destino; se ignora null. Salvo al inicializar, pasa un estado inicializado.

count

Número de articulaciones, incluida la cabeza, de 1 a capacity.

head_x

Coordenada X de la cabeza, ajustada de forma circular al ancho del campo.

head_y

Coordenada Y de la cabeza, ajustada de forma circular al alto del campo.

heading

Direcció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

c
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.

chain_body_reset: DMG — 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.
DMG — 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.
chain_body_reset: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\chain_body.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\chain_body.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/chain.h:57

Notas de la declaración (original)
Seed count joints in a straight pose behind the head; count includes the head.
Return 0 without changing the pose if count is zero or exceeds capacity.
Coordinates wrap to the playfield and headings are masked to 0..15.

kitaqgb/lib/chain.c:135

c
u8 chain_body_reset(ChainBody* body, u8 count, u8 head_x, u8 head_y, u8 heading)
{
    u8 i;
    u8 x;
    u8 y;
    s16 ox;
    s16 oy;
    if (body == 0) return 0;
    if (count == 0 || count > body->capacity) return 0;
    heading = (u8)(heading & 15);
    x = chain_body_wrap((s16)head_x, body->width);
    y = chain_body_wrap((s16)head_y, body->height);
    ox = chain_body_offset_x(heading);
    oy = chain_body_offset_y(heading);
    i = 0;
    while (i < count) {
        body->x[(__safe_index u8)i] = x;
        body->y[(__safe_index u8)i] = y;
        body->heading[(__safe_index u8)i] = heading;
        x = chain_body_wrap((s16)((s16)x - ox), body->width);
        y = chain_body_wrap((s16)((s16)y - oy), body->height);
        i = (u8)(i + 1);
    }
    body->count = count;
    return 1;
}
chain_body_step

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

c
void chain_body_step(ChainBody* body, u8 head_x, u8 head_y, u8 heading);

Parámetros

body

ChainBody de destino; se ignora null. Salvo al inicializar, pasa un estado inicializado.

head_x

Coordenada X de la cabeza, ajustada de forma circular al ancho del campo.

head_y

Coordenada Y de la cabeza, ajustada de forma circular al alto del campo.

heading

Direcció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

c
chain_body_step(&body,48,20,4); // The head turns down; only joint 1 receives 4.
    show_pose(8,34);
    for(step=1;step<4;step++) {
        chain_body_step(&body,48,(u8)(20+step),4);
    }
    // After four ticks, the new heading has reached joints 1 through 4.

Este fragmento 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.

chain_body_step: DMG — 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.
DMG — 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.
chain_body_step: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\chain_body.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\chain_body.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/chain.h:62

Notas de la declaración (original)
Install the caller's head pose, then pull joints from front to rear.
Each joint aims four pixels behind its updated predecessor and receives that
predecessor's OLD heading. Each axis moves 1 pixel, or 2 when error exceeds 4.
Call once per simulation tick; this does not advance head physics or render.

kitaqgb/lib/chain.c:162

c
void chain_body_step(ChainBody* body, u8 head_x, u8 head_y, u8 heading)
{
    u8 i;
    u8 previous;
    u8 pull;
    u8 old;
    u8 x;
    u8 y;
    u8 tx;
    u8 ty;
    s16 sx;
    s16 sy;
    if (body == 0) return;
    if (body->count == 0) return;
    heading = (u8)(heading & 15);
    body->x[0] = chain_body_wrap((s16)head_x, body->width);
    body->y[0] = chain_body_wrap((s16)head_y, body->height);
    body->heading[0] = heading;
    pull = heading;
    i = 1;
    while (i < body->count) {
        previous = (u8)(i - 1);
        old = body->heading[(__safe_index u8)i];
        x = body->x[(__safe_index u8)i];
        y = body->y[(__safe_index u8)i];
        tx = chain_body_wrap((s16)((s16)body->x[(__safe_index u8)previous] - chain_body_offset_x(pull)), body->width);
        ty = chain_body_wrap((s16)((s16)body->y[(__safe_index u8)previous] - chain_body_offset_y(pull)), body->height);
        sx = chain_body_correction(chain_wrap_delta(tx, x, body->width));
        sy = chain_body_correction(chain_wrap_delta(ty, y, body->height));
        body->heading[(__safe_index u8)i] = pull;
        body->x[(__safe_index u8)i] = chain_body_wrap((s16)((s16)x + sx), body->width);
        body->y[(__safe_index u8)i] = chain_body_wrap((s16)((s16)y + sy), body->height);
        // Save before overwriting: a bend advances by one joint per update.
        pull = old;
        i = (u8)(i + 1);
    }
}
chain_body_grow

Copia la posición y dirección actuales de la cola al siguiente hueco libre y aumenta el número en uno.

Sintaxis

c
u8 chain_body_grow(ChainBody* body);

Parámetros

body

ChainBody de 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

c
chain_body_grow(&body); // Copy the tail pose into the eighth slot.
    chain_body_step(&body,48,16,0);
    chain_body_step(&body,48,16,0);
    chain_body_step(&body,48,16,0);
    chain_body_step(&body,48,16,0); // Allow the duplicated tail to separate.

Este fragmento 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.

chain_body_grow: DMG — 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.
DMG — 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.
chain_body_grow: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\chain_body.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\chain_body.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/chain.h:65

Notas de la declaración (original)
Append a copy of the current tail; later steps separate the new joint.
Return 1 on growth, or 0 for an empty, disabled or full body.

kitaqgb/lib/chain.c:200

c
u8 chain_body_grow(ChainBody* body)
{
    u8 tail;
    u8 next;
    if (body == 0) return 0;
    next = body->count;
    if (next == 0 || next >= body->capacity) return 0;
    tail = (u8)(next - 1);
    body->x[(__safe_index u8)next] = body->x[(__safe_index u8)tail];
    body->y[(__safe_index u8)next] = body->y[(__safe_index u8)tail];
    body->heading[(__safe_index u8)next] = body->heading[(__safe_index u8)tail];
    body->count = (u8)(next + 1);
    return 1;
}
chain_body_clear

Pone a cero el número de articulaciones y conserva los arrays y la configuración del campo.

Sintaxis

c
void chain_body_clear(ChainBody* body);

Parámetros

body

ChainBody de 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

c
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.

chain_body_clear: DMG — 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.
DMG — 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.
chain_body_clear: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\chain_body.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\chain_body.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/chain.h:67

Notas de la declaración (original)
Remove all joints while retaining caller-owned storage and playfield settings.

kitaqgb/lib/chain.c:215

c
void chain_body_clear(ChainBody* body)
{
    if (body == 0) return;
    body->count = 0;
}
chain_clear

Descarta el historial registrado para reutilizar la misma matriz de almacenamiento.

Sintaxis

c
void chain_clear(Chain* chain);

Parámetros

chain

Puntero al Chain inicializado.

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

c
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.

chain_clear: DMG
DMG
chain_clear: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_chain.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_chain.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/chain.h:21

Notas de la declaración (original)
Forget the recorded points without clearing or freeing the backing storage.

kitaqgb/lib/chain.c:14

c
void chain_clear(Chain* chain)
{
    chain->count = 0;
    chain->head = 0;
}
chain_get_count

Lee el número de posiciones disponibles actualmente en el historial.

Sintaxis

c
u8 chain_get_count(const Chain* chain);

Parámetros

chain

Puntero al Chain inicializado.

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

c
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.

chain_get_count: DMG
DMG
chain_get_count: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_chain.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_chain.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/chain.h:30

Notas de la declaración (original)
Return the number of stored points, or zero for a null chain.

kitaqgb/lib/chain.c:63

c
u8 chain_get_count(const Chain* chain)
{
    if (chain == 0) return 0;
    return chain->count;
}
chain_get_segment

Lee una posición almacenada según su antigüedad en el historial.

Sintaxis

c
u8 chain_get_segment(const Chain* chain, u8 index, ChainPoint* out);

Parámetros

chain

Puntero al Chain inicializado.

index

Antigüedad del punto: 0 es el más reciente y count - 1 el más antiguo conservado.

out

ChainPoint independiente 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

c
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).

chain_get_segment: DMG
DMG
chain_get_segment: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_chain.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_chain.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/chain.h:28

Notas de la declaración (original)
Read a point by age, with index zero denoting the newest point. Return zero
for an invalid request and clear a non-null output first. Keep head + index
within the 8-bit range: addition is narrowed before the capacity wrap.

kitaqgb/lib/chain.c:40

c
u8 chain_get_segment(const Chain* chain, u8 index, ChainPoint* out)
{
    u8 pos;
    if (out != 0) {
        out->x = 0;
        out->y = 0;
    }

    if (out == 0) return 0;
    if (chain == 0) return 0;
    if (chain->capacity == 0) return 0;
    if (index >= chain->count) return 0;

    pos = (u8)(chain->head + index);
    while (pos >= chain->capacity) {
        pos = (u8)(pos - chain->capacity);
    }
    out->x = chain->points[pos].x;
    out->y = chain->points[pos].y;
    return 1;
}
chain_init

Asocia almacenamiento a un historial circular de posiciones y comienza sin puntos registrados.

Sintaxis

c
void chain_init(Chain* chain, ChainPoint* storage, u8 capacity);

Parámetros

chain

Chain escribible que se va a inicializar.

storage

Matriz con espacio para capacity elementos ChainPoint.

capacity

Nú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

c
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.

chain_init: DMG
DMG
chain_init: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_chain.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_chain.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/chain.h:19

Notas de la declaración (original)
Attach caller-owned ring storage and start with no recorded points.
The storage must remain valid for the lifetime of the chain.
Use a valid chain pointer and capacity entries of caller-owned storage.
Capacity at most 128 keeps every head+age sum in the byte range used by the reader.

kitaqgb/lib/chain.c:5

c
void chain_init(Chain* chain, ChainPoint* storage, u8 capacity)
{
    chain->points = storage;
    chain->capacity = capacity;
    chain->count = 0;
    chain->head = 0;
}
chain_push_head

Añade la posición más reciente a la cabeza del historial y sustituye el punto más antiguo si está lleno.

Sintaxis

c
void chain_push_head(Chain* chain, s16 x, s16 y);

Parámetros

chain

Puntero al Chain inicializado.

x

Coordenada X con signo del punto nuevo.

y

Coordenada 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

c
chain_push_head(&trail,8,8);chain_push_head(&trail,16,8);chain_push_head(&trail,24,16);chain_push_head(&trail,32,16);chain_push_head(&trail,40,24);

Este fragmento 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.

chain_push_head: DMG
DMG
chain_push_head: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_chain.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_chain.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/chain.h:24

Notas de la declaración (original)
Move the ring head backward and store the newest point. Once full, each push
replaces the oldest point; zero capacity is a no-op.

kitaqgb/lib/chain.c:22

c
void chain_push_head(Chain* chain, s16 x, s16 y)
{
    if (chain == 0) return;
    if (chain->capacity == 0) return;

    if (chain->head == 0) chain->head = (u8)(chain->capacity - 1);
    else chain->head--;

    chain->points[chain->head].x = x;
    chain->points[chain->head].y = y;

    if (chain->count < chain->capacity) chain->count++;
}

danmaku.h — 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

c
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

c
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.

danmaku_clear: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_danmaku.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_danmaku.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementación y código fuente

kitaqgb/lib/danmaku.h:35

Notas de la declaración (original)
Deactivate the pool while retaining peak/spawn/rejection counters and the RAM map.

kitaqgb/lib/danmaku.c:28

c
void danmaku_clear() {
    u8 i;
    for (i=0; i<DANMAKU_MAX; i++) dm_bullets[i].active=0;
    dm_count=0; dm_hit=0; dm_graze=0; dm_cursor=0;
}
danmaku_clear_map

Borra los 576 bytes del mapa de tiles de RAM de 32×18.

Sintaxis

c
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

c
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.

danmaku_clear_map: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_danmaku.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_danmaku.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementación y código fuente

kitaqgb/lib/danmaku.h:42

Notas de la declaración (original)
32 directions, 0=right, 8=down, 16=left, 24=up. speed in 1/16 px.
Clear the 32x18 RAM map before drawing the next frame; no transfer is performed.

kitaqgb/lib/danmaku.c:78

c
void danmaku_clear_map() {
    __asm {
        LD_HL_IMM dm_map
        LD_B_IMM 72
        XOR_A
    dm_clm_loop:
        LDI_HL_A
        LDI_HL_A
        LDI_HL_A
        LDI_HL_A
        LDI_HL_A
        LDI_HL_A
        LDI_HL_A
        LDI_HL_A
        DEC_B
        JR_NZ dm_clm_loop
        RET
    }
}
danmaku_fan

Genera un abanico con una tabla de velocidades de 32 direcciones y un paso angular fijo.

Sintaxis

c
void danmaku_fan(u8 x, u8 y, u8 direction, u8 step, u8 count, u8 speed);

Parámetros

x

X inicial en píxeles, de 0 a 159.

y

Y inicial en píxeles, de 0 a 127.

direction

Ángulo inicial, limitado a cinco bits: 0=derecha, 8=abajo, 16=izquierda, 24=arriba.

step

Incremento angular por proyectil, circular sobre 32 direcciones.

count

Número de intentos, limitado a 96.

speed

Velocidad 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

c
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.

danmaku_fan: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_danmaku.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_danmaku.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementación y código fuente

kitaqgb/lib/danmaku.h:39

Notas de la declaración (original)
Attempt a fan using wrapping 32-step angles; count is capped at 96 and speed at 64.

kitaqgb/lib/danmaku.c:62

c
void danmaku_fan(u8 x,u8 y,u8 direction,u8 step,u8 count,u8 speed) {
    u8 n;
    u8 a;
    s8 vx;
    s8 vy;
    if(count>DANMAKU_MAX) count=DANMAKU_MAX;
    if(speed>64) speed=64;
    a=direction&31;
    for(n=0;n<count;n++) {
        vx=(s8)(((s16)dm_cos[a]*(s16)speed)>>6);
        vy=(s8)(((s16)dm_sin[a]*(s16)speed)>>6);
        danmaku_spawn(x,y,vx,vy);
        a=(u8)((a+step)&31);
    }
}
danmaku_present_now

Transfiere de forma síncrona los 576 bytes de dm_map al mapa de fondo $9800 mediante GDMA de CGB.

Sintaxis

c
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

c
// 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.

danmaku_present_now: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_danmaku.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_danmaku.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementación y código fuente

kitaqgb/lib/danmaku.h:48

Notas de la declaración (original)
Requires CGB and LCD off or the beginning of VBlank. VBK restored to 0.
Transfers 18 rows (32-byte stride) to BG map 9800 with 36-block GDMA.

kitaqgb/lib/danmaku.c:301

c
void danmaku_present_now() {
    __asm {
        XOR_A
        LDH_MEM_A 0x4F
        LD_HL_IMM dm_map
        LD_A_H
        LDH_MEM_A 0x51
        LD_A_L
        LDH_MEM_A 0x52
        LD_A_IMM 0x18
        LDH_MEM_A 0x53
        XOR_A
        LDH_MEM_A 0x54
        LD_A_IMM 35
        LDH_MEM_A 0x55
        RET
    }
}
danmaku_reset

Vacía el pool de 96 proyectiles y restablece los contadores de máximo simultáneo, creaciones acumuladas y rechazos por pool lleno.

Sintaxis

c
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

c
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.

danmaku_reset: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_danmaku.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_danmaku.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementación y código fuente

kitaqgb/lib/danmaku.h:33

Notas de la declaración (original)
Reset pool, peak and lifetime counters; player fields and map contents remain caller-owned state.

kitaqgb/lib/danmaku.c:34

c
void danmaku_reset() {
    danmaku_clear(); dm_peak=0; dm_spawned=0; dm_rejected=0;
}
danmaku_spawn

Busca un hueco libre de forma circular y crea un proyectil con la posición y velocidad indicadas.

Sintaxis

c
u8 danmaku_spawn(u8 x, u8 y, s8 vx, s8 vy);

Parámetros

x

X inicial en píxeles, de 0 a 159.

y

Y inicial en píxeles, de 0 a 127.

vx

Velocidad Q4.4 con signo de −128 a 127; 16 mueve un píxel a la derecha por actualización.

vy

Velocidad 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

c
result[2]=danmaku_spawn(40,40,16,0);result[3]=danmaku_spawn(160,40,0,0);result[4]=dm_count;result[5]=dm_rejected;

Este fragmento 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.

danmaku_spawn: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_danmaku.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_danmaku.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementación y código fuente

kitaqgb/lib/danmaku.h:37

Notas de la declaración (original)
Use pixel origins inside 160x128 and signed sixteenth-pixel velocities; return one if a slot was allocated.

kitaqgb/lib/danmaku.c:39

c
u8 danmaku_spawn(u8 x, u8 y, s8 vx, s8 vy) {
    u8 n;
    u8 i;
    if (x>=160 || y>=128) return 0;
    for(n=0;n<DANMAKU_MAX;n++) {
        i=dm_cursor;
        dm_cursor++;
        if(dm_cursor>=DANMAKU_MAX) dm_cursor=0;
        if(dm_bullets[i].active==0) {
            dm_bullets[i].x=(s16)((u16)x<<4);
            dm_bullets[i].y=(s16)((u16)y<<4);
            dm_bullets[i].vx=vx; dm_bullets[i].vy=vy;
            dm_bullets[i].active=1; dm_bullets[i].grazed=0;
            dm_count++; dm_spawned++;
            if(dm_count>dm_peak) dm_peak=dm_count;
            return 1;
        }
    }
    dm_rejected++;
    return 0;
}
danmaku_step

Avanza cada proyectil una vez, elimina los que salen del área, compone los tiles de proyectiles y detecta impactos y roces.

Sintaxis

c
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

c
dm_player_x=0;dm_player_y=0;dm_invulnerable=0;for(i=0;i<8;i++){danmaku_clear_map();danmaku_step();}result[12]=dm_count;result[13]=dm_hit;result[14]=dm_graze;

Este fragmento 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.

danmaku_step: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_danmaku.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_danmaku.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementación y código fuente

kitaqgb/lib/danmaku.h:45

Notas de la declaración (original)
Caller fills decoration after clear_map, then calls step to overlay bullets.
hit and graze are events for this step. Collision uses rendered centers.

kitaqgb/lib/danmaku.c:99

c
void danmaku_step() {
    // One linear pass. No per-bullet bank calls, multiplication or division.
    // The 8-byte packed public layout is x16,y16,vx8,vy8,active,graze.
    __asm {
        XOR_A
        LD_MEM_A dm_hit
        LD_MEM_A dm_graze
        LD_A_IMM 96
        LD_MEM_A dm_remaining
        LD_HL_IMM dm_bullets
    dm_tick_loop:
        PUSH_HL
        LD_BC_IMM 6
        ADD_HL_BC
        LD_A_HL
        OR_A
        JP_Z dm_tick_next
        DEC_HL
        LD_A_HL
        LD_MEM_A dm_vy
        DEC_HL
        LD_A_HL
        LD_C_A
        LD_B_IMM 0
        AND_IMM 128
        JR_Z dm_tick_xsign
        DEC_B
    // B:C is the sign-extended X velocity. Add to Q12.4 position; high byte >=10 also rejects negative X.
    dm_tick_xsign:
        POP_HL
        PUSH_HL
        LD_A_HL
        ADD_C
        LDI_HL_A
        LD_E_A
        LD_A_HL
        ADC_B
        LDI_HL_A
        CP_IMM 10
        JP_NC dm_tick_kill
        RRCA
        RRCA
        RRCA
        RRCA
        LD_D_A
        LD_A_E
        RRCA
        RRCA
        RRCA
        RRCA
        AND_IMM 15
        OR_D
        LD_MEM_A dm_px
        LD_A_MEM dm_vy
        LD_C_A
        LD_B_IMM 0
        AND_IMM 128
        JR_Z dm_tick_ysign
        DEC_B
    // Apply signed Y velocity similarly; high byte >=8 rejects negative Y and positions at or below 128 pixels.
    dm_tick_ysign:
        LD_A_HL
        ADD_C
        LDI_HL_A
        LD_E_A
        LD_A_HL
        ADC_B
        LDI_HL_A
        CP_IMM 8
        JP_NC dm_tick_kill
        RRCA
        RRCA
        RRCA
        RRCA
        LD_D_A
        LD_A_E
        RRCA
        RRCA
        RRCA
        RRCA
        AND_IMM 15
        OR_D
        LD_MEM_A dm_py
        // Signed differences shifted into 0..16 for a wrap-safe range test.
        // Rendered centers are (pixel & FC)+2. Test a square of radius eight around the player for graze eligibility.
        LD_A_MEM dm_player_x
        LD_C_A
        LD_A_MEM dm_px
        AND_IMM 252
        ADD_A_IMM 10
        SUB_C
        CP_IMM 17
        JR_NC dm_tick_plot
        LD_B_A
        LD_A_MEM dm_player_y
        LD_C_A
        LD_A_MEM dm_py
        AND_IMM 252
        ADD_A_IMM 10
        SUB_C
        CP_IMM 17
        JR_NC dm_tick_plot
        LD_C_A
        INC_HL
        INC_HL
        INC_HL
        LD_A_HL
        OR_A
        JR_NZ dm_tick_check_hit
        LD_A_IMM 1
        LD_HL_A
        LD_A_MEM dm_graze
        INC_A
        LD_MEM_A dm_graze
    // A bullet grazes at most once during its lifetime. Invulnerability suppresses hits, but not first-graze events.
    // The inner hit test uses a square of radius three around the same quantized center.
    dm_tick_check_hit:
        LD_A_MEM dm_invulnerable
        OR_A
        JR_NZ dm_tick_plot
        LD_A_B
        SUB_IMM 5
        CP_IMM 7
        JR_NC dm_tick_plot
        LD_A_C
        SUB_IMM 5
        CP_IMM 7
        JR_NC dm_tick_plot
        LD_A_IMM 1
        LD_MEM_A dm_hit
    // Select one of four quadrant bits from pixel bit 2, then address map[(y>>3)*32+(x>>3)].
    // Decoration IDs >=16 are replaced at occupied cells; bullet IDs 0..15 merge with OR.
    dm_tick_plot:
        LD_A_MEM dm_py
        AND_IMM 4
        AND_IMM 254
        RRCA
        LD_B_A
        LD_A_MEM dm_px
        AND_IMM 4
        AND_IMM 254
        RRCA
        AND_IMM 254
        RRCA
        OR_B
        LD_E_A
        LD_D_IMM 0
        LD_HL_IMM dm_bits
        ADD_HL_DE
        LD_A_HL
        LD_C_A
        LD_A_MEM dm_py
        AND_IMM 120
        LD_L_A
        LD_H_IMM 0
        ADD_HL_HL
        ADD_HL_HL
        LD_A_MEM dm_px
        AND_IMM 254
        RRCA
        AND_IMM 254
        RRCA
        AND_IMM 254
        RRCA
        LD_E_A
        LD_D_IMM 0
        ADD_HL_DE
        LD_DE_IMM dm_map
        ADD_HL_DE
        LD_A_HL
        CP_IMM 16
        JR_C dm_tick_merge
        XOR_A
    dm_tick_merge:
        OR_C
        LD_HL_A
        JR dm_tick_next
    // Restore the saved record base, clear active at offset six and decrement the live count exactly once.
    dm_tick_kill:
        POP_HL
        PUSH_HL
        LD_BC_IMM 6
        ADD_HL_BC
        XOR_A
        LD_HL_A
        LD_A_MEM dm_count
        DEC_A
        LD_MEM_A dm_count
    // Restore the saved base even for inactive or culled bullets, then advance by the fixed eight-byte record size.
    dm_tick_next:
        POP_HL
        LD_BC_IMM 8
        ADD_HL_BC
        LD_A_MEM dm_remaining
        DEC_A
        LD_MEM_A dm_remaining
        JP_NZ dm_tick_loop
        RET
    }
}

debug.h — 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

c
void debug_assert_fail(u16 code);

Parámetros

code

Identificador 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

c
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.

debug_assert_fail: DMG
DMG
debug_assert_fail: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_debug.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_debug.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/debug.h:33

Notas de la declaración (original)
Record the assertion code and attempt to append an ASSERT entry. This helper
does not halt execution, and the code is retained even if the log is full.

kitaqgb/lib/debug.c:56

c
void debug_assert_fail(u16 code)
{
    kq_debug_last_assert = code;
    debug_push((const u8*)"ASSERT", code);
}
debug_get_last_assert

Lee el último código de aserción independientemente del espacio disponible en el registro.

Sintaxis

c
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

c
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.

debug_get_last_assert: DMG
DMG
debug_get_last_assert: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_debug.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_debug.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/debug.h:39

Notas de la declaración (original)
Read the last recorded assertion code, or the zero value installed by initialization.

kitaqgb/lib/debug.c:75

c
u16 debug_get_last_assert()
{
    return kq_debug_last_assert;
}
debug_get_trace_count

Lee el número de entradas válidas de la matriz de trazas.

Sintaxis

c
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

c
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.

debug_get_trace_count: DMG
DMG
debug_get_trace_count: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_debug.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_debug.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/debug.h:35

Notas de la declaración (original)
Return the number of valid entries in the fixed trace buffer.

kitaqgb/lib/debug.c:63

c
u8 debug_get_trace_count()
{
    return kq_debug_trace_count;
}
debug_get_trace_log

Obtiene una referencia a la matriz interna para inspeccionar los nombres, valores y etiquetas de fotograma registrados.

Sintaxis

c
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

c
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.

debug_get_trace_log: DMG
DMG
debug_get_trace_log: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_debug.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_debug.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/debug.h:37

Notas de la declaración (original)
Expose the internal trace array for inspection; use the count to bound reads.

kitaqgb/lib/debug.c:69

c
const DebugTraceEntry* debug_get_trace_log()
{
    return kq_debug_trace_log;
}
debug_init

Inicializa la longitud válida del registro, la etiqueta de fotograma y el último código de aserción.

Sintaxis

c
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

c
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.

debug_init: DMG
DMG
debug_init: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_debug.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_debug.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/debug.h:22

Notas de la declaración (original)
Reset log length, frame tag and last assertion code; existing entry bytes are not erased.

kitaqgb/lib/debug.c:10

c
void debug_init()
{
    kq_debug_trace_count = 0;
    kq_debug_frame = 0;
    kq_debug_last_assert = 0;
}
debug_mark_frame

Registra un marcador de fotograma con nombre para identificar un punto del flujo de ejecución.

Sintaxis

c
void debug_mark_frame(const u8* label);

Parámetros

label

Etiqueta 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

c
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.

debug_mark_frame: DMG
DMG
debug_mark_frame: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_debug.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_debug.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/debug.h:26

Notas de la declaración (original)
Append a named frame marker using 0xFFFF as its value.

kitaqgb/lib/debug.c:37

c
void debug_mark_frame(const u8* label)
{
    debug_push(label, 0xFFFF);
}
debug_set_frame

Establece la etiqueta de fotograma que se copiará en las entradas posteriores.

Sintaxis

c
void debug_set_frame(u16 frame);

Parámetros

frame

Nú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

c
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.

debug_set_frame: DMG
DMG
debug_set_frame: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_debug.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_debug.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/debug.h:24

Notas de la declaración (original)
Set the frame tag copied into subsequently recorded entries.

kitaqgb/lib/debug.c:18

c
void debug_set_frame(u16 frame)
{
    kq_debug_frame = frame;
}
debug_trace_u16

Registra una puntuación o contador de 16 bits con nombre.

Sintaxis

c
void debug_trace_u16(const u8* name, u16 value);

Parámetros

name

Etiqueta terminada en cero cuya memoria debe permanecer legible hasta la inspección.

value

Valor 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

c
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.

debug_trace_u16: DMG
DMG
debug_trace_u16: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_debug.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_debug.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/debug.h:30

Notas de la declaración (original)
Append a 16-bit value with the current frame tag.

kitaqgb/lib/debug.c:49

c
void debug_trace_u16(const u8* name, u16 value)
{
    debug_push(name, value);
}
debug_trace_u8

Registra un valor de estado de ocho bits con su nombre y la etiqueta de fotograma actual.

Sintaxis

c
void debug_trace_u8(const u8* name, u8 value);

Parámetros

name

Etiqueta terminada en cero cuya memoria debe permanecer legible hasta la inspección.

value

Valor 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

c
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.

debug_trace_u8: DMG
DMG
debug_trace_u8: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_debug.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_debug.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/debug.h:28

Notas de la declaración (original)
Append an unsigned byte value, widened to the log's 16-bit value field.

kitaqgb/lib/debug.c:43

c
void debug_trace_u8(const u8* name, u8 value)
{
    debug_push(name, (u16)value);
}
KITAQGB_ASSERT

Macro que se usa como una sentencia y registra el código de aserción 1 cuando su condición es falsa.

Sintaxis

c
#define KITAQGB_ASSERT(cond) do { if (!(cond)) debug_assert_fail((u16)1); } while (0)

Parámetros

cond

Condició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

c
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.

KITAQGB_ASSERT: DMG
DMG
KITAQGB_ASSERT: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_debug.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_debug.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/debug.h:45

c
#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

c
#define KITAQGB_ASSERT_CODE(cond, code) do { if (!(cond)) debug_assert_fail((u16)(code)); } while (0)

Parámetros

cond

Condición que debería cumplirse.

code

Expresió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

c
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.

KITAQGB_ASSERT_CODE: DMG
DMG
KITAQGB_ASSERT_CODE: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_debug.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_debug.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/debug.h:46

c
#define KITAQGB_ASSERT_CODE(cond, code) do { if (!(cond)) debug_assert_fail((u16)(code)); } while (0)
KITAQGB_MARK_FRAME

Convierte una etiqueta a puntero de cadena y añade un marcador de fotograma con valor 0xFFFF.

Sintaxis

c
#define KITAQGB_MARK_FRAME(label) debug_mark_frame((const u8*)(label))

Parámetros

label

Etiqueta 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

c
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.

KITAQGB_MARK_FRAME: DMG
DMG
KITAQGB_MARK_FRAME: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_debug.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_debug.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/debug.h:44

c
#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

c
#define KITAQGB_TRACE(name, value) debug_trace_u16((const u8*)(name), (u16)(value))

Parámetros

name

Etiqueta terminada en cero cuya memoria debe permanecer legible hasta la inspección.

value

Expresió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

c
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.

KITAQGB_TRACE: DMG
DMG
KITAQGB_TRACE: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_debug.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_debug.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/debug.h:43

c
#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

c
#define KITAQGB_TRACE_U16(name, value) debug_trace_u16((const u8*)(name), (u16)(value))

Parámetros

name

Etiqueta terminada en cero cuya memoria debe permanecer legible hasta la inspección.

value

Expresió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

c
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.

KITAQGB_TRACE_U16: DMG
DMG
KITAQGB_TRACE_U16: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_debug.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_debug.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/debug.h:42

c
#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

c
#define KITAQGB_TRACE_U8(name, value) debug_trace_u8((const u8*)(name), (u8)(value))

Parámetros

name

Etiqueta terminada en cero cuya memoria debe permanecer legible hasta la inspección.

value

Expresió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

c
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.

KITAQGB_TRACE_U8: DMG
DMG
KITAQGB_TRACE_U8: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_debug.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_debug.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/debug.h:41

c
#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

c
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

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    DMG3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    DMG3D_SetCamera(8,0,0,0,0,0);
    result[1]=DMG3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=DMG3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    DMG3D_SetCamera(0,0,0,0,0,0);
    DMG3D_BeginFrame();
    DMG3D_DrawLine2D(8,8,56,8);
    DMG3D_DrawLine2D(56,8,56,40);
    DMG3D_DrawLine2D(56,40,8,40);
    DMG3D_DrawLine2D(8,40,8,8);
    DMG3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    DMG3D_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    DMG3D_PutBgTile(1,1,160);
    DMG3D_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

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.

DMG3D_BeginFrame: DMG — 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.
DMG — 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.
DMG3D_BeginFrame: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_raster.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/dmg3d.h:17

Notas de la declaración (original)
WIRE3D_DMG_HEIGHT = 120.
Disable occlusion filtering only. Stage clearing normally happens during
transfer, and Init supplies the first clean stage. This does not discard an
unsubmitted frame, clear the mask, or reset pending BG writes/dirty flags.

kitaqgb/lib/wire3d_dmg.c:2641

c
void Wire3DDMG_BeginFrame()
{




    /* The consuming stage transfer clears D000 as it uploads, so BeginFrame only
       resets draw state. Wire3DDMG_Init supplies the first clean buffer. */

    w3ddmg_occlusion_active = 0;
}
DMG3D_DrawIndexedEdges

Dibuja un modelo de líneas con escala entera a partir de vértices y pares de índices de arista de dos bytes.

Sintaxis

c
void DMG3D_DrawIndexedEdges(const Wire3DDMG_Vec3* vertices, w3ddmg_u8 vertex_count, const w3ddmg_u8* edges, w3ddmg_u8 edge_count, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 scale);

Parámetros

vertices

Array de vértices 3D.

vertex_count

Cantidad 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_count

Cantidad de aristas.

x

Componente X del punto o del origen del objeto en coordenadas del mundo.

y

Componente Y del punto o del origen del objeto en coordenadas del mundo.

z

Componente Z del punto o del origen del objeto en coordenadas del mundo.

scale

Escala 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

c
#pragma bank 0
// Upload a main line and an auxiliary block separately; verify source consumption.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom DMG3D_Vec3 vertices[2]={{-32,0,0},{32,0,0}};
__prg_rom u8 edge_pairs[2]={0,1};
u8* stage_byte;

void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    DMG3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
        DMG3D_BeginFrame();
    DMG3D_DrawIndexedEdges(vertices,2,edge_pairs,1,-64,104,96,1);
    DMG3D_TransferMainNow();
    // Direct auxiliary transfer writes a separate tile after the main upload.
    for(i=24;i<=31;i++) DMG3D_DrawLine2D(40,i,47,i);
    stage_byte=(u8*)0xD518;result[1]=*stage_byte;
    DMG3D_TransferAuxNow();result[2]=*stage_byte;

    // Do not upload the consumed stage again.
    result[7]=0xA55A; while(1) {}
}

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.

DMG3D_DrawIndexedEdges: DMG — 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.
DMG — 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.
DMG3D_DrawIndexedEdges: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_direct.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_direct.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/dmg3d.h:20

Notas de la declaración (original)
WIRE3D_DMG_HEIGHT = 120.
Draw byte-pair edge indices after integer scaling and translation; scale
zero means one, and there is no object rotation or face filtering. Project at
most 24 vertices. Supply at most 128 edge pairs because byte offsets wrap
after 255. Invalid vertex IDs/depth-rejected endpoints are skipped; null arrays
are ignored. Keep coordinate products/sums representable as s16.

kitaqgb/lib/wire3d_dmg.c:3824

c
void Wire3DDMG_DrawIndexedEdges(const Wire3DDMG_Vec3* vertices, w3ddmg_u8 vertex_count, const w3ddmg_u8* edges, w3ddmg_u8 edge_count, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 scale)
{
    w3ddmg_u8 i;
    w3ddmg_u8 count;

    if (vertices == 0) return;
    if (edges == 0) return;

    count = vertex_count;
    if (count > WIRE3D_DMG_MODEL_VERTEX_LIMIT) count = WIRE3D_DMG_MODEL_VERTEX_LIMIT;
    if (scale == 0) scale = 1;

    i = 0;
    while (i < count)
    {
        const Wire3DDMG_Vec3* v;
        w3ddmg_i16 vx;
        w3ddmg_i16 vy;
        w3ddmg_i16 vz;
        w3ddmg_u8 sx;
        w3ddmg_u8 sy;

        v = &vertices[(__safe_index w3ddmg_u8)i];
        vx = (w3ddmg_i16)(x + (w3ddmg_i16)(v->x * scale));
        vy = (w3ddmg_i16)(y + (w3ddmg_i16)(v->y * scale));
        vz = (w3ddmg_i16)(z + (w3ddmg_i16)(v->z * scale));

        if (w3ddmg_project_world(vx, vy, vz, &sx, &sy))
        {
            w3ddmg_screen_x[(__safe_index w3ddmg_u8)i] = sx;
            w3ddmg_screen_y[(__safe_index w3ddmg_u8)i] = sy;
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 1;
        }
        else
        {
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 0;
        }

        i = (w3ddmg_u8)(i + 1);
    }

    i = 0;
    while (i < edge_count)
    {
        w3ddmg_u8 a;
        w3ddmg_u8 b;

        a = edges[(__safe_index w3ddmg_u8)((w3ddmg_u8)(i << 1))];
        b = edges[(__safe_index w3ddmg_u8)((w3ddmg_u8)((i << 1) + 1))];
        if ((a < count) && (b < count) &&
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)a] &&
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)b])
        {
            Wire3DDMG_DrawLine2D(
                w3ddmg_screen_x[(__safe_index w3ddmg_u8)a],
                w3ddmg_screen_y[(__safe_index w3ddmg_u8)a],
                w3ddmg_screen_x[(__safe_index w3ddmg_u8)b],
                w3ddmg_screen_y[(__safe_index w3ddmg_u8)b]);
        }

        i = (w3ddmg_u8)(i + 1);
    }
}
DMG3D_DrawLine2D

Dibuja en el área de preparación una línea de pantalla con conectividad de cuatro vecinos, incluidos los extremos.

Sintaxis

c
void DMG3D_DrawLine2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by);

Parámetros

ax

Coordenada X del vértice A en píxeles de la ventana gráfica.

ay

Coordenada Y del vértice A en píxeles de la ventana gráfica.

bx

Coordenada X del vértice B en píxeles de la ventana gráfica.

by

Coordenada 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

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    DMG3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    DMG3D_SetCamera(8,0,0,0,0,0);
    result[1]=DMG3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=DMG3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    DMG3D_SetCamera(0,0,0,0,0,0);
    DMG3D_BeginFrame();
    DMG3D_DrawLine2D(8,8,56,8);
    DMG3D_DrawLine2D(56,8,56,40);
    DMG3D_DrawLine2D(56,40,8,40);
    DMG3D_DrawLine2D(8,40,8,8);
    DMG3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    DMG3D_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    DMG3D_PutBgTile(1,1,160);
    DMG3D_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

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.

DMG3D_DrawLine2D: DMG — 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.
DMG — 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.
DMG3D_DrawLine2D: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_raster.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/dmg3d.h:21

Notas de la declaración (original)
WIRE3D_DMG_HEIGHT = 120.
Mark the bounding tile rectangle when dirty transfer is enabled, then draw
a connected staged line. Scene drawing may reject it using five mask samples.
Supply 128x120 viewport endpoints; low-level pixel bounds checks do not clip
the segment geometrically.

kitaqgb/lib/wire3d_dmg.c:2685

c
void Wire3DDMG_DrawLine2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by)
{

    w3ddmg_mark_line_dirty(ax, ay, bx, by);


    if (w3ddmg_occlusion_active)
    {
        w3ddmg_line_stage_masked_c(ax, ay, bx, by);
        return;
    }

    w3ddmg_line_x0 = ax;
    w3ddmg_line_y0 = ay;
    w3ddmg_line_x1 = bx;
    w3ddmg_line_y1 = by;
    if (ax < 128 && bx < 128 && ay < WIRE3D_DMG_SCREEN_H && by < WIRE3D_DMG_SCREEN_H)
        w3ddmg_line_inside_asm();
    else
        w3ddmg_line_stage_asm();
}
DMG3D_DrawLine3D

Proyecta dos extremos en coordenadas del mundo y dibuja una línea entre ellos.

Sintaxis

c
void DMG3D_DrawLine3D(w3ddmg_i16 ax, w3ddmg_i16 ay, w3ddmg_i16 az, w3ddmg_i16 bx, w3ddmg_i16 by, w3ddmg_i16 bz);

Parámetros

ax

Componente X del punto inicial en coordenadas del mundo.

ay

Componente Y del punto inicial en coordenadas del mundo.

az

Componente Z del punto inicial en coordenadas del mundo.

bx

Componente X del punto final en coordenadas del mundo.

by

Componente Y del punto final en coordenadas del mundo.

bz

Componente 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

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    DMG3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    DMG3D_SetCamera(8,0,0,0,0,0);
    result[1]=DMG3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=DMG3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    DMG3D_SetCamera(0,0,0,0,0,0);
    DMG3D_BeginFrame();
    DMG3D_DrawLine2D(8,8,56,8);
    DMG3D_DrawLine2D(56,8,56,40);
    DMG3D_DrawLine2D(56,40,8,40);
    DMG3D_DrawLine2D(8,40,8,8);
    DMG3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    DMG3D_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    DMG3D_PutBgTile(1,1,160);
    DMG3D_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

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.

DMG3D_DrawLine3D: DMG — 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.
DMG — 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.
DMG3D_DrawLine3D: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_raster.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/dmg3d.h:22

Notas de la declaración (original)
WIRE3D_DMG_HEIGHT = 120.
Project both world endpoints and draw only when both pass the depth range.
Do not intersect a crossing segment with near/far planes; projected endpoints
are independently clamped to the screen edges.

kitaqgb/lib/wire3d_dmg.c:2808

c
void Wire3DDMG_DrawLine3D(w3ddmg_i16 ax, w3ddmg_i16 ay, w3ddmg_i16 az, w3ddmg_i16 bx, w3ddmg_i16 by, w3ddmg_i16 bz)
{
    w3ddmg_u8 sx0;
    w3ddmg_u8 sy0;
    w3ddmg_u8 sx1;
    w3ddmg_u8 sy1;

    if (w3ddmg_project_world(ax, ay, az, &sx0, &sy0) == 0) return;
    if (w3ddmg_project_world(bx, by, bz, &sx1, &sy1) == 0) return;
    Wire3DDMG_DrawLine2D(sx0, sy0, sx1, sy1);
}
DMG3D_DrawModel

Dibuja un modelo de vértices y aristas en la posición y con la rotación indicadas, a escala unitaria.

Sintaxis

c
void DMG3D_DrawModel(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz);

Parámetros

model

Modelo que contiene los arrays de vértices, aristas y caras y sus cantidades; las tablas deben permanecer legibles durante la llamada.

x

Componente X del punto o del origen del objeto en coordenadas del mundo.

y

Componente Y del punto o del origen del objeto en coordenadas del mundo.

z

Componente Z del punto o del origen del objeto en coordenadas del mundo.

rx

Rotación alrededor de X; dieciséis pasos forman una vuelta completa.

ry

Rotación alrededor de Y; dieciséis pasos forman una vuelta completa.

rz

Rotació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

c
#pragma bank 0
// Compare direct model scaling with an object-array scene.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom DMG3D_Vec3 vertices[8]={{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}};
__prg_rom DMG3D_Edge edges[12]={{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}};
DMG3D_Model cube;
DMG3D_Object objects[2];
s16 px; s16 py; s16 pz;
void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    DMG3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;

    cube.vertices=vertices;cube.edges=edges;cube.faces=0;cube.edge_faces=0;
    cube.vertex_count=8;cube.edge_count=12;cube.face_count=0;cube.flags=0;

    DMG3D_BeginFrame();
    // Upper pair: direct model calls at unity and half scale.
    DMG3D_DrawModel(&cube,-32,32,96,0,0,0);
    DMG3D_DrawModelScaled(&cube,32,32,96,0,0,0,128);
    // Lower pair: the caller owns both object records and the model tables.
    for(i=0;i<2;i++) {
        objects[i].model=&cube;objects[i].x=-32+(s16)i*64;
        objects[i].y=-32;objects[i].z=96;
        objects[i].rx=0;objects[i].ry=0;objects[i].rz=0;
        objects[i].scale_q8=256-(s16)i*128;objects[i].visible=1;
    }
    DMG3D_DrawScene(objects,2);
    // Numeric checks cover the operation supplied by this viewport profile.
    px=16;py=0;pz=0;DMG3D_RotatePoint(&px,&py,&pz,0,4,0);
    result[1]=px; result[2]=py; result[3]=pz;
    DMG3D_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

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.

DMG3D_DrawModel: DMG — 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.
DMG — 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.
DMG3D_DrawModel: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_models.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/dmg3d.h:23

Notas de la declaración (original)
WIRE3D_DMG_HEIGHT = 120.
Draw an unscaled model by delegating to DrawModelScaled with scale 256.

kitaqgb/lib/wire3d_dmg.c:2827

c
void Wire3DDMG_DrawModel(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz)

{
    Wire3DDMG_DrawModelScaled(model, x, y, z, rx, ry, rz, 256);
}
DMG3D_DrawModelScaled

Escala un modelo, lo rota en orden Y/X/Z, traslada y proyecta sus vértices y dibuja las aristas.

Sintaxis

c
void DMG3D_DrawModelScaled(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz, w3ddmg_i16 scale_q8);

Parámetros

model

Modelo que contiene los arrays de vértices, aristas y caras y sus cantidades; las tablas deben permanecer legibles durante la llamada.

x

Componente X del punto o del origen del objeto en coordenadas del mundo.

y

Componente Y del punto o del origen del objeto en coordenadas del mundo.

z

Componente Z del punto o del origen del objeto en coordenadas del mundo.

rx

Rotación alrededor de X; dieciséis pasos forman una vuelta completa.

ry

Rotación alrededor de Y; dieciséis pasos forman una vuelta completa.

rz

Rotación alrededor de Z; dieciséis pasos forman una vuelta completa.

scale_q8

Escala 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

c
#pragma bank 0
// Compare direct model scaling with an object-array scene.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom DMG3D_Vec3 vertices[8]={{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}};
__prg_rom DMG3D_Edge edges[12]={{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}};
DMG3D_Model cube;
DMG3D_Object objects[2];
s16 px; s16 py; s16 pz;
void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    DMG3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;

    cube.vertices=vertices;cube.edges=edges;cube.faces=0;cube.edge_faces=0;
    cube.vertex_count=8;cube.edge_count=12;cube.face_count=0;cube.flags=0;

    DMG3D_BeginFrame();
    // Upper pair: direct model calls at unity and half scale.
    DMG3D_DrawModel(&cube,-32,32,96,0,0,0);
    DMG3D_DrawModelScaled(&cube,32,32,96,0,0,0,128);
    // Lower pair: the caller owns both object records and the model tables.
    for(i=0;i<2;i++) {
        objects[i].model=&cube;objects[i].x=-32+(s16)i*64;
        objects[i].y=-32;objects[i].z=96;
        objects[i].rx=0;objects[i].ry=0;objects[i].rz=0;
        objects[i].scale_q8=256-(s16)i*128;objects[i].visible=1;
    }
    DMG3D_DrawScene(objects,2);
    // Numeric checks cover the operation supplied by this viewport profile.
    px=16;py=0;pz=0;DMG3D_RotatePoint(&px,&py,&pz,0,4,0);
    result[1]=px; result[2]=py; result[3]=pz;
    DMG3D_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

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.

DMG3D_DrawModelScaled: DMG — 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.
DMG — 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.
DMG3D_DrawModelScaled: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_models.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/dmg3d.h:24

Notas de la declaración (original)
WIRE3D_DMG_HEIGHT = 120.
Scale up to 24 vertices, rotate Y/X/Z, translate and project, then traverse
all edge_count entries (a byte count) with optional adjacent-face filtering.
Face scratch is capped at 16; edge tables must contain all declared entries.
Nonpositive scale means 256. Null model/vertex/edge pointers are ignored.
Keep products/translations in signed 16-bit range; depth-crossing edges are dropped.

kitaqgb/lib/wire3d_dmg.c:2972

c
void Wire3DDMG_DrawModelScaled(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz, w3ddmg_i16 scale_q8)

{
    w3ddmg_u8 i;
    w3ddmg_u8 count;
    w3ddmg_u8 edge_count;
    w3ddmg_u8 face_count;

    if (model == 0) return;
    if (model->vertices == 0) return;
    if (model->edges == 0) return;
    if (scale_q8 <= 0) scale_q8 = 256;

    count = model->vertex_count;
    if (count > WIRE3D_DMG_MODEL_VERTEX_LIMIT) count = WIRE3D_DMG_MODEL_VERTEX_LIMIT;

    i = 0;
    while (i < count)
    {
        const Wire3DDMG_Vec3* v;
        w3ddmg_i16 vx;
        w3ddmg_i16 vy;
        w3ddmg_i16 vz;
        w3ddmg_u8 sx;
        w3ddmg_u8 sy;

        v = &model->vertices[(__safe_index w3ddmg_u8)i];
        vx = (w3ddmg_i16)((v->x * scale_q8) >> 8);
        vy = (w3ddmg_i16)((v->y * scale_q8) >> 8);
        vz = (w3ddmg_i16)((v->z * scale_q8) >> 8);






        w3ddmg_rotate_y(&vx, &vz, ry);
        w3ddmg_rotate_x(&vy, &vz, rx);
        w3ddmg_rotate_z(&vx, &vy, rz);


        vx = (w3ddmg_i16)(vx + x);
        vy = (w3ddmg_i16)(vy + y);
        vz = (w3ddmg_i16)(vz + z);

        if (w3ddmg_project_world(vx, vy, vz, &sx, &sy))
        {
            w3ddmg_screen_x[(__safe_index w3ddmg_u8)i] = sx;
            w3ddmg_screen_y[(__safe_index w3ddmg_u8)i] = sy;
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 1;
        }
        else
        {
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 0;
        }
        i = (w3ddmg_u8)(i + 1);
    }

    face_count = model->face_count;
    if (face_count > WIRE3D_DMG_MODEL_FACE_LIMIT) face_count = WIRE3D_DMG_MODEL_FACE_LIMIT;
    if ((model->flags & WIRE3D_DMG_MODEL_HIDDEN_LINES) && (model->faces != 0) && (model->edge_faces != 0))
    {
        w3ddmg_build_face_visibility(model, count, face_count);
    }

    edge_count = model->edge_count;




    i = 0;
    while (i < edge_count)
    {
        const Wire3DDMG_Edge* e;
        e = &model->edges[(__safe_index w3ddmg_u8)i];
        if ((e->a < count) && (e->b < count))
        {
            if (w3ddmg_screen_visible[(__safe_index w3ddmg_u8)e->a] &&
                w3ddmg_screen_visible[(__safe_index w3ddmg_u8)e->b] &&



                w3ddmg_is_edge_visible(model, i, face_count))

            {
                Wire3DDMG_DrawLine2D(
                    w3ddmg_screen_x[(__safe_index w3ddmg_u8)e->a],
                    w3ddmg_screen_y[(__safe_index w3ddmg_u8)e->a],
                    w3ddmg_screen_x[(__safe_index w3ddmg_u8)e->b],
                    w3ddmg_screen_y[(__safe_index w3ddmg_u8)e->b]);
            }
        }
        i = (w3ddmg_u8)(i + 1);
    }
}
DMG3D_DrawScene

Dibuja hasta ocho objetos de cerca a lejos, usando las caras cercanas para ocultar las aristas posteriores.

Sintaxis

c
void DMG3D_DrawScene(Wire3DDMG_Object* objects, w3ddmg_u8 count);

Parámetros

objects

Array de objetos con posiciones, rotaciones, escalas e indicadores de visibilidad.

count

Cantidad 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

c
#pragma bank 0
// Compare direct model scaling with an object-array scene.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom DMG3D_Vec3 vertices[8]={{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}};
__prg_rom DMG3D_Edge edges[12]={{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}};
DMG3D_Model cube;
DMG3D_Object objects[2];
s16 px; s16 py; s16 pz;
void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    DMG3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;

    cube.vertices=vertices;cube.edges=edges;cube.faces=0;cube.edge_faces=0;
    cube.vertex_count=8;cube.edge_count=12;cube.face_count=0;cube.flags=0;

    DMG3D_BeginFrame();
    // Upper pair: direct model calls at unity and half scale.
    DMG3D_DrawModel(&cube,-32,32,96,0,0,0);
    DMG3D_DrawModelScaled(&cube,32,32,96,0,0,0,128);
    // Lower pair: the caller owns both object records and the model tables.
    for(i=0;i<2;i++) {
        objects[i].model=&cube;objects[i].x=-32+(s16)i*64;
        objects[i].y=-32;objects[i].z=96;
        objects[i].rx=0;objects[i].ry=0;objects[i].rz=0;
        objects[i].scale_q8=256-(s16)i*128;objects[i].visible=1;
    }
    DMG3D_DrawScene(objects,2);
    // Numeric checks cover the operation supplied by this viewport profile.
    px=16;py=0;pz=0;DMG3D_RotatePoint(&px,&py,&pz,0,4,0);
    result[1]=px; result[2]=py; result[3]=pz;
    DMG3D_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

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.

DMG3D_DrawScene: DMG — 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.
DMG — 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.
DMG3D_DrawScene: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_models.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/dmg3d.h:25

Notas de la declaración (original)
WIRE3D_DMG_HEIGHT = 120.
Sort at most eight object origins by camera depth, near to far. Draw visible
valid models and mark front-face bounding rectangles for later objects. The
first sorted slot bypasses mask tests and the last needs no new occluder.
This is coarse line rejection, not a depth buffer. Null/empty input is ignored;
caller data and the current projection cache must remain valid during traversal.

kitaqgb/lib/wire3d_dmg.c:2723

c
void Wire3DDMG_DrawScene(Wire3DDMG_Object* objects, w3ddmg_u8 count)
{
    w3ddmg_u8 scene_count;
    w3ddmg_u8 i;

    if (objects == 0) return;

    scene_count = count;
    if (scene_count > WIRE3D_DMG_SCENE_OBJECT_LIMIT) scene_count = WIRE3D_DMG_SCENE_OBJECT_LIMIT;

    if (scene_count == 0) return;


    i = 0;
    while (i < scene_count)
    {
        w3ddmg_scene_order[(__safe_index w3ddmg_u8)i] = i;
        w3ddmg_scene_depth[(__safe_index w3ddmg_u8)i] = w3ddmg_scene_object_depth(&objects[(__safe_index w3ddmg_u8)i]);
        i = (w3ddmg_u8)(i + 1);
    }

    i = 0;
    while (i < scene_count)
    {
        w3ddmg_u8 j;
        j = (w3ddmg_u8)(i + 1);
        while (j < scene_count)
        {
            w3ddmg_u8 oi;
            w3ddmg_u8 oj;
            oi = w3ddmg_scene_order[(__safe_index w3ddmg_u8)i];
            oj = w3ddmg_scene_order[(__safe_index w3ddmg_u8)j];





            if (w3ddmg_scene_depth[(__safe_index w3ddmg_u8)oj] < w3ddmg_scene_depth[(__safe_index w3ddmg_u8)oi])
            {
                w3ddmg_scene_order[(__safe_index w3ddmg_u8)i] = oj;
                w3ddmg_scene_order[(__safe_index w3ddmg_u8)j] = oi;
            }
            j = (w3ddmg_u8)(j + 1);
        }
        i = (w3ddmg_u8)(i + 1);
    }

    w3ddmg_clear_occlusion_mask();



    w3ddmg_occlusion_active = 0;


    i = 0;
    while (i < scene_count)
    {
        Wire3DDMG_Object* obj;
        obj = &objects[(__safe_index w3ddmg_u8)w3ddmg_scene_order[(__safe_index w3ddmg_u8)i]];
        if ((obj->visible != 0) && (obj->model != 0))
        {




            w3ddmg_occlusion_active = i == 0 ? 0 : 1;
            Wire3DDMG_DrawModelScaled(obj->model, obj->x, obj->y, obj->z, obj->rx, obj->ry, obj->rz, obj->scale_q8);
            if ((w3ddmg_u8)(i + 1) < scene_count)
            {
                w3ddmg_mark_model_occluder(obj->model);
            }

        }
        i = (w3ddmg_u8)(i + 1);
    }

    w3ddmg_occlusion_active = 0;
}
DMG3D_EndFrame

Envía a VRAM las escrituras del fondo pendientes y el dibujo preparado.

Sintaxis

c
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

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    DMG3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    DMG3D_SetCamera(8,0,0,0,0,0);
    result[1]=DMG3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=DMG3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    DMG3D_SetCamera(0,0,0,0,0,0);
    DMG3D_BeginFrame();
    DMG3D_DrawLine2D(8,8,56,8);
    DMG3D_DrawLine2D(56,8,56,40);
    DMG3D_DrawLine2D(56,40,8,40);
    DMG3D_DrawLine2D(8,40,8,8);
    DMG3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    DMG3D_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    DMG3D_PutBgTile(1,1,160);
    DMG3D_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

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.

DMG3D_EndFrame: DMG — 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.
DMG — 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.
DMG3D_EndFrame: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_raster.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/dmg3d.h:28

Notas de la declaración (original)
WIRE3D_DMG_HEIGHT = 120.
Wait for the next VBlank and flush BG writes, then optionally consume the
auxiliary strips before uploading either dirty tiles or the entire main stage.
Auxiliary/main source overlap makes that ordering significant. STAT polling
continues across access windows; the update need not fit one VBlank.

kitaqgb/lib/wire3d_dmg.c:3081

c
void Wire3DDMG_EndFrame()
{
    w3ddmg_wait_vblank_start();
    w3ddmg_flush_bg_queue();



    if (w3ddmg_aux_transfer_enabled)
    {
        w3ddmg_transfer_stage_aux_asm();
    }
    if (w3ddmg_dirty_transfer_enabled)
    {
        w3ddmg_transfer_dirty_stage();
    }
    else
    {
        w3ddmg_transfer_stage_asm();
    }

}
DMG3D_EraseModelFaces

Proyecta los triángulos frontales del modelo y borra los píxeles preparados de su interior.

Sintaxis

c
void DMG3D_EraseModelFaces(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz, w3ddmg_i16 scale_q8);

Parámetros

model

Modelo que contiene los arrays de vértices, aristas y caras y sus cantidades; las tablas deben permanecer legibles durante la llamada.

x

Componente X del punto o del origen del objeto en coordenadas del mundo.

y

Componente Y del punto o del origen del objeto en coordenadas del mundo.

z

Componente Z del punto o del origen del objeto en coordenadas del mundo.

rx

Rotación alrededor de X; dieciséis pasos forman una vuelta completa.

ry

Rotación alrededor de Y; dieciséis pasos forman una vuelta completa.

rz

Rotación alrededor de Z; dieciséis pasos forman una vuelta completa.

scale_q8

Escala 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

c
#pragma bank 0
// Erase a screen triangle and a projected model face from separate filled panels.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom DMG3D_Vec3 vertices[4]={{-24,-24,0},{24,-24,0},{24,24,0},{-24,24,0}};
__prg_rom DMG3D_Edge edges[4]={{0,1},{1,2},{2,3},{3,0}};
__prg_rom DMG3D_Face faces[2]={{0,2,1},{0,3,2}};
DMG3D_Model plane;

void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    DMG3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
        plane.vertices=vertices;plane.edges=edges;plane.faces=faces;plane.edge_faces=0;
    plane.vertex_count=4;plane.edge_count=4;plane.face_count=2;plane.flags=1;
    DMG3D_BeginFrame();
    // Separate panels show a direct screen triangle and a projected square face.
    for(i=8;i<=32;i++) DMG3D_DrawLine2D(8,i,32,i);
    for(i=36;i<=84;i++) DMG3D_DrawLine2D(40,i,88,i);
    DMG3D_EraseTriangle2D(12,12,28,12,12,28);
    DMG3D_EraseModelFaces(&plane,0,0,64,0,0,0,256);

    DMG3D_EndFrame(); result[7]=0xA55A; while(1) {}
}

Resultado esperado

Las caras proyectadas borran una región rellena y permiten distinguir las zonas conservadas de las borradas.

DMG3D_EraseModelFaces: DMG — Las caras proyectadas borran una región rellena y permiten distinguir las zonas conservadas de las borradas.
DMG — Las caras proyectadas borran una región rellena y permiten distinguir las zonas conservadas de las borradas.
DMG3D_EraseModelFaces: CGB — Las caras proyectadas borran una región rellena y permiten distinguir las zonas conservadas de las borradas.
CGB — Las caras proyectadas borran una región rellena y permiten distinguir las zonas conservadas de las borradas.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_faces.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_faces.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/dmg3d.h:29

Notas de la declaración (original)
WIRE3D_DMG_HEIGHT = 120.
Project up to 24 vertices and erase front-facing triangle interiors from
the stage for a model with hidden-line flags and face data. Nonpositive scale
means 256 (unity). Up to 16 faces are considered; depth-crossing faces are
skipped. This also replaces shared projection caches, but does not update VRAM.

kitaqgb/lib/wire3d_dmg.c:2843

c
void Wire3DDMG_EraseModelFaces(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz, w3ddmg_i16 scale_q8)

{
    w3ddmg_u8 i;
    w3ddmg_u8 count;
    w3ddmg_u8 face_count;

    if (model == 0) return;
    if (model->vertices == 0) return;
    if (model->faces == 0) return;
    if ((model->flags & WIRE3D_DMG_MODEL_HIDDEN_LINES) == 0) return;
    if (scale_q8 <= 0) scale_q8 = 256;

    count = model->vertex_count;
    if (count > WIRE3D_DMG_MODEL_VERTEX_LIMIT) count = WIRE3D_DMG_MODEL_VERTEX_LIMIT;

    i = 0;
    while (i < count)
    {
        const Wire3DDMG_Vec3* v;
        w3ddmg_i16 vx;
        w3ddmg_i16 vy;
        w3ddmg_i16 vz;
        w3ddmg_u8 sx;
        w3ddmg_u8 sy;

        v = &model->vertices[(__safe_index w3ddmg_u8)i];
        vx = (w3ddmg_i16)((v->x * scale_q8) >> 8);
        vy = (w3ddmg_i16)((v->y * scale_q8) >> 8);
        vz = (w3ddmg_i16)((v->z * scale_q8) >> 8);






        w3ddmg_rotate_y(&vx, &vz, ry);
        w3ddmg_rotate_x(&vy, &vz, rx);
        w3ddmg_rotate_z(&vx, &vy, rz);


        vx = (w3ddmg_i16)(vx + x);
        vy = (w3ddmg_i16)(vy + y);
        vz = (w3ddmg_i16)(vz + z);

        if (w3ddmg_project_world(vx, vy, vz, &sx, &sy))
        {
            w3ddmg_screen_x[(__safe_index w3ddmg_u8)i] = sx;
            w3ddmg_screen_y[(__safe_index w3ddmg_u8)i] = sy;
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 1;
        }
        else
        {
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 0;
        }
        i = (w3ddmg_u8)(i + 1);
    }

    face_count = model->face_count;
    if (face_count > WIRE3D_DMG_MODEL_FACE_LIMIT) face_count = WIRE3D_DMG_MODEL_FACE_LIMIT;
    w3ddmg_build_face_visibility(model, count, face_count);

    i = 0;
    while (i < face_count)
    {
        const Wire3DDMG_Face* f;
        f = &model->faces[(__safe_index w3ddmg_u8)i];
        if (w3ddmg_face_visible[(__safe_index w3ddmg_u8)i] &&
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)f->a] &&
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)f->b] &&
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)f->c])
        {
            w3ddmg_clear_triangle(
                w3ddmg_screen_x[(__safe_index w3ddmg_u8)f->a],
                w3ddmg_screen_y[(__safe_index w3ddmg_u8)f->a],
                w3ddmg_screen_x[(__safe_index w3ddmg_u8)f->b],
                w3ddmg_screen_y[(__safe_index w3ddmg_u8)f->b],
                w3ddmg_screen_x[(__safe_index w3ddmg_u8)f->c],
                w3ddmg_screen_y[(__safe_index w3ddmg_u8)f->c]);
        }
        i = (w3ddmg_u8)(i + 1);
    }
}
DMG3D_EraseSpan2D

Borra un tramo horizontal, con ambos extremos incluidos, de una fila preparada.

Sintaxis

c
void DMG3D_EraseSpan2D(w3ddmg_u8 y, w3ddmg_u8 x0, w3ddmg_u8 x1);

Parámetros

y

Coordenada Y en píxeles de la fila que se va a borrar.

x0

Extremo X inferior, en píxeles de la ventana gráfica; el orden y el recorte siguen las notas de esta operación.

x1

Extremo 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

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    DMG3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    DMG3D_SetCamera(8,0,0,0,0,0);
    result[1]=DMG3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=DMG3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    DMG3D_SetCamera(0,0,0,0,0,0);
    DMG3D_BeginFrame();
    DMG3D_DrawLine2D(8,8,56,8);
    DMG3D_DrawLine2D(56,8,56,40);
    DMG3D_DrawLine2D(56,40,8,40);
    DMG3D_DrawLine2D(8,40,8,8);
    DMG3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    DMG3D_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    DMG3D_PutBgTile(1,1,160);
    DMG3D_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

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.

DMG3D_EraseSpan2D: DMG — 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.
DMG — 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.
DMG3D_EraseSpan2D: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_raster.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/dmg3d.h:30

Notas de la declaración (original)
WIRE3D_DMG_HEIGHT = 120.
Order the X endpoints and erase the inclusive staged span. Both endpoints
must be in 0..127; invalid Y is ignored. The routine does not clip X for you.

kitaqgb/lib/wire3d_dmg.c:2943

c
void Wire3DDMG_EraseSpan2D(w3ddmg_u8 y, w3ddmg_u8 x0, w3ddmg_u8 x1)
{
    w3ddmg_u8 tx;

    if (x0 > x1)
    {
        tx = x0;
        x0 = x1;
        x1 = tx;
    }
    w3ddmg_stage_clear_span(y, x0, x1);
}
DMG3D_EraseTriangle2D

Borra un triángulo de pantalla del área de preparación mediante tramos horizontales de líneas de barrido.

Sintaxis

c
void DMG3D_EraseTriangle2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by, w3ddmg_u8 cx, w3ddmg_u8 cy);

Parámetros

ax

Coordenada X del vértice A en píxeles de la ventana gráfica.

ay

Coordenada Y del vértice A en píxeles de la ventana gráfica.

bx

Coordenada X del vértice B en píxeles de la ventana gráfica.

by

Coordenada Y del vértice B en píxeles de la ventana gráfica.

cx

Coordenada X del vértice C en píxeles de la ventana gráfica.

cy

Coordenada 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

c
#pragma bank 0
// Erase a screen triangle and a projected model face from separate filled panels.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom DMG3D_Vec3 vertices[4]={{-24,-24,0},{24,-24,0},{24,24,0},{-24,24,0}};
__prg_rom DMG3D_Edge edges[4]={{0,1},{1,2},{2,3},{3,0}};
__prg_rom DMG3D_Face faces[2]={{0,2,1},{0,3,2}};
DMG3D_Model plane;

void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    DMG3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
        plane.vertices=vertices;plane.edges=edges;plane.faces=faces;plane.edge_faces=0;
    plane.vertex_count=4;plane.edge_count=4;plane.face_count=2;plane.flags=1;
    DMG3D_BeginFrame();
    // Separate panels show a direct screen triangle and a projected square face.
    for(i=8;i<=32;i++) DMG3D_DrawLine2D(8,i,32,i);
    for(i=36;i<=84;i++) DMG3D_DrawLine2D(40,i,88,i);
    DMG3D_EraseTriangle2D(12,12,28,12,12,28);
    DMG3D_EraseModelFaces(&plane,0,0,64,0,0,0,256);

    DMG3D_EndFrame(); result[7]=0xA55A; while(1) {}
}

Resultado esperado

Las caras proyectadas borran una región rellena y permiten distinguir las zonas conservadas de las borradas.

DMG3D_EraseTriangle2D: DMG — Las caras proyectadas borran una región rellena y permiten distinguir las zonas conservadas de las borradas.
DMG — Las caras proyectadas borran una región rellena y permiten distinguir las zonas conservadas de las borradas.
DMG3D_EraseTriangle2D: CGB — Las caras proyectadas borran una región rellena y permiten distinguir las zonas conservadas de las borradas.
CGB — Las caras proyectadas borran una región rellena y permiten distinguir las zonas conservadas de las borradas.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_faces.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_faces.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/dmg3d.h:31

Notas de la declaración (original)
WIRE3D_DMG_HEIGHT = 120.
Erase a triangle from staged pixels using integer scanline intersections.
Supply viewport coordinates. Degenerate triangles are ignored; the occlusion
mask and VRAM are unchanged.

kitaqgb/lib/wire3d_dmg.c:2933

c
void Wire3DDMG_EraseTriangle2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by, w3ddmg_u8 cx, w3ddmg_u8 cy)
{
    w3ddmg_clear_triangle(ax, ay, bx, by, cx, cy);
}
DMG3D_Init

Inicializa el LCD, los tiles y el mapa del fondo para una ventana gráfica de alambre monocroma.

Sintaxis

c
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

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    DMG3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    DMG3D_SetCamera(8,0,0,0,0,0);
    result[1]=DMG3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=DMG3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    DMG3D_SetCamera(0,0,0,0,0,0);
    DMG3D_BeginFrame();
    DMG3D_DrawLine2D(8,8,56,8);
    DMG3D_DrawLine2D(56,8,56,40);
    DMG3D_DrawLine2D(56,40,8,40);
    DMG3D_DrawLine2D(8,40,8,8);
    DMG3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    DMG3D_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    DMG3D_PutBgTile(1,1,160);
    DMG3D_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

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.

DMG3D_Init: DMG — 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.
DMG — 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.
DMG3D_Init: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_raster.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/dmg3d.h:35

Notas de la declaración (original)
WIRE3D_DMG_HEIGHT = 120.
Take over LCD state, clear tile VRAM and the BG map, and install a 16x15
viewport beginning at map tile (3,1). Set scroll (8,0), BGP=0xB4 and BG display.
Reset camera, queues, transfer modes, both dirty tables and stage. Reserve
0xD000..0xDFFF and retain its WRAM mapping; auxiliary storage aliases it.
Call BeginFrame before drawing to establish occlusion state.

kitaqgb/lib/wire3d_dmg.c:2572

c
void Wire3DDMG_Init()
{
    w3ddmg_u8 row;
    w3ddmg_u8 col;
    w3ddmg_u8 tid;
    w3ddmg_u16 off;

    w3ddmg_wait_vblank_start();
    w3ddmg_reg_lcdc = 0;

    w3ddmg_clear_vram_asm();



    w3ddmg_fill_bg_map_asm();

    row = 0;
    tid = 0x90;
    while (row < WIRE3D_DMG_TILE_H)
    {



        off = (w3ddmg_u16)(0x23 + ((w3ddmg_u16)row << 5));

        col = 0;
        while (col < WIRE3D_DMG_TILE_W)
        {
            w3ddmg_bg_map_9800[(w3ddmg_u16)(off + (w3ddmg_u16)col)] = tid;
            tid = (w3ddmg_u8)(tid + WIRE3D_DMG_TILE_H);
            col = (w3ddmg_u8)(col + 1);
        }
        row = (w3ddmg_u8)(row + 1);
        tid = (w3ddmg_u8)(0x90 + row);
    }




    w3ddmg_reg_scx = 8;

    w3ddmg_reg_scy = 0;
    w3ddmg_reg_bgp = 0xB4;
    w3ddmg_reg_lcdc = 0x81;
    w3ddmg_bgq_count = 0;

    w3ddmg_aux_transfer_enabled = 0;
    w3ddmg_dirty_transfer_enabled = 0;


    Wire3DDMG_SetCamera(0, 0, 0, 0, 0, 0);
    w3ddmg_clear_stage_asm();

    w3ddmg_clear_stage_aux_asm();
    w3ddmg_clear_dirty_tables();

}
DMG3D_ProjectPoint

Proyecta un punto del mundo mediante la cámara a coordenadas de la ventana gráfica.

Sintaxis

c
w3ddmg_u8 DMG3D_ProjectPoint(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8* sx, w3ddmg_u8* sy);

Parámetros

x

Componente X del punto o del origen del objeto en coordenadas del mundo.

y

Componente Y del punto o del origen del objeto en coordenadas del mundo.

z

Componente Z del punto o del origen del objeto en coordenadas del mundo.

sx

Puntero u8 válido y escribible que recibe la coordenada X proyectada.

sy

Puntero 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

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    DMG3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    DMG3D_SetCamera(8,0,0,0,0,0);
    result[1]=DMG3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=DMG3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    DMG3D_SetCamera(0,0,0,0,0,0);
    DMG3D_BeginFrame();
    DMG3D_DrawLine2D(8,8,56,8);
    DMG3D_DrawLine2D(56,8,56,40);
    DMG3D_DrawLine2D(56,40,8,40);
    DMG3D_DrawLine2D(8,40,8,8);
    DMG3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    DMG3D_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    DMG3D_PutBgTile(1,1,160);
    DMG3D_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

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.

DMG3D_ProjectPoint: DMG — 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.
DMG — 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.
DMG3D_ProjectPoint: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_raster.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/dmg3d.h:43

Notas de la declaración (original)
WIRE3D_DMG_HEIGHT = 120.
Project a world point with the current camera. Return zero for invalid
depth without changing outputs; success writes clamped 128x120 coordinates.
Both output pointers must be valid. Coordinate differences must fit s16.

kitaqgb/lib/wire3d_dmg.c:549

c
w3ddmg_u8 Wire3DDMG_ProjectPoint(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8* sx, w3ddmg_u8* sy)
{
    return w3ddmg_project_world(x, y, z, sx, sy);
}
DMG3D_PutBgTile

Encola una escritura de número de tile en una celda del mapa del fondo.

Sintaxis

c
void DMG3D_PutBgTile(w3ddmg_u8 x, w3ddmg_u8 y, w3ddmg_u8 tile);

Parámetros

x

Coordenada X de tile en el mapa del fondo de 32×32.

y

Coordenada Y de tile en el mapa del fondo de 32×32.

tile

Nú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

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    DMG3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    DMG3D_SetCamera(8,0,0,0,0,0);
    result[1]=DMG3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=DMG3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    DMG3D_SetCamera(0,0,0,0,0,0);
    DMG3D_BeginFrame();
    DMG3D_DrawLine2D(8,8,56,8);
    DMG3D_DrawLine2D(56,8,56,40);
    DMG3D_DrawLine2D(56,40,8,40);
    DMG3D_DrawLine2D(8,40,8,8);
    DMG3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    DMG3D_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    DMG3D_PutBgTile(1,1,160);
    DMG3D_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

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.

DMG3D_PutBgTile: DMG — 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.
DMG — 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.
DMG3D_PutBgTile: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_raster.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/dmg3d.h:44

Notas de la declaración (original)
WIRE3D_DMG_HEIGHT = 120.
Queue a tile write to the 32x32 map at 0x9800 for EndFrame. Invalid map
coordinates and submissions beyond 48 pending writes are silently ignored.
This queue is separate from the general vram library queue.

kitaqgb/lib/wire3d_dmg.c:582

c
void Wire3DDMG_PutBgTile(w3ddmg_u8 x, w3ddmg_u8 y, w3ddmg_u8 tile)
{
    if (x >= 32) return;
    if (y >= 32) return;
    if (w3ddmg_bgq_count >= WIRE3D_DMG_BG_QUEUE_LIMIT) return;
    w3ddmg_bgq_x[(__safe_index w3ddmg_u8)w3ddmg_bgq_count] = x;
    w3ddmg_bgq_y[(__safe_index w3ddmg_u8)w3ddmg_bgq_count] = y;
    w3ddmg_bgq_tile[(__safe_index w3ddmg_u8)w3ddmg_bgq_count] = tile;
    w3ddmg_bgq_count = (w3ddmg_u8)(w3ddmg_bgq_count + 1);
}
DMG3D_RotatePoint

Rota un punto en sus propias variables según los ángulos indicados.

Sintaxis

c
void DMG3D_RotatePoint(w3ddmg_i16* x, w3ddmg_i16* y, w3ddmg_i16* z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz);

Parámetros

x

Puntero s16 escribible y distinto de los demás para la componente X.

y

Puntero s16 escribible y distinto de los demás para la componente Y.

z

Puntero s16 escribible y distinto de los demás para la componente Z.

rx

Rotación alrededor de X; dieciséis pasos forman una vuelta completa.

ry

Rotación alrededor de Y; dieciséis pasos forman una vuelta completa.

rz

Rotació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

c
#pragma bank 0
// Compare direct model scaling with an object-array scene.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom DMG3D_Vec3 vertices[8]={{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}};
__prg_rom DMG3D_Edge edges[12]={{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}};
DMG3D_Model cube;
DMG3D_Object objects[2];
s16 px; s16 py; s16 pz;
void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    DMG3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;

    cube.vertices=vertices;cube.edges=edges;cube.faces=0;cube.edge_faces=0;
    cube.vertex_count=8;cube.edge_count=12;cube.face_count=0;cube.flags=0;

    DMG3D_BeginFrame();
    // Upper pair: direct model calls at unity and half scale.
    DMG3D_DrawModel(&cube,-32,32,96,0,0,0);
    DMG3D_DrawModelScaled(&cube,32,32,96,0,0,0,128);
    // Lower pair: the caller owns both object records and the model tables.
    for(i=0;i<2;i++) {
        objects[i].model=&cube;objects[i].x=-32+(s16)i*64;
        objects[i].y=-32;objects[i].z=96;
        objects[i].rx=0;objects[i].ry=0;objects[i].rz=0;
        objects[i].scale_q8=256-(s16)i*128;objects[i].visible=1;
    }
    DMG3D_DrawScene(objects,2);
    // Numeric checks cover the operation supplied by this viewport profile.
    px=16;py=0;pz=0;DMG3D_RotatePoint(&px,&py,&pz,0,4,0);
    result[1]=px; result[2]=py; result[3]=pz;
    DMG3D_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

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.

DMG3D_RotatePoint: DMG — 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.
DMG — 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.
DMG3D_RotatePoint: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_models.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/dmg3d.h:46

Notas de la declaración (original)
WIRE3D_DMG_HEIGHT = 120.
Rotate in place in Y/X/Z order using 16 steps per full turn. A null
component pointer makes the whole call a no-op; use distinct pointers.
Each axis rotation clamps its inputs to +/-220.

kitaqgb/lib/wire3d_dmg.c:3121

c
void Wire3DDMG_RotatePoint(w3ddmg_i16* x, w3ddmg_i16* y, w3ddmg_i16* z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz)
{
    if (x == 0) return;
    if (y == 0) return;
    if (z == 0) return;

    w3ddmg_rotate_y(x, z, ry);
    w3ddmg_rotate_x(y, z, rx);
    w3ddmg_rotate_z(x, y, rz);
}
DMG3D_SetAuxTransfer

Elige si EndFrame también transfiere las franjas auxiliares.

Sintaxis

c
void DMG3D_SetAuxTransfer(w3ddmg_u8 flag);

Parámetros

flag

Cero 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

c
#pragma bank 0
// Use the auxiliary-transfer gate to consume an overlapping stage strip.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;

void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    DMG3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
        DMG3D_SetDirtyTransfer(1); DMG3D_SetAuxTransfer(1);
    DMG3D_BeginFrame();
    for(i=24;i<=31;i++) DMG3D_DrawLine2D(40,i,47,i);
    // Auxiliary upload consumes this source before the dirty main tile is sent.

    DMG3D_EndFrame(); result[7]=0xA55A; while(1) {}
}

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).

DMG3D_SetAuxTransfer: DMG — La transferencia auxiliar consume parte del área principal y produce un bloque negro de 8×8 en las coordenadas de pantalla (80,24).
DMG — La transferencia auxiliar consume parte del área principal y produce un bloque negro de 8×8 en las coordenadas de pantalla (80,24).
DMG3D_SetAuxTransfer: CGB — La transferencia auxiliar consume parte del área principal y produce un bloque negro de 8×8 en las coordenadas de pantalla (80,24).
CGB — La transferencia auxiliar consume parte del área principal y produce un bloque negro de 8×8 en las coordenadas de pantalla (80,24).

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_aux_gate.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_aux_gate.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/dmg3d.h:50

Notas de la declaración (original)
WIRE3D_DMG_HEIGHT = 120.
Store the EndFrame auxiliary-transfer gate; any nonzero value enables it.
No data is copied or cleared here. Auxiliary source bytes alias the main stage.

kitaqgb/lib/wire3d_dmg.c:3895

c
void Wire3DDMG_SetAuxTransfer(w3ddmg_u8 flag)
{
    w3ddmg_aux_transfer_enabled = flag;
}
DMG3D_SetCamera

Guarda la posición y la orientación de la cámara para las proyecciones posteriores.

Sintaxis

c
void DMG3D_SetCamera(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 pitch, w3ddmg_u8 yaw, w3ddmg_u8 roll);

Parámetros

x

Componente X de la cámara en coordenadas del mundo.

y

Componente Y de la cámara en coordenadas del mundo.

z

Componente Z de la cámara en coordenadas del mundo.

pitch

Rotación alrededor de X; dieciséis pasos forman una vuelta completa.

yaw

Rotación alrededor de Y; dieciséis pasos forman una vuelta completa.

roll

Rotació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

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    DMG3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    DMG3D_SetCamera(8,0,0,0,0,0);
    result[1]=DMG3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=DMG3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    DMG3D_SetCamera(0,0,0,0,0,0);
    DMG3D_BeginFrame();
    DMG3D_DrawLine2D(8,8,56,8);
    DMG3D_DrawLine2D(56,8,56,40);
    DMG3D_DrawLine2D(56,40,8,40);
    DMG3D_DrawLine2D(8,40,8,8);
    DMG3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    DMG3D_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    DMG3D_PutBgTile(1,1,160);
    DMG3D_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

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.

DMG3D_SetCamera: DMG — 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.
DMG — 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.
DMG3D_SetCamera: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_raster.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/dmg3d.h:51

Notas de la declaración (original)
WIRE3D_DMG_HEIGHT = 120.
Store camera position and angles for later draws; a full turn is 16 angle
steps. No existing drawing is reprojected and no input range validation occurs.

kitaqgb/lib/wire3d_dmg.c:2661

c
void Wire3DDMG_SetCamera(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 pitch, w3ddmg_u8 yaw, w3ddmg_u8 roll)

{
    w3ddmg_cam_x = x;
    w3ddmg_cam_y = y;
    w3ddmg_cam_z = z;
    w3ddmg_cam_pitch = pitch;
    w3ddmg_cam_yaw = yaw;
    w3ddmg_cam_roll = roll;
}
DMG3D_SetDirtyTransfer

Selecciona la transferencia de tiles modificados para la ventana gráfica principal de 120 filas.

Sintaxis

c
void DMG3D_SetDirtyTransfer(w3ddmg_u8 flag);

Parámetros

flag

Cero 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

c
#pragma bank 0
// Remove the previous frame and upload only the tracked current/previous tiles.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;

void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    DMG3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
        DMG3D_SetDirtyTransfer(1); DMG3D_SetAuxTransfer(0);
    DMG3D_BeginFrame();
    DMG3D_DrawLine2D(8,8,24,8); DMG3D_DrawLine2D(24,8,24,24);
    DMG3D_DrawLine2D(24,24,8,24); DMG3D_DrawLine2D(8,24,8,8);
    DMG3D_EndFrame();
    DMG3D_BeginFrame();
    DMG3D_DrawLine2D(80,80,104,80); DMG3D_DrawLine2D(104,80,104,104);
    DMG3D_DrawLine2D(104,104,80,104); DMG3D_DrawLine2D(80,104,80,80);

    DMG3D_EndFrame(); result[7]=0xA55A; while(1) {}
}

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).

DMG3D_SetDirtyTransfer: DMG — Desaparece el marco anterior de arriba a la izquierda y solo queda el nuevo en las coordenadas de pantalla (96,88)..(120,112).
DMG — Desaparece el marco anterior de arriba a la izquierda y solo queda el nuevo en las coordenadas de pantalla (96,88)..(120,112).
DMG3D_SetDirtyTransfer: CGB — Desaparece el marco anterior de arriba a la izquierda y solo queda el nuevo en las coordenadas de pantalla (96,88)..(120,112).
CGB — Desaparece el marco anterior de arriba a la izquierda y solo queda el nuevo en las coordenadas de pantalla (96,88)..(120,112).

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_dirty.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_dirty.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/dmg3d.h:52

Notas de la declaración (original)
WIRE3D_DMG_HEIGHT = 120.
Store the dirty-transfer gate and clear both dirty histories and the main
stage, even if the value is unchanged. VRAM is retained; enabling this over an
old image can leave unmarked old tiles, so arrange a clean displayed baseline.

kitaqgb/lib/wire3d_dmg.c:3955

c
void Wire3DDMG_SetDirtyTransfer(w3ddmg_u8 flag)
{
    w3ddmg_dirty_transfer_enabled = flag;
    w3ddmg_clear_dirty_tables();
    w3ddmg_clear_stage_asm();
}
DMG3D_SetPalette

Escribe la correspondencia de cuatro tonos en el registro de paleta del fondo monocromo BGP.

Sintaxis

c
void DMG3D_SetPalette(w3ddmg_u8 bgp);

Parámetros

bgp

Valor 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

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    DMG3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    DMG3D_SetCamera(8,0,0,0,0,0);
    result[1]=DMG3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=DMG3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    DMG3D_SetCamera(0,0,0,0,0,0);
    DMG3D_BeginFrame();
    DMG3D_DrawLine2D(8,8,56,8);
    DMG3D_DrawLine2D(56,8,56,40);
    DMG3D_DrawLine2D(56,40,8,40);
    DMG3D_DrawLine2D(8,40,8,8);
    DMG3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    DMG3D_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    DMG3D_PutBgTile(1,1,160);
    DMG3D_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

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.

DMG3D_SetPalette: DMG — 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.
DMG — 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.
DMG3D_SetPalette: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_raster.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/dmg3d.h:53

Notas de la declaración (original)
WIRE3D_DMG_HEIGHT = 120.
Write the raw DMG BGP palette encoding immediately; no frame synchronization occurs.

kitaqgb/lib/wire3d_dmg.c:597

c
void Wire3DDMG_SetPalette(w3ddmg_u8 bgp)
{
    w3ddmg_reg_bgp = bgp;
}
DMG3D_TransferAuxNow

Transfiere inmediatamente seis franjas auxiliares y borra sus bytes fuente.

Sintaxis

c
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

c
#pragma bank 0
// Upload a main line and an auxiliary block separately; verify source consumption.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom DMG3D_Vec3 vertices[2]={{-32,0,0},{32,0,0}};
__prg_rom u8 edge_pairs[2]={0,1};
u8* stage_byte;

void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    DMG3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
        DMG3D_BeginFrame();
    DMG3D_DrawIndexedEdges(vertices,2,edge_pairs,1,-64,104,96,1);
    DMG3D_TransferMainNow();
    // Direct auxiliary transfer writes a separate tile after the main upload.
    for(i=24;i<=31;i++) DMG3D_DrawLine2D(40,i,47,i);
    stage_byte=(u8*)0xD518;result[1]=*stage_byte;
    DMG3D_TransferAuxNow();result[2]=*stage_byte;

    // Do not upload the consumed stage again.
    result[7]=0xA55A; while(1) {}
}

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.

DMG3D_TransferAuxNow: DMG — 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.
DMG — 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.
DMG3D_TransferAuxNow: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_direct.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_direct.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/dmg3d.h:57

Notas de la declaración (original)
WIRE3D_DMG_HEIGHT = 120.
Upload and consume auxiliary source strips immediately, independent of the
auxiliary gate. No VBlank-start wait or dirty-history/BG-queue update occurs.
The source overlaps the main stage and must be coordinated with its upload.

kitaqgb/lib/wire3d_dmg.c:3983

c
void Wire3DDMG_TransferAuxNow()
{
    w3ddmg_transfer_stage_aux_asm();
}
DMG3D_TransferMainNow

Transfiere inmediatamente toda el área principal y borra los píxeles fuente consumidos.

Sintaxis

c
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

c
#pragma bank 0
// Upload a main line and an auxiliary block separately; verify source consumption.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "dmg3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom DMG3D_Vec3 vertices[2]={{-32,0,0},{32,0,0}};
__prg_rom u8 edge_pairs[2]={0,1};
u8* stage_byte;

void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    DMG3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    DMG3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
        DMG3D_BeginFrame();
    DMG3D_DrawIndexedEdges(vertices,2,edge_pairs,1,-64,104,96,1);
    DMG3D_TransferMainNow();
    // Direct auxiliary transfer writes a separate tile after the main upload.
    for(i=24;i<=31;i++) DMG3D_DrawLine2D(40,i,47,i);
    stage_byte=(u8*)0xD518;result[1]=*stage_byte;
    DMG3D_TransferAuxNow();result[2]=*stage_byte;

    // Do not upload the consumed stage again.
    result[7]=0xA55A; while(1) {}
}

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.

DMG3D_TransferMainNow: DMG — 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.
DMG — 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.
DMG3D_TransferMainNow: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg3d_direct.c .\kitaqgb\lib\dmg3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg3d_direct.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/dmg3d.h:58

Notas de la declaración (original)
WIRE3D_DMG_HEIGHT = 120.
Upload and consume the full main stage immediately, polling STAT but not
waiting for the next VBlank. Ignore transfer gates and leave dirty histories
and BG tile queue unchanged; the caller coordinates the frame lifecycle.

kitaqgb/lib/wire3d_dmg.c:3970

c
void Wire3DDMG_TransferMainNow()
{
    w3ddmg_transfer_stage_asm();
}

entity.h — 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

c
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

c
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.

entity_clear_all: DMG
DMG
entity_clear_all: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\entity.c .\kitaq-docs\samples\api-examples\gb\entity_pool.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\entity_pool.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm
Implementación y código fuente

kitaqgb/lib/entity.h:43

Notas de la declaración (original)
Release every entity and restore deterministic defaults, including the no-sprite sentinel.

kitaqgb/lib/entity.c:14

c
void entity_clear_all()
{
    u8 i = 0;
    while (i < ENTITY_MAX) {
        entity_pool[i].active = 0;
        entity_pool[i].type = 0;
        entity_pool[i].x = 0;
        entity_pool[i].y = 0;
        entity_pool[i].vx = 0;
        entity_pool[i].vy = 0;
        entity_pool[i].state = 0;
        entity_pool[i].timer = 0;
        entity_pool[i].sprite = 0xFF;
        i++;
    }
}
entity_count_active

Cuenta los espacios ocupados por entidades sin modificarlos.

Sintaxis

c
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

c
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.

entity_count_active: DMG
DMG
entity_count_active: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\entity.c .\kitaq-docs\samples\api-examples\gb\entity_pool.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\entity_pool.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm
Implementación y código fuente

kitaqgb/lib/entity.h:41

Notas de la declaración (original)
Count occupied slots without changing entity state.

kitaqgb/lib/entity.c:93

c
u8 entity_count_active()
{
    u8 i = 0;
    u8 count = 0;
    while (i < ENTITY_MAX) {
        if (entity_pool[i].active != 0) count++;
        i++;
    }
    return count;
}
entity_create

Reserva una entidad del tipo y posición indicados; devuelve su ID reutilizable o 0xFF si el pool está lleno.

Sintaxis

c
u8 entity_create(u8 type, s16 x, s16 y);

Parámetros

type

Etiqueta 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, y

Coordenadas 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

c
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.

entity_create: DMG
DMG
entity_create: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\entity.c .\kitaq-docs\samples\api-examples\gb\entity_pool.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\entity_pool.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm
Implementación y código fuente

kitaqgb/lib/entity.h:29

Notas de la declaración (original)
Returns a reusable slot ID, or 0xFF if no slot is free.

kitaqgb/lib/entity.c:33

c
u8 entity_create(u8 type, s16 x, s16 y)
{
    u8 i = 0;
    while (i < ENTITY_MAX) {
        if (entity_pool[i].active == 0) {
            entity_pool[i].active = 1;
            entity_pool[i].type = type;
            entity_pool[i].x = x;
            entity_pool[i].y = y;
            entity_pool[i].vx = 0;
            entity_pool[i].vy = 0;
            entity_pool[i].state = 0;
            entity_pool[i].timer = 0;
            entity_pool[i].sprite = 0xFF;
            return i;
        }
        i++;
    }
    return 0xFF;
}
entity_destroy

Libera la entidad id; sus datos se conservan hasta que se reutiliza el espacio.

Sintaxis

c
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

c
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.

entity_destroy: DMG
DMG
entity_destroy: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\entity.c .\kitaq-docs\samples\api-examples\gb\entity_pool.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\entity_pool.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm
Implementación y código fuente

kitaqgb/lib/entity.h:32

Notas de la declaración (original)
Release a valid slot without clearing its payload. Reallocation resets the payload;
a saved pointer or ID must not be treated as a persistent entity identity.

kitaqgb/lib/entity.c:56

c
void entity_destroy(u8 id)
{
    if (id >= ENTITY_MAX) return;
    // Deactivation only releases this pool slot; the caller handles sprite/resource cleanup.
    entity_pool[id].active = 0;
}
entity_draw_all

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

c
void entity_draw_all(EntityFn fn);

Parámetros

fn

Puntero a función con firma void fn(u8 id). Recibe un ID; usa entity_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

c
void demo_draw(u8 id) {
    Entity* entity;
    entity = entity_get(id);
    if (entity != 0) {
        m_put((u8)entity->x, (u8)entity->y, (u8)('A' + entity->type - 1));
        draw_calls++;
    }
}

// From main(), after creating two entities:
draw_calls = 0;
entity_draw_all(demo_draw);
automatic_draws = draw_calls;
if (automatic_draws != 2) { failures++; }

Este fragmento 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.

entity_draw_all: DMG
DMG
entity_draw_all: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\entity.c .\kitaq-docs\samples\api-examples\gb\entity_pool.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\entity_pool.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm
Implementación y código fuente

kitaqgb/lib/entity.h:39

Notas de la declaración (original)
Use the same active-slot traversal for drawing; the callback supplies all rendering.

kitaqgb/lib/entity.c:87

c
void entity_draw_all(EntityFn fn)
{
    entity_update_all(fn);
}
entity_get

Devuelve un puntero a la entidad activa, o null si el ID no es válido o está libre. El almacenamiento se reutiliza.

Sintaxis

c
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

c
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.

entity_get: DMG
DMG
entity_get: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\entity.c .\kitaq-docs\samples\api-examples\gb\entity_pool.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\entity_pool.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm
Implementación y código fuente

kitaqgb/lib/entity.h:34

Notas de la declaración (original)
Returns null for an invalid or inactive ID; the returned pointer aliases reusable pool storage.

kitaqgb/lib/entity.c:65

c
Entity* entity_get(u8 id)
{
    if (id >= ENTITY_MAX) return 0;
    if (entity_pool[id].active == 0) return 0;
    return &entity_pool[(__safe_index u8)id];
}
entity_init

Inicializa todos los espacios del pool de entidades.

Sintaxis

c
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

c
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.

entity_init: DMG
DMG
entity_init: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\entity.c .\kitaq-docs\samples\api-examples\gb\entity_pool.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\entity_pool.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm
Implementación y código fuente

kitaqgb/lib/entity.h:27

Notas de la declaración (original)
Reset every slot before the game starts using the pool.

kitaqgb/lib/entity.c:8

c
void entity_init()
{
    entity_clear_all();
}
entity_update_all

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

c
void entity_update_all(EntityFn fn);

Parámetros

fn

Puntero a función con firma void fn(u8 id). Recibe un ID; usa entity_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

c
void demo_update(u8 id) {
    Entity* entity;
    entity = entity_get(id);
    if (entity != 0) { entity->x = entity->x + 1; update_calls++; }
}

// From main(), after creating two entities:
update_calls = 0;
entity_update_all(demo_update);
automatic_updates = update_calls;
if (automatic_updates != 2) { failures++; }

Este fragmento 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.

entity_update_all: DMG
DMG
entity_update_all: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\entity.c .\kitaq-docs\samples\api-examples\gb\entity_pool.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\entity_pool.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm
Implementación y código fuente

kitaqgb/lib/entity.h:37

Notas de la declaración (original)
Call fn for each slot that is active when the scan reaches it; null is a no-op.
Callbacks may change the pool, so newly activated later slots can run in this pass.

kitaqgb/lib/entity.c:74

c
void entity_update_all(EntityFn fn)
{
    u8 i = 0;
    if (fn == 0) return;
    while (i < ENTITY_MAX) {
        if (entity_pool[i].active != 0) {
            fn(i);
        }
        i++;
    }
}

fixed.h — 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

c
fix8 fix_div(fix8 a, fix8 b);

Parámetros

a

Operando izquierdo en Q8.8.

b

Operando 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

c
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.

fix_div: DMG
DMG
fix_div: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_math.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_math.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/fixed.h:32

Notas de la declaración (original)
Scale the reduced-precision quotient back to 8.8 and return zero for b == 0.
Callers must also ensure (b >> 4) is nonzero; the explicit check only tests b.
The intermediate product must fit the compiler's integer arithmetic.

kitaqgb/lib/fixed.c:26

c
fix8 fix_div(fix8 a, fix8 b)
{
    if (b == 0) return 0;
    return (fix8)(((a >> 4) * 256) / (b >> 4));
}
fix_from_int

Convierte una coordenada o velocidad entera a Q8.8 para conservar la parte fraccionaria en los cálculos posteriores.

Sintaxis

c
fix8 fix_from_int(s16 n);

Parámetros

n

Entero 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

c
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.

fix_from_int: DMG
DMG
fix_from_int: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_math.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_math.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/fixed.h:23

Notas de la declaración (original)
Convert an integer to signed 8.8 fixed point by moving it into the high byte.
The caller must keep the result within the representable 16-bit range.

kitaqgb/lib/fixed.c:5

c
fix8 fix_from_int(s16 n)
{
    return (fix8)(n << 8);
}
fix_lerp

Interpola de un valor Q8.8 hacia otro usando un peso de ocho bits.

Sintaxis

c
fix8 fix_lerp(fix8 a, fix8 b, u8 t_q8);

Parámetros

a

Operando izquierdo en Q8.8.

b

Operando derecho en Q8.8.

t_q8

Peso 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

c
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.

fix_lerp: DMG
DMG
fix_lerp: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_math.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_math.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/fixed.h:35

Notas de la declaración (original)
Interpolate toward b using a quantized Q0.8 weight. Both shifts discard low
bits, so small changes may vanish and a weight of 255 need not reach b.

kitaqgb/lib/fixed.c:34

c
fix8 fix_lerp(fix8 a, fix8 b, u8 t_q8)
{
    // The endpoint difference must fit s16 before the reduced-precision multiplication.
    fix8 d = (fix8)(b - a);
    return (fix8)(a + (fix8)((d >> 4) * (s16)(t_q8 >> 4)));
}
fix_mul

Multiplica dos valores Q8.8 mediante una aproximación de bajo coste.

Sintaxis

c
fix8 fix_mul(fix8 a, fix8 b);

Parámetros

a

Operando izquierdo en Q8.8.

b

Operando 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

c
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.

fix_mul: DMG
DMG
fix_mul: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_math.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_math.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/fixed.h:28

Notas de la declaración (original)
Approximate 8.8 multiplication by discarding four low bits from each operand
before multiplying. This trades precision for a smaller intermediate product.

kitaqgb/lib/fixed.c:18

c
fix8 fix_mul(fix8 a, fix8 b)
{
    return (fix8)((a >> 4) * (b >> 4));
}
fix_to_int

Extrae una coordenada entera de Q8.8 descartando los bits fraccionarios. Los valores negativos se redondean hacia menos infinito.

Sintaxis

c
s16 fix_to_int(fix8 x);

Parámetros

x

Valor 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

c
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.

fix_to_int: DMG
DMG
fix_to_int: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_math.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_math.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/fixed.h:25

Notas de la declaración (original)
Discard the eight fractional bits using a signed right shift.

kitaqgb/lib/fixed.c:11

c
s16 fix_to_int(fix8 x)
{
    return (s16)(x >> 8);
}
kq_abs_s16

Calcula el valor absoluto de un entero de 16 bits con signo.

Sintaxis

c
s16 kq_abs_s16(s16 v);

Parámetros

v

Valor 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

c
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.

kq_abs_s16: DMG
DMG
kq_abs_s16: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_math_limits.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_math_limits.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/fixed.h:38

Notas de la declaración (original)
Return the magnitude in s16. The most-negative s16 has no positive s16
representation and must be excluded by callers needing a nonnegative result.

kitaqgb/lib/fixed.c:43

c
s16 kq_abs_s16(s16 v)
{
    if (v < 0) return (s16)(0 - v);
    return v;
}
kq_clamp_s16

Limita una coordenada o velocidad a un intervalo que incluye ambos extremos.

Sintaxis

c
s16 kq_clamp_s16(s16 v, s16 lo, s16 hi);

Parámetros

v

Valor con signo que se va a limitar.

lo

Límite inferior incluido.

hi

Lí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

c
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.

kq_clamp_s16: DMG
DMG
kq_clamp_s16: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_math_limits.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_math_limits.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/fixed.h:44

Notas de la declaración (original)
Clamp to an inclusive interval; callers must provide lo <= hi.

kitaqgb/lib/fixed.c:64

c
s16 kq_clamp_s16(s16 v, s16 lo, s16 hi)
{
    if (v < lo) return lo;
    if (v > hi) return hi;
    return v;
}
kq_max_s16

Selecciona el mayor de dos valores de 16 bits con signo.

Sintaxis

c
s16 kq_max_s16(s16 a, s16 b);

Parámetros

a

Primer valor con signo que se va a comparar.

b

Segundo 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

c
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.

kq_max_s16: DMG
DMG
kq_max_s16: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_math_limits.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_math_limits.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/fixed.h:42

Notas de la declaración (original)
Select the larger signed value.

kitaqgb/lib/fixed.c:57

c
s16 kq_max_s16(s16 a, s16 b)
{
    if (a > b) return a;
    return b;
}
kq_min_s16

Selecciona el menor de dos valores de 16 bits con signo.

Sintaxis

c
s16 kq_min_s16(s16 a, s16 b);

Parámetros

a

Primer valor con signo que se va a comparar.

b

Segundo 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

c
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.

kq_min_s16: DMG
DMG
kq_min_s16: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_math_limits.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_math_limits.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/fixed.h:40

Notas de la declaración (original)
Select the smaller signed value.

kitaqgb/lib/fixed.c:50

c
s16 kq_min_s16(s16 a, s16 b)
{
    if (a < b) return a;
    return b;
}
kq_point_in_rect

Comprueba si un punto está dentro de un rectángulo, incluidos sus bordes izquierdo y superior.

Sintaxis

c
u8 kq_point_in_rect(s16 x, s16 y, KQRect r);

Parámetros

x

Coordenada X del punto, en el sistema de coordenadas del rectángulo.

y

Coordenada Y del punto.

r

Rectá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

c
result[1]=kq_point_in_rect(9,1,a);
for(gy=0;gy<11;gy++){for(gx=0;gx<15;gx++){
inside_a=kq_point_in_rect(gx,gy,a);inside_b=kq_point_in_rect(gx,gy,b);
tile=0;if(inside_a){tile=65;result[3]=result[3]+1;}if(inside_b)tile=66;if(inside_a && inside_b){tile=79;result[4]=result[4]+1;}
m_put(1+gx,2+gy,tile);if(tile!=0)vram_example_color(1+gx,2+gy,1,1,tile==65?1:(tile==66?2:3));
}}

Este fragmento 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.

kq_point_in_rect: DMG
DMG
kq_point_in_rect: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_geometry.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_geometry.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/fixed.h:51

Notas de la declaración (original)
Test a half-open rectangle: left/top edges are included, right/bottom excluded.
The coordinate-plus-size sums must remain representable as s16.

kitaqgb/lib/fixed.c:85

c
u8 kq_point_in_rect(s16 x, s16 y, KQRect r)
{
    if (x < r.x) return 0;
    if (y < r.y) return 0;
    if (x >= (s16)(r.x + r.w)) return 0;
    if (y >= (s16)(r.y + r.h)) return 0;
    return 1;
}
kq_rect_intersect

Comprueba si dos rectángulos alineados con los ejes se solapan con un área mayor que cero.

Sintaxis

c
u8 kq_rect_intersect(KQRect a, KQRect b);

Parámetros

a

Primer rectángulo, pasado por valor: x, y indican su esquina superior izquierda; w, h son su anchura y altura.

b

Segundo 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

c
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.

kq_rect_intersect: DMG
DMG
kq_rect_intersect: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_geometry.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_geometry.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/fixed.h:48

Notas de la declaración (original)
Test overlap using exclusive right/bottom edges; touching edges do not collide.
Require positive dimensions and edge sums that fit s16; zero-sized rectangles
are not explicitly rejected and may be reported as overlapping.

kitaqgb/lib/fixed.c:74

c
u8 kq_rect_intersect(KQRect a, KQRect b)
{
    if ((s16)(a.x + a.w) <= b.x) return 0;
    if ((s16)(b.x + b.w) <= a.x) return 0;
    if ((s16)(a.y + a.h) <= b.y) return 0;
    if ((s16)(b.y + b.h) <= a.y) return 0;
    return 1;
}

input.h — 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

c
u8 btn_down(u8 mask);

Parámetros

mask

Una máscara BTN_* o varias combinadas con |. Basta con que coincida cualquiera de los botones seleccionados; BTN_A | BTN_B no 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.

input_down

Ejemplo de uso

c
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.

btn_down: DMG
DMG
btn_down: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\input.c .\kitaq-docs\samples\api-examples\gb\input_aliases.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\input_aliases.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm --no-cache
Implementación y código fuente

kitaqgb/lib/input.h:48

c
#define btn_down input_down

kitaqgb/lib/input.c:68

c
u8 input_down(u8 mask)
{
    return (u8)((kq_input_keys & mask) != 0);
}
btn_pressed

btn_pressed 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

c
u8 btn_pressed(u8 mask);

Parámetros

mask

Una máscara BTN_* o varias combinadas con |. Basta con que coincida cualquiera de los botones seleccionados; BTN_A | BTN_B no 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.

input_pressed

Ejemplo de uso

c
if (btn_pressed(BTN_A)!=0) {
        press_count++; seen_press=1;
        first_down=btn_down(BTN_A); first_press=btn_pressed(BTN_A);
        first_repeat=btn_repeat(BTN_A);
        first_current=input_current(); // Only A held: BTN_A, or decimal 16.
        first_previous=input_previous(); // No buttons in the preceding sample: 0.
        if (first_down!=1 || first_press!=1 || first_repeat!=1) failures++;
        if (first_current!=BTN_A || first_previous!=0) failures++;
        if (btn_down(BTN_A|BTN_B)!=1 || btn_down(0)!=0) failures++;
    }

Este fragmento 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.

btn_pressed: DMG
DMG
btn_pressed: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\input.c .\kitaq-docs\samples\api-examples\gb\input_aliases.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\input_aliases.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm --no-cache
Implementación y código fuente

kitaqgb/lib/input.h:49

c
#define btn_pressed input_pressed

kitaqgb/lib/input.c:74

c
u8 input_pressed(u8 mask)
{
    return (u8)((kq_input_press_keys & mask) != 0);
}
btn_released

btn_released 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

c
u8 btn_released(u8 mask);

Parámetros

mask

Una máscara BTN_* o varias combinadas con |. Basta con que coincida cualquiera de los botones seleccionados; BTN_A | BTN_B no 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.

input_released

Ejemplo de uso

c
if (btn_released(BTN_A)!=0) {
        release_result=btn_released(BTN_A);
        last_current=input_current(); last_previous=input_previous();
        if (btn_down(BTN_A)!=0 || btn_pressed(BTN_A)!=0 || btn_repeat(BTN_A)!=0) failures++;
        break;
    }

Este fragmento 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.

btn_released: DMG
DMG
btn_released: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\input.c .\kitaq-docs\samples\api-examples\gb\input_aliases.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\input_aliases.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm --no-cache
Implementación y código fuente

kitaqgb/lib/input.h:50

c
#define btn_released input_released

kitaqgb/lib/input.c:80

c
u8 input_released(u8 mask)
{
    return (u8)((kq_input_release_keys & mask) != 0);
}
btn_repeat

btn_repeat 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

c
u8 btn_repeat(u8 mask);

Parámetros

mask

Una máscara BTN_* o varias combinadas con |. Basta con que coincida cualquiera de los botones seleccionados; BTN_A | BTN_B no 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.

input_repeat

Ejemplo de uso

c
if (btn_repeat(BTN_A)!=0) {
        // The initial press is pulse 1. Defaults then wait 19 updates, followed by 6.
        if (repeat_count==1 && held_ticks-previous_pulse!=19) failures++;
        if (repeat_count>1 && held_ticks-previous_pulse!=6) failures++;
        previous_pulse=held_ticks; repeat_count++;
        if (btn_repeat(BTN_A)!=1) failures++; // Reading again does not consume it.
    }

Este fragmento 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.

btn_repeat: DMG
DMG
btn_repeat: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\input.c .\kitaq-docs\samples\api-examples\gb\input_aliases.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\input_aliases.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm --no-cache
Implementación y código fuente

kitaqgb/lib/input.h:51

c
#define btn_repeat input_repeat

kitaqgb/lib/input.c:86

c
u8 input_repeat(u8 mask)
{
    return (u8)((kq_input_repeat_keys & mask) != 0);
}
input_current

Devuelve la máscara completa de botones mantenidos de la última actualización.

Sintaxis

c
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

c
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.

input_current: DMG
DMG
input_current: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\input.c .\kitaq-docs\samples\api-examples\gb\input_edges.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\input_edges.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm --no-cache
Implementación y código fuente

kitaqgb/lib/input.h:44

Notas de la declaración (original)
Return the complete held-button mask from the latest update.

kitaqgb/lib/input.c:92

c
u8 input_current()
{
    return kq_input_keys;
}
input_down

Comprueba si está mantenido algún botón seleccionado por mask.

Sintaxis

c
u8 input_down(u8 mask);

Parámetros

mask

Una máscara BTN_* o varias combinadas con |. Basta con que coincida cualquiera de los botones seleccionados; BTN_A | BTN_B no 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

c
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.

input_down: DMG
DMG
input_down: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\input.c .\kitaq-docs\samples\api-examples\gb\input_edges.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\input_edges.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm --no-cache
Implementación y código fuente

kitaqgb/lib/input.h:36

Notas de la declaración (original)
Return whether any masked button is currently held.

kitaqgb/lib/input.c:68

c
u8 input_down(u8 mask)
{
    return (u8)((kq_input_keys & mask) != 0);
}
input_init

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

c
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

c
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.

input_init: DMG
DMG
input_init: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\input.c .\kitaq-docs\samples\api-examples\gb\input_edges.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\input_edges.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm --no-cache
Implementación y código fuente

kitaqgb/lib/input.h:31

Notas de la declaración (original)
Clear sampled/edge state and initialize an independent repeat timer for each button.

kitaqgb/lib/input.c:18

c
void input_init()
{
    u8 i;
    kq_input_prev_keys = 0;
    kq_input_keys = 0;
    kq_input_press_keys = 0;
    kq_input_release_keys = 0;
    kq_input_repeat_keys = 0;
    i = 0;
    while (i < 8) {
        input_repeat_timer[i] = INPUT_REPEAT_DELAY;
        i++;
    }
}
input_pressed

Detecta si un botón de la máscara pasó de suelto a pulsado en la última actualización.

Sintaxis

c
u8 input_pressed(u8 mask);

Parámetros

mask

Una máscara BTN_* o varias combinadas con |. Basta con que coincida cualquiera de los botones seleccionados; BTN_A | BTN_B no 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

c
if (input_pressed(BTN_A)!=0) {
        press_count++; seen_press=1;
        first_down=input_down(BTN_A); first_press=input_pressed(BTN_A);
        first_repeat=input_repeat(BTN_A);
        first_current=input_current(); // Only A held: BTN_A, or decimal 16.
        first_previous=input_previous(); // No buttons in the preceding sample: 0.
        if (first_down!=1 || first_press!=1 || first_repeat!=1) failures++;
        if (first_current!=BTN_A || first_previous!=0) failures++;
        if (input_down(BTN_A|BTN_B)!=1 || input_down(0)!=0) failures++;
    }

Este fragmento 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.

input_pressed: DMG
DMG
input_pressed: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\input.c .\kitaq-docs\samples\api-examples\gb\input_edges.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\input_edges.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm --no-cache
Implementación y código fuente

kitaqgb/lib/input.h:38

Notas de la declaración (original)
Return whether any masked button became pressed in the latest sample.

kitaqgb/lib/input.c:74

c
u8 input_pressed(u8 mask)
{
    return (u8)((kq_input_press_keys & mask) != 0);
}
input_previous

Devuelve la máscara de botones mantenidos anterior a la última actualización.

Sintaxis

c
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

c
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.

input_previous: DMG
DMG
input_previous: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\input.c .\kitaq-docs\samples\api-examples\gb\input_edges.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\input_edges.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm --no-cache
Implementación y código fuente

kitaqgb/lib/input.h:46

Notas de la declaración (original)
Return the held-button mask that preceded the latest update.

kitaqgb/lib/input.c:98

c
u8 input_previous()
{
    return kq_input_prev_keys;
}
input_released

Detecta si un botón de la máscara pasó de pulsado a suelto en la última actualización.

Sintaxis

c
u8 input_released(u8 mask);

Parámetros

mask

Una máscara BTN_* o varias combinadas con |. Basta con que coincida cualquiera de los botones seleccionados; BTN_A | BTN_B no 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

c
if (input_released(BTN_A)!=0) {
        release_result=input_released(BTN_A);
        last_current=input_current(); last_previous=input_previous();
        if (input_down(BTN_A)!=0 || input_pressed(BTN_A)!=0 || input_repeat(BTN_A)!=0) failures++;
        break;
    }

Este fragmento 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.

input_released: DMG
DMG
input_released: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\input.c .\kitaq-docs\samples\api-examples\gb\input_edges.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\input_edges.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm --no-cache
Implementación y código fuente

kitaqgb/lib/input.h:40

Notas de la declaración (original)
Return whether any masked button became released in the latest sample.

kitaqgb/lib/input.c:80

c
u8 input_released(u8 mask)
{
    return (u8)((kq_input_release_keys & mask) != 0);
}
input_repeat

Detecta una pulsación inicial o un pulso de repetición de un botón de la máscara.

Sintaxis

c
u8 input_repeat(u8 mask);

Parámetros

mask

Una máscara BTN_* o varias combinadas con |. Basta con que coincida cualquiera de los botones seleccionados; BTN_A | BTN_B no 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

c
if (input_repeat(BTN_A)!=0) {
        // The initial press is pulse 1. Defaults then wait 19 updates, followed by 6.
        if (repeat_count==1 && held_ticks-previous_pulse!=19) failures++;
        if (repeat_count>1 && held_ticks-previous_pulse!=6) failures++;
        previous_pulse=held_ticks; repeat_count++;
        if (input_repeat(BTN_A)!=1) failures++; // Reading again does not consume it.
    }

Este fragmento 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.

input_repeat: DMG
DMG
input_repeat: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\input.c .\kitaq-docs\samples\api-examples\gb\input_edges.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\input_edges.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm --no-cache
Implementación y código fuente

kitaqgb/lib/input.h:42

Notas de la declaración (original)
Return whether any masked button produced a fresh press or scheduled repeat pulse.

kitaqgb/lib/input.c:86

c
u8 input_repeat(u8 mask)
{
    return (u8)((kq_input_repeat_keys & mask) != 0);
}
input_update

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

c
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

c
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.

input_update: DMG
DMG
input_update: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\input.c .\kitaq-docs\samples\api-examples\gb\input_edges.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\input_edges.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-disasm --no-cache
Implementación y código fuente

kitaqgb/lib/input.h:34

Notas de la declaración (original)
Sample input once per game tick and derive press, release and repeat masks.
Repeat delays are measured in calls to this function, not elapsed wall-clock time.

kitaqgb/lib/input.c:35

c
void input_update()
{
    u8 i;
    u16 kt;

    kq_input_prev_keys = kq_input_keys;
    // The intrinsic packs held buttons in the low byte and new presses in the high byte.
    kt = __readpadex(kq_input_prev_keys);
    kq_input_keys = (u8)kt;
    kq_input_press_keys = (u8)(kt >> 8);
    kq_input_release_keys = (u8)(kq_input_prev_keys & (u8)(kq_input_keys ^ 0xFF));
    kq_input_repeat_keys = kq_input_press_keys;

    i = 0;
    while (i < 8) {
        u8 mask = input_mask_for_index(i);
        if ((kq_input_keys & mask) != 0) {
            if ((kq_input_press_keys & mask) != 0) {
                input_repeat_timer[i] = INPUT_REPEAT_DELAY;
            } else if (input_repeat_timer[i] != 0) {
                input_repeat_timer[i]--;
            } else {
                kq_input_repeat_keys = (u8)(kq_input_repeat_keys | mask);
                input_repeat_timer[i] = INPUT_REPEAT_RATE;
            }
        } else {
            input_repeat_timer[i] = INPUT_REPEAT_DELAY;
        }
        i++;
    }
}

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

c
u8 __stackcall Link4_BeginTransferTo(u8 peer_slot, u8 out);

Parámetros

peer_slot

Posición remota configurada: 1..slot_count−1 desde el anfitrión o 0 desde un interlocutor.

out

Valor 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

c
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.

Link4_BeginTransferTo: DMG
DMG
Link4_BeginTransferTo: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.png
Implementación y código fuente

kitaqgb/lib/link.h:129

Notas de la declaración (original)
Select the logical peer and start a byte exchange, returning the first error.

kitaqgb/lib/link.c:584

c
u8 __stackcall Link4_BeginTransferTo(u8 peer_slot, u8 out) {
    u8 err = Link4_SelectPeer(peer_slot);
    if (err != LINK_ERR_NONE) return err;
    return Link_BeginTransfer(out);
}
Link4_GetLastRxPeer

Lee el interlocutor atribuido al último byte completado.

Sintaxis

c
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

c
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.

Link4_GetLastRxPeer: DMG
DMG
Link4_GetLastRxPeer: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.png
Implementación y código fuente

kitaqgb/lib/link.h:121

Notas de la declaración (original)
Return the peer attributed to the last completed byte transfer.

kitaqgb/lib/link.c:540

c
u8 Link4_GetLastRxPeer() {
    return Link4_LastRxPeer;
}
Link4_GetLastTxPeer

Lee el destino registrado al iniciar la última transferencia de byte.

Sintaxis

c
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

c
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.

Link4_GetLastTxPeer: DMG
DMG
Link4_GetLastTxPeer: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.png
Implementación y código fuente

kitaqgb/lib/link.h:123

Notas de la declaración (original)
Return the peer attributed when the last byte transfer was started.

kitaqgb/lib/link.c:545

c
u8 Link4_GetLastTxPeer() {
    return Link4_LastTxPeer;
}
Link4_GetLocalSlot

Lee la posición configurada de esta máquina.

Sintaxis

c
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

c
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.

Link4_GetLocalSlot: DMG
DMG
Link4_GetLocalSlot: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.png
Implementación y código fuente

kitaqgb/lib/link.h:115

Notas de la declaración (original)
Return the configured zero-based local slot.

kitaqgb/lib/link.c:525

c
u8 Link4_GetLocalSlot() {
    return Link4_LocalSlot;
}
Link4_GetMode

Lee el rol lógico configurado.

Sintaxis

c
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

c
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.

Link4_GetMode: DMG
DMG
Link4_GetMode: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.png
Implementación y código fuente

kitaqgb/lib/link.h:113

Notas de la declaración (original)
Return the configured cooperative role; this is not a hardware connection probe.

kitaqgb/lib/link.c:520

c
u8 Link4_GetMode() {
    return Link4_ModeState;
}
Link4_GetSelectedPeer

Lee el destino lógico seleccionado actualmente.

Sintaxis

c
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

c
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.

Link4_GetSelectedPeer: DMG
DMG
Link4_GetSelectedPeer: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.png
Implementación y código fuente

kitaqgb/lib/link.h:119

Notas de la declaración (original)
Return the current logical destination, or the invalid-slot sentinel when unset.

kitaqgb/lib/link.c:535

c
u8 Link4_GetSelectedPeer() {
    return Link4_SelectedPeer;
}
Link4_GetSlotCount

Lee el total de posiciones configurado.

Sintaxis

c
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

c
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.

Link4_GetSlotCount: DMG
DMG
Link4_GetSlotCount: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.png
Implementación y código fuente

kitaqgb/lib/link.h:117

Notas de la declaración (original)
Return the configured number of logical slots, not a live connection count.

kitaqgb/lib/link.c:530

c
u8 Link4_GetSlotCount() {
    return Link4_SlotCount;
}
Link4_HasByteFrom

Consulta los datos sin leer del búfer de recepción de un interlocutor.

Sintaxis

c
u8 __stackcall Link4_HasByteFrom(u8 peer_slot);

Parámetros

peer_slot

Posició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

c
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.

Link4_HasByteFrom: DMG
DMG
Link4_HasByteFrom: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.png
Implementación y código fuente

kitaqgb/lib/link.h:131

Notas de la declaración (original)
Inspect a valid peer ring without polling the hardware.

kitaqgb/lib/link.c:591

c
u8 __stackcall Link4_HasByteFrom(u8 peer_slot) {
    if (Link4_IsValidRemoteSlotInternal(peer_slot) == 0) return 0;
    if (Link4_RxHead[(__safe_index u8)peer_slot] == Link4_RxTail[(__safe_index u8)peer_slot]) return 0;
    return 1;
}
Link4_HasPacketFrom

Consulta el buzón de paquetes completados de una posición remota.

Sintaxis

c
u8 __stackcall Link4_HasPacketFrom(u8 peer_slot);

Parámetros

peer_slot

Posició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

c
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.

Link4_HasPacketFrom: DMG
DMG
Link4_HasPacketFrom: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.png
Implementación y código fuente

kitaqgb/lib/link.h:142

Notas de la declaración (original)
Inspect the one-packet mailbox for a valid remote slot without consuming it.

kitaqgb/lib/link_packet.c:484

c
u8 __stackcall Link4_HasPacketFrom(u8 peer_slot) {
    return Link4_PacketPeerReady(peer_slot);
}
Link4_InitHost

Inicializa un anfitrión lógico con dos a cuatro posiciones y selecciona el interlocutor 1.

Sintaxis

c
u8 __stackcall Link4_InitHost(u8 slot_count);

Parámetros

slot_count

Nú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

c
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.

Link4_InitHost: DMG
DMG
Link4_InitHost: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.png
Implementación y código fuente

kitaqgb/lib/link.h:108

Notas de la declaración (original)
Cooperative 4-player adapter helpers.

This layer models the common host-selected adapter pattern:
- Slot 0 is always the host.
- The host selects one active peer slot at a time.
- Packet mailboxes stay one-deep per peer.
- The original Link_* API remains available for normal 2-player projects.
Reset as master, validate slot count and select logical peer one. Invalid configuration still discards old link state.

kitaqgb/lib/link.c:489

c
u8 __stackcall Link4_InitHost(u8 slot_count) {
    u8 err;

    Link_InitMaster();
    err = Link4_ValidateConfig(LINK4_MODE_HOST, LINK4_HOST_SLOT, slot_count);
    if (err != LINK_ERR_NONE) {
        Link_SetErrorInternal(err);
        return err;
    }

    Link4_ApplyConfig(LINK4_MODE_HOST, LINK4_HOST_SLOT, slot_count);
    return LINK_ERR_NONE;
}
Link4_InitPeer

Inicializa un interlocutor con reloj externo y selecciona la posición de anfitrión 0.

Sintaxis

c
u8 __stackcall Link4_InitPeer(u8 local_slot, u8 slot_count);

Parámetros

local_slot

Posición local, de 1 a slot_count−1.

slot_count

Total 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

c
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.

Link4_InitPeer: DMG
DMG
Link4_InitPeer: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.png
Implementación y código fuente

kitaqgb/lib/link.h:111

Notas de la declaración (original)
Reset as slave and validate the local nonzero slot and total slot count.
An invalid configuration still discards the previous link state.

kitaqgb/lib/link.c:505

c
u8 __stackcall Link4_InitPeer(u8 local_slot, u8 slot_count) {
    u8 err;

    Link_InitSlave();
    err = Link4_ValidateConfig(LINK4_MODE_PEER, local_slot, slot_count);
    if (err != LINK_ERR_NONE) {
        Link_SetErrorInternal(err);
        return err;
    }

    Link4_ApplyConfig(LINK4_MODE_PEER, local_slot, slot_count);
    return LINK_ERR_NONE;
}
Link4_PollPacket

Avanza una vez el motor de paquetes compartido para el interlocutor seleccionado.

Sintaxis

c
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

c
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.

Link4_PollPacket: DMG
DMG
Link4_PollPacket: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.png
Implementación y código fuente

kitaqgb/lib/link.h:140

Notas de la declaración (original)
Advance the shared packet engine; this does not poll every logical peer in turn.

kitaqgb/lib/link_packet.c:479

c
void Link4_PollPacket() {
    Link_PollPacket();
}
Link4_ReadPacketFrom

Copia un paquete de un interlocutor concreto y lo consume de su buzón.

Sintaxis

c
u8 __stackcall Link4_ReadPacketFrom(u8 peer_slot, u8 *cmd, u8 *len, u8 *dst);

Parámetros

peer_slot

Posición remota configurada: 1..slot_count−1 desde el anfitrión o 0 desde un interlocutor.

cmd

Byte de orden escribible; null omite esta salida.

len

Byte de longitud escribible, de 0 a 24; null omite esta salida.

dst

Bú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

c
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.

Link4_ReadPacketFrom: DMG
DMG
Link4_ReadPacketFrom: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.png
Implementación y código fuente

kitaqgb/lib/link.h:146

Notas de la declaración (original)
Consume a peer mailbox, copying to optional outputs. A nonnull destination
needs room for the entire payload. Clear the shared mailbox only when it
refers to this same peer.

kitaqgb/lib/link_packet.c:491

c
u8 __stackcall Link4_ReadPacketFrom(u8 peer_slot, u8 *cmd, u8 *len, u8 *dst) {
    u8 i;
    u8 offset;

    if (Link4_PacketPeerReady(peer_slot) == 0) return 0;

    if (cmd != 0) *cmd = Link4_ReceivedPacketCmd[(__safe_index u8)peer_slot];
    if (len != 0) *len = Link4_ReceivedPacketLen[(__safe_index u8)peer_slot];

    if (dst != 0) {
        for (i = 0; i < Link4_ReceivedPacketLen[(__safe_index u8)peer_slot]; ++i) {
            offset = Link4_PacketOffset(peer_slot, i);
            dst[(__safe_index u8)i] = Link4_ReceivedPacketBuf[(__safe_index u8)offset];
        }
    }

    Link4_ReceivedPacketReady[(__safe_index u8)peer_slot] = 0;
    if (Link4_LastPacketPeer == peer_slot) {
        Link_ReceivedPacketReady = 0;
        Link4_LastPacketPeer = LINK4_INVALID_SLOT;
    }
    return 1;
}
Link4_SelectPeer

Consulta la finalización y cambia el destino lógico solo cuando está inactivo.

Sintaxis

c
u8 __stackcall Link4_SelectPeer(u8 peer_slot);

Parámetros

peer_slot

Posició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

c
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.

Link4_SelectPeer: DMG
DMG
Link4_SelectPeer: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.png
Implementación y código fuente

kitaqgb/lib/link.h:127

Notas de la declaración (original)
Poll completion, then change the logical destination only while byte and
packet state are idle. A peer can select only the host. No adapter-routing
command is sent here; the transport must provide the matching physical route.

kitaqgb/lib/link.c:552

c
u8 __stackcall Link4_SelectPeer(u8 peer_slot) {
    Link_Poll();

    if (Link4_IsEnabledInternal() == 0) {
        Link_SetErrorInternal(LINK_ERR_PROTOCOL);
        return LINK_ERR_PROTOCOL;
    }

    if (Link_Busy != 0 || Link_PacketState != LINK_PKT_STATE_IDLE || Link_PendingAck != 0) {
        Link_SetErrorInternal(LINK_ERR_BUSY);
        return LINK_ERR_BUSY;
    }

    if (Link4_ModeState == LINK4_MODE_HOST) {
        if (Link4_IsValidRemoteSlotInternal(peer_slot) == 0) {
            Link_SetErrorInternal(LINK_ERR_PROTOCOL);
            return LINK_ERR_PROTOCOL;
        }
        Link4_SelectedPeer = peer_slot;
        return LINK_ERR_NONE;
    }

    if (Link4_ModeState == LINK4_MODE_PEER && peer_slot == LINK4_HOST_SLOT) {
        Link4_SelectedPeer = LINK4_HOST_SLOT;
        return LINK_ERR_NONE;
    }

    Link_SetErrorInternal(LINK_ERR_PROTOCOL);
    return LINK_ERR_PROTOCOL;
}
Link4_SendPacketTo

Selecciona un interlocutor lógico, copia el paquete y programa su transmisión.

Sintaxis

c
u8 __stackcall Link4_SendPacketTo(u8 peer_slot, const u8 *data, u8 len, u8 cmd);

Parámetros

peer_slot

Posición remota configurada: 1..slot_count−1 desde el anfitrión o 0 desde un interlocutor.

data

Origen legible de len bytes; solo puede ser null si len es cero.

len

Longitud de la carga útil en bytes, de 0 a 24.

cmd

Orden 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

c
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.

Link4_SendPacketTo: DMG
DMG
Link4_SendPacketTo: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.png
Implementación y código fuente

kitaqgb/lib/link.h:138

Notas de la declaración (original)
Select a logical peer, then copy and schedule a packet; return the first error.

kitaqgb/lib/link_packet.c:472

c
u8 __stackcall Link4_SendPacketTo(u8 peer_slot, const u8 *data, u8 len, u8 cmd) {
    u8 err = Link4_SelectPeer(peer_slot);
    if (err != LINK_ERR_NONE) return err;
    return Link_SendPacket(data, len, cmd);
}
Link4_TryReadByteAny

Recorre las posiciones remotas en orden ascendente y extrae el primer byte disponible.

Sintaxis

c
u8 __stackcall Link4_TryReadByteAny(u8 *peer_slot, u8 *out);

Parámetros

peer_slot

Byte escribible para la posición de origen; null omite esa salida.

out

Destino 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

c
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.

Link4_TryReadByteAny: DMG
DMG
Link4_TryReadByteAny: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.png
Implementación y código fuente

kitaqgb/lib/link.h:136

Notas de la declaración (original)
Scan remote rings in increasing slot order and return the first available
byte. Null output pointers are allowed; lower slots have polling priority.

kitaqgb/lib/link.c:604

c
u8 __stackcall Link4_TryReadByteAny(u8 *peer_slot, u8 *out) {
    u8 slot;

    if (Link4_IsEnabledInternal() == 0) return 0;

    for (slot = 0; slot < Link4_SlotCount; ++slot) {
        if (slot != Link4_LocalSlot) {
            if (Link4_PopRxByte(slot, out) != 0) {
                if (peer_slot != 0) *peer_slot = slot;
                return 1;
            }
        }
    }

    return 0;
}
Link4_TryReadByteFrom

Extrae un byte del búfer de recepción de un interlocutor concreto.

Sintaxis

c
u8 __stackcall Link4_TryReadByteFrom(u8 peer_slot, u8 *out);

Parámetros

peer_slot

Posición remota configurada: 1..slot_count−1 desde el anfitrión o 0 desde un interlocutor.

out

Destino 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

c
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.

Link4_TryReadByteFrom: DMG
DMG
Link4_TryReadByteFrom: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_host.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_host.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer1.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer1.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer2.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\link_four_peer3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\link_four_peer3.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology link4 --run-frames 360 --link-session "name=four_host|slot=0|rom=.\out\link_four_host.gb|save_state=.\out\four_host.kqs" --link-session "name=four_peer1|slot=1|rom=.\out\link_four_peer1.gb|save_state=.\out\four_peer1.kqs" --link-session "name=four_peer2|slot=2|rom=.\out\link_four_peer2.gb|save_state=.\out\four_peer2.kqs" --link-session "name=four_peer3|slot=3|rom=.\out\link_four_peer3.gb|save_state=.\out\four_peer3.kqs"
.\kokura\kokura-cli.exe .\out\link_four_host.gb --hardware cgb --load-state .\out\four_host.kqs --run-frames 2 --png .\out\four_host.png
.\kokura\kokura-cli.exe .\out\link_four_peer1.gb --hardware cgb --load-state .\out\four_peer1.kqs --run-frames 2 --png .\out\four_peer1.png
.\kokura\kokura-cli.exe .\out\link_four_peer2.gb --hardware cgb --load-state .\out\four_peer2.kqs --run-frames 2 --png .\out\four_peer2.png
.\kokura\kokura-cli.exe .\out\link_four_peer3.gb --hardware cgb --load-state .\out\four_peer3.kqs --run-frames 2 --png .\out\four_peer3.png
Implementación y código fuente

kitaqgb/lib/link.h:133

Notas de la declaración (original)
Pop one byte from the selected peer ring; null output discards it.

kitaqgb/lib/link.c:598

c
u8 __stackcall Link4_TryReadByteFrom(u8 peer_slot, u8 *out) {
    return Link4_PopRxByte(peer_slot, out);
}

DMG-07 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

c
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

c
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.

LinkDmg07_ClearError: DMG / jugador 1
DMG / jugador 1
LinkDmg07_ClearError: CGB / jugador 1
CGB / jugador 1

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_overflow.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_overflow.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_overflow.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_overflow.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_overflow.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_overflow.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_overflow.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_overflow.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_overflow.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_overflow.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.png
Implementación y código fuente

kitaqgb/lib/link_dmg07.h:125

Notas de la declaración (original)
Clear only the latest error code, preserving counters and protocol state.

kitaqgb/lib/link_dmg07.c:541

c
void LinkDmg07_ClearError() {
    LinkDmg07_LastErrorCode = LINK_DMG07_ERR_NONE;
}
LinkDmg07_ConsumePingStatus

Consume y borra una notificación de descubrimiento completado.

Sintaxis

c
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

c
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.

LinkDmg07_ConsumePingStatus: DMG / jugador 1
DMG / jugador 1
LinkDmg07_ConsumePingStatus: CGB / jugador 1
CGB / jugador 1

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.png
Implementación y código fuente

kitaqgb/lib/link_dmg07.h:71

Notas de la declaración (original)
Clear and report the completed-discovery flag; return zero if no new status exists.

kitaqgb/lib/link_dmg07.c:418

c
u8 LinkDmg07_ConsumePingStatus() {
    if (LinkDmg07_PingStatusReady == 0) return 0;
    LinkDmg07_PingStatusReady = 0;
    return 1;
}
LinkDmg07_GetConnectedMask

Lee el conjunto de jugadores de cuatro bits del último estado aceptado.

Sintaxis

c
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

c
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.

LinkDmg07_GetConnectedMask: DMG / jugador 1
DMG / jugador 1
LinkDmg07_GetConnectedMask: CGB / jugador 1
CGB / jugador 1

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.png
Implementación y código fuente

kitaqgb/lib/link_dmg07.h:65

Notas de la declaración (original)
Normalized mask: bit 0 is player 1, ..., bit 3 is player 4.

kitaqgb/lib/link_dmg07.c:403

c
u8 LinkDmg07_GetConnectedMask() {
    return LinkDmg07_ConnectedMask;
}
LinkDmg07_GetDisconnectCount

Lee las pérdidas registradas: silencio tras detectar adaptador o jugadores que desaparecen del estado de descubrimiento.

Sintaxis

c
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

c
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.

LinkDmg07_GetDisconnectCount: DMG / jugador 1
DMG / jugador 1
LinkDmg07_GetDisconnectCount: CGB / jugador 1
CGB / jugador 1

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_absent.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_absent.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe .\out\dmg07_absent.gb --hardware cgb --run-frames 90 --png .\out\absent.png
Implementación y código fuente

kitaqgb/lib/link_dmg07.h:118

Notas de la declaración (original)
Return the saturating count of removed-player and previously-seen-adapter timeout events.

kitaqgb/lib/link_dmg07.c:525

c
u8 LinkDmg07_GetDisconnectCount() {
    return LinkDmg07_DisconnectCount;
}
LinkDmg07_GetErrorCount

Lee el número de errores de protocolo recibidos y sobrescrituras de paquetes sin leer.

Sintaxis

c
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

c
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.

LinkDmg07_GetErrorCount: DMG / jugador 1
DMG / jugador 1
LinkDmg07_GetErrorCount: CGB / jugador 1
CGB / jugador 1

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_overflow.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_overflow.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_overflow.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_overflow.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_overflow.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_overflow.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_overflow.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_overflow.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_overflow.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_overflow.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.png
Implementación y código fuente

kitaqgb/lib/link_dmg07.h:121

Notas de la declaración (original)
Return the saturating protocol/overflow error count. Timeout and request
validation paths use separate counters or latches and do not increment this value.

kitaqgb/lib/link_dmg07.c:531

c
u8 LinkDmg07_GetErrorCount() {
    return LinkDmg07_ErrorCount;
}
LinkDmg07_GetLastStatus

Lee el último byte de estado bruto validado del adaptador.

Sintaxis

c
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

c
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.

LinkDmg07_GetLastStatus: DMG / jugador 1
DMG / jugador 1
LinkDmg07_GetLastStatus: CGB / jugador 1
CGB / jugador 1

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.png
Implementación y código fuente

kitaqgb/lib/link_dmg07.h:67

Notas de la declaración (original)
Return the last validated raw adapter status byte.

kitaqgb/lib/link_dmg07.c:408

c
u8 LinkDmg07_GetLastStatus() {
    return LinkDmg07_LastStatus;
}
LinkDmg07_GetLocalSlot

Lee el número de jugador de esta consola obtenido del estado del adaptador.

Sintaxis

c
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

c
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.

LinkDmg07_GetLocalSlot: DMG / jugador 1
DMG / jugador 1
LinkDmg07_GetLocalSlot: CGB / jugador 1
CGB / jugador 1

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.png
Implementación y código fuente

kitaqgb/lib/link_dmg07.h:62

Notas de la declaración (original)
Return the one-based player slot, or LINK_DMG07_NO_SLOT before discovery.

kitaqgb/lib/link_dmg07.c:398

c
u8 LinkDmg07_GetLocalSlot() {
    return LinkDmg07_LocalSlot;
}
LinkDmg07_GetPacketSequence

Lee la secuencia asignada al último paquete publicado.

Sintaxis

c
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

c
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.

LinkDmg07_GetPacketSequence: DMG / jugador 1
DMG / jugador 1
LinkDmg07_GetPacketSequence: CGB / jugador 1
CGB / jugador 1

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.png
Implementación y código fuente

kitaqgb/lib/link_dmg07.h:109

Notas de la declaración (original)
Return the modulo-256 sequence associated with the most recently published packet.

kitaqgb/lib/link_dmg07.c:510

c
u8 LinkDmg07_GetPacketSequence() {
    return LinkDmg07_PacketSequence;
}
LinkDmg07_GetPacketSlot

Lee el byte de un jugador del paquete guardado.

Sintaxis

c
u8 __stackcall LinkDmg07_GetPacketSlot(u8 player_slot);

Parámetros

player_slot

Nú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

c
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.

LinkDmg07_GetPacketSlot: DMG / jugador 1
DMG / jugador 1
LinkDmg07_GetPacketSlot: CGB / jugador 1
CGB / jugador 1

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.png
Implementación y código fuente

kitaqgb/lib/link_dmg07.h:102

Notas de la declaración (original)
Read one cached player byte using a one-based slot. Invalid slots return
zero; the function neither requires readiness nor consumes the packet.

kitaqgb/lib/link_dmg07.c:499

c
u8 __stackcall LinkDmg07_GetPacketSlot(u8 player_slot) {
    if ((player_slot == 0) || (player_slot > LINK_DMG07_MAX_PLAYERS)) return 0;
    return LinkDmg07_RxPacket[(__safe_index u8)(player_slot - 1)];
}
LinkDmg07_GetPhase

Lee la fase actual: descubrimiento, solicitud de inicio, confirmación o transferencia.

Sintaxis

c
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

c
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.

LinkDmg07_GetPhase: DMG / jugador 1
DMG / jugador 1
LinkDmg07_GetPhase: CGB / jugador 1
CGB / jugador 1

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.png
Implementación y código fuente

kitaqgb/lib/link_dmg07.h:60

Notas de la declaración (original)
Return the discovery, start-handshake or transfer phase without polling.

kitaqgb/lib/link_dmg07.c:393

c
u8 LinkDmg07_GetPhase() {
    return LinkDmg07_Phase;
}
LinkDmg07_GetRestartState

Lee si el control de reinicio está ausente, pendiente o enviándose.

Sintaxis

c
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

c
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.

LinkDmg07_GetRestartState: DMG / jugador 2
DMG / jugador 2
LinkDmg07_GetRestartState: CGB / jugador 2
CGB / jugador 2

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_restart.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_restart.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_restart.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_restart.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_restart.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_restart.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_restart.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_restart.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_restart.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_restart.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.png
Implementación y código fuente

kitaqgb/lib/link_dmg07.h:85

Notas de la declaración (original)
Return whether aligned recovery is absent, pending or sending control traffic.

kitaqgb/lib/link_dmg07.c:457

c
u8 LinkDmg07_GetRestartState() {
    return LinkDmg07_RestartState;
}
LinkDmg07_GetSentSequence

Lee el número de bytes de aplicación realmente transmitidos con el reloj.

Sintaxis

c
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

c
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.

LinkDmg07_GetSentSequence: DMG / jugador 1
DMG / jugador 1
LinkDmg07_GetSentSequence: CGB / jugador 1
CGB / jugador 1

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.png
Implementación y código fuente

kitaqgb/lib/link_dmg07.h:107

Notas de la declaración (original)
SentSequence increments when this console's packet byte is clocked out.
PacketSequence labels the returned four-byte packet.  For a valid packet it
is one less than SentSequence, making the DMG-07 one-packet delay explicit.

kitaqgb/lib/link_dmg07.c:505

c
u8 LinkDmg07_GetSentSequence() {
    return LinkDmg07_SentSequence;
}
LinkDmg07_GetSilenceFrames

Lee los fotogramas contados desde la última finalización serie procesada.

Sintaxis

c
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

c
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.

LinkDmg07_GetSilenceFrames: DMG / jugador 1
DMG / jugador 1
LinkDmg07_GetSilenceFrames: CGB / jugador 1
CGB / jugador 1

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_absent.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_absent.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe .\out\dmg07_absent.gb --hardware cgb --run-frames 90 --png .\out\absent.png
Implementación y código fuente

kitaqgb/lib/link_dmg07.h:114

Notas de la declaración (original)
SilenceFrames is reset by every completed serial byte.  TimeoutCount counts
distinct serial-silence or AA/CC/restart handshake timeouts. DisconnectCount counts
adapter-silence outages and ping-status membership drops.  All saturate.

kitaqgb/lib/link_dmg07.c:515

c
u8 LinkDmg07_GetSilenceFrames() {
    return LinkDmg07_SilenceFrames;
}
LinkDmg07_GetTimeoutCount

Lee el número de plazos agotados de silencio o negociación.

Sintaxis

c
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

c
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.

LinkDmg07_GetTimeoutCount: DMG / jugador 1
DMG / jugador 1
LinkDmg07_GetTimeoutCount: CGB / jugador 1
CGB / jugador 1

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_absent.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_absent.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe .\out\dmg07_absent.gb --hardware cgb --run-frames 90 --png .\out\absent.png
Implementación y código fuente

kitaqgb/lib/link_dmg07.h:116

Notas de la declaración (original)
Return the saturating lifetime timeout count, preserved across protocol restarts.

kitaqgb/lib/link_dmg07.c:520

c
u8 LinkDmg07_GetTimeoutCount() {
    return LinkDmg07_TimeoutCount;
}
LinkDmg07_HasPacket

Comprueba si hay un paquete completo de cuatro bytes sin leer.

Sintaxis

c
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

c
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.

LinkDmg07_HasPacket: DMG / jugador 1
DMG / jugador 1
LinkDmg07_HasPacket: CGB / jugador 1
CGB / jugador 1

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.png
Implementación y código fuente

kitaqgb/lib/link_dmg07.h:96

Notas de la declaración (original)
Inspect the one-packet receive mailbox without consuming it.

kitaqgb/lib/link_dmg07.c:473

c
u8 LinkDmg07_HasPacket() {
    return LinkDmg07_PacketReady;
}
LinkDmg07_HasPingStatus

Comprueba si un intercambio de descubrimiento de cuatro bytes completado espera confirmación.

Sintaxis

c
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

c
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.

LinkDmg07_HasPingStatus: DMG / jugador 1
DMG / jugador 1
LinkDmg07_HasPingStatus: CGB / jugador 1
CGB / jugador 1

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.png
Implementación y código fuente

kitaqgb/lib/link_dmg07.h:69

Notas de la declaración (original)
Read the completed-discovery status flag without clearing it.

kitaqgb/lib/link_dmg07.c:413

c
u8 LinkDmg07_HasPingStatus() {
    return LinkDmg07_PingStatusReady;
}
LinkDmg07_Init

Restablece descubrimiento, almacenamiento de recepción y diagnósticos, y prepara la recepción con el reloj del adaptador.

Sintaxis

c
void __stackcall LinkDmg07_Init(u8 rate);

Parámetros

rate

Respuesta 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

c
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.

LinkDmg07_Init: DMG / jugador 1
DMG / jugador 1
LinkDmg07_Init: CGB / jugador 1
CGB / jugador 1

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.png
Implementación y código fuente

kitaqgb/lib/link_dmg07.h:50

Notas de la declaración (original)
Initializes polling-only external-clock operation.  A zero RATE is replaced
with LINK_DMG07_DEFAULT_RATE.  This driver disables only the serial IRQ bit.

kitaqgb/lib/link_dmg07.c:282

c
void __stackcall LinkDmg07_Init(u8 rate) {
    u8 i;

    LinkDmg07_Rate = rate;
    if (LinkDmg07_Rate == 0) LinkDmg07_Rate = LINK_DMG07_DEFAULT_RATE;
    LinkDmg07_LocalByte = 0;
    LinkDmg07_SentSequence = 0;
    LinkDmg07_PacketSequence = 0;
    LinkDmg07_RestartState = LINK_DMG07_RESTART_NONE;
    LinkDmg07_SilenceFrames = 0;
    LinkDmg07_TimeoutCount = 0;
    LinkDmg07_DisconnectCount = 0;
    LinkDmg07_ErrorCount = 0;
    LinkDmg07_LastErrorCode = LINK_DMG07_ERR_NONE;
    LinkDmg07_SeenAdapter = 0;
    LinkDmg07_TimeoutLatched = 0;
    for (i = 0; i < LINK_DMG07_PACKET_BYTES; ++i) {
        LinkDmg07_RxBuild[(__safe_index u8)i] = 0;
        LinkDmg07_RxPacket[(__safe_index u8)i] = 0;
    }
    LinkDmg07_ResetToPingInternal();

    LinkHw_WriteIE((u8)(LinkHw_ReadIE() & LINK_DMG07_IRQ_SERIAL_CLEAR));
    LinkHw_WriteIF((u8)(LinkHw_ReadIF() & LINK_DMG07_IRQ_SERIAL_CLEAR));
    LinkDmg07_ArmInternal(LINK_DMG07_ACK);
}
LinkDmg07_IsPipelinePrimed

Comprueba si se ha descartado la difusión inicial indefinida.

Sintaxis

c
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

c
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.

LinkDmg07_IsPipelinePrimed: DMG / jugador 1
DMG / jugador 1
LinkDmg07_IsPipelinePrimed: CGB / jugador 1
CGB / jugador 1

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.png
Implementación y código fuente

kitaqgb/lib/link_dmg07.h:94

Notas de la declaración (original)
The first incoming adapter data packet is discarded.  Thereafter ReadPacket
copies four bytes in physical slot order (players 1..4).

kitaqgb/lib/link_dmg07.c:468

c
u8 LinkDmg07_IsPipelinePrimed() {
    return LinkDmg07_PipelinePrimed;
}
LinkDmg07_LastError

Lee el último código de error registrado.

Sintaxis

c
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

c
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.

LinkDmg07_LastError: DMG / jugador 1
DMG / jugador 1
LinkDmg07_LastError: CGB / jugador 1
CGB / jugador 1

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_absent.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_absent.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe .\out\dmg07_absent.gb --hardware cgb --run-frames 90 --png .\out\absent.png
Implementación y código fuente

kitaqgb/lib/link_dmg07.h:123

Notas de la declaración (original)
Return the latest error latch without clearing counters or restarting the protocol.

kitaqgb/lib/link_dmg07.c:536

c
u8 LinkDmg07_LastError() {
    return LinkDmg07_LastErrorCode;
}
LinkDmg07_Poll

Procesa un byte serie completado en la fase actual y prepara de inmediato la siguiente respuesta.

Sintaxis

c
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

c
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.

LinkDmg07_Poll: DMG / jugador 1
DMG / jugador 1
LinkDmg07_Poll: CGB / jugador 1
CGB / jugador 1

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.png
Implementación y código fuente

kitaqgb/lib/link_dmg07.h:54

Notas de la declaración (original)
Services at most one completed serial byte and immediately re-arms SC=$80.
Call continuously from the main loop, including between VBlanks.

kitaqgb/lib/link_dmg07.c:311

c
void LinkDmg07_Poll() {
    u8 value;
    u8 next;

    if ((LinkHw_ReadSC() & LINK_DMG07_SC_EXTERNAL_START) != 0) return;

    value = LinkHw_ReadSB();
    LinkDmg07_SilenceFrames = 0;
    LinkDmg07_TimeoutLatched = 0;
    LinkDmg07_SeenAdapter = 1;

    next = 0;
    if (LinkDmg07_Phase == LINK_DMG07_PHASE_PING) {
        next = LinkDmg07_ProcessPingInternal(value);
    } else if (LinkDmg07_Phase == LINK_DMG07_PHASE_REQUEST_AA) {
        next = LinkDmg07_ProcessRequestInternal(value);
    } else if (LinkDmg07_Phase == LINK_DMG07_PHASE_WAIT_CC) {
        next = LinkDmg07_ProcessWaitCcInternal(value);
    } else if (LinkDmg07_Phase == LINK_DMG07_PHASE_TRANSFER) {
        next = LinkDmg07_ProcessTransferInternal(value);
    } else {
        LinkDmg07_SetRuntimeErrorInternal(LINK_DMG07_ERR_PROTOCOL);
        LinkDmg07_ResetToPingInternal();
        next = LINK_DMG07_ACK;
    }

    LinkDmg07_ArmInternal(next);
}
LinkDmg07_ReadPacket

Copia el último paquete completo y borra su indicador de no leído.

Sintaxis

c
u8 __stackcall LinkDmg07_ReadPacket(u8 *dst);

Parámetros

dst

Cuatro 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

c
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.

LinkDmg07_ReadPacket: DMG / jugador 1
DMG / jugador 1
LinkDmg07_ReadPacket: CGB / jugador 1
CGB / jugador 1

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.png
Implementación y código fuente

kitaqgb/lib/link_dmg07.h:99

Notas de la declaración (original)
Consume the latest four-byte packet. A nonnull destination must hold four
bytes; null discards the packet. Packet storage remains after the flag clears.

kitaqgb/lib/link_dmg07.c:479

c
u8 __stackcall LinkDmg07_ReadPacket(u8 *dst) {
    if (LinkDmg07_PacketReady == 0) return 0;
    if (dst != 0) {
        // Keep this as a sequential pointer copy.  Besides being smaller for a
        // fixed four-byte packet, it avoids making a serial hot-path copy
        // depend on general variable-index pointer lowering.
        *dst = LinkDmg07_RxPacket[0];
        dst++;
        *dst = LinkDmg07_RxPacket[1];
        dst++;
        *dst = LinkDmg07_RxPacket[2];
        dst++;
        *dst = LinkDmg07_RxPacket[3];
    }
    LinkDmg07_PacketReady = 0;
    return 1;
}
LinkDmg07_RequestRestart

Programa tráfico de control de reinicio a partir de un límite de paquete de transferencia.

Sintaxis

c
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

c
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.

LinkDmg07_RequestRestart: DMG / jugador 2
DMG / jugador 2
LinkDmg07_RequestRestart: CGB / jugador 2
CGB / jugador 2

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_restart.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_restart.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_restart.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_restart.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_restart.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_restart.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_restart.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_restart.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_restart.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_restart.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.png
Implementación y código fuente

kitaqgb/lib/link_dmg07.h:83

Notas de la declaración (original)
Any physical slot may schedule FF FF FF FF at the next four-byte packet
boundary while remaining in TRANSFER phase.  The driver keeps sending aligned
FF bytes until it sees the adapter's complete all-FF indicator packet, then
returns to PING.  A transfer-phase silence timeout schedules the same recovery
automatically and preserves the current byte position for clocks that resume.

kitaqgb/lib/link_dmg07.c:445

c
u8 LinkDmg07_RequestRestart() {
    if (LinkDmg07_Phase != LINK_DMG07_PHASE_TRANSFER) {
        LinkDmg07_LastErrorCode = LINK_DMG07_ERR_STATE;
        return LINK_DMG07_ERR_STATE;
    }
    if (LinkDmg07_RestartState == LINK_DMG07_RESTART_NONE) {
        LinkDmg07_RestartState = LINK_DMG07_RESTART_PENDING;
    }
    return LINK_DMG07_ERR_NONE;
}
LinkDmg07_RequestTransmission

Programa la solicitud de inicio del jugador físico 1 en el siguiente límite de paquete de descubrimiento.

Sintaxis

c
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

c
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.

LinkDmg07_RequestTransmission: DMG / jugador 1
DMG / jugador 1
LinkDmg07_RequestTransmission: CGB / jugador 1
CGB / jugador 1

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.png
Implementación y código fuente

kitaqgb/lib/link_dmg07.h:76

Notas de la declaración (original)
Only physical player 1 may request AA AA AA AA.  The bytes are aligned to
the next FE/status/status/status ping packet.  All consoles enter transfer
mode only after receiving four consecutive CC bytes.

kitaqgb/lib/link_dmg07.c:426

c
u8 LinkDmg07_RequestTransmission() {
    if (LinkDmg07_Phase != LINK_DMG07_PHASE_PING) {
        LinkDmg07_LastErrorCode = LINK_DMG07_ERR_STATE;
        return LINK_DMG07_ERR_STATE;
    }
    if (LinkDmg07_LocalSlot != 1) {
        LinkDmg07_LastErrorCode = LINK_DMG07_ERR_NOT_PLAYER1;
        return LINK_DMG07_ERR_NOT_PLAYER1;
    }
    if ((LinkDmg07_ConnectedMask & (u8)0x01) == 0) {
        LinkDmg07_LastErrorCode = LINK_DMG07_ERR_NOT_READY;
        return LINK_DMG07_ERR_NOT_READY;
    }
    LinkDmg07_StartRequested = 1;
    return LINK_DMG07_ERR_NONE;
}
LinkDmg07_SetLocalByte

Establece el valor de aplicación de un byte para un próximo paquete saliente.

Sintaxis

c
void __stackcall LinkDmg07_SetLocalByte(u8 value);

Parámetros

value

Valor 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

c
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.

LinkDmg07_SetLocalByte: DMG / jugador 1
DMG / jugador 1
LinkDmg07_SetLocalByte: CGB / jugador 1
CGB / jugador 1

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_exchange.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_exchange.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe --link-topology dmg07 --run-frames 90 --link-session "name=player1|slot=0|rom=.\out\dmg07_exchange.gb|save_state=.\out\player1.kqs" --link-session "name=player2|slot=1|rom=.\out\dmg07_exchange.gb|save_state=.\out\player2.kqs" --link-session "name=player3|slot=2|rom=.\out\dmg07_exchange.gb|save_state=.\out\player3.kqs" --link-session "name=player4|slot=3|rom=.\out\dmg07_exchange.gb|save_state=.\out\player4.kqs"
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player1.kqs --run-frames 2 --png .\out\player1.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player2.kqs --run-frames 2 --png .\out\player2.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player3.kqs --run-frames 2 --png .\out\player3.png
.\kokura\kokura-cli.exe .\out\dmg07_exchange.gb --hardware cgb --load-state .\out\player4.kqs --run-frames 2 --png .\out\player4.png
Implementación y código fuente

kitaqgb/lib/link_dmg07.h:90

Notas de la declaración (original)
Sets the byte sampled when byte 0 of the next adapter packet is armed.
Set it before the current packet completes (and before requesting start for
the first submission).  During normal transfer, bytes 1..3 are sent as zero.

kitaqgb/lib/link_dmg07.c:463

c
void __stackcall LinkDmg07_SetLocalByte(u8 value) {
    LinkDmg07_LocalByte = value;
}
LinkDmg07_TickFrame

Avanza un fotograma las vigilancias de silencio e inicio/reinicio y solicita recuperación al alcanzar el plazo.

Sintaxis

c
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

c
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.

LinkDmg07_TickFrame: DMG / jugador 1
DMG / jugador 1
LinkDmg07_TickFrame: CGB / jugador 1
CGB / jugador 1

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dmg07_absent.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dmg07_absent.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
.\kokura\kokura-cli.exe .\out\dmg07_absent.gb --hardware cgb --run-frames 90 --png .\out\absent.png
Implementación y código fuente

kitaqgb/lib/link_dmg07.h:57

Notas de la declaración (original)
Advances saturating frame-based silence and handshake timeout counters.

kitaqgb/lib/link_dmg07.c:369

c
void LinkDmg07_TickFrame() {
    LinkDmg07_SilenceFrames = LinkDmg07_IncrementSaturatingInternal(LinkDmg07_SilenceFrames);

    if ((LinkDmg07_Phase == LINK_DMG07_PHASE_REQUEST_AA) ||
        (LinkDmg07_Phase == LINK_DMG07_PHASE_WAIT_CC) ||
        (LinkDmg07_RestartState == LINK_DMG07_RESTART_SENDING)) {
        LinkDmg07_HandshakeFrames = LinkDmg07_IncrementSaturatingInternal(LinkDmg07_HandshakeFrames);
    } else {
        LinkDmg07_HandshakeFrames = 0;
    }

    if ((LinkDmg07_SilenceFrames >= LINK_DMG07_TIMEOUT_FRAMES) &&
        (LinkDmg07_TimeoutLatched == 0)) {
        LinkDmg07_TimeoutInternal(1);
        return;
    }

    if ((LinkDmg07_HandshakeFrames >= LINK_DMG07_TIMEOUT_FRAMES) &&
        (LinkDmg07_TimeoutLatched == 0)) {
        LinkDmg07_TimeoutInternal(0);
    }
}

physics2d.h — 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

c
void kq2d_body_apply_friction(KQBody2D* body, u8 friction_q8);

Parámetros

body

Puntero al cuerpo que se va a modificar. Los campos que no usa esta operación se conservan.

friction_q8

Multiplicador 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

c
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.

kq2d_body_apply_friction: DMG — 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.
DMG — 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.
kq2d_body_apply_friction: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body2d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body2d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/physics2d.h:66

Notas de la declaración (original)
Scale both velocities through the signed 8-bit coefficient intrinsic.
Despite the unsigned parameter, values 128..255 become negative coefficients;
this is not a full-range unsigned Q8 damping helper. Null is ignored.

kitaqgb/lib/physics2d.c:654

c
void kq2d_body_apply_friction(KQBody2D* body, u8 friction_q8)
{
    if (body == 0) return;
    body->vx = (s16)__smul16x8(body->vx, (s8)friction_q8);
    body->vy = (s16)__smul16x8(body->vy, (s8)friction_q8);
}
kq2d_body_apply_gravity

Añade gravedad a un cuerpo dinámico activo y limita cada eje a +/-max_speed sin actualizar la posición.

Sintaxis

c
void kq2d_body_apply_gravity(KQBody2D* body, s16 gravity_x, s16 gravity_y, s16 max_speed);

Parámetros

body

Puntero al cuerpo que se va a modificar. Los campos que no usa esta operación se conservan.

gravity_x

Aceleración que esta llamada suma a la velocidad X.

gravity_y

Aceleración que esta llamada suma a la velocidad Y.

max_speed

Lí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

c
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.

kq2d_body_apply_gravity: DMG — 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.
DMG — 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.
kq2d_body_apply_gravity: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body2d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body2d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/physics2d.h:62

Notas de la declaración (original)
Add gravity and clamp each velocity axis separately for an active dynamic
body. Null, inactive and static bodies are ignored. Supply a nonnegative limit
and avoid overflow in the additions before clamping; position is unchanged.

kitaqgb/lib/physics2d.c:630

c
void kq2d_body_apply_gravity(KQBody2D* body, s16 gravity_x, s16 gravity_y, s16 max_speed)
{
    if (body == 0) return;
    if (body->active == 0) return;
    if (body->inv_mass_q8 <= 0) return;

    kq2d_asm_value = body->vx;
    kq2d_asm_operand = gravity_x;
    kq2d_add_s16_asm();
    kq2d_asm_limit = max_speed;
    kq2d_clamp_abs_s16_asm();
    body->vx = kq2d_asm_value;

    kq2d_asm_value = body->vy;
    kq2d_asm_operand = gravity_y;
    kq2d_add_s16_asm();
    kq2d_asm_limit = max_speed;
    kq2d_clamp_abs_s16_asm();
    body->vy = kq2d_asm_value;
}
kq2d_body_init

Inicializa una caja definida por su centro con las semiextensiones indicadas, velocidad cero, masa inversa 256 y estado activo.

Sintaxis

c
void kq2d_body_init(KQBody2D* body, s16 x, s16 y, s16 half_x, s16 half_y);

Parámetros

body

Puntero al cuerpo que se va a modificar. Los campos que no usa esta operación se conservan.

x

Coordenada X del centro o del punto, en píxeles en el ejemplo.

y

Coordenada Y del centro o del punto; en el ejemplo, el sentido positivo es hacia abajo.

half_x

Semiextensión en X; el ancho total de la caja es el doble de este valor.

half_y

Semiextensió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

c
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.

kq2d_body_init: DMG — 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.
DMG — 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.
kq2d_body_init: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body2d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body2d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/physics2d.h:54

Notas de la declaración (original)
Initialize an active unit-inverse-mass body at the supplied center and half
extents, with zero velocity and reserved restitution set to zero. Null is ignored.

kitaqgb/lib/physics2d.c:597

c
void kq2d_body_init(KQBody2D* body, s16 x, s16 y, s16 half_x, s16 half_y)
{
    if (body == 0) return;
    body->x = x;
    body->y = y;
    body->vx = 0;
    body->vy = 0;
    body->half_x = half_x;
    body->half_y = half_y;
    body->inv_mass_q8 = 256;
    body->restitution_q8 = 0;
    body->active = 1;
}
kq2d_body_limit_speed

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

c
void kq2d_body_limit_speed(KQBody2D* body, s16 max_speed);

Parámetros

body

Puntero al cuerpo que se va a modificar. Los campos que no usa esta operación se conservan.

max_speed

Lí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

c
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.

kq2d_body_limit_speed: DMG — 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.
DMG — 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.
kq2d_body_limit_speed: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_surface.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_surface.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/physics2d.h:92

Notas de la declaración (original)
Conservative circular bound, with a shared Q8 scale for both components.
Quantizes toward zero; very small limits relative to input may yield zero.
Components and positive max_speed must be <= 16383 in magnitude.

kitaqgb/lib/physics2d.c:260

c
void kq2d_body_limit_speed(KQBody2D* body, s16 max_speed)
{
    u16 x;
    u16 y;
    u16 swap;
    u16 ratio;
    u16 length;
    if (body == 0) return;
    if (max_speed <= 0) { body->vx = 0; body->vy = 0; return; }
    x = (u16)body->vx;
    y = (u16)body->vy;
    if (body->vx < 0) x = (u16)(0 - body->vx);
    if (body->vy < 0) y = (u16)(0 - body->vy);
    if (x + y <= (u16)max_speed) return;
    if (x < y) { swap = x; x = y; y = swap; }
    // major + minor/2 bounds hypot from above for 0 <= minor <= major.
    if (x + (y >> 1) + 1 <= (u16)max_speed) return;
    // Round the minor/major ratio upward for the 65-entry upper-bound table.
    // The extra unit covers truncation when converting the estimate back to speed.
    ratio = (kq2d__fraction_q8(y, x) + 4) >> 2;
    if (ratio > 64) ratio = 64;
    length = x + (u16)kq2d_scale_q8((s16)x, (s16)kq2d_hypot_extra[(__safe_index u8)ratio]) + 1;
    if (length <= (u16)max_speed) return;
    ratio = kq2d__fraction_q8((u16)max_speed, length);
    body->vx = kq2d_scale_q8(body->vx, (s16)ratio);
    body->vy = kq2d_scale_q8(body->vy, (s16)ratio);
}
kq2d_body_resolve_surface

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

c
s16 kq2d_body_resolve_surface(KQBody2D* body, const KQSurface2D* surface);

Parámetros

body

Puntero al cuerpo que se va a modificar. Los campos que no usa esta operación se conservan.

surface

Puntero 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

c
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.

kq2d_body_resolve_surface: DMG — 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.
DMG — 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.
kq2d_body_resolve_surface: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_surface.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_surface.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/physics2d.h:95

Notas de la declaración (original)
Kinematic surface response; returns incoming normal speed, or zero if separating.
Caller resolves penetration separately. Relative components must fit +/-8191.

kitaqgb/lib/physics2d.c:314

c
s16 kq2d_body_resolve_surface(KQBody2D* body, const KQSurface2D* surface)
{
    s16 vx;
    s16 vy;
    s16 speed;
    s16 tangent;
    s16 bounce = 0;
    s16 impulse;
    s16 friction;
    if (body == 0 || surface == 0) return 0;
    vx = (s16)(body->vx - surface->vx);
    vy = (s16)(body->vy - surface->vy);
    speed = (s16)(kq2d_scale_q8(vx,surface->nx_q8) + kq2d_scale_q8(vy,surface->ny_q8));
    if (speed >= 0) return 0;
    speed = (s16)(0 - speed);
    if (speed > surface->bounce_threshold) bounce = kq2d_scale_q8(speed,(s16)surface->restitution_q8);
    if (bounce < surface->kick) bounce = surface->kick;
    impulse = (s16)(speed + bounce);
    // A resting contact is a tangent constraint, not a tiny rounded bounce.
    if (bounce == 0) {
        tangent = (s16)(kq2d__rest_component(vy,surface->nx_q8) - kq2d__rest_component(vx,surface->ny_q8));
        friction = kq2d_scale_q8(impulse,(s16)surface->friction_q8);
        if (tangent > friction) tangent = (s16)(tangent - friction);
        else if (tangent < (s16)(0 - friction)) tangent = (s16)(tangent + friction);
        else tangent = 0;
        body->vx = (s16)(surface->vx - kq2d__rest_component(tangent,surface->ny_q8));
        body->vy = (s16)(surface->vy + kq2d__rest_component(tangent,surface->nx_q8));
        return speed;
    }
    body->vx = (s16)(body->vx + kq2d_scale_q8(impulse,surface->nx_q8));
    body->vy = (s16)(body->vy + kq2d_scale_q8(impulse,surface->ny_q8));
    if (surface->friction_q8 != 0) {
        tangent = (s16)(kq2d_scale_q8(vy,surface->nx_q8) - kq2d_scale_q8(vx,surface->ny_q8));
        friction = kq2d_scale_q8(impulse,(s16)surface->friction_q8);
        if (tangent > friction) tangent = friction;
        if (tangent < (s16)(0 - friction)) tangent = (s16)(0 - friction);
        body->vx = (s16)(body->vx + kq2d_scale_q8(tangent,surface->ny_q8));
        body->vy = (s16)(body->vy - kq2d_scale_q8(tangent,surface->nx_q8));
    }
    return speed;
}
kq2d_body_set_pos

Sustituye solo el centro del cuerpo y conserva la velocidad, las dimensiones y el estado de actividad.

Sintaxis

c
void kq2d_body_set_pos(KQBody2D* body, s16 x, s16 y);

Parámetros

body

Puntero al cuerpo que se va a modificar. Los campos que no usa esta operación se conservan.

x

Coordenada X del centro o del punto, en píxeles en el ejemplo.

y

Coordenada 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

c
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.

kq2d_body_set_pos: DMG — 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.
DMG — 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.
kq2d_body_set_pos: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body2d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body2d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/physics2d.h:56

Notas de la declaración (original)
Replace the center without altering velocity, extents or activity. Null is ignored.

kitaqgb/lib/physics2d.c:612

c
void kq2d_body_set_pos(KQBody2D* body, s16 x, s16 y)
{
    if (body == 0) return;
    body->x = x;
    body->y = y;
}
kq2d_body_set_velocity

Establece directamente la velocidad sin limitarla ni actualizar la posición.

Sintaxis

c
void kq2d_body_set_velocity(KQBody2D* body, s16 vx, s16 vy);

Parámetros

body

Puntero al cuerpo que se va a modificar. Los campos que no usa esta operación se conservan.

vx

Desplazamiento en X por tick de simulación, en las mismas unidades que la posición.

vy

Desplazamiento 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

c
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.

kq2d_body_set_velocity: DMG — 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.
DMG — 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.
kq2d_body_set_velocity: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body2d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body2d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/physics2d.h:58

Notas de la declaración (original)
Replace velocity without clamping or checking activity/mass. Null is ignored.

kitaqgb/lib/physics2d.c:620

c
void kq2d_body_set_velocity(KQBody2D* body, s16 vx, s16 vy)
{
    if (body == 0) return;
    body->vx = vx;
    body->vy = vy;
}
kq2d_integrate_body

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

c
void kq2d_integrate_body(KQWorld2D* world, KQBody2D* body);

Parámetros

world

Puntero al mundo que contiene el array de cuerpos y los ajustes de simulación.

body

Puntero 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

c
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.

kq2d_integrate_body: DMG — 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.
DMG — 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.
kq2d_integrate_body: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body2d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body2d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/physics2d.h:47

Notas de la declaración (original)
For one active dynamic body, add gravity, clamp each velocity axis and then
add velocity to position. Null inputs are ignored; no contacts are solved.
Use a nonnegative speed limit and keep additions in signed 16-bit range.

kitaqgb/lib/physics2d.c:664

c
void kq2d_integrate_body(KQWorld2D* world, KQBody2D* body)
{
    if (world == 0) return;
    if (body == 0) return;
    if (body->active == 0) return;
    if (body->inv_mass_q8 <= 0) return;

    kq2d_asm_value = body->vx;
    kq2d_asm_operand = world->gravity_x;
    kq2d_add_s16_asm();
    kq2d_asm_limit = world->max_speed;
    kq2d_clamp_abs_s16_asm();
    body->vx = kq2d_asm_value;

    kq2d_asm_value = body->vy;
    kq2d_asm_operand = world->gravity_y;
    kq2d_add_s16_asm();
    kq2d_asm_limit = world->max_speed;
    kq2d_clamp_abs_s16_asm();
    body->vy = kq2d_asm_value;

    kq2d_asm_value = body->x;
    kq2d_asm_operand = body->vx;
    kq2d_add_s16_asm();
    body->x = kq2d_asm_value;

    kq2d_asm_value = body->y;
    kq2d_asm_operand = body->vy;
    kq2d_add_s16_asm();
    body->y = kq2d_asm_value;
}
kq2d_overlap_aabb

Comprueba el solapamiento estricto de dos cajas definidas por su centro en los ejes X e Y.

Sintaxis

c
u8 kq2d_overlap_aabb(const KQBody2D* a, const KQBody2D* b);

Parámetros

a

Puntero válido a un cuerpo. La consulta ignora la actividad, la masa y las banderas.

b

Puntero 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

c
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.

kq2d_overlap_aabb: DMG — 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.
DMG — 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.
kq2d_overlap_aabb: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body2d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body2d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/physics2d.h:51

Notas de la declaración (original)
Test strict overlap of two centered boxes; touching edges return false.
Both pointers must be valid. Active/mass flags are ignored, and coordinate
differences and extent sums must fit the signed 16-bit calculations.

kitaqgb/lib/physics2d.c:579

c
u8 kq2d_overlap_aabb(const KQBody2D* a, const KQBody2D* b)
{
    s16 dx = (s16)(b->x - a->x);
    s16 dy = (s16)(b->y - a->y);

    s16 adx = kq2d__abs_s16(dx);
    s16 ady = kq2d__abs_s16(dy);

    s16 sx = (s16)(a->half_x + b->half_x);
    s16 sy = (s16)(a->half_y + b->half_y);

    if (adx >= sx) return 0;
    if (ady >= sy) return 0;
    return 1;
}
kq2d_point_in_rect

Comprueba si un punto está dentro de un rectángulo, incluidos los bordes izquierdo y superior, pero excluidos el derecho y el inferior.

Sintaxis

c
u8 kq2d_point_in_rect(s16 x, s16 y, KQRect r);

Parámetros

x

Coordenada X del centro o del punto, en píxeles en el ejemplo.

y

Coordenada Y del centro o del punto; en el ejemplo, el sentido positivo es hacia abajo.

r

Valor 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

c
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.

kq2d_point_in_rect: DMG — 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.
DMG — 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.
kq2d_point_in_rect: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body2d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body2d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/physics2d.h:72

Notas de la declaración (original)
Delegate the half-open point test: include left/top and exclude right/bottom.
Coordinate-plus-size sums must remain representable as s16.

kitaqgb/lib/physics2d.c:705

c
u8 kq2d_point_in_rect(s16 x, s16 y, KQRect r)
{
    return kq_point_in_rect(x, y, r);
}
kq2d_rect_intersect

Comprueba el solapamiento interior de dos rectángulos representados por la esquina superior izquierda y el tamaño.

Sintaxis

c
u8 kq2d_rect_intersect(KQRect a, KQRect b);

Parámetros

a

Valor KQRect con coordenadas de la esquina superior izquierda y ancho y alto positivos.

b

Valor 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

c
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.

kq2d_rect_intersect: DMG — 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.
DMG — 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.
kq2d_rect_intersect: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body2d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body2d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/physics2d.h:69

Notas de la declaración (original)
Delegate strict rectangle overlap to the fixed-point utility; edge-only
contact is false. Coordinate-plus-size sums must remain representable as s16.

kitaqgb/lib/physics2d.c:698

c
u8 kq2d_rect_intersect(KQRect a, KQRect b)
{
    return kq_rect_intersect(a, b);
}
kq2d_scale_q8

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

c
s16 kq2d_scale_q8(s16 value, s16 coefficient);

Parámetros

value

Valor de 16 bits con signo al que se aplica el factor de escala.

coefficient

Coeficiente 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

c
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.

kq2d_scale_q8: DMG — 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.
DMG — 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.
kq2d_scale_q8: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_surface.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_surface.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/physics2d.h:88

Notas de la declaración (original)
Truncates toward zero, including negative values; coefficient is -256..256.

kitaqgb/lib/physics2d.c:8

c
s16 kq2d_scale_q8(s16 value, s16 coefficient)
{
    // Eight-bit shift/add product in HL:C, with sign applied after truncation.
    __asm {
        LD_HL_IMM value
        LD_A_HL
        LD_E_A
        INC_HL
        LD_A_HL
        LD_D_A
        OR_E
        JP_Z kqscale_zero
        LD_HL_IMM coefficient
        LD_A_HL
        LD_C_A
        INC_HL
        LD_A_HL
        LD_B_A
        LD_A_C
        OR_A
        JR_NZ kqscale_fraction
        LD_A_B
        OR_A
        JP_Z kqscale_zero
        LD_H_D
        LD_L_E
        AND_IMM 128
        RET_Z
        JP kqscale_negate
kqscale_fraction:
        LD_A_D
        XOR_B
        AND_IMM 128
        PUSH_AF
        LD_A_D
        AND_IMM 128
        JR_Z kqscale_value_positive
        XOR_A
        SUB_E
        LD_E_A
        LD_A_IMM 0
        SBC_D
        LD_D_A
kqscale_value_positive:
        LD_A_B
        AND_IMM 128
        JR_Z kqscale_coefficient_positive
        XOR_A
        SUB_C
        LD_C_A
kqscale_coefficient_positive:
        LD_HL_IMM 0
        // Unroll eight bits: avoid a loop branch on every fixed-point product.
        LD_A_C
        AND_IMM 1
        JR_Z kqscale_shift_0
        ADD_HL_DE
kqscale_shift_0:
        LD_A_H
        RRA
        LD_H_A
        LD_A_L
        RRA
        LD_L_A
        LD_A_C
        RRA
        LD_C_A
        LD_A_C
        AND_IMM 1
        JR_Z kqscale_shift_1
        ADD_HL_DE
kqscale_shift_1:
        LD_A_H
        RRA
        LD_H_A
        LD_A_L
        RRA
        LD_L_A
        LD_A_C
        RRA
        LD_C_A
        LD_A_C
        AND_IMM 1
        JR_Z kqscale_shift_2
        ADD_HL_DE
kqscale_shift_2:
        LD_A_H
        RRA
        LD_H_A
        LD_A_L
        RRA
        LD_L_A
        LD_A_C
        RRA
        LD_C_A
        LD_A_C
        AND_IMM 1
        JR_Z kqscale_shift_3
        ADD_HL_DE
kqscale_shift_3:
        LD_A_H
        RRA
        LD_H_A
        LD_A_L
        RRA
        LD_L_A
        LD_A_C
        RRA
        LD_C_A
        LD_A_C
        AND_IMM 1
        JR_Z kqscale_shift_4
        ADD_HL_DE
kqscale_shift_4:
        LD_A_H
        RRA
        LD_H_A
        LD_A_L
        RRA
        LD_L_A
        LD_A_C
        RRA
        LD_C_A
        LD_A_C
        AND_IMM 1
        JR_Z kqscale_shift_5
        ADD_HL_DE
kqscale_shift_5:
        LD_A_H
        RRA
        LD_H_A
        LD_A_L
        RRA
        LD_L_A
        LD_A_C
        RRA
        LD_C_A
        LD_A_C
        AND_IMM 1
        JR_Z kqscale_shift_6
        ADD_HL_DE
kqscale_shift_6:
        LD_A_H
        RRA
        LD_H_A
        LD_A_L
        RRA
        LD_L_A
        LD_A_C
        RRA
        LD_C_A
        LD_A_C
        AND_IMM 1
        JR_Z kqscale_shift_7
        ADD_HL_DE
kqscale_shift_7:
        LD_A_H
        RRA
        LD_H_A
        LD_A_L
        RRA
        LD_L_A
        LD_A_C
        RRA
        LD_C_A
        POP_AF
        OR_A
        RET_Z
kqscale_negate:
        XOR_A
        SUB_L
        LD_L_A
        LD_A_IMM 0
        SBC_H
        LD_H_A
        RET
kqscale_zero:
        LD_HL_IMM 0
        RET
    }
}
kq2d_step

Integra los cuerpos dinámicos activos y después resuelve los contactos entre las entradas activas del array.

Sintaxis

c
void kq2d_step(KQWorld2D* world);

Parámetros

world

Puntero 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

c
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.

kq2d_step: DMG — 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.
DMG — 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.
kq2d_step: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body2d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body2d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/physics2d.h:43

Notas de la declaración (original)
Advance active dynamic bodies, then visit each active unordered pair for
the configured contact passes (zero means one). Static bodies still participate
as obstacles. The world borrows its array and shares non-reentrant ASM scratch.
This is discrete integration; fast bodies can pass through thin obstacles.

kitaqgb/lib/physics2d.c:794

c
void kq2d_step(KQWorld2D* world)
{
    if (world == 0) return;
    if (world->bodies == 0) return;

    KQBody2D* bodies = world->bodies;
    u8 count = world->body_count;

    // Integrate dynamic bodies.
    u8 i;
    for (i = 0; i < count; i++)
    {
        KQBody2D* b = &bodies[(__safe_index u8)i];
        if (b->active == 0) continue;
        if (b->inv_mass_q8 <= 0) continue;

        kq2d_asm_value = b->vx;
        kq2d_asm_operand = world->gravity_x;
        kq2d_add_s16_asm();
        kq2d_asm_limit = world->max_speed;
        kq2d_clamp_abs_s16_asm();
        b->vx = kq2d_asm_value;

        kq2d_asm_value = b->vy;
        kq2d_asm_operand = world->gravity_y;
        kq2d_add_s16_asm();
        kq2d_asm_limit = world->max_speed;
        kq2d_clamp_abs_s16_asm();
        b->vy = kq2d_asm_value;

        kq2d_asm_value = b->x;
        kq2d_asm_operand = b->vx;
        kq2d_add_s16_asm();
        b->x = kq2d_asm_value;

        kq2d_asm_value = b->y;
        kq2d_asm_operand = b->vy;
        kq2d_add_s16_asm();
        b->y = kq2d_asm_value;
    }

    // Solve contacts with a small fixed iteration count.
    u8 iterations = world->solver_iterations;
    if (iterations == 0) iterations = 1;

    u8 it;
    for (it = 0; it < iterations; it++)
    {
        for (i = 0; i < count; i++)
        {
            KQBody2D* a = &bodies[(__safe_index u8)i];
            if (a->active == 0) continue;

            u8 j;
            for (j = (u8)(i + 1); j < count; j++)
            {
                KQBody2D* b = &bodies[(__safe_index u8)j];
                if (b->active == 0) continue;
                kq2d__resolve_pair(a, b);
            }
        }
    }
}
kq2d_surface_toi_q8

Estima el instante de cruce dentro del tick a partir de las distancias inicial y final con signo, suponiendo un movimiento lineal.

Sintaxis

c
u16 kq2d_surface_toi_q8(s16 start_gap, s16 end_gap);

Parámetros

start_gap

Distancia con signo al inicio del tick; un valor positivo indica que está fuera de la superficie.

end_gap

Distancia 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

c
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.

kq2d_surface_toi_q8: DMG — 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.
DMG — 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.
kq2d_surface_toi_q8: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_surface.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_surface.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/physics2d.h:98

Notas de la declaración (original)
Linear crossing time in Q8 (0..256); positive separation is outside.
Returns 0 for initial overlap, 256 for no crossing. Gaps must fit +/-8191.

kitaqgb/lib/physics2d.c:291

c
u16 kq2d_surface_toi_q8(s16 start_gap, s16 end_gap)
{
    if (start_gap <= 0) return 0;
    if (end_gap >= 0) return 256;
    return kq2d__fraction_q8((u16)start_gap, (u16)(start_gap - end_gap));
}
kq2d_world_init

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

c
void kq2d_world_init(KQWorld2D* world, KQBody2D* bodies, u8 body_count);

Parámetros

world

Puntero al mundo que contiene el array de cuerpos y los ajustes de simulación.

bodies

Inicio de un array de cuerpos propiedad del código que llama, con body_count elementos.

body_count

Nú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

c
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.

kq2d_world_init: DMG — 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.
DMG — 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.
kq2d_world_init: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body2d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body2d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/physics2d.h:38

Notas de la declaración (original)
Retain the caller-owned body array without initializing its elements.
Set gravity to (0,32), four contact iterations and a per-axis speed limit of 512.
A null world is ignored; the array must outlive subsequent world operations.

kitaqgb/lib/physics2d.c:564

c
void kq2d_world_init(KQWorld2D* world, KQBody2D* bodies, u8 body_count)
{
    if (world == 0) return;

    world->bodies = bodies;
    world->body_count = body_count;
    world->gravity_x = 0;
    world->gravity_y = 32;
    world->solver_iterations = 4;
    world->max_speed = 512;
}

physics2d_circle.h — 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

c
u8 kq2dc_overlap_circle(const KQCircleBody2D* a, const KQCircleBody2D* b);

Parámetros

a

Puntero válido al primer círculo.

b

Puntero 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

c
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.

kq2dc_overlap_circle: DMG — 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.
DMG — 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.
kq2dc_overlap_circle: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_circle.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_circle.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/physics2d_circle.h:55

Notas de la declaración (original)
Compare a reduced integer center distance with the reduced radius sum.
Valid pointers and positive radii are required; activity and mass are ignored.
This approximate test requires representable differences, radius sums and
squared-distance sum. Touching at the computed distance returns false.

kitaqgb/lib/physics2d_circle.c:397

c
u8 kq2dc_overlap_circle(const KQCircleBody2D* a, const KQCircleBody2D* b)
{
    s16 dx;
    s16 dy;
    s16 sdx;
    s16 sdy;
    u8 shift;
    u16 adx;
    u16 ady;
    u16 dist_sq;
    u16 dist_scaled;
    s16 radius_sum;
    u16 radius_sum_scaled;

    dx = (s16)(b->x - a->x);
    dy = (s16)(b->y - a->y);
    sdx = dx;
    sdy = dy;
    shift = kq2dc__reduce_vector(&sdx, &sdy);

    adx = (u16)kq2dc__abs_s16(sdx);
    ady = (u16)kq2dc__abs_s16(sdy);
    dist_sq = (u16)((adx * adx) + (ady * ady));
    dist_scaled = kq2dc__isqrt_u16(dist_sq);

    radius_sum = (s16)(a->radius + b->radius);
    radius_sum_scaled = kq2dc__scale_down_positive(radius_sum, shift);

    if (dist_scaled >= radius_sum_scaled) return 0;
    return 1;
}
kq2dc_set_bounds

Guarda y activa los límites del mundo de círculos sin mover inmediatamente los cuerpos.

Sintaxis

c
void kq2dc_set_bounds(KQCircleWorld2D* world, s16 min_x, s16 min_y, s16 max_x, s16 max_y);

Parámetros

world

Puntero al mundo que contiene el array de cuerpos y los ajustes de simulación.

min_x

Límite izquierdo; el centro del círculo no puede ser menor que min_x + radius.

min_y

Límite superior; el centro del círculo no puede ser menor que min_y + radius.

max_x

Límite derecho; el centro del círculo no puede superar max_x - radius.

max_y

Lí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

c
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.

kq2dc_set_bounds: DMG — 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.
DMG — 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.
kq2dc_set_bounds: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_circle.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_circle.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/physics2d_circle.h:45

Notas de la declaración (original)
Store and enable bounds without validating their order or fitting bodies
immediately. Supply extents large enough for body diameters. Null is ignored.

kitaqgb/lib/physics2d_circle.c:382

c
void kq2dc_set_bounds(KQCircleWorld2D* world, s16 min_x, s16 min_y, s16 max_x, s16 max_y)
{
    if (world == 0) return;

    world->use_bounds = 1;
    world->min_x = min_x;
    world->min_y = min_y;
    world->max_x = max_x;
    world->max_y = max_y;
}
kq2dc_step

Integra los círculos, resuelve los límites y los contactos entre círculos y después aplica amortiguamiento lineal.

Sintaxis

c
void kq2dc_step(KQCircleWorld2D* world);

Parámetros

world

Puntero 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

c
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.

kq2dc_step: DMG — 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.
DMG — 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.
kq2dc_step: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_circle.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_circle.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/physics2d_circle.h:50

Notas de la declaración (original)
Integrate active dynamic bodies, apply bounds, solve contacts, then damp
velocity and snap components in -1..1 to zero. Zero solver iterations means one.
Pairs with both velocities zero are skipped, so resting overlaps can remain.
Bounds can reposition static bodies; null world/array inputs are ignored.

kitaqgb/lib/physics2d_circle.c:433

c
void kq2dc_step(KQCircleWorld2D* world)
{
    KQCircleBody2D* bodies;
    u8 count;
    u8 i;
    u8 iterations;
    u8 it;

    if (world == 0) return;
    if (world->bodies == 0) return;

    bodies = world->bodies;
    count = world->body_count;

    for (i = 0; i < count; i++)
    {
        KQCircleBody2D* body = &bodies[(__safe_index u8)i];
        if (body->active == 0) continue;
        if (body->inv_mass_q8 <= 0)
        {
            if (world->use_bounds != 0) kq2dc__resolve_bounds(world, body);
            continue;
        }

        body->vx = (s16)(body->vx + world->gravity_x);
        body->vy = (s16)(body->vy + world->gravity_y);
        body->vx = kq2dc__clamp_abs(body->vx, world->max_speed);
        body->vy = kq2dc__clamp_abs(body->vy, world->max_speed);

        body->x = (s16)(body->x + body->vx);
        body->y = (s16)(body->y + body->vy);

        if (world->use_bounds != 0) kq2dc__resolve_bounds(world, body);
    }

    iterations = world->solver_iterations;
    if (iterations == 0) iterations = 1;

    for (it = 0; it < iterations; it++)
    {
        for (i = 0; i < count; i++)
        {
            KQCircleBody2D* a = &bodies[(__safe_index u8)i];
            if (a->active == 0) continue;
            if (a->vx == 0 && a->vy == 0) continue;

            if (world->use_bounds != 0) kq2dc__resolve_bounds(world, a);

            {
                u8 j;
                for (j = 0; j < count; j++)
                {
                    KQCircleBody2D* b = &bodies[(__safe_index u8)j];
                    s16 radius_sum;
                    if (j == i) continue;
                    if (b->active == 0) continue;
                    // Avoid revisiting an earlier moving body, but still allow a moving body
                    // to resolve against a stationary slot with a lower index. Velocities are live
                    // solver state, so contact ordering can change which later pairs are visited.
                    if (j < i && (b->vx != 0 || b->vy != 0)) continue;
                    radius_sum = (s16)(a->radius + b->radius);
                    if (kq2dc__abs_s16((s16)(b->x - a->x)) >= radius_sum) continue;
                    if (kq2dc__abs_s16((s16)(b->y - a->y)) >= radius_sum) continue;
                    kq2dc__resolve_pair(a, b);
                }
            }
        }
    }

    for (i = 0; i < count; i++)
    {
        KQCircleBody2D* body = &bodies[(__safe_index u8)i];
        if (body->active == 0) continue;
        if (body->inv_mass_q8 <= 0) continue;

        body->vx = kq2dc__mul_q8(body->vx, world->linear_damping_q8);
        body->vy = kq2dc__mul_q8(body->vy, world->linear_damping_q8);

        if (body->vx >= -1 && body->vx <= 1) body->vx = 0;
        if (body->vy >= -1 && body->vy <= 1) body->vy = 0;

        if (world->use_bounds != 0) kq2dc__resolve_bounds(world, body);
    }
}
kq2dc_world_init

Asocia un array de círculos y establece gravedad cero, cuatro pasadas, límite por eje 768 y amortiguamiento 252/256.

Sintaxis

c
void kq2dc_world_init(KQCircleWorld2D* world, KQCircleBody2D* bodies, u8 body_count);

Parámetros

world

Puntero al mundo que contiene el array de cuerpos y los ajustes de simulación.

bodies

Inicio de un array de cuerpos propiedad del código que llama, con body_count elementos.

body_count

Nú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

c
kq2dc_world_init(&world,balls,1);
    result[0]=world.gravity_y; result[1]=world.solver_iterations;
    result[2]=world.max_speed; result[3]=world.linear_damping_q8;

Este fragmento 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.

kq2dc_world_init: DMG — 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.
DMG — 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.
kq2dc_world_init: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_circle.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_circle.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/physics2d_circle.h:42

Notas de la declaración (original)
Retain a caller-owned array without initializing bodies. Set zero gravity,
four contact passes, per-axis limit 768 and damping 252/256; bounds start disabled.
A null world is ignored. Keep the array alive for subsequent steps.

kitaqgb/lib/physics2d_circle.c:360

c
void kq2dc_world_init(KQCircleWorld2D* world, KQCircleBody2D* bodies, u8 body_count)
{
    if (world == 0) return;

    world->bodies = bodies;
    world->body_count = body_count;
    world->gravity_x = 0;
    world->gravity_y = 0;
    world->solver_iterations = 4;
    world->max_speed = 768;
    world->linear_damping_q8 = 252;
    world->use_bounds = 0;
    world->min_x = 0;
    world->min_y = 0;
    world->max_x = 159;
    world->max_y = 143;
    world->wall_restitution_q8 = 240;
    world->wall_friction_q8 = 16;
}

physics3d.h — 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

c
void kq3d_body_init(KQBody3D* body, s16 x, s16 y, s16 z, s16 half_x, s16 half_y, s16 half_z, s16 mass_q8);

Parámetros

body

Puntero al cuerpo que se va a modificar. Los campos que no usa esta operación se conservan.

x

Coordenada X del centro o del punto, en píxeles en el ejemplo.

y

Coordenada Y del centro o del punto; en el ejemplo, el sentido positivo es hacia abajo.

z

Coordenada Z del centro, representada verticalmente en la vista superior del ejemplo.

half_x

Semiextensión en X; el ancho total de la caja es el doble de este valor.

half_y

Semiextensión en Y; la altura total de la caja es el doble de este valor.

half_z

Semiextensión en Z; la profundidad total es el doble de este valor.

mass_q8

Valor 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

c
kq3d_body_init(&temp,10,20,30,8,8,8,256);
    result[3]=temp.inv_mass_q8; result[4]=temp.restitution_q8; result[5]=temp.active;

Este fragmento 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.

kq3d_body_init: DMG — 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.
DMG — 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.
kq3d_body_init: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body3d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/physics3d.h:50

Notas de la declaración (original)
Initialize an active centered box with zero velocity/acceleration,
restitution 224, cleared impact/flags and mass set through the weight helper.
The caller supplies valid half extents. Null body is ignored.

kitaqgb/lib/physics3d.c:330

c
void kq3d_body_init(KQBody3D* body, s16 x, s16 y, s16 z, s16 half_x, s16 half_y, s16 half_z, s16 mass_q8)
{
    if (body == 0) return;

    body->x = x;
    body->y = y;
    body->z = z;
    body->vx = 0;
    body->vy = 0;
    body->vz = 0;
    body->ax = 0;
    body->ay = 0;
    body->az = 0;
    body->half_x = half_x;
    body->half_y = half_y;
    body->half_z = half_z;
    body->restitution_q8 = 224;
    body->break_speed = 0;
    body->last_impact_speed = 0;
    body->active = 1;
    body->flags = 0;
    kq3d_body_set_mass(body, mass_q8);
}
kq3d_body_set_mass

Guarda la masa solicitada y calcula un peso de masa inversa para la corrección y el rebote.

Sintaxis

c
void kq3d_body_set_mass(KQBody3D* body, s16 mass_q8);

Parámetros

body

Puntero al cuerpo que se va a modificar. Los campos que no usa esta operación se conservan.

mass_q8

Valor 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

c
kq3d_body_set_mass(&temp,32); result[6]=temp.mass_q8; result[7]=temp.inv_mass_q8;
    kq3d_body_set_mass(&temp,0); result[8]=temp.inv_mass_q8;
    kq3d_body_set_mass(&temp,256);

Este fragmento 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.

kq3d_body_set_mass: DMG — 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.
DMG — 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.
kq3d_body_set_mass: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body3d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/physics3d.h:55

Notas de la declaración (original)
Store the requested mass; nonpositive mass makes the body static.
For positive mass compute inverse weight as max(1,32767/max(mass,64)).
The stored mass retains the original input; this is a relative solver weight,
not an exact Q8 reciprocal. Null body is ignored.

kitaqgb/lib/physics3d.c:311

c
void kq3d_body_set_mass(KQBody3D* body, s16 mass_q8)
{
    if (body == 0) return;

    body->mass_q8 = mass_q8;
    if (mass_q8 <= 0)
    {
        body->inv_mass_q8 = 0;
        return;
    }

    if (mass_q8 < 64) mass_q8 = 64;
    body->inv_mass_q8 = (s16)(32767 / mass_q8);
    if (body->inv_mass_q8 <= 0) body->inv_mass_q8 = 1;
}
kq3d_dot_q8_8

Divide cada uno de los tres productos con signo entre 256, trunca cada término hacia cero y después los suma.

Sintaxis

c
s16 kq3d_dot_q8_8(s16 x, s16 y, s16 z, s8 ax, s8 ay, s8 az);

Parámetros

x

Componente de 16 bits con signo que se multiplica por el coeficiente correspondiente; puede representar posición o velocidad.

y

Componente de 16 bits con signo que se multiplica por el coeficiente correspondiente; puede representar posición o velocidad.

z

Componente de 16 bits con signo que se multiplica por el coeficiente correspondiente; puede representar posición o velocidad.

ax

Coeficiente de un byte con signo para este eje (-128..127), aplicado con escala 1/256.

ay

Coeficiente de un byte con signo para este eje (-128..127), aplicado con escala 1/256.

az

Coeficiente 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

c
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.

kq3d_dot_q8_8: DMG — 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.
DMG — 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.
kq3d_dot_q8_8: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body3d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/physics3d.h:74

Notas de la declaración (original)
Sum three signed products, shifting each by eight bits before addition.
Coefficients are signed bytes scaled by 1/256; the 16-bit sum is not saturated.

kitaqgb/lib/physics3d.c:576

c
s16 kq3d_dot_q8_8(s16 x, s16 y, s16 z, s8 ax, s8 ay, s8 az)
{
    return __sdot3_q8_8(x, y, z, ax, ay, az);
}
kq3d_integrate_body

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

c
void kq3d_integrate_body(KQWorld3D* world, KQBody3D* body);

Parámetros

world

Puntero al mundo que contiene el array de cuerpos y los ajustes de simulación.

body

Puntero 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

c
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.

kq3d_integrate_body: DMG — 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.
DMG — 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.
kq3d_integrate_body: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body3d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/physics3d.h:66

Notas de la declaración (original)
Reset impact for one active dynamic body, add gravity and persistent body
acceleration, clamp velocity per axis and advance position. Static/inactive
bodies retain impact state. Null inputs are ignored; no contacts are solved.
Use a nonnegative speed limit and avoid overflow before clamping.

kitaqgb/lib/physics3d.c:436

c
void kq3d_integrate_body(KQWorld3D* world, KQBody3D* body)
{
    if (world == 0) return;
    if (body == 0) return;
    if (body->active == 0) return;
    if (body->inv_mass_q8 <= 0) return;

    body->last_impact_speed = 0;
    kq3d_asm_value = body->vx;
    kq3d_asm_operand = world->gravity_x;
    kq3d_add_s16_asm();
    kq3d_asm_operand = body->ax;
    kq3d_add_s16_asm();
    kq3d_asm_limit = world->max_speed;
    kq3d_clamp_abs_s16_asm();
    body->vx = kq3d_asm_value;

    kq3d_asm_value = body->vy;
    kq3d_asm_operand = world->gravity_y;
    kq3d_add_s16_asm();
    kq3d_asm_operand = body->ay;
    kq3d_add_s16_asm();
    kq3d_asm_limit = world->max_speed;
    kq3d_clamp_abs_s16_asm();
    body->vy = kq3d_asm_value;

    kq3d_asm_value = body->vz;
    kq3d_asm_operand = world->gravity_z;
    kq3d_add_s16_asm();
    kq3d_asm_operand = body->az;
    kq3d_add_s16_asm();
    kq3d_asm_limit = world->max_speed;
    kq3d_clamp_abs_s16_asm();
    body->vz = kq3d_asm_value;

    kq3d_asm_value = body->x;
    kq3d_asm_operand = body->vx;
    kq3d_add_s16_asm();
    body->x = kq3d_asm_value;

    kq3d_asm_value = body->y;
    kq3d_asm_operand = body->vy;
    kq3d_add_s16_asm();
    body->y = kq3d_asm_value;

    kq3d_asm_value = body->z;
    kq3d_asm_operand = body->vz;
    kq3d_add_s16_asm();
    body->z = kq3d_asm_value;
}
kq3d_overlap_aabb

Comprueba el solapamiento estricto de dos cajas definidas por su centro en los tres ejes.

Sintaxis

c
u8 kq3d_overlap_aabb(const KQBody3D* a, const KQBody3D* b);

Parámetros

a

Puntero válido a un cuerpo. La consulta ignora la actividad, la masa y las banderas.

b

Puntero 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

c
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.

kq3d_overlap_aabb: DMG — 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.
DMG — 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.
kq3d_overlap_aabb: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body3d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/physics3d.h:70

Notas de la declaración (original)
Test strict overlap on all three axes; face-only contact returns false.
Valid pointers are required and flags are ignored. Center differences and
extent sums must fit the signed 16-bit magnitude calculations.

kitaqgb/lib/physics3d.c:357

c
u8 kq3d_overlap_aabb(const KQBody3D* a, const KQBody3D* b)
{
    s16 dx = kq3d__abs_s16((s16)(b->x - a->x));
    s16 dy = kq3d__abs_s16((s16)(b->y - a->y));
    s16 dz = kq3d__abs_s16((s16)(b->z - a->z));

    s16 sx = (s16)(a->half_x + b->half_x);
    s16 sy = (s16)(a->half_y + b->half_y);
    s16 sz = (s16)(a->half_z + b->half_z);

    if (dx >= sx) return 0;
    if (dy >= sy) return 0;
    if (dz >= sz) return 0;
    return 1;
}
kq3d_step

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

c
void kq3d_step(KQWorld3D* world);

Parámetros

world

Puntero 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

c
kq3d_step(&world);
    result[16]=bodies[0].x; result[17]=bodies[0].y; result[18]=bodies[0].z;
    result[19]=bodies[0].vx; result[20]=bodies[0].vz;
    result[21]=bodies[0].last_impact_speed; result[22]=bodies[0].flags;

Este fragmento 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.

kq3d_step: DMG — 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.
DMG — 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.
kq3d_step: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body3d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/physics3d.h:61

Notas de la declaración (original)
Integrate active dynamic bodies and reset their impact values, then solve
each active unordered pair for the configured passes (zero means one).
Static bodies retain previous impact maxima until the game clears them.
Acceleration persists; flags and break thresholds remain game-owned.
This discrete solver shares non-reentrant ASM scratch and can miss fast crossings.

kitaqgb/lib/physics3d.c:492

c
void kq3d_step(KQWorld3D* world)
{
    if (world == 0) return;
    if (world->bodies == 0) return;

    KQBody3D* bodies = world->bodies;
    u8 count = world->body_count;

    u8 i;
    for (i = 0; i < count; i++)
    {
        KQBody3D* b = &bodies[(__safe_index u8)i];
        if (b->active == 0) continue;
        if (b->inv_mass_q8 <= 0) continue;

        b->last_impact_speed = 0;
        kq3d_asm_value = b->vx;
        kq3d_asm_operand = world->gravity_x;
        kq3d_add_s16_asm();
        kq3d_asm_operand = b->ax;
        kq3d_add_s16_asm();
        kq3d_asm_limit = world->max_speed;
        kq3d_clamp_abs_s16_asm();
        b->vx = kq3d_asm_value;

        kq3d_asm_value = b->vy;
        kq3d_asm_operand = world->gravity_y;
        kq3d_add_s16_asm();
        kq3d_asm_operand = b->ay;
        kq3d_add_s16_asm();
        kq3d_asm_limit = world->max_speed;
        kq3d_clamp_abs_s16_asm();
        b->vy = kq3d_asm_value;

        kq3d_asm_value = b->vz;
        kq3d_asm_operand = world->gravity_z;
        kq3d_add_s16_asm();
        kq3d_asm_operand = b->az;
        kq3d_add_s16_asm();
        kq3d_asm_limit = world->max_speed;
        kq3d_clamp_abs_s16_asm();
        b->vz = kq3d_asm_value;

        kq3d_asm_value = b->x;
        kq3d_asm_operand = b->vx;
        kq3d_add_s16_asm();
        b->x = kq3d_asm_value;

        kq3d_asm_value = b->y;
        kq3d_asm_operand = b->vy;
        kq3d_add_s16_asm();
        b->y = kq3d_asm_value;

        kq3d_asm_value = b->z;
        kq3d_asm_operand = b->vz;
        kq3d_add_s16_asm();
        b->z = kq3d_asm_value;
    }

    u8 iterations = world->solver_iterations;
    if (iterations == 0) iterations = 1;

    u8 it;
    for (it = 0; it < iterations; it++)
    {
        for (i = 0; i < count; i++)
        {
            KQBody3D* a = &bodies[(__safe_index u8)i];
            if (a->active == 0) continue;

            u8 j;
            for (j = (u8)(i + 1); j < count; j++)
            {
                KQBody3D* b = &bodies[(__safe_index u8)j];
                if (b->active == 0) continue;
                kq3d__resolve_pair(a, b);
            }
        }
    }
}
kq3d_world_init

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

c
void kq3d_world_init(KQWorld3D* world, KQBody3D* bodies, u8 body_count);

Parámetros

world

Puntero al mundo que contiene el array de cuerpos y los ajustes de simulación.

bodies

Inicio de un array de cuerpos propiedad del código que llama, con body_count elementos.

body_count

Nú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

c
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.

kq3d_world_init: DMG — 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.
DMG — 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.
kq3d_world_init: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\physics_body3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\physics_body3d.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=128k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/physics3d.h:46

Notas de la declaración (original)
Borrow the body array without initializing it. Set gravity (0,24,0), four
contact passes and a per-axis speed limit of 512. Null world is ignored;
the caller retains ownership and must keep the array alive.

kitaqgb/lib/physics3d.c:294

c
void kq3d_world_init(KQWorld3D* world, KQBody3D* bodies, u8 body_count)
{
    if (world == 0) return;

    world->bodies = bodies;
    world->body_count = body_count;
    world->gravity_x = 0;
    world->gravity_y = 24;
    world->gravity_z = 0;
    world->solver_iterations = 4;
    world->max_speed = 512;
}

raster.h — 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.

Captura CGB: cada línea curva los bordes de los pilares. Una onda de 64 líneas recorre la escena, con un desplazamiento de hasta 24 píxeles en cada dirección.
Captura CGB: cada línea curva los bordes de los pilares. Una onda de 64 líneas recorre la escena, con un desplazamiento de hasta 24 píxeles en cada dirección.

Ejemplo de onda continua

Ejemplo de entrada del título

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

c
u8 Raster_BuildHudBottom(u8 hud_y, u8 camera_x, u8 camera_y);

Parámetros

hud_y

Línea de división, de 1 a 143. Cero o valores de 144 en adelante devuelven BAD_RANGE.

camera_x

Byte 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_y

Byte 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

c
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.

Raster_BuildHudBottom: DMG — 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.
DMG — 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.
Raster_BuildHudBottom: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_hud_bottom.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/raster.h:73

Notas de la declaración (original)
Build a scrolling upper playfield and fixed bottom HUD after validating the split.

kitaqgb/lib/raster.c:183

c
u8 Raster_BuildHudBottom(u8 hud_y, u8 camera_x, u8 camera_y)
{
    u8 r;

    if (hud_y == 0) return Raster_SetError(KQ_RASTER_BAD_RANGE);
    if (hud_y >= 144) return Raster_SetError(KQ_RASTER_BAD_RANGE);

    Raster_Clear();
    r = Raster_Push(0, camera_x, camera_y);
    if (r != KQ_RASTER_OK) return r;
    return Raster_Push(hud_y, 0, 0);
}
Raster_BuildHudTop

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

c
u8 Raster_BuildHudTop(u8 hud_height, u8 camera_x, u8 camera_y);

Parámetros

hud_height

Línea de división, de 1 a 143. Cero o valores de 144 en adelante devuelven BAD_RANGE.

camera_x

Byte 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_y

Byte 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

c
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.

Raster_BuildHudTop: DMG — 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.
DMG — 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.
Raster_BuildHudTop: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_hud_top.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/raster.h:71

Notas de la declaración (original)
Validate the HUD height, then replace pending splits with a fixed top band
and scrolling playfield. The new table still requires an explicit commit.

kitaqgb/lib/raster.c:169

c
u8 Raster_BuildHudTop(u8 hud_height, u8 camera_x, u8 camera_y)
{
    u8 r;

    if (hud_height == 0) return Raster_SetError(KQ_RASTER_BAD_RANGE);
    if (hud_height >= 144) return Raster_SetError(KQ_RASTER_BAD_RANGE);

    Raster_Clear();
    r = Raster_Push(0, 0, 0);
    if (r != KQ_RASTER_OK) return r;
    return Raster_Push(hud_height, camera_x, camera_y);
}
Raster_BuildParallax2

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

c
u8 Raster_BuildParallax2(u8 split_y, u8 far_scx, u8 near_scx, u8 scy);

Parámetros

split_y

Línea de división, de 1 a 143. Cero o valores de 144 en adelante devuelven BAD_RANGE.

far_scx

Byte 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_scx

Byte 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.

scy

Byte 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

c
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.

Raster_BuildParallax2: DMG — 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.
DMG — 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.
Raster_BuildParallax2: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_parallax2.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/raster.h:76

Notas de la declaración (original)
Build two horizontal-scroll bands sharing one vertical scroll value.

kitaqgb/lib/raster.c:197

c
u8 Raster_BuildParallax2(u8 split_y, u8 far_scx, u8 near_scx, u8 scy)
{
    u8 r;

    if (split_y == 0) return Raster_SetError(KQ_RASTER_BAD_RANGE);
    if (split_y >= 144) return Raster_SetError(KQ_RASTER_BAD_RANGE);

    Raster_Clear();
    r = Raster_Push(0, far_scx, scy);
    if (r != KQ_RASTER_OK) return r;
    return Raster_Push(split_y, near_scx, scy);
}
Raster_BuildParallax3

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

c
u8 Raster_BuildParallax3(u8 y1, u8 y2, u8 scx0, u8 scx1, u8 scx2, u8 scy);

Parámetros

y1

Líneas de división; deben cumplir 1 <= y1 < y2 <= 143.

y2

Líneas de división; deben cumplir 1 <= y1 < y2 <= 143.

scx0

Byte 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.

scx1

Byte 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.

scx2

Byte 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.

scy

Byte 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

c
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.

Raster_BuildParallax3: DMG — 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.
DMG — 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.
Raster_BuildParallax3: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_parallax3.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/raster.h:79

Notas de la declaración (original)
Build three horizontal-scroll bands at ordered visible split lines. Invalid
parameters leave the previous pending table intact and set the error status.

kitaqgb/lib/raster.c:212

c
u8 Raster_BuildParallax3(u8 y1, u8 y2, u8 scx0, u8 scx1, u8 scx2, u8 scy)
{
    u8 r;

    if (y1 == 0) return Raster_SetError(KQ_RASTER_BAD_RANGE);
    if (y2 >= 144) return Raster_SetError(KQ_RASTER_BAD_RANGE);
    if (y2 <= y1) return Raster_SetError(KQ_RASTER_BAD_RANGE);

    Raster_Clear();
    r = Raster_Push(0, scx0, scy);
    if (r != KQ_RASTER_OK) return r;
    r = Raster_Push(y1, scx1, scy);
    if (r != KQ_RASTER_OK) return r;
    return Raster_Push(y2, scx2, scy);
}
Raster_Clear

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

c
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

c
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.

Raster_Clear: DMG — 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.
DMG — 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.
Raster_Clear: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_bands.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/raster.h:39

Notas de la declaración (original)
Stop splits immediately and clear bookkeeping. Build and commit a new table to restart.

kitaqgb/lib/raster.c:65

c
void Raster_Clear()
{
    Scroll_SplitReset();
    Raster_CountValue = 0;
    Raster_LastLyValue = 0;
    Raster_HasLastLy = 0;
    Raster_LastErrorValue = KQ_RASTER_OK;
}
Raster_Commit

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

c
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

c
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.

Raster_Commit: DMG — 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.
DMG — 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.
Raster_Commit: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_bands.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/raster.h:67

Notas de la declaración (original)
Publish pending splits and return the stored status. This commits even if an
earlier append failed; callers should inspect errors while building the table.

kitaqgb/lib/raster.c:161

c
u8 Raster_Commit()
{
    Scroll_SplitCommit();
    return Raster_LastErrorValue;
}
Raster_Disable

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

c
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

c
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.

Raster_Disable: DMG — 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.
DMG — 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.
Raster_Disable: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_bands.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/raster.h:41

Notas de la declaración (original)
Commit an empty split table so no raster bands remain active.

kitaqgb/lib/raster.c:75

c
void Raster_Disable()
{
    Raster_Clear();
    Scroll_SplitCommit();
}
Raster_GetCount

Lee el número de franjas registradas mediante la capa Raster. Clear/Disable lo pone a cero; confirmar por sí solo lo conserva.

Sintaxis

c
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

c
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.

Raster_GetCount: DMG — 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.
DMG — 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.
Raster_GetCount: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_bands.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/raster.h:44

Notas de la declaración (original)
Read the number of bands currently recorded by this wrapper.

kitaqgb/lib/raster.c:82

c
u8 Raster_GetCount()
{
    return Raster_CountValue;
}
Raster_GetLastError

Lee el último estado Raster guardado sin borrarlo. No es un registro acumulado de todos los fallos anteriores.

Sintaxis

c
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

c
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.

Raster_GetLastError: DMG — 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.
DMG — 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.
Raster_GetLastError: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_bands.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/raster.h:46

Notas de la declaración (original)
Read the last stored status without clearing it.

kitaqgb/lib/raster.c:88

c
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

c
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

c
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.

Raster_Init: DMG — 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.
DMG — 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.
Raster_Init: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_bands.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/raster.h:37

Notas de la declaración (original)
Stop split scheduling, empty the shared table and clear error/count state.

kitaqgb/lib/raster.c:59

c
void Raster_Init()
{
    Raster_Clear();
}
Raster_LineXGetOffset

Calcula SCX para la línea solicitada sin cambiar el estado, la imagen ni la fase.

Sintaxis

c
u8 Raster_LineXGetOffset(const RasterLineX* effect, u8 ly);

Parámetros

effect

Puntero a un RasterLineX inicializado que siga siendo válido durante toda la llamada.

ly

Coordenada 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

c
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.

Raster_LineXGetOffset: DMG / fotograma 60 — 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.
DMG / fotograma 60 — 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.
Raster_LineXGetOffset: CGB / fotograma 60 — 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.
CGB / fotograma 60 — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_wave.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_wave.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
.\kokura\kokura-cli.exe .\out\raster_wave.gb --hardware cgb --run-frames 120 --png .\out\raster_wave.png
Implementación y código fuente

kitaqgb/lib/raster.h:91

Notas de la declaración (original)
Look up the selected periodic profile at LY + phase and add base X modulo
256. An unknown profile returns the unmodified base X.

kitaqgb/lib/raster.c:264

c
u8 Raster_LineXGetOffset(const RasterLineX* effect, u8 ly)
{
    u8 index;

    if (effect->profile == KQ_RASTER_LINE_X_TITLE) {
        index = (u8)((ly + effect->phase) & 15);
        return (u8)(effect->base_x + Raster_LineXXTitle[(__safe_index u8)index]);
    }

    if (effect->profile == KQ_RASTER_LINE_TRAVEL_GATE) {
        index = (u8)((ly + effect->phase) & 63);
        return (u8)(effect->base_x + Raster_LineXTravelGate[(__safe_index u8)index]);
    }

    return effect->base_x;
}
Raster_LineXInit

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

c
void Raster_LineXInit(RasterLineX* effect, u8 profile, u8 base_x);

Parámetros

effect

Puntero a memoria RasterLineX escribible; no requiere inicialización previa.

profile

0 (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_x

X 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

c
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.

Raster_LineXInit: DMG / fotograma 60 — 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.
DMG / fotograma 60 — 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.
Raster_LineXInit: CGB / fotograma 60 — 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.
CGB / fotograma 60 — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_wave.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_wave.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
.\kokura\kokura-cli.exe .\out\raster_wave.gb --hardware cgb --run-frames 120 --png .\out\raster_wave.png
Implementación y código fuente

kitaqgb/lib/raster.h:82

Notas de la declaración (original)
Initialize a scanline-wave state with phase zero and one phase step per frame.

kitaqgb/lib/raster.c:229

c
void Raster_LineXInit(RasterLineX* effect, u8 profile, u8 base_x)
{
    effect->profile = profile;
    effect->base_x = base_x;
    effect->phase = 0;
    effect->phase_step = 1;
    effect->frame_divider = 1;
    effect->frame_counter = 0;
}
Raster_LineXRunFrame

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

c
void Raster_LineXRunFrame(RasterLineX* effect);

Parámetros

effect

Puntero 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

c
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.

Raster_LineXRunFrame: DMG / fotograma 60 — 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.
DMG / fotograma 60 — 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.
Raster_LineXRunFrame: CGB / fotograma 60 — 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.
CGB / fotograma 60 — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_wave.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_wave.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
.\kokura\kokura-cli.exe .\out\raster_wave.gb --hardware cgb --run-frames 120 --png .\out\raster_wave.png
Implementación y código fuente

kitaqgb/lib/raster.h:96

Notas de la declaración (original)
Render all 144 visible lines with one SCX write per line, then advance phase.
This foreground renderer masks interrupts during the visible frame. Do game
and audio work between calls; do not combine it with a STAT raster driver.
Returns without changing the effect when the LCD is off.

kitaqgb/lib/raster.c:298

c
void Raster_LineXRunFrame(RasterLineX* effect)
{
    u8 interrupt_state;
    if ((Raster_LineXLcdc & 0x80) == 0) return;
    Raster_LineXTable = Raster_LineXFlat;
    Raster_LineXMask = 15;
    if (effect->profile == KQ_RASTER_LINE_X_TITLE) {
        Raster_LineXTable = Raster_LineXXTitle;
    }
    if (effect->profile == KQ_RASTER_LINE_TRAVEL_GATE) {
        Raster_LineXTable = Raster_LineXTravelGate;
        Raster_LineXMask = 63;
    }
    Raster_LineXPhase = effect->phase;
    Raster_LineXBase = effect->base_x;
    interrupt_state = __critical_enter();
    __asm {
        PUSH_AF
        PUSH_BC
        PUSH_DE
        PUSH_HL
        // Use the current VBlank when the preceding frame ended there.
        // Waiting for another VBlank edge would leave every second frame flat.
raster_linex_vblank:
        LDH_A_MEM 0x44
        CP_IMM 144
        JR_C raster_linex_vblank
        LD_B_IMM 0
        LD_A_MEM Raster_LineXPhase
        LD_C_A
        LD_A_MEM Raster_LineXMask
        LD_D_A
        LD_A_MEM Raster_LineXBase
        LD_E_A
raster_linex_line:
        LD_A_B
        ADD_C
        AND_D
        LD_L_A
        LD_H_IMM 0
        PUSH_DE
        LD_A_MEM Raster_LineXTable
        LD_E_A
        LD_A_MEM Raster_LineXTable+1
        LD_D_A
        ADD_HL_DE
        POP_DE
        LD_A_HL
        ADD_E
        PUSH_AF
raster_linex_wait:
        LDH_A_MEM 0x44
        CP_B
        JR_NZ raster_linex_wait
        POP_AF
        LDH_MEM_A 0x43
        INC_B
        LD_A_B
        CP_IMM 144
        JR_NZ raster_linex_line
        POP_HL
        POP_DE
        POP_BC
        POP_AF
    }
    // Synchronize the scroll helper's tracked state with the last hardware write.
    __scroll_bg_x_set(Raster_LineXScx);
    __critical_leave(interrupt_state);
    effect->frame_counter++;
    if (effect->frame_counter >= effect->frame_divider) {
        effect->frame_counter = 0;
        effect->phase = (u8)(effect->phase + effect->phase_step);
    }
}
Raster_LineXSetPhase

Establece directamente la posición de la onda, conservando la X base, la velocidad y el contador divisor.

Sintaxis

c
void Raster_LineXSetPhase(RasterLineX* effect, u8 phase);

Parámetros

effect

Puntero a un RasterLineX inicializado que siga siendo válido durante toda la llamada.

phase

Valor 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

c
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.

Raster_LineXSetPhase: DMG / fotograma 60 — 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.
DMG / fotograma 60 — 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.
Raster_LineXSetPhase: CGB / fotograma 60 — 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.
CGB / fotograma 60 — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_wave.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_wave.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
.\kokura\kokura-cli.exe .\out\raster_wave.gb --hardware cgb --run-frames 120 --png .\out\raster_wave.png
Implementación y código fuente

kitaqgb/lib/raster.h:88

Notas de la declaración (original)
Set the byte phase directly without resetting the frame-divider counter.

kitaqgb/lib/raster.c:257

c
void Raster_LineXSetPhase(RasterLineX* effect, u8 phase)
{
    effect->phase = phase;
}
Raster_LineXSetProfile

Selecciona un perfil y pone a cero la fase y el contador divisor de fotogramas. Conserva la X base y la velocidad.

Sintaxis

c
void Raster_LineXSetProfile(RasterLineX* effect, u8 profile);

Parámetros

effect

Puntero a un RasterLineX inicializado que siga siendo válido durante toda la llamada.

profile

0 (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

c
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.

Raster_LineXSetProfile: DMG / fotograma 16 — 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.
DMG / fotograma 16 — 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.
Raster_LineXSetProfile: DMG / fotograma 60 — 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.
DMG / fotograma 60 — 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.
Raster_LineXSetProfile: DMG / fotograma 120 — 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.
DMG / fotograma 120 — 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.
Raster_LineXSetProfile: CGB / fotograma 16 — 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.
CGB / fotograma 16 — 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.
Raster_LineXSetProfile: CGB / fotograma 60 — 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.
CGB / fotograma 60 — 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.
Raster_LineXSetProfile: CGB / fotograma 120 — 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.
CGB / fotograma 120 — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_title_entry.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_title_entry.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
.\kokura\kokura-cli.exe .\out\raster_title_entry.gb --hardware cgb --run-frames 120 --png .\out\raster_title_entry.png
Implementación y código fuente

kitaqgb/lib/raster.h:84

Notas de la declaración (original)
Change the wave profile and restart its phase/divider counter.

kitaqgb/lib/raster.c:240

c
void Raster_LineXSetProfile(RasterLineX* effect, u8 profile)
{
    effect->profile = profile;
    effect->phase = 0;
    effect->frame_counter = 0;
}
Raster_LineXSetSpeed

Establece el incremento de fase y el intervalo de actualización. Reinicia el contador divisor conservando la fase actual.

Sintaxis

c
void Raster_LineXSetSpeed(RasterLineX* effect, u8 phase_step, u8 frame_divider);

Parámetros

effect

Puntero a un RasterLineX inicializado que siga siendo válido durante toda la llamada.

phase_step

Incremento 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_divider

Nú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

c
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.

Raster_LineXSetSpeed: DMG / fotograma 60 — 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.
DMG / fotograma 60 — 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.
Raster_LineXSetSpeed: CGB / fotograma 60 — 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.
CGB / fotograma 60 — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_wave.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_wave.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
.\kokura\kokura-cli.exe .\out\raster_wave.gb --hardware cgb --run-frames 120 --png .\out\raster_wave.png
Implementación y código fuente

kitaqgb/lib/raster.h:86

Notas de la declaración (original)
Configure the phase increment and frame interval; clamp a zero interval to one.

kitaqgb/lib/raster.c:248

c
void Raster_LineXSetSpeed(RasterLineX* effect, u8 phase_step, u8 frame_divider)
{
    effect->phase_step = phase_step;
    if (frame_divider == 0) frame_divider = 1;
    effect->frame_divider = frame_divider;
    effect->frame_counter = 0;
}
Raster_Push

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

c
u8 Raster_Push(u8 ly, u8 scx, u8 scy);

Parámetros

ly

Lí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.

scx

Byte 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.

scy

Byte 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

c
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.

Raster_Push: DMG — 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.
DMG — 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.
Raster_Push: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_bands.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/raster.h:50

Notas de la declaración (original)
Append a validated background-scroll band and advance the monotonic-LY
bookkeeping. A successful append clears the previous error.

kitaqgb/lib/raster.c:95

c
u8 Raster_Push(u8 ly, u8 scx, u8 scy)
{
    u8 r;

    r = Raster_CheckPush(ly);
    if (r != KQ_RASTER_OK) return r;

    Scroll_SplitPush(ly, scx, scy);

    Raster_LastLyValue = ly;
    Raster_HasLastLy = 1;
    Raster_CountValue++;
    Raster_LastErrorValue = KQ_RASTER_OK;
    return KQ_RASTER_OK;
}
Raster_PushBgColor0

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

c
u8 Raster_PushBgColor0(u8 ly, u16 rgb15);

Parámetros

ly

Lí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.

rgb15

RGB15: 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

c
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.

Raster_PushBgColor0: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_color.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/raster.h:63

Notas de la declaración (original)
Pack a 15-bit color into the extended band's two scroll-byte fields and select
the color-zero operation, which interprets those fields as color data.

kitaqgb/lib/raster.c:154

c
u8 Raster_PushBgColor0(u8 ly, u16 rgb15)
{
    return Raster_PushEx(ly, (u8)rgb15, (u8)(rgb15 >> 8), 0, 0, KQ_RASTER_BG_COLOR0);
}
Raster_PushBgWindowScreen

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

c
u8 Raster_PushBgWindowScreen(u8 ly, u8 scx, u8 scy, u8 screen_x, u8 screen_y, u8 flags);

Parámetros

ly

Lí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.

scx

Byte 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.

scy

Byte 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_x

Coordenada 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_y

WY 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.

flags

Normalmente 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

c
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.

Raster_PushBgWindowScreen: DMG — 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.
DMG — 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.
Raster_PushBgWindowScreen: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_bg_window.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/raster.h:60

Notas de la declaración (original)
Queue both background and window updates, converting window screen X to WX.

kitaqgb/lib/raster.c:145

c
u8 Raster_PushBgWindowScreen(u8 ly, u8 scx, u8 scy, u8 screen_x, u8 screen_y, u8 flags)
{
    flags = (u8)(flags | KQ_RASTER_BG | KQ_RASTER_WIN);
    return Raster_PushEx(ly, scx, scy, (u8)(screen_x + 7), screen_y, flags);
}
Raster_PushEx

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

c
u8 Raster_PushEx(u8 ly, u8 scx, u8 scy, u8 wx, u8 wy, u8 flags);

Parámetros

ly

Lí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.

scx

Byte 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.

scy

Byte 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.

wx

Valor 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.

wy

WY 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.

flags

Banderas: 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

c
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.

Raster_PushEx: DMG — 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.
DMG — 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.
Raster_PushEx: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_bands.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/raster.h:52

Notas de la declaración (original)
Append a validated extended band after masking flags to supported operations.

kitaqgb/lib/raster.c:112

c
u8 Raster_PushEx(u8 ly, u8 scx, u8 scy, u8 wx, u8 wy, u8 flags)
{
    u8 r;

    r = Raster_CheckPush(ly);
    if (r != KQ_RASTER_OK) return r;

    // Masking removes unknown bits but does not reject conflicting supported operations.
    flags = (u8)(flags & KQ_RASTER_FLAG_MASK);
    Scroll_SplitPushEx(ly, scx, scy, wx, wy, flags);

    Raster_LastLyValue = ly;
    Raster_HasLastLy = 1;
    Raster_CountValue++;
    Raster_LastErrorValue = KQ_RASTER_OK;
    return KQ_RASTER_OK;
}
Raster_PushWindowRaw

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

c
u8 Raster_PushWindowRaw(u8 ly, u8 wx, u8 wy, u8 flags);

Parámetros

ly

Lí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.

wx

Valor 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.

wy

WY 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.

flags

Normalmente 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

c
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.

Raster_PushWindowRaw: DMG — 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.
DMG — 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.
Raster_PushWindowRaw: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_window_raw.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/raster.h:55

Notas de la declaración (original)
Enable window updates and pass hardware WX/WY values without coordinate conversion.

kitaqgb/lib/raster.c:131

c
u8 Raster_PushWindowRaw(u8 ly, u8 wx, u8 wy, u8 flags)
{
    flags = (u8)(flags | KQ_RASTER_WIN);
    return Raster_PushEx(ly, 0, 0, wx, wy, flags);
}
Raster_PushWindowScreen

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

c
u8 Raster_PushWindowScreen(u8 ly, u8 screen_x, u8 screen_y, u8 flags);

Parámetros

ly

Lí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_x

Coordenada 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_y

WY 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.

flags

Normalmente 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

c
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).

Raster_PushWindowScreen: DMG — 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).
DMG — 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).
Raster_PushWindowScreen: CGB — 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).
CGB — 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).

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\raster_bands_window_screen.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\raster_bands.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/raster.h:58

Notas de la declaración (original)
Convert screen X to hardware WX by adding seven, then queue a window band.
The byte addition wraps if callers supply an excessive X coordinate.

kitaqgb/lib/raster.c:139

c
u8 Raster_PushWindowScreen(u8 ly, u8 screen_x, u8 screen_y, u8 flags)
{
    return Raster_PushWindowRaw(ly, (u8)(screen_x + 7), screen_y, flags);
}

rpg.h — 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

c
void camera_center(u8 x, u8 y);

Parámetros

x

Coordenada X de la celda.

y

Coordenada 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

c
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.

camera_center: DMG
DMG
camera_center: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_map_path.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_map_path.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementación y código fuente

kitaqgb/lib/rpg.h:297

Notas de la declaración (original)
Center an ordinary-map tile coordinate within a 20-by-18 viewport and clamp
the scroll origin to its edges. This adjusts scroll registers only; it does
not stream newly exposed map rows into VRAM.

kitaqgb/lib/map.c:105

c
void camera_center(u8 x, u8 y)
{
    u8 tile_x = 0;
    u8 tile_y = 0;
    u8 max_x = 0;
    u8 max_y = 0;

    map_camera_x = x;
    map_camera_y = y;

    if (map_loaded == 0) return;

    if (map_current.width > 20) max_x = (u8)(map_current.width - 20);
    if (map_current.height > 18) max_y = (u8)(map_current.height - 18);

    if (x > 10) tile_x = (u8)(x - 10);
    if (y > 9) tile_y = (u8)(y - 9);

    if (tile_x > max_x) tile_x = max_x;
    if (tile_y > max_y) tile_y = max_y;

    __scroll_bg_set((u8)(tile_x << 3), (u8)(tile_y << 3));
}
far_read16

Lee una palabra little-endian mediante un puntero con información de banco.

Sintaxis

c
#define far_read16(p) __farpeek16((p).bank, (p).ptr)

Parámetros

p

far_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

c
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.

far_read16: DMG
DMG
far_read16: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_far.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_far.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementación y código fuente

kitaqgb/lib/rpg.h:172

far_read8

Lee un byte mediante un puntero con información de banco.

Sintaxis

c
#define far_read8(p) __farpeek8((p).bank, (p).ptr)

Parámetros

p

far_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

c
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.

far_read8: DMG
DMG
far_read8: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_far.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_far.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementació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

c
#define far_read_block(dst, p, len) __farmemcpy((dst), (p).bank, (p).ptr, (len))

Parámetros

dst

Inicio de len bytes escribibles de RAM.

p

far_ptr_t con bank y ptr, donde ptr es una dirección visible para la CPU.

len

Nú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

c
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.

far_read_block: DMG
DMG
far_read_block: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_far.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_far.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementació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

c
void flag_clear(u16 id);

Parámetros

id

Nú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

c
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.

flag_clear: DMG
DMG
flag_clear: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\flags_quests.c .\kitaqgb\lib\flags.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\flags_quests.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/rpg.h:372

Notas de la declaración (original)
Clear a flag bit; id must be below 2048.

kitaqgb/lib/flags.c:21

c
void flag_clear(u16 id)
{
    __bit_clear(flags_bits, id);
}
flag_get

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

c
u8 flag_get(u16 id);

Parámetros

id

Nú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

c
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.

flag_get: DMG
DMG
flag_get: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\flags_quests.c .\kitaqgb\lib\flags.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\flags_quests.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/rpg.h:368

Notas de la declaración (original)
Read a bit from the flag array. Callers must keep id below 2048.

kitaqgb/lib/flags.c:9

c
u8 flag_get(u16 id)
{
    return __bit_test(flags_bits, id);
}
flag_set

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

c
void flag_set(u16 id);

Parámetros

id

Nú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

c
flag_set(9); // Mark the door as open; setting an already set flag is harmless.
flag_set(9);
opened=flag_get(9);neighbor=flag_get(8); // 1 and 0: adjacent flag is unchanged.

Este fragmento 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.

flag_set: DMG
DMG
flag_set: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\flags_quests.c .\kitaqgb\lib\flags.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\flags_quests.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/rpg.h:370

Notas de la declaración (original)
Set a flag bit without disturbing adjacent flags; id must be below 2048.

kitaqgb/lib/flags.c:15

c
void flag_set(u16 id)
{
    __bit_set(flags_bits, id);
}
map_current_height

Lee el alto del mapa activo.

Sintaxis

c
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

c
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.

map_current_height: DMG
DMG
map_current_height: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_map_path.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_map_path.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementación y código fuente

kitaqgb/lib/rpg.h:391

Notas de la declaración (original)
Return the active map height in its own cell units, or zero when no map is loaded.

kitaqgb/lib/map.c:25

c
u8 map_current_height()
{
    if (map_meta_loaded != 0) return map_meta_current.height;
    if (map_loaded == 0) return 0;
    return map_current.height;
}
map_current_width

Lee el ancho del mapa activo.

Sintaxis

c
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

c
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.

map_current_width: DMG
DMG
map_current_width: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_map_path.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_map_path.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementación y código fuente

kitaqgb/lib/rpg.h:389

Notas de la declaración (original)
Return the active map width in its own cell units, or zero when no map is loaded.

kitaqgb/lib/map.c:17

c
u8 map_current_width()
{
    if (map_meta_loaded != 0) return map_meta_current.width;
    if (map_loaded == 0) return 0;
    return map_current.width;
}
map_draw_visible

Dibuja 10×9 metatiles desde el origen indicado y guarda esa posición de cámara para redibujar cuando haya cambios pendientes.

Sintaxis

c
void map_draw_visible(u8 camera_tx, u8 camera_ty);

Parámetros

camera_tx

X de la celda más a la izquierda; mantenla como máximo en 246 para evitar el desbordamiento de byte durante el recorrido.

camera_ty

Y 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

c
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.

map_draw_visible: DMG
DMG
map_draw_visible: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_metatile.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_metatile.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementación y código fuente

kitaqgb/lib/rpg.h:304

Notas de la declaración (original)
Draw a 10-by-9 metatile viewport as 20-by-18 individual background tiles.
Out-of-range cells use definition zero; palette attributes are not written.
Remember the camera and clear the dirty flag after the full redraw.

kitaqgb/lib/map.c:212

c
void map_draw_visible(u8 camera_tx, u8 camera_ty)
{
    u8 my;

    if (map_meta_loaded == 0) return;

    map_camera_x = camera_tx;
    map_camera_y = camera_ty;

    my = 0;
    while (my < 9) {
        u8 mx = 0;
        while (mx < 10) {
            u8 tx = (u8)(camera_tx + mx);
            u8 ty = (u8)(camera_ty + my);
            u8 sx = (u8)(mx << 1);
            u8 sy = (u8)(my << 1);
            metatile_t meta;
            u8 id = map_get_metatile(tx, ty);
            map_read_metatile(id, &meta);
            __settile_xy(sx, sy, meta.tile_tl);
            __settile_xy((u8)(sx + 1), sy, meta.tile_tr);
            __settile_xy(sx, (u8)(sy + 1), meta.tile_bl);
            __settile_xy((u8)(sx + 1), (u8)(sy + 1), meta.tile_br);
            mx++;
        }
        my++;
    }
    map_dirty = 0;
}
map_flush_dirty

Si hay cambios pendientes, redibuja el área visible desde el origen de cámara guardado y borra el indicador de cambio.

Sintaxis

c
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

c
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.

map_flush_dirty: DMG
DMG
map_flush_dirty: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_metatile.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_metatile.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementación y código fuente

kitaqgb/lib/rpg.h:321

Notas de la declaración (original)
Redraw the remembered metatile viewport only when the shared dirty flag is set.

kitaqgb/lib/map.c:254

c
void map_flush_dirty()
{
    if (map_dirty == 0) return;
    map_draw_visible(map_camera_x, map_camera_y);
}
map_get_attr

Lee los metadatos de paleta de la definición de metatile de la celda.

Sintaxis

c
u8 map_get_attr(u8 tx, u8 ty);

Parámetros

tx

Coordenada X del metatile.

ty

Coordenada 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

c
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.

map_get_attr: DMG
DMG
map_get_attr: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_metatile.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_metatile.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementación y código fuente

kitaqgb/lib/rpg.h:310

Notas de la declaración (original)
Return the selected definition's palette byte. An out-of-range coordinate
uses the metatile-zero fallback; this function does not write CGB attributes.

kitaqgb/lib/map.c:172

c
u8 map_get_attr(u8 tx, u8 ty)
{
    metatile_t meta;
    u8 id;
    if (map_meta_loaded == 0) return 0;
    id = map_get_metatile(tx, ty);
    map_read_metatile(id, &meta);
    return meta.palette;
}
map_get_event

Lee un ID de evento de metatile; los mapas normales indican si hay un evento.

Sintaxis

c
u8 map_get_event(u8 tx, u8 ty);

Parámetros

tx

Coordenada X del metatile.

ty

Coordenada 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

c
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.

map_get_event: DMG
DMG
map_get_event: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_metatile.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_metatile.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementación y código fuente

kitaqgb/lib/rpg.h:316

Notas de la declaración (original)
Return a metatile event ID, or the ordinary-map Boolean trigger result.
Missing/out-of-range metatile cells have no event.

kitaqgb/lib/map.c:197

c
u8 map_get_event(u8 tx, u8 ty)
{
    metatile_t meta;
    u8 id;
    if (map_meta_loaded == 0) return map_trigger_at(tx, ty);
    if (tx >= map_meta_current.width || ty >= map_meta_current.height) return 0;
    id = map_get_metatile(tx, ty);
    map_read_metatile(id, &meta);
    return meta.event;
}
map_get_metatile

Lee el ID de metatile de una celda.

Sintaxis

c
u8 map_get_metatile(u8 tx, u8 ty);

Parámetros

tx

Coordenada X del metatile.

ty

Coordenada 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

c
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.

map_get_metatile: DMG
DMG
map_get_metatile: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_metatile.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_metatile.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementación y código fuente

kitaqgb/lib/rpg.h:307

Notas de la declaración (original)
Read a row-major metatile ID, returning ID zero for inactive or out-of-range
lookups. Callers must provide a usable definition for metatile zero.

kitaqgb/lib/map.c:159

c
u8 map_get_metatile(u8 tx, u8 ty)
{
    u16 index;

    if (map_meta_loaded == 0) return 0;
    if (tx >= map_meta_current.width || ty >= map_meta_current.height) return 0;

    index = __map_index(tx, ty, map_meta_current.width);
    return __farpeek8(map_meta_data_bank(), map_meta_current.metatile_ids + index);
}
map_is_blocked

Comprueba si la celda de destino bloquea el movimiento; el modo metatile usa el campo collision de su definición.

Sintaxis

c
u8 map_is_blocked(u8 x, u8 y);

Parámetros

x

Coordenada X de la celda.

y

Coordenada 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

c
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.

map_is_blocked: DMG
DMG
map_is_blocked: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_map_path.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_map_path.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementación y código fuente

kitaqgb/lib/rpg.h:290

Notas de la declaración (original)
Use metatile collision when that mode is active; otherwise read one packed
collision bit. Missing maps/out-of-range cells block movement, but a valid
ordinary map without a collision array is entirely passable.

kitaqgb/lib/map.c:68

c
u8 map_is_blocked(u8 x, u8 y)
{
    u16 index;
    u8 value;

    if (map_meta_loaded != 0) return map_is_solid(x, y);
    if (map_loaded == 0) return 1;
    if (x >= map_current.width || y >= map_current.height) return 1;
    if (map_current.collision_bits == 0) return 0;

    index = __map_index(x, y, map_current.width);
    // Collision uses least-significant bit first within each row-major group of eight cells.
    value = __farpeek8(map_bank, map_current.collision_bits + (index >> 3));
    if ((value & (u8)(1 << (index & 7))) != 0) return 1;
    return 0;
}
map_is_solid

Comprueba la solidez; en modo de mapa normal delega en los bits de colisión.

Sintaxis

c
u8 map_is_solid(u8 tx, u8 ty);

Parámetros

tx

Coordenada X del metatile.

ty

Coordenada 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

c
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.

map_is_solid: DMG
DMG
map_is_solid: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_metatile.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_metatile.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementación y código fuente

kitaqgb/lib/rpg.h:313

Notas de la declaración (original)
Treat out-of-range metatile cells as solid; otherwise inspect the definition
collision flag. In ordinary-map mode, delegate to its packed collision bits.

kitaqgb/lib/map.c:184

c
u8 map_is_solid(u8 tx, u8 ty)
{
    metatile_t meta;
    u8 id;
    if (map_meta_loaded == 0) return map_is_blocked(tx, ty);
    if (tx >= map_meta_current.width || ty >= map_meta_current.height) return 1;
    id = map_get_metatile(tx, ty);
    map_read_metatile(id, &meta);
    return (u8)(meta.collision != 0);
}
map_load

Carga un descriptor de mapa normal y dibuja hasta 20×18 tiles desde su esquina superior izquierda en el mapa de fondo seleccionado.

Sintaxis

c
void map_load(u8 bank, const map_t* map);

Parámetros

bank

Banco ROM del descriptor, los bits de colisión y los eventos.

map

map_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

c
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.

map_load: DMG
DMG
map_load: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_map_path.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_map_path.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementación y código fuente

kitaqgb/lib/rpg.h:286

Notas de la declaración (original)
Load the nine-byte ordinary-map descriptor and draw up to 20 by 18 tiles
from its top-left corner. Drawing does not upload tile graphics or clear
background cells beyond smaller map dimensions.

kitaqgb/lib/map.c:35

c
void map_load(u8 bank, const map_t* map)
{
    u8 row;
    u8 h;
    u8 w;

    // The literal copy size depends on the packed map_t layout; changing that layout requires updating this copy.
    __farmemcpy(&map_current, bank, map, 9);
    map_bank = bank;
    map_loaded = 1;
    map_meta_loaded = 0;

    w = map_current.width;
    h = map_current.height;
    if (w > 20) w = 20;
    if (h > 18) h = 18;

    row = 0;
    while (row < h) {
        u8 x = 0;
        u16 base_index = __map_index(0, row, map_current.width);
        while (x < w) {
            map_row[x] = __farpeek8(map_current.bank_tiles, map_current.tiles + base_index + x);
            x++;
        }
        __settile_row(0, row, map_row, w);
        row++;
    }
}
map_load_metatile

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

c
void map_load_metatile(u8 bank, const metatile_map_t* map);

Parámetros

bank

Banco ROM que contiene el descriptor.

map

Puntero 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

c
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.

map_load_metatile: DMG
DMG
map_load_metatile: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_metatile.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_metatile.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementación y código fuente

kitaqgb/lib/rpg.h:300

Notas de la declaración (original)
Select metatile mode, copy its descriptor and draw the initial viewport
with the camera at cell (0,0).

kitaqgb/lib/map.c:145

c
void map_load_metatile(u8 bank, const metatile_map_t* map)
{
    map_meta_bank = bank;
    __farmemcpy(&map_meta_current, bank, map, sizeof(metatile_map_t));
    map_meta_loaded = 1;
    map_loaded = 0;
    map_dirty = 0;
    map_camera_x = 0;
    map_camera_y = 0;
    map_draw_visible(0, 0);
}
map_mark_dirty

Marca el área visible para redibujar cuando recibe una coordenada de metatile válida.

Sintaxis

c
void map_mark_dirty(u8 tx, u8 ty);

Parámetros

tx

Coordenada X del metatile.

ty

Coordenada 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

c
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.

map_mark_dirty: DMG
DMG
map_mark_dirty: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_metatile.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_metatile.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementación y código fuente

kitaqgb/lib/rpg.h:319

Notas de la declaración (original)
Mark the viewport for a full redraw when a valid metatile cell changes.
The coordinate is validated but no per-cell dirty list is retained.

kitaqgb/lib/map.c:246

c
void map_mark_dirty(u8 tx, u8 ty)
{
    if (map_meta_loaded == 0) return;
    if (tx >= map_meta_current.width || ty >= map_meta_current.height) return;
    map_dirty = 1;
}
map_trigger_at

Comprueba si una celda tiene un evento, sin ejecutarlo.

Sintaxis

c
u8 map_trigger_at(u8 x, u8 y);

Parámetros

x

Coordenada X de la celda.

y

Coordenada 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

c
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.

map_trigger_at: DMG
DMG
map_trigger_at: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_map_path.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_map_path.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementación y código fuente

kitaqgb/lib/rpg.h:293

Notas de la declaración (original)
Report whether an event exists at the cell. Ordinary maps expose a Boolean
byte-presence test; metatile maps reduce their event ID to a Boolean here.

kitaqgb/lib/map.c:87

c
u8 map_trigger_at(u8 x, u8 y)
{
    u16 index;
    u8 value;

    if (map_meta_loaded != 0) return (u8)(map_get_event(x, y) != 0);
    if (map_loaded == 0) return 0;
    if (x >= map_current.width || y >= map_current.height) return 0;
    if (map_current.events == 0) return 0;

    index = __map_index(x, y, map_current.width);
    value = __farpeek8(map_bank, ((const u8*)map_current.events) + index);
    return (u8)((value != 0) ? 1 : 0);
}
menu_draw

Dibuja el borde, las etiquetas de las opciones y el cursor actual a partir del estado del menú.

Sintaxis

c
void menu_draw(menu_state_t* state);

Parámetros

state

Puntero a un estado de menú inicializado.

Valor devuelto

No devuelve ningún valor.

Condiciones y límites

Un puntero nulo no tiene efecto. Cada llamada vuelve a abrir la ventana con text_open() y también actualiza el estado compartido de la ventana de texto. No lee entradas. Carga de antemano los tiles del borde, el cursor y el texto. El código que llama debe conservar el array de opciones y las cadenas. El texto no se ajusta automáticamente a otra línea ni se recorta; elige posiciones, cantidades de opciones y longitudes de etiquetas que quepan en la ventana.

Ejemplo de uso

c
menu_draw(&menu_state);

Este fragmento 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 dibuja el menú al inicio y lo vuelve a dibujar tras una entrada. Después de DOWN, el cursor queda junto a SHIELD.

menu_draw: DMG
DMG
menu_draw: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_menu_state.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_menu_state.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/rpg.h:273

Notas de la declaración (original)
Draw the current menu and cursor without waiting or sampling input. The
caller schedules suitable display timing and keeps item text within bounds.

kitaqgb/lib/menu.c:94

c
void menu_draw(menu_state_t* state)
{
    u8 i;
    if (state == 0) return;

    text_open(state->x, state->y, state->w, state->h);
    i = 0;
    while (i < state->count) {
        u8 py = (u8)(state->y + 1 + i);
        const u8* s = state->items[i];
        u8 px = (u8)(state->x + 2);
        __settile_xy((u8)(state->x + 1), py, (i == state->cursor) ? TEXT_TILE_CURSOR : TEXT_TILE_FILL);
        while (*s != 0) {
            __settile_xy(px, py, *s);
            px++;
            s++;
        }
        i++;
    }
}
menu_get_selected

Lee la selección guardada por un menú procesado paso a paso.

Sintaxis

c
u8 menu_get_selected(menu_state_t* state);

Parámetros

state

Puntero a un estado de menú inicializado.

Valor devuelto

Devuelve el índice seleccionado, contado desde cero, o 255 si aún está pendiente, se ha cancelado o se pasa un puntero nulo.

Condiciones y límites

La lectura no borra el resultado. Deja de actualizar al terminar y llama a menu_init_state() antes de iniciar una nueva interacción.

Ejemplo de uso

c
result[0]=menu_get_selected(&menu_state);

Este fragmento 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 selección 1 de SHIELD y comprueba que un puntero nulo devuelve 255.

menu_get_selected: DMG
DMG
menu_get_selected: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_menu_state.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_menu_state.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/rpg.h:279

Notas de la declaración (original)
Read the latched selection without clearing it; null state returns 0xFF.

kitaqgb/lib/menu.c:148

c
u8 menu_get_selected(menu_state_t* state)
{
    if (state == 0) return 0xFF;
    return state->selected;
}
menu_init_state

Inicializa un menú que se procesará paso a paso desde el bucle del juego.

Sintaxis

c
void menu_init_state(menu_state_t* state, u8 x, u8 y, u8 w, u8 h, const u8* const* items, u8 count);

Parámetros

state

menu_state_t no nulo y accesible para escritura que se va a inicializar.

x

Columna de tiles del borde izquierdo de la ventana.

y

Fila de tiles del borde superior de la ventana.

w

Ancho en tiles, incluido el borde.

h

Alto en tiles, incluido el borde.

items

Array de punteros a las etiquetas de las opciones, terminadas en cero.

count

Número de opciones, que no debe superar las filas disponibles dentro de la ventana.

Valor devuelto

No devuelve ningún valor.

Condiciones y límites

Pone el cursor y el estado anterior de los botones a cero, la selección a 255 y la cancelación a cero. No dibuja ni espera una entrada. Carga de antemano los tiles del borde, el cursor y el texto. El código que llama debe conservar el array de opciones y las cadenas. El texto no se ajusta automáticamente a otra línea ni se recorta; elige posiciones, cantidades de opciones y longitudes de etiquetas que quepan en la ventana.

Ejemplo de uso

c
menu_init_state(&menu_state,1,2,18,5,choices,3);result[2]=menu_state.selected;

Este fragmento 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 prepara un menú de tres opciones en (1,2), de 18×5 tiles, con un valor de selección inicial de 255.

menu_init_state: DMG
DMG
menu_init_state: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_menu_state.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_menu_state.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/rpg.h:270

Notas de la declaración (original)
Initialize a nonblocking menu state that borrows the item pointer table.
Selection starts unset (0xFF), and the cancellation flag starts clear.

kitaqgb/lib/menu.c:78

c
void menu_init_state(menu_state_t* state, u8 x, u8 y, u8 w, u8 h, const u8* const* items, u8 count)
{
    state->x = x;
    state->y = y;
    state->w = w;
    state->h = h;
    state->items = items;
    state->count = count;
    state->cursor = 0;
    state->prev_keys = 0;
    state->selected = 0xFF;
    state->cancelled = 0;
}
menu_inventory

Muestra los nombres de los objetos del inventario y sus cantidades con dos dígitos, y permite elegir un objeto.

Sintaxis

c
u8 menu_inventory(const item_t* items, u8 count);

Parámetros

items

Array item_t accesible para lectura, con los ID, las cantidades y los nombres.

count

Número de objetos: de 1 a 15 para una lista visible, o cero para una lista vacía.

Valor devuelto

Devuelve el índice del array seleccionado, no el ID del objeto, o 255 si se cancela o la lista está vacía.

Condiciones y límites

No modifica los objetos ni sus cantidades. Usa cantidades de 0 a 99 y un máximo de 15 objetos visibles. La ventana está en (1,1), con ancho 18 y alto igual al número de objetos más 2. Los nombres empiezan en la columna 3 y las cantidades ocupan las columnas 15–16; un nombre largo puede sobrescribirlas. UP/DOWN recorre la lista de forma circular y A tiene prioridad sobre B si se pulsan a la vez. Carga de antemano los tiles del borde, el cursor y el texto. El código que llama debe conservar el array de opciones y las cadenas. El texto no se ajusta automáticamente a otra línea ni se recorta; elige posiciones, cantidades de opciones y longitudes de etiquetas que quepan en la ventana.

Ejemplo de uso

c
result[0]=menu_inventory(items,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

La ventana muestra SWORD 07, SHIELD 42 y POTION 99. Seleccionar SHIELD devuelve el índice 1 y mantiene su cantidad en 42.

menu_inventory: DMG
DMG
menu_inventory: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_menu_inventory.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_menu_inventory.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/rpg.h:267

Notas de la declaración (original)
Run a blocking item menu, drawing names and two-digit quantities. Return
the selected index or 0xFF on empty input/B; this does not consume an item.

kitaqgb/lib/menu.c:176

c
u8 menu_inventory(const item_t* items, u8 count)
{
    u8 cursor;
    u8 prev;
    u8 i;

    if (count == 0) return 0xFF;

    text_open(1, 1, 18, (u8)(count + 2));
    cursor = 0;
    prev = 0;

    while (1) {
        for (i = 0; i < count; i++) {
            u8 py = (u8)(2 + i);
            const u8* s = items[i].name;
            u8 px = 3;
            __settile_xy(2, py, (i == cursor) ? TEXT_TILE_CURSOR : TEXT_TILE_FILL);
            while (*s != 0) {
                __settile_xy(px, py, *s);
                px++;
                s++;
            }
            menu_draw_ascii_qty(15, py, items[i].qty);
        }

        __wait_vblank();
        {
            u16 kt = __readpadex(prev);
            u8 trigger;
            prev = (u8)kt;
            trigger = (u8)(kt >> 8);

            if ((trigger & PAD_KEY_UP) != 0) {
                if (cursor == 0) cursor = (u8)(count - 1);
                else cursor--;
            }
            if ((trigger & PAD_KEY_DOWN) != 0) {
                cursor++;
                if (cursor >= count) cursor = 0;
            }
            if ((trigger & PAD_KEY_A) != 0) return cursor;
            if ((trigger & PAD_KEY_B) != 0) return 0xFF;
        }
    }
}
menu_run

Muestra un menú de opciones y espera a que se confirme o cancele la selección.

Sintaxis

c
u8 menu_run(const menu_t* menu);

Parámetros

menu

menu_t no nulo que define la posición, el tamaño, las opciones, su número y el cursor inicial. Si la posición inicial está fuera de rango, se usa cero.

Valor devuelto

Devuelve el índice seleccionado, contado desde cero, o 255 al cancelar con B o si la lista está vacía.

Condiciones y límites

Cada nueva pulsación de UP/DOWN mueve el cursor y recorre la lista de forma circular, sin repetición al mantener pulsado. A tiene prioridad sobre B si se pulsan a la vez. Los botones que ya estén pulsados al entrar se consideran pulsaciones nuevas. menu->cursor indica la posición inicial y no se actualiza con el resultado. La ventana permanece visible después de volver. Carga de antemano los tiles del borde, el cursor y el texto. El código que llama debe conservar el array de opciones y las cadenas. El texto no se ajusta automáticamente a otra línea ni se recorta; elige posiciones, cantidades de opciones y longitudes de etiquetas que quepan en la ventana.

Ejemplo de uso

c
result[0]=menu_run(&menu);

Este fragmento 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 lista SWORD/SHIELD/POTION, pulsar DOWN y después A selecciona SHIELD, de índice 1. La posición inicial almacenada del cursor sigue siendo cero.

menu_run: DMG
DMG
menu_run: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_menu_run.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_menu_run.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/rpg.h:262

Notas de la declaración (original)
Run a blocking menu loop with wraparound up/down selection, A to accept
and B to cancel. Return 0xFF for an empty menu or cancellation. Item strings
and menu dimensions must fit the visible tile area.

kitaqgb/lib/menu.c:25

c
u8 menu_run(const menu_t* menu)
{
    u8 cursor;
    u8 prev;

    if (menu->count == 0) return 0xFF;

    text_open(menu->x, menu->y, menu->w, menu->h);
    cursor = menu->cursor;
    if (cursor >= menu->count) cursor = 0;
    prev = 0;

    while (1) {
        u8 i;
        for (i = 0; i < menu->count; i++) {
            u8 py = (u8)(menu->y + 1 + i);
            __settile_xy((u8)(menu->x + 1), py, (i == cursor) ? TEXT_TILE_CURSOR : TEXT_TILE_FILL);
            {
                const u8* s = menu->items[i];
                u8 px = (u8)(menu->x + 2);
                while (*s != 0) {
                    __settile_xy(px, py, *s);
                    px++;
                    s++;
                }
            }
        }

        __wait_vblank();
        {
            u16 kt = __readpadex(prev);
            u8 trigger;
            prev = (u8)kt;
            trigger = (u8)(kt >> 8);

            if ((trigger & PAD_KEY_UP) != 0) {
                if (cursor == 0) cursor = (u8)(menu->count - 1);
                else cursor--;
            }
            if ((trigger & PAD_KEY_DOWN) != 0) {
                cursor++;
                if (cursor >= menu->count) cursor = 0;
            }
            if ((trigger & PAD_KEY_A) != 0) return cursor;
            if ((trigger & PAD_KEY_B) != 0) return 0xFF;
        }
    }
}
menu_update

Lee un cambio de los botones del mando y actualiza el cursor, la selección y el estado de cancelación.

Sintaxis

c
void menu_update(menu_state_t* state);

Parámetros

state

Estado de menú inicializado cuyo historial de entradas y resultados se van a actualizar.

Valor devuelto

No devuelve ningún valor.

Condiciones y límites

No hace nada si se pasa un puntero nulo o la lista está vacía. No espera un fotograma ni dibuja; llámala aproximadamente una vez por fotograma del bucle del juego. UP/DOWN recorre la lista de forma circular, sin repetición al mantener pulsado. B se procesa después de A, así que pulsar A/B a la vez cancela.

Ejemplo de uso

c
menu_update(&menu_state);menu_draw(&menu_state);

Este fragmento 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 bucle espera a VBlank, actualiza el menú y lo dibuja hasta que se confirma o cancela. DOWN seguido de A produce una selección de 1 y un indicador de cancelación de 0.

menu_update: DMG
DMG
menu_update: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_menu_state.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_menu_state.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/rpg.h:277

Notas de la declaración (original)
Sample new button presses and update cursor/selection state without drawing.
Selected and cancelled results remain latched; a B press in the same update
as A clears selection and leaves cancellation set.

kitaqgb/lib/menu.c:118

c
void menu_update(menu_state_t* state)
{
    u16 kt;
    u8 trigger;

    if (state == 0) return;
    if (state->count == 0) return;

    kt = __readpadex(state->prev_keys);
    state->prev_keys = (u8)kt;
    trigger = (u8)(kt >> 8);

    if ((trigger & PAD_KEY_UP) != 0) {
        if (state->cursor == 0) state->cursor = (u8)(state->count - 1);
        else state->cursor--;
    }
    if ((trigger & PAD_KEY_DOWN) != 0) {
        state->cursor++;
        if (state->cursor >= state->count) state->cursor = 0;
    }
    if ((trigger & PAD_KEY_A) != 0) {
        state->selected = state->cursor;
    }
    if ((trigger & PAD_KEY_B) != 0) {
        state->cancelled = 1;
        state->selected = 0xFF;
    }
}
menu_was_cancelled

Comprueba si se ha cancelado con B un menú procesado paso a paso.

Sintaxis

c
u8 menu_was_cancelled(menu_state_t* state);

Parámetros

state

Puntero a un estado de menú inicializado.

Valor devuelto

Devuelve 1 si se ha cancelado; en caso contrario, 0, también si el puntero es nulo.

Condiciones y límites

La lectura no borra el indicador. Reinicializa antes de reutilizarlo. Consúltalo junto con la selección, ya que 255 por sí solo no distingue entre una entrada pendiente y una cancelación.

Ejemplo de uso

c
result[1]=menu_was_cancelled(&menu_state);

Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.

Resultado esperado

Confirmar con A deja el indicador en cero. Otra comprobación de entrada cancela con B y verifica que sea uno.

menu_was_cancelled: DMG
DMG
menu_was_cancelled: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_menu_state.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_menu_state.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/rpg.h:281

Notas de la declaración (original)
Read the latched cancellation flag; null state returns false.

kitaqgb/lib/menu.c:155

c
u8 menu_was_cancelled(menu_state_t* state)
{
    if (state == 0) return 0;
    return state->cancelled;
}
menu_yesno

Muestra un menú YES/NO en una posición fija y espera una entrada.

Sintaxis

c
u8 menu_yesno();

Valor devuelto

Devuelve 0 para YES, 1 para NO o 255 al cancelar con B.

Condiciones y límites

La ventana comienza en el tile (6,10) y mide 8×4 tiles. La selección usa text_choice(). El código que llama ejecuta la acción elegida al volver de la función. Carga de antemano los tiles del borde, el cursor y el texto. El código que llama debe conservar el array de opciones y las cadenas. El texto no se ajusta automáticamente a otra línea ni se recorta; elige posiciones, cantidades de opciones y longitudes de etiquetas que quepan en la ventana.

Ejemplo de uso

c
result[0]=menu_yesno();

Este fragmento muestra la llamada. Antes de incorporarlo a un programa completo, cumple los requisitos de inicialización y de los búferes indicados.

Resultado esperado

DOWN seguido de A selecciona NO. El cursor aparece a la izquierda de NO y SELECTED muestra 00001.

menu_yesno: DMG
DMG
menu_yesno: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_menu_yesno.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_menu_yesno.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/rpg.h:264

Notas de la declaración (original)
Open a two-choice dialog and return the text-choice result (YES first, NO second).

kitaqgb/lib/menu.c:162

c
u8 menu_yesno()
{
    const u8* items[2];

    items[0] = menu_yes;
    items[1] = menu_no;
    text_open(6, 10, 8, 4);
    return text_choice(items, 2);
}
path_find_bfs

Encuentra una ruta ortogonal más corta y escribe sus direcciones en orden desde el inicio hasta el destino.

Sintaxis

c
u8 path_find_bfs(u8 sx, u8 sy, u8 gx, u8 gy, u8* out_path, u8 max_len);

Parámetros

sx

X de la celda inicial, dentro del mapa.

sy

Y de la celda inicial.

gx

X de la celda de destino; se rechaza un destino bloqueado distinto del origen.

gy

Y de la celda de destino.

out_path

Array escribible de al menos max_len bytes; 0=arriba, 1=derecha, 2=abajo, 3=izquierda.

max_len

Capacidad 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

c
result[49]=path_find_bfs(0,2,5,2,route,30);x=0;y=2;for(i=0;i<result[49];i++){if(route[i]==0)y--;if(route[i]==1)x++;if(route[i]==2)y++;if(route[i]==3)x--;}result[50]=x;result[51]=y;result[52]=path_find_bfs(0,2,5,2,route,2);result[53]=path_find_bfs(0,2,2,2,route,30);

Este fragmento 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.

path_find_bfs: DMG
DMG
path_find_bfs: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_map_path.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_map_path.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementación y código fuente

kitaqgb/lib/rpg.h:361

Notas de la declaración (original)
Find a shortest cardinal path with BFS and write direction codes 0=up,
1=right, 2=down, 3=left. Return its byte length, or zero for failure or an
already-reached goal. The caller supplies max_len output bytes and respects
the shared workspace/distance limits; excessive paths are not truncated.

kitaqgb/lib/slg_path.c:78

c
u8 path_find_bfs(u8 sx, u8 sy, u8 gx, u8 gy, u8* out_path, u8 max_len)
{
    u8 w = map_current_width();
    u8 h = map_current_height();
    u16 total;
    u16 head = 0;
    u16 tail = 0;
    u16 start;
    u16 goal;
    u8 found = 0;

    if (w == 0 || h == 0) return 0;
    if (sx >= w || sy >= h || gx >= w || gy >= h) return 0;
    if ((sx != gx || sy != gy) && map_is_blocked(gx, gy) != 0) return 0;

    total = (u16)((u16)w * (u16)h);
    __memset(path_dist, 0xFF, total);

    start = __map_index(sx, sy, w);
    goal = __map_index(gx, gy, w);

    path_dist[start] = 0;
    path_queue[tail++] = start;

    while (head < tail) {
        u16 cur = path_queue[head++];
        u8 cost = path_dist[cur];
        u8 y = (u8)(cur / w);
        u8 x = (u8)(cur - ((u16)y * (u16)w));

        if (cur == goal) {
            found = 1;
            break;
        }

        if (y > 0) {
            u16 next = (u16)(cur - w);
            if (path_dist[next] == 0xFF && map_is_blocked(x, (u8)(y - 1)) == 0) {
                path_dist[next] = (u8)(cost + 1);
                path_queue[tail++] = next;
            }
        }
        if ((u8)(x + 1) < w) {
            u16 next = (u16)(cur + 1);
            if (path_dist[next] == 0xFF && map_is_blocked((u8)(x + 1), y) == 0) {
                path_dist[next] = (u8)(cost + 1);
                path_queue[tail++] = next;
            }
        }
        if ((u8)(y + 1) < h) {
            u16 next = (u16)(cur + w);
            if (path_dist[next] == 0xFF && map_is_blocked(x, (u8)(y + 1)) == 0) {
                path_dist[next] = (u8)(cost + 1);
                path_queue[tail++] = next;
            }
        }
        if (x > 0) {
            u16 next = (u16)(cur - 1);
            if (path_dist[next] == 0xFF && map_is_blocked((u8)(x - 1), y) == 0) {
                path_dist[next] = (u8)(cost + 1);
                path_queue[tail++] = next;
            }
        }
    }

    // Reject unreachable or oversized paths before reconstructing output.
    if (found == 0) return 0;
    if (path_dist[goal] > max_len) return 0;

    {
        // Walk backward through decreasing costs, recording forward directions in
        // reverse order. The fixed neighbor order makes tied routes deterministic.
        u8 len = 0;
        u16 cur = goal;

        while (cur != start) {
            u8 cur_cost = path_dist[cur];
            u8 y = (u8)(cur / w);
            u8 x = (u8)(cur - ((u16)y * (u16)w));

            if (y > 0 && path_dist[(u16)(cur - w)] == (u8)(cur_cost - 1)) {
                path_rev[len++] = 2;
                cur = (u16)(cur - w);
                continue;
            }
            if ((u8)(x + 1) < w && path_dist[(u16)(cur + 1)] == (u8)(cur_cost - 1)) {
                path_rev[len++] = 3;
                cur = (u16)(cur + 1);
                continue;
            }
            if ((u8)(y + 1) < h && path_dist[(u16)(cur + w)] == (u8)(cur_cost - 1)) {
                path_rev[len++] = 0;
                cur = (u16)(cur + w);
                continue;
            }
            if (x > 0 && path_dist[(u16)(cur - 1)] == (u8)(cur_cost - 1)) {
                path_rev[len++] = 1;
                cur = (u16)(cur - 1);
                continue;
            }
            return 0;
        }

        // Reverse the recovered directions so the first output step starts at the origin.
        while (len != 0) {
            len--;
            out_path[path_dist[goal] - 1 - len] = path_rev[len];
        }

        return path_dist[goal];
    }
}
quest_set_state

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

c
void quest_set_state(u8 quest_id, u8 state);

Parámetros

quest_id

Nú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.

state

Nuevo 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

c
quest_set_state(2,1); // In this game, 1 means accepted.
started=quest_state(2);
quest_set_state(2,3); // In this game, 3 means completed; replace the whole byte.

Este fragmento 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.

quest_set_state: DMG
DMG
quest_set_state: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\flags_quests.c .\kitaqgb\lib\flags.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\flags_quests.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/rpg.h:377

Notas de la declaración (original)
Replace a quest-state byte without validating its game-specific meaning.
The caller must keep quest_id below 64.

kitaqgb/lib/flags.c:34

c
void quest_set_state(u8 quest_id, u8 state)
{
    quest_states[quest_id] = state;
}
quest_state

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

c
u8 quest_state(u8 quest_id);

Parámetros

quest_id

Nú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

c
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.

quest_state: DMG
DMG
quest_state: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\flags_quests.c .\kitaqgb\lib\flags.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\flags_quests.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/rpg.h:374

Notas de la declaración (original)
Read a quest-state byte; quest_id must be below 64.

kitaqgb/lib/flags.c:27

c
u8 quest_state(u8 quest_id)
{
    return quest_states[quest_id];
}
rand_range

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

c
u8 rand_range(u8 max);

Parámetros

max

Lí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

c
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.

rand_range: DMG
DMG
rand_range: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\rng_choices.c .\kitaqgb\lib\rng.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\rng_choices.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/rpg.h:199

Notas de la declaración (original)
Reduce a random byte modulo max; zero returns zero without consuming randomness.
Modulo reduction is biased unless max divides the generator range.

kitaqgb/lib/rng.c:37

c
u8 rand_range(u8 max)
{
    if (max == 0) return 0;
    return (u8)(rng8() % max);
}
range_fill_move

Recorre los vecinos ortogonales con coste unitario mediante búsqueda en anchura para calcular los costes de movimiento.

Sintaxis

c
void range_fill_move(u8 sx, u8 sy, u8 move, u8* out_costmap);

Parámetros

sx

X de la celda inicial, dentro del mapa.

sy

Y de la celda inicial.

move

Límite de movimiento de 0 a 254; cero alcanza solo el origen.

out_costmap

Array 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

c
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.

range_fill_move: DMG
DMG
range_fill_move: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_map_path.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_map_path.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementación y código fuente

kitaqgb/lib/rpg.h:365

Notas de la declaración (original)
Flood cardinal neighbors at unit cost, stopping expansion at the movement
limit and rejecting blocked destinations. Initialize output to 0xFF only
after validating the map and origin; invalid input leaves output unchanged.

kitaqgb/lib/slg_path.c:14

c
void range_fill_move(u8 sx, u8 sy, u8 move, u8* out_costmap)
{
    u8 w = map_current_width();
    u8 h = map_current_height();
    u16 total;
    u16 head = 0;
    u16 tail = 0;
    u16 start;

    if (w == 0 || h == 0) return;
    if (sx >= w || sy >= h) return;

    total = (u16)((u16)w * (u16)h);
    __memset(out_costmap, 0xFF, total);

    start = __map_index(sx, sy, w);
    out_costmap[start] = 0;
    path_queue[tail++] = start;

    while (head < tail) {
        u16 cur = path_queue[head++];
        u8 cost = out_costmap[cur];
        u8 y = (u8)(cur / w);
        u8 x = (u8)(cur - ((u16)y * (u16)w));

        if (cost >= move) continue;

        if (y > 0) {
            u16 next = (u16)(cur - w);
            if (out_costmap[next] == 0xFF && map_is_blocked(x, (u8)(y - 1)) == 0) {
                out_costmap[next] = (u8)(cost + 1);
                path_queue[tail++] = next;
            }
        }
        if ((u8)(x + 1) < w) {
            u16 next = (u16)(cur + 1);
            if (out_costmap[next] == 0xFF && map_is_blocked((u8)(x + 1), y) == 0) {
                out_costmap[next] = (u8)(cost + 1);
                path_queue[tail++] = next;
            }
        }
        if ((u8)(y + 1) < h) {
            u16 next = (u16)(cur + w);
            if (out_costmap[next] == 0xFF && map_is_blocked(x, (u8)(y + 1)) == 0) {
                out_costmap[next] = (u8)(cost + 1);
                path_queue[tail++] = next;
            }
        }
        if (x > 0) {
            u16 next = (u16)(cur - 1);
            if (out_costmap[next] == 0xFF && map_is_blocked((u8)(x - 1), y) == 0) {
                out_costmap[next] = (u8)(cost + 1);
                path_queue[tail++] = next;
            }
        }
    }
}
rle_decode

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

c
u16 rle_decode(void* dst, const void* src);

Parámetros

dst

Puntero 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.

src

Puntero 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

c
near_count=rle_decode(near_buffer+1,local_rle); // 48 bytes in writable RAM.
__vram_copy(0x8800,near_buffer+1,near_count); // Upload those bytes while the LCD is off.

Este fragmento 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.

rle_decode: DMG
DMG
rle_decode: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\rle_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\rle_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/rpg.h:382

Notas de la declaración (original)
Expand count/value byte pairs until a zero count terminates the stream.
The caller must provide a valid terminator and sufficient destination storage;
there are no source or destination bounds parameters. Return the 16-bit byte count.

kitaqgb/lib/rle.c:8

c
u16 rle_decode(void* dst, const void* src)
{
    const u8* in = (const u8*)src;
    u8* out = (u8*)dst;
    u16 total = 0;

    while (1) {
        u8 count = *in++;
        u8 value;
        if (count == 0) break;
        value = *in++;
        while (count != 0) {
            *out++ = value;
            total++;
            count--;
        }
    }

    return total;
}
rle_decode_far

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

c
u16 rle_decode_far(void* dst, u8 bank, const void* src);

Parámetros

dst

Puntero 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.

bank

Nú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.

src

Puntero 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

c
far_count=rle_decode_far(far_buffer+1,2,banked_rle); // Read encoded pairs from ROM bank 2.
if(*rle_bank_marker!=0xA1)failures++; // ROM bank 1 must be visible again.
__vram_copy(0x8830,far_buffer+1,far_count);

Este fragmento 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.

rle_decode_far: DMG
DMG
rle_decode_far: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\rle_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\rle_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/rpg.h:386

Notas de la declaración (original)
Decode the same count/value format using bank-qualified reads for every source
byte. Keep the encoded stream within the supplied bank/address mapping and
provide enough destination space; a zero count ends the stream.

kitaqgb/lib/rle.c:34

c
u16 rle_decode_far(void* dst, u8 bank, const void* src)
{
    const u8* p = (const u8*)src;
    u8* out = (u8*)dst;
    u16 total = 0;

    while (1) {
        u8 count = __farpeek8(bank, p);
        u8 value;
        p++;
        if (count == 0) break;
        value = __farpeek8(bank, p);
        p++;
        while (count != 0) {
            *out++ = value;
            total++;
            count--;
        }
    }

    return total;
}
rng16

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

c
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

c
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.

rng16: DMG
DMG
rng16: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\rng_values.c .\kitaqgb\lib\rng.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\rng_values.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/rpg.h:196

Notas de la declaración (original)
Consume two generator bytes in high-byte/low-byte order to form a 16-bit value.

kitaqgb/lib/rng.c:22

c
u16 rng16()
{
    u16 hi = (u16)rng8();
    u16 lo = (u16)rng8();
    return (u16)((hi << 8) | lo);
}
rng8

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

c
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

c
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.

rng8: DMG
DMG
rng8: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\rng_values.c .\kitaqgb\lib\rng.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\rng_values.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/rpg.h:194

Notas de la declaración (original)
Advance the compiler-provided pseudorandom generator and return one byte.

kitaqgb/lib/rng.c:4

c
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

c
u8 rng_chance(u8 percent);

Parámetros

percent

Probabilidad 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

c
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.

rng_chance: DMG
DMG
rng_chance: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\rng_choices.c .\kitaqgb\lib\rng.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\rng_choices.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/rpg.h:214

Notas de la declaración (original)
Return false for zero and true for values at least 100. Intermediate values
use the modulo-based range generator, so percentages are approximate.

kitaqgb/lib/rng.c:51

c
u8 rng_chance(u8 percent)
{
    if (percent == 0) return 0;
    if (percent >= 100) return 1;
    return (u8)(rng_range(100) < percent);
}
rng_next16

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

c
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

c
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.

rng_next16: DMG
DMG
rng_next16: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\rng_values.c .\kitaqgb\lib\rng.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\rng_values.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/rpg.h:209

Notas de la declaración (original)
Alias the two-step 16-bit generator.

kitaqgb/lib/rng.c:30

c
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

c
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

c
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.

rng_next8: DMG
DMG
rng_next8: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\rng_values.c .\kitaqgb\lib\rng.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\rng_values.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/rpg.h:207

Notas de la declaración (original)
Alias the byte generator; this consumes one generator step.

kitaqgb/lib/rng.c:16

c
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

c
u8 rng_range(u8 max);

Parámetros

max

Lí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

c
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.

rng_range: DMG
DMG
rng_range: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\rng_choices.c .\kitaqgb\lib\rng.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\rng_choices.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/rpg.h:211

Notas de la declaración (original)
Alias rand_range and return a value in [0,max), or zero when max is zero.

kitaqgb/lib/rng.c:44

c
u8 rng_range(u8 max)
{
    return rand_range(max);
}
rng_seed

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

c
void rng_seed(u16 seed);

Parámetros

seed

Semilla 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

c
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.

rng_seed: DMG
DMG
rng_seed: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\rng_values.c .\kitaqgb\lib\rng.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\rng_values.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/rpg.h:205

Notas de la declaración (original)
Replace the generator seed so subsequent calls can reproduce a sequence.

kitaqgb/lib/rng.c:10

c
void rng_seed(u16 seed)
{
    __rng_seed(seed);
}
save_check

Realiza la misma comprobación de integridad que save_exists sin extraer los datos.

Sintaxis

c
u8 save_check(u8 slot);

Parámetros

slot

Nú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

c
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.

save_check: DMG
DMG
save_check: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_save.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_save.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=8k
Implementación y código fuente

kitaqgb/lib/rpg.h:341

Notas de la declaración (original)
Alias save_exists, including its header and checksum validation.

kitaqgb/lib/save.c:175

c
u8 save_check(u8 slot)
{
    return save_exists(slot);
}
save_clear

Pone a cero los 512 bytes de una ranura para invalidar su guardado.

Sintaxis

c
void save_clear(u8 slot);

Parámetros

slot

Nú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

c
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.

save_clear: DMG
DMG
save_clear: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_save.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_save.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=8k
Implementación y código fuente

kitaqgb/lib/rpg.h:344

Notas de la declaración (original)
Zero the complete selected slot, including header and payload; invalid slot
IDs are ignored. Cartridge RAM is disabled when clearing finishes.

kitaqgb/lib/save.c:225

c
void save_clear(u8 slot)
{
    u16 base;
    u16 i;

    if (slot >= SAVE_SLOT_COUNT) return;

    base = save_slot_base(slot);
    save_enable();

    i = 0;
    while (i < SAVE_SLOT_SIZE) {
        save_write_abs((u16)(base + i), 0);
        i++;
    }

    save_disable();
}
save_exists

Valida la cabecera, la longitud y la suma de comprobación de una ranura para comprobar si contiene un guardado utilizable.

Sintaxis

c
u8 save_exists(u8 slot);

Parámetros

slot

Nú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

c
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.

save_exists: DMG
DMG
save_exists: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_save.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_save.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=8k
Implementación y código fuente

kitaqgb/lib/rpg.h:334

Notas de la declaración (original)
Validate a slot's header, payload bounds and checksum without copying the
payload out. A nonzero result means the stored record passes these checks.

kitaqgb/lib/save.c:182

c
u8 save_exists(u8 slot)
{
    u16 base;
    u16 stored_len;
    u8 stored_sum;

    if (slot >= SAVE_SLOT_COUNT) return 0;

    base = save_slot_base(slot);
    save_enable();

    if (save_read_abs(base + 0) != SAVE_MAGIC0) {
        save_disable();
        return 0;
    }
    if (save_read_abs(base + 1) != SAVE_MAGIC1) {
        save_disable();
        return 0;
    }
    if (save_read_abs(base + 2) != SAVE_VERSION) {
        save_disable();
        return 0;
    }

    stored_len = (u16)save_read_abs(base + 3);
    stored_len |= (u16)((u16)save_read_abs(base + 4) << 8);
    stored_sum = save_read_abs(base + 5);

    if (stored_len > (u16)(SAVE_SLOT_SIZE - SAVE_HEADER_SIZE)) {
        save_disable();
        return 0;
    }
    if (save_checksum_ram((u16)(base + SAVE_HEADER_SIZE), stored_len) != stored_sum) {
        save_disable();
        return 0;
    }

    save_disable();
    return 1;
}
save_init

Selecciona el banco RAM cero, lo activa brevemente y después lo desactiva.

Sintaxis

c
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

c
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.

save_init: DMG
DMG
save_init: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_save.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_save.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=8k
Implementación y código fuente

kitaqgb/lib/rpg.h:337

Notas de la declaración (original)
Initialize the expected RAM access state and leave cartridge RAM disabled.
Existing slot contents are preserved.

kitaqgb/lib/save.c:70

c
void save_init()
{
    save_enable();
    save_disable();
}
save_load

Carga los datos guardados con la misma validación que save_read.

Sintaxis

c
u8 save_load(u8 slot, void* data, u16 len);

Parámetros

slot

Número de ranura de 0 a 3.

data

Destino escribible de len bytes.

len

Longitud 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

c
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.

save_load: DMG
DMG
save_load: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_save.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_save.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=8k
Implementación y código fuente

kitaqgb/lib/rpg.h:339

Notas de la declaración (original)
Alias the checked save_read operation.

kitaqgb/lib/save.c:114

c
u8 save_load(u8 slot, void* data, u16 len)
{
    return save_read(slot, data, len);
}
save_read

Valida la cabecera, la longitud exacta y la suma de comprobación, y copia los datos solo si la validación es correcta.

Sintaxis

c
u8 save_read(u8 slot, void* data, u16 len);

Parámetros

slot

Número de ranura de 0 a 3.

data

Destino escribible de len bytes.

len

Longitud 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

c
readback[0]=99;result[5]=save_read(0,readback,2);result[6]=readback[0];result[7]=save_read(0,readback,3);result[8]=readback[0];result[9]=readback[2];

Este fragmento 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.

save_read: DMG
DMG
save_read: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_save.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_save.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=8k
Implementación y código fuente

kitaqgb/lib/rpg.h:331

Notas de la declaración (original)
Require matching magic/version, exact requested length and a valid checksum
before copying data into the destination. Validation failure leaves the
destination unchanged. An invalid slot returns before touching RAM control;
validation failures after enabling RAM disable it before returning zero.

kitaqgb/lib/save.c:125

c
u8 save_read(u8 slot, void* data, u16 len)
{
    u8* dst = (u8*)data;
    u16 base;
    u16 stored_len;
    u8 stored_sum;
    u16 i;

    if (slot >= SAVE_SLOT_COUNT) return 0;

    base = save_slot_base(slot);
    save_enable();

    if (save_read_abs(base + 0) != SAVE_MAGIC0) {
        save_disable();
        return 0;
    }
    if (save_read_abs(base + 1) != SAVE_MAGIC1) {
        save_disable();
        return 0;
    }
    if (save_read_abs(base + 2) != SAVE_VERSION) {
        save_disable();
        return 0;
    }

    stored_len = (u16)save_read_abs(base + 3);
    stored_len |= (u16)((u16)save_read_abs(base + 4) << 8);
    stored_sum = save_read_abs(base + 5);

    if (stored_len != len || stored_len > (u16)(SAVE_SLOT_SIZE - SAVE_HEADER_SIZE)) {
        save_disable();
        return 0;
    }
    if (save_checksum_ram((u16)(base + SAVE_HEADER_SIZE), stored_len) != stored_sum) {
        save_disable();
        return 0;
    }

    i = 0;
    while (i < stored_len) {
        dst[i] = save_read_abs((u16)(base + SAVE_HEADER_SIZE + i));
        i++;
    }

    save_disable();
    return 1;
}
save_write

Escribe los datos, la longitud y la suma de comprobación en una ranura.

Sintaxis

c
u8 save_write(u8 slot, const void* data, u16 len);

Parámetros

slot

Número de ranura de 0 a 3.

data

Fuente legible de len bytes.

len

Longitud 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

c
payload[0]=7;payload[1]=42;payload[2]=255;result[1]=save_write(0,payload,3);result[2]=save_write(4,payload,3);result[3]=save_write(0,payload,507);

Este fragmento 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.

save_write: DMG
DMG
save_write: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_save.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_save.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=8k
Implementación y código fuente

kitaqgb/lib/rpg.h:326

Notas de la declaración (original)
Validate slot and payload length, write payload bytes, then write the header
and checksum. Return one after completing the writes; interruption can leave
a partially replaced slot, so this is not transactional save storage.

kitaqgb/lib/save.c:81

c
u8 save_write(u8 slot, const void* data, u16 len)
{
    const u8* src = (const u8*)data;
    u16 base;
    u16 i;
    u8 sum = 0;

    if (slot >= SAVE_SLOT_COUNT) return 0;
    if (len > (u16)(SAVE_SLOT_SIZE - SAVE_HEADER_SIZE)) return 0;

    base = save_slot_base(slot);
    save_enable();

    i = 0;
    while (i < len) {
        u8 v = src[i];
        save_write_abs((u16)(base + SAVE_HEADER_SIZE + i), v);
        sum = (u8)(sum + v);
        i++;
    }

    save_write_abs(base + 0, SAVE_MAGIC0);
    save_write_abs(base + 1, SAVE_MAGIC1);
    save_write_abs(base + 2, SAVE_VERSION);
    save_write_abs(base + 3, (u8)(len & 0xFF));
    save_write_abs(base + 4, (u8)(len >> 8));
    save_write_abs(base + 5, sum);

    save_disable();
    return 1;
}
script_run

Selecciona un script y restablece su contador de espera, el resultado de elección y la posición de retorno guardada.

Sintaxis

c
void script_run(u8 bank, const u8* script);

Parámetros

bank

Banco ROM del flujo de instrucciones.

script

Inicio 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

c
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.

script_run: DMG
DMG
script_run: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_script.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_script.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementación y código fuente

kitaqgb/lib/rpg.h:250

Notas de la declaración (original)
Replace the active script and clear wait, choice and saved-return state.

kitaqgb/lib/script.c:105

c
void script_run(u8 bank, const u8* script)
{
    script_active = 1;
    script_bank = bank;
    script_pc = script;
    script_wait = 0;
    script_last_choice = 0xFF;
    script_return_active = 0;
}
script_step

Avanza por los comandos hasta que una salida, elección, espera o finalización devuelve el control.

Sintaxis

c
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

c
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.

script_step: DMG
DMG
script_step: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_script.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_script.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementación y código fuente

kitaqgb/lib/rpg.h:254

Notas de la declaración (original)
Execute commands until an output/choice yields (0), a wait yields (1), or
execution ends (2). Control/flag commands continue within the same call, so
a script loop without a yielding command can block the game loop indefinitely.

kitaqgb/lib/script.c:125

c
u8 script_step()
{
    if (script_active == 0) return 2;
    if (script_wait != 0) {
        script_wait--;
        return 1;
    }

    while (script_active != 0) {
        u8 op = script_read8();

        // An END returns to the one saved caller when present; otherwise it ends the script.
        if (op == SCRIPT_OP_END) {
            if (script_return_active != 0) {
                script_bank = script_return_bank;
                script_pc = script_return_pc;
                script_return_active = 0;
                continue;
            }
            script_active = 0;
            return 2;
        }

        if (op == SCRIPT_OP_TEXT) {
            u8 bank = script_read8();
            u16 ptr = script_read16();
            text_print_far(bank, (const u8*)ptr);
            return 0;
        }

        if (op == SCRIPT_OP_SET_FLAG) {
            u16 id = script_read16();
            flag_set(id);
            continue;
        }

        if (op == SCRIPT_OP_CLEAR_FLAG) {
            u16 id = script_read16();
            flag_clear(id);
            continue;
        }

        if (op == SCRIPT_OP_JUMP) {
            // Read all operands in the source bank before installing the destination.
            u8 bank = script_read8();
            u16 ptr = script_read16();
            script_bank = bank;
            script_pc = (const u8*)ptr;
            continue;
        }

        // Read all branch operands before switching bank/address so an untaken branch
        // still consumes the full instruction.
        if (op == SCRIPT_OP_IF_FLAG) {
            u16 id = script_read16();
            u8 bank = script_read8();
            u16 ptr = script_read16();
            if (flag_get(id) != 0) {
                script_bank = bank;
                script_pc = (const u8*)ptr;
            }
            continue;
        }

        if (op == SCRIPT_OP_CHOICE) {
            u8 count = script_read8();
            u16 table = script_read16();
            script_last_choice = script_choice(script_bank, (const u8*)table, count);
            return 0;
        }

        if (op == SCRIPT_OP_WAIT) {
            script_wait = script_read8();
            return 1;
        }

        // Save the continuation only when the single return slot is empty. Nested
        // calls replace the current script but do not push another return address.
        if (op == SCRIPT_OP_CALL_EVENT) {
            u8 bank = script_read8();
            u16 ptr = script_read16();
            if (script_return_active == 0) {
                script_return_active = 1;
                script_return_bank = script_bank;
                script_return_pc = script_pc;
            }
            script_bank = bank;
            script_pc = (const u8*)ptr;
            continue;
        }

        // Unknown opcodes terminate with the same return code as END; there is no distinct malformed-stream error.
        script_active = 0;
        return 2;
    }

    return 2;
}
script_wait_frames

Hace que las siguientes llamadas a script_step esperen el número indicado de veces.

Sintaxis

c
void script_wait_frames(u8 n);

Parámetros

n

Nú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

c
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.

script_wait_frames: DMG
DMG
script_wait_frames: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_script.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_script.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementación y código fuente

kitaqgb/lib/rpg.h:257

Notas de la declaración (original)
Set the number of subsequent script_step calls to spend waiting. Frame-based
timing requires the application to call script_step once per frame.

kitaqgb/lib/script.c:117

c
void script_wait_frames(u8 n)
{
    script_wait = n;
}
text_choice

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

c
u8 text_choice(const u8* const* choices, u8 count);

Parámetros

choices

Puntero 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.

count

Nú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

c
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.

text_choice: DMG
DMG
text_choice: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dialogue_choice.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dialogue_choice.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/rpg.h:231

Notas de la declaración (original)
Redraw choices and block for edge-triggered navigation: UP/DOWN wrap, A
accepts, and B returns 0xFF. Zero choices also returns 0xFF. Choice strings
use raw tile bytes, and the caller must fit them inside the available rows.

kitaqgb/lib/text.c:316

c
u8 text_choice(const u8* const* choices, u8 count)
{
    u8 cursor;
    u8 prev;

    if (count == 0) return 0xFF;

    cursor = 0;
    prev = 0;
    while (1) {
        u8 i;
        for (i = 0; i < count; i++) {
            u8 py = (u8)(text_y + 1 + i);
            __settile_xy((u8)(text_x + 1), py, (i == cursor) ? TEXT_TILE_CURSOR : TEXT_TILE_FILL);
            text_draw_string_at((u8)(text_x + 2), py, choices[i]);
        }

        __wait_vblank();
        {
            u16 kt = __readpadex(prev);
            u8 trigger;
            prev = (u8)kt;
            trigger = (u8)(kt >> 8);

            if ((trigger & PAD_KEY_UP) != 0) {
                if (cursor == 0) cursor = (u8)(count - 1);
                else cursor--;
            }
            if ((trigger & PAD_KEY_DOWN) != 0) {
                cursor++;
                if (cursor >= count) cursor = 0;
            }
            if ((trigger & PAD_KEY_A) != 0) return cursor;
            if ((trigger & PAD_KEY_B) != 0) return 0xFF;
        }
    }
}
text_clear_rect

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

c
void text_clear_rect(u8 x, u8 y, u8 w, u8 h);

Parámetros

x

Columna 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.

y

Fila 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.

w

Anchura 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.

h

Altura 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

c
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.

text_clear_rect: DMG
DMG
text_clear_rect: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\text_layout.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\text_layout.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/rpg.h:237

Notas de la declaración (original)
Fill the supplied tile rectangle without changing the active text window or cursor.

kitaqgb/lib/text.c:220

c
void text_clear_rect(u8 x, u8 y, u8 w, u8 h)
{
    __settile_rect(x, y, w, h, TEXT_TILE_FILL);
}
text_close

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

c
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

c
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.

text_close: DMG
DMG
text_close: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dialogue_flow.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dialogue_flow.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/rpg.h:220

Notas de la declaración (original)
Erase the open window with the fill tile and disable windowed character output.

kitaqgb/lib/text.c:200

c
void text_close()
{
    if (text_opened == 0) return;
    __settile_rect(text_x, text_y, text_w, text_h, TEXT_TILE_FILL);
    text_opened = 0;
}
text_open

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

c
void text_open(u8 x, u8 y, u8 w, u8 h);

Parámetros

x

Columna izquierda del área en celdas BG de 8×8. Mantén todo el ancho dentro de las columnas 0–31.

y

Fila superior del área en celdas BG de 8×8. Mantén todo el alto dentro de las filas 0–31.

w

Ancho total en celdas, incluidos los bordes izquierdo y derecho. Se necesitan al menos tres celdas para una columna interior de caracteres.

h

Alto 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

c
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.

text_open: DMG
DMG
text_open: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dialogue_flow.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dialogue_flow.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/rpg.h:218

Notas de la declaración (original)
Set the tile-space window, reset its cursor and redraw it immediately.
Opening does not reset the existing character speed or load font tiles.

kitaqgb/lib/text.c:187

c
void text_open(u8 x, u8 y, u8 w, u8 h)
{
    text_x = x;
    text_y = y;
    text_w = w;
    text_h = h;
    text_opened = 1;
    text_reset_cursor();
    text_draw_frame();
    text_clear_inside();
}
text_print

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

c
void text_print(const u8* str);

Parámetros

str

Puntero 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

c
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.

text_print: DMG
DMG
text_print: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dialogue_flow.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dialogue_flow.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/rpg.h:224

Notas de la declaración (original)
Decode an END-terminated stream of tile bytes and newline/wait/page controls.
WAIT consumes a following frame-count byte. The source must remain readable
through blocking waits; the routine does not validate stream length.

kitaqgb/lib/text.c:261

c
void text_print(const u8* str)
{
    while (*str != TEXT_CTRL_END) {
        u8 c = *str++;
        if (c == TEXT_CTRL_NEWLINE) {
            text_newline();
            continue;
        }
        if (c == TEXT_CTRL_WAIT) {
            u8 frames = *str++;
            text_delay_frames(frames);
            continue;
        }
        if (c == TEXT_CTRL_PAGE_WAIT) {
            text_wait_advance();
            text_clear_inside();
            text_reset_cursor();
            continue;
        }
        text_put_tile(c);
    }
}
text_print_far

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

c
void text_print_far(u8 bank, const u8* str);

Parámetros

bank

Nú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.

str

Direcció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

c
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.

text_print_far: DMG
DMG
text_print_far: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dialogue_flow.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dialogue_flow.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/rpg.h:227

Notas de la declaración (original)
Decode the same text controls while fetching each byte from the specified
ROM bank. The pointer advances within that bank; it does not roll into the next bank.

kitaqgb/lib/text.c:286

c
void text_print_far(u8 bank, const u8* str)
{
    const u8* p = str;
    while (1) {
        u8 c = __farpeek8(bank, p);
        p++;
        if (c == TEXT_CTRL_END) return;
        if (c == TEXT_CTRL_NEWLINE) {
            text_newline();
            continue;
        }
        if (c == TEXT_CTRL_WAIT) {
            u8 frames = __farpeek8(bank, p);
            p++;
            text_delay_frames(frames);
            continue;
        }
        if (c == TEXT_CTRL_PAGE_WAIT) {
            text_wait_advance();
            text_clear_inside();
            text_reset_cursor();
            continue;
        }
        text_put_tile(c);
    }
}
text_print_s16

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

c
void text_print_s16(u8 x, u8 y, s16 value);

Parámetros

x

Columna 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.

y

Fila 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.

value

Valor 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

c
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.

text_print_s16: DMG
DMG
text_print_s16: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\text_layout.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\text_layout.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/rpg.h:247

Notas de la declaración (original)
Print a minus tile for negative values, followed by the unsigned magnitude.
Positive values use the unsigned decimal path; no plus sign is emitted.

kitaqgb/lib/text.c:246

c
void text_print_s16(u8 x, u8 y, s16 value)
{
    u16 magnitude;
    if (value < 0) {
        __settile_xy(x, y, (u8)'-');
        magnitude = (u16)((s16)0 - value);
        text_print_u16_width((u8)(x + 1), y, magnitude, text_dec_digits_u16(magnitude));
        return;
    }
    text_print_u16(x, y, (u16)value);
}
text_print_u16

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

c
void text_print_u16(u8 x, u8 y, u16 value);

Parámetros

x

Columna 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.

y

Fila 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.

value

Valor 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

c
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.

text_print_u16: DMG
DMG
text_print_u16: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\text_layout.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\text_layout.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/rpg.h:244

Notas de la declaración (original)
Print an unsigned word in decimal using only the required number of cells.

kitaqgb/lib/text.c:239

c
void text_print_u16(u8 x, u8 y, u16 value)
{
    text_print_u16_width(x, y, value, text_dec_digits_u16(value));
}
text_print_u8

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

c
void text_print_u8(u8 x, u8 y, u8 value);

Parámetros

x

Columna 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.

y

Fila 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.

value

Valor 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

c
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.

text_print_u8: DMG
DMG
text_print_u8: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\text_layout.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\text_layout.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/rpg.h:242

Notas de la declaración (original)
Print an unsigned byte in decimal using only the required number of cells.

kitaqgb/lib/text.c:233

c
void text_print_u8(u8 x, u8 y, u8 value)
{
    text_print_u16_width(x, y, (u16)value, text_dec_digits_u16((u16)value));
}
text_print_xy

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

c
void text_print_xy(u8 x, u8 y, const u8* str);

Parámetros

x

Columna 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.

y

Fila 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.

str

Puntero 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

c
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.

text_print_xy: DMG
DMG
text_print_xy: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\text_layout.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\text_layout.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/rpg.h:240

Notas de la declaración (original)
Draw a zero-terminated tile string at absolute tile coordinates, without
window clipping, control codes or the windowed printing delay.

kitaqgb/lib/text.c:227

c
void text_print_xy(u8 x, u8 y, const u8* str)
{
    text_draw_string_at(x, y, str);
}
text_set_speed

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

c
void text_set_speed(u8 speed);

Parámetros

speed

Esperas 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

c
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.

text_set_speed: DMG
DMG
text_set_speed: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\dialogue_flow.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\dialogue_flow.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/rpg.h:233

Notas de la declaración (original)
Set VBlank waits per windowed character; zero prints without character delays.

kitaqgb/lib/text.c:208

c
void text_set_speed(u8 speed)
{
    text_speed = speed;
}
text_window

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

c
void text_window(u8 x, u8 y, u8 w, u8 h);

Parámetros

x

Columna 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.

y

Fila 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.

w

Anchura 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.

h

Altura 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

c
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.

text_window: DMG
DMG
text_window: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\text_layout.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\text_layout.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/rpg.h:235

Notas de la declaración (original)
Open and redraw a window using the same tile-space arguments as text_open.

kitaqgb/lib/text.c:214

c
void text_window(u8 x, u8 y, u8 w, u8 h)
{
    text_open(x, y, w, h);
}
unit_attack_range

Marca las celdas cuya distancia Manhattan está entre atk_min y atk_max, ambos incluidos.

Sintaxis

c
u8 unit_attack_range(unit_t* u, u8* out_mask);

Parámetros

u

unit_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_mask

width*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

c
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.

unit_attack_range: DMG
DMG
unit_attack_range: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_map_path.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_map_path.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementación y código fuente

kitaqgb/lib/rpg.h:352

Notas de la declaración (original)
Mark cells whose Manhattan distance falls within the inclusive attack range.
This geometric mask does not test obstacles, line of sight or other units.

kitaqgb/lib/slg_unit.c:38

c
u8 unit_attack_range(unit_t* u, u8* out_mask)
{
    u8 w = map_current_width();
    u8 h = map_current_height();
    u8 y;

    if (w == 0 || h == 0) return 0;

    __memset(out_mask, 0, (u16)((u16)w * (u16)h));
    y = 0;
    while (y < h) {
        u8 x = 0;
        while (x < w) {
            u8 dist = __manhattan(u->x, u->y, x, y);
            if (dist >= u->atk_min && dist <= u->atk_max) {
                out_mask[__map_index(x, y, w)] = 1;
            }
            x++;
        }
        y++;
    }
    return 1;
}
unit_can_act

Comprueba que una unidad tenga PV y aún no haya actuado.

Sintaxis

c
u8 unit_can_act(const unit_t* u);

Parámetros

u

unit_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

c
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.

unit_can_act: DMG
DMG
unit_can_act: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_map_path.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_map_path.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementación y código fuente

kitaqgb/lib/rpg.h:355

Notas de la declaración (original)
A unit can act only while HP is nonzero and its acted flag is clear.
The unit pointer must refer to a valid record.

kitaqgb/lib/slg_unit.c:5

c
u8 unit_can_act(const unit_t* u)
{
    if (u->hp == 0) return 0;
    if (u->acted != 0) return 0;
    return 1;
}
unit_move_range

Construye una máscara de las celdas alcanzables dentro del movimiento permitido de la unidad.

Sintaxis

c
u8 unit_move_range(unit_t* u, u8* out_mask);

Parámetros

u

unit_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_mask

width*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

c
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.

unit_move_range: DMG
DMG
unit_move_range: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch3_map_path.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch3_map_path.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k --ramsize=none
Implementación y código fuente

kitaqgb/lib/rpg.h:349

Notas de la declaración (original)
Build movement costs, then convert reachable cells to one and unreachable
0xFF cells to zero. The caller provides one output byte per current-map cell
and a valid unit origin; path-search workspace limits also apply.

kitaqgb/lib/slg_unit.c:15

c
u8 unit_move_range(unit_t* u, u8* out_mask)
{
    u8 w = map_current_width();
    u8 h = map_current_height();
    u16 total;
    u16 i;

    if (w == 0 || h == 0) return 0;

    // A valid origin is required: the fill leaves storage unchanged on invalid origins, but this loop still converts it.
    range_fill_move(u->x, u->y, u->move, out_mask);
    total = (u16)((u16)w * (u16)h);
    i = 0;
    while (i < total) {
        out_mask[i] = (u8)((out_mask[i] == 0xFF) ? 0 : 1);
        i++;
    }
    return 1;
}
weighted_choice

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

c
u8 weighted_choice(const u8* weights, u8 count);

Parámetros

weights

Puntero 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.

count

Nú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

c
weights[0]=1;weights[1]=3;weights[2]=6;
rng_seed(0x1234);
chosen=weighted_choice(weights,3); // 546 % 10 = 6 selects index 2.
empty=weighted_choice((const u8*)0,0); // No items: 0 is a fallback, not a chosen item.

Este fragmento 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.

weighted_choice: DMG
DMG
weighted_choice: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\rng_choices.c .\kitaqgb\lib\rng.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\rng_choices.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/rpg.h:203

Notas de la declaración (original)
Select an index from cumulative byte weights using a 16-bit random draw.
A zero total, including an empty list, returns zero; callers must distinguish
that case from a valid index. Modulo reduction can introduce a small bias.

kitaqgb/lib/rng.c:61

c
u8 weighted_choice(const u8* weights, u8 count)
{
    u8 i;
    u16 total;
    u16 pick;
    u16 acc;

    // At most 255 byte weights sum to 65025, so this accumulator fits u16.
    // A nonempty list requires count readable weight bytes.
    total = 0;
    i = 0;
    while (i < count) {
        total = (u16)(total + (u16)weights[i]);
        i++;
    }

    if (total == 0) return 0;

    pick = (u16)(rng16() % total);
    acc = 0;
    i = 0;
    while (i < count) {
        acc = (u16)(acc + (u16)weights[i]);
        if (pick < acc) return i;
        i++;
    }

    return (u8)(count - 1);
}

scene.h — 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

c
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

c
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.

scene_change: DMG
DMG
scene_change: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_services.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_services.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/scene.h:20

Notas de la declaración (original)
Ignore invalid IDs; otherwise exit the current scene and enter the requested one.
Selecting the current ID still performs exit/enter. Callbacks run synchronously.

kitaqgb/lib/scene.c:27

c
void scene_change(u8 scene_id)
{
    SceneFunc fn;

    if (scene_id >= scene_count) return;

    // Exit/enter handlers must not recursively change scenes or replace this shared table.
    if (scene_has_current != 0) {
        fn = scene_table[(__safe_index u8)scene_current].exit;
        if (fn != 0) fn();
    }

    scene_current = scene_id;
    scene_has_current = 1;
    scene_changed = 1;

    fn = scene_table[(__safe_index u8)scene_current].enter;
    if (fn != 0) fn();
}
scene_draw

Llama una vez a la función de retorno draw de la escena activa.

Sintaxis

c
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

c
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.

scene_draw: DMG
DMG
scene_draw: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_services.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_services.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/scene.h:25

Notas de la declaración (original)
Call the active scene's draw handler if one exists; no current scene is a no-op.

kitaqgb/lib/scene.c:60

c
void scene_draw()
{
    SceneFunc fn;

    if (scene_has_current == 0) return;
    fn = scene_table[(__safe_index u8)scene_current].draw;
    if (fn != 0) fn();
}
scene_get_current

Lee el ID de escena actual almacenado.

Sintaxis

c
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

c
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.

scene_get_current: DMG
DMG
scene_get_current: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_services.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_services.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/scene.h:27

Notas de la declaración (original)
Return the stored scene ID; zero is also returned before the first transition.

kitaqgb/lib/scene.c:70

c
u8 scene_get_current()
{
    return scene_current;
}
scene_init

Registra una tabla de escenas sin activar ninguna.

Sintaxis

c
void scene_init(const SceneDef* scenes, u8 count);

Parámetros

scenes

Array de entradas SceneDef con las funciones de retorno enter, update, draw y exit.

count

Nú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

c
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.

scene_init: DMG
DMG
scene_init: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_services.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_services.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/scene.h:15

Notas de la declaración (original)
Attach the caller-owned scene table and clear current-scene state without invoking callbacks.

kitaqgb/lib/scene.c:10

c
void scene_init(const SceneDef* scenes, u8 count)
{
    scene_table = scenes;
    scene_count = count;
    scene_current = 0;
    scene_changed = 0;
    scene_has_current = 0;
}
scene_set_table

Sustituye la tabla de escenas y deja todas las escenas inactivas.

Sintaxis

c
void scene_set_table(const SceneDef* scenes, u8 count);

Parámetros

scenes

Array de entradas SceneDef con las funciones de retorno enter, update, draw y exit.

count

Nú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

c
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.

scene_set_table: DMG
DMG
scene_set_table: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_services.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_services.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/scene.h:17

Notas de la declaración (original)
Replace the table by resetting scene state; this does not call the old scene's exit handler.

kitaqgb/lib/scene.c:20

c
void scene_set_table(const SceneDef* scenes, u8 count)
{
    scene_init(scenes, count);
}
scene_update

Llama una vez a la función de retorno update de la escena activa.

Sintaxis

c
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

c
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.

scene_update: DMG
DMG
scene_update: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_services.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_services.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/scene.h:23

Notas de la declaración (original)
Clear the change flag before calling the active scene's update handler, so a
transition made during that handler is visible afterward.

kitaqgb/lib/scene.c:49

c
void scene_update()
{
    SceneFunc fn;

    if (scene_has_current == 0) return;
    scene_changed = 0;
    fn = scene_table[(__safe_index u8)scene_current].update;
    if (fn != 0) fn();
}
scene_was_changed

Consulta si hay un cambio de escena registrado.

Sintaxis

c
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

c
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.

scene_was_changed: DMG
DMG
scene_was_changed: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_services.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_services.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/scene.h:29

Notas de la declaración (original)
Read the transition flag, which is cleared at the start of an active scene update.

kitaqgb/lib/scene.c:76

c
u8 scene_was_changed()
{
    return scene_changed;
}

scroll.h — 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

c
void Scroll_BgAdd(s8 dx, s8 dy);

Parámetros

dx

Desplazamiento horizontal con signo en píxeles, de −128 a 127.

dy

Desplazamiento 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

c
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.

Scroll_BgAdd: DMG
DMG
Scroll_BgAdd: CGB
CGB

Programa de ejemplo completo

Comando de compilación

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

Ejemplo de uso

c
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.

Scroll_BgAdd: DMG
DMG
Scroll_BgAdd: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/scroll.h:73

Notas de la declaración (original)
Apply signed deltas to the byte-sized background-scroll coordinates.

kitaqgb/lib/scroll.c:41

c
void Scroll_BgAdd(s8 dx, s8 dy) { __scroll_bg_add(dx, dy); }
Scroll_Flush

Aplica las coordenadas modificadas del fondo y la ventana al estado registrado y al hardware, y borra sus indicadores de actualización pendiente.

Sintaxis

c
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

c
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.

Scroll_Flush: DMG
DMG
Scroll_Flush: CGB
CGB

Programa de ejemplo completo

Comando de compilación

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

Ejemplo de uso

c
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.

Scroll_Flush: DMG
DMG
Scroll_Flush: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/scroll.h:70

Notas de la declaración (original)
Apply the buffered scroll/window state through the compiler runtime.

kitaqgb/lib/scroll.c:38

c
void Scroll_Flush() { __scroll_flush(); }
Scroll_GetBgX

Lee el valor actual registrado del desplazamiento horizontal del fondo.

Sintaxis

c
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

c
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.

Scroll_GetBgX: DMG
DMG
Scroll_GetBgX: CGB
CGB

Programa de ejemplo completo

Comando de compilación

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

Ejemplo de uso

c
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.

Scroll_GetBgX: DMG
DMG
Scroll_GetBgX: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/scroll.h:50

Notas de la declaración (original)
Read the tracked current background X; this is not a direct SCX register read.

kitaqgb/lib/scroll.c:18

c
u8 Scroll_GetBgX() { return __scroll_bg_x_get(); }
Scroll_GetBgY

Lee el valor actual registrado del desplazamiento vertical del fondo.

Sintaxis

c
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

c
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.

Scroll_GetBgY: DMG
DMG
Scroll_GetBgY: CGB
CGB

Programa de ejemplo completo

Comando de compilación

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

Ejemplo de uso

c
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.

Scroll_GetBgY: DMG
DMG
Scroll_GetBgY: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/scroll.h:52

Notas de la declaración (original)
Read the tracked current background Y; pending and raster-only values are excluded.

kitaqgb/lib/scroll.c:20

c
u8 Scroll_GetBgY() { return __scroll_bg_y_get(); }
Scroll_GetWindowX

Lee el valor WX actual registrado de la ventana.

Sintaxis

c
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

c
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.

Scroll_GetWindowX: DMG
DMG
Scroll_GetWindowX: CGB
CGB

Programa de ejemplo completo

Comando de compilación

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

Ejemplo de uso

c
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.

Scroll_GetWindowX: DMG
DMG
Scroll_GetWindowX: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/scroll.h:61

Notas de la declaración (original)
Read tracked current WX, including its seven-pixel offset; not a live hardware read.

kitaqgb/lib/scroll.c:29

c
u8 Scroll_GetWindowX() { return __scroll_win_x_get(); }
Scroll_GetWindowY

Lee el valor WY actual registrado de la ventana.

Sintaxis

c
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

c
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.

Scroll_GetWindowY: DMG
DMG
Scroll_GetWindowY: CGB
CGB

Programa de ejemplo completo

Comando de compilación

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

Ejemplo de uso

c
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.

Scroll_GetWindowY: DMG
DMG
Scroll_GetWindowY: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/scroll.h:63

Notas de la declaración (original)
Read tracked current WY; pending and raster-only values are excluded.

kitaqgb/lib/scroll.c:31

c
u8 Scroll_GetWindowY() { return __scroll_win_y_get(); }
Scroll_Init

Inicializa el desplazamiento del fondo en (0,0) y la posición de la ventana en WX=7, WY=0.

Sintaxis

c
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

c
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.

Scroll_Init: DMG
DMG
Scroll_Init: CGB
CGB

Programa de ejemplo completo

Comando de compilación

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

Ejemplo de uso

c
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.

Scroll_Init: DMG
DMG
Scroll_Init: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/scroll.h:42

Notas de la declaración (original)
Reset background scroll to zero and place the window at screen origin
using hardware WX=7 and WY=0.

kitaqgb/lib/scroll.c:5

c
void Scroll_Init()
{
    __scroll_bg_set(0, 0);
    __scroll_win_set(7, 0);
}
Scroll_SetBg

Establece de inmediato las dos coordenadas de desplazamiento del fondo.

Sintaxis

c
void Scroll_SetBg(u8 scx, u8 scy);

Parámetros

scx

Desplazamiento horizontal del fondo, de 0 a 255 píxeles; al aumentarlo, el fondo se mueve a la izquierda.

scy

Desplazamiento 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

c
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.

Scroll_SetBg: DMG
DMG
Scroll_SetBg: CGB
CGB

Programa de ejemplo completo

Comando de compilación

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

Ejemplo de uso

c
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.

Scroll_SetBg: DMG
DMG
Scroll_SetBg: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/scroll.h:44

Notas de la declaración (original)
Write both hardware background-scroll bytes immediately.

kitaqgb/lib/scroll.c:12

c
void Scroll_SetBg(u8 scx, u8 scy) { __scroll_bg_set(scx, scy); }
Scroll_SetBgBuffered

Deja pendientes las dos coordenadas de desplazamiento del fondo para aplicarlas más tarde.

Sintaxis

c
void Scroll_SetBgBuffered(u8 scx, u8 scy);

Parámetros

scx

Desplazamiento horizontal del fondo, de 0 a 255 píxeles; al aumentarlo, el fondo se mueve a la izquierda.

scy

Desplazamiento 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

c
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.

Scroll_SetBgBuffered: DMG
DMG
Scroll_SetBgBuffered: CGB
CGB

Programa de ejemplo completo

Comando de compilación

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

Ejemplo de uso

c
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.

Scroll_SetBgBuffered: DMG
DMG
Scroll_SetBgBuffered: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/scroll.h:66

Notas de la declaración (original)
Stage background-scroll values in the intrinsic buffer for a later flush.

kitaqgb/lib/scroll.c:34

c
void Scroll_SetBgBuffered(u8 scx, u8 scy) { __scroll_bg_set_buffered(scx, scy); }
Scroll_SetBgX

Establece de inmediato el desplazamiento horizontal del fondo.

Sintaxis

c
void Scroll_SetBgX(u8 scx);

Parámetros

scx

Desplazamiento 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

c
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.

Scroll_SetBgX: DMG
DMG
Scroll_SetBgX: CGB
CGB

Programa de ejemplo completo

Comando de compilación

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

Ejemplo de uso

c
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.

Scroll_SetBgX: DMG
DMG
Scroll_SetBgX: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/scroll.h:46

Notas de la declaración (original)
Write horizontal background scroll while leaving vertical scroll unchanged.

kitaqgb/lib/scroll.c:14

c
void Scroll_SetBgX(u8 scx) { __scroll_bg_x_set(scx); }
Scroll_SetBgY

Establece de inmediato el desplazamiento vertical del fondo.

Sintaxis

c
void Scroll_SetBgY(u8 scy);

Parámetros

scy

Desplazamiento 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

c
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.

Scroll_SetBgY: DMG
DMG
Scroll_SetBgY: CGB
CGB

Programa de ejemplo completo

Comando de compilación

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

Ejemplo de uso

c
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.

Scroll_SetBgY: DMG
DMG
Scroll_SetBgY: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/scroll.h:48

Notas de la declaración (original)
Write vertical background scroll while leaving horizontal scroll unchanged.

kitaqgb/lib/scroll.c:16

c
void Scroll_SetBgY(u8 scy) { __scroll_bg_y_set(scy); }
Scroll_SetWindow

Establece de inmediato WX y WY de la ventana.

Sintaxis

c
void Scroll_SetWindow(u8 wx, u8 wy);

Parámetros

wx

Byte WX sin ajustar, de 0 a 255: suma 7 a la X de pantalla deseada; el borde izquierdo usa 7.

wy

Parte 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

c
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.

Scroll_SetWindow: DMG
DMG
Scroll_SetWindow: CGB
CGB

Programa de ejemplo completo

Comando de compilación

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

Ejemplo de uso

c
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.

Scroll_SetWindow: DMG
DMG
Scroll_SetWindow: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/scroll.h:55

Notas de la declaración (original)
Write raw hardware WX/WY values; callers add seven to a screen-space window X.

kitaqgb/lib/scroll.c:23

c
void Scroll_SetWindow(u8 wx, u8 wy) { __scroll_win_set(wx, wy); }
Scroll_SetWindowBuffered

Deja pendientes las dos coordenadas de la ventana para aplicarlas más tarde.

Sintaxis

c
void Scroll_SetWindowBuffered(u8 wx, u8 wy);

Parámetros

wx

Byte WX sin ajustar, de 0 a 255: suma 7 a la X de pantalla deseada; el borde izquierdo usa 7.

wy

Parte 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

c
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.

Scroll_SetWindowBuffered: DMG
DMG
Scroll_SetWindowBuffered: CGB
CGB

Programa de ejemplo completo

Comando de compilación

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

Ejemplo de uso

c
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.

Scroll_SetWindowBuffered: DMG
DMG
Scroll_SetWindowBuffered: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/scroll.h:68

Notas de la declaración (original)
Stage raw window-coordinate values for a later flush.

kitaqgb/lib/scroll.c:36

c
void Scroll_SetWindowBuffered(u8 wx, u8 wy) { __scroll_win_set_buffered(wx, wy); }
Scroll_SetWindowX

Establece de inmediato solo la coordenada WX sin ajustar de la ventana.

Sintaxis

c
void Scroll_SetWindowX(u8 wx);

Parámetros

wx

Byte 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

c
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.

Scroll_SetWindowX: DMG
DMG
Scroll_SetWindowX: CGB
CGB

Programa de ejemplo completo

Comando de compilación

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

Ejemplo de uso

c
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.

Scroll_SetWindowX: DMG
DMG
Scroll_SetWindowX: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/scroll.h:57

Notas de la declaración (original)
Write raw hardware WX without converting a screen-space X coordinate.

kitaqgb/lib/scroll.c:25

c
void Scroll_SetWindowX(u8 wx) { __scroll_win_x_set(wx); }
Scroll_SetWindowY

Establece de inmediato solo la coordenada WY de la ventana.

Sintaxis

c
void Scroll_SetWindowY(u8 wy);

Parámetros

wy

Parte 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

c
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.

Scroll_SetWindowY: DMG
DMG
Scroll_SetWindowY: CGB
CGB

Programa de ejemplo completo

Comando de compilación

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

Ejemplo de uso

c
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.

Scroll_SetWindowY: DMG
DMG
Scroll_SetWindowY: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/scroll.h:59

Notas de la declaración (original)
Write the window Y coordinate through the intrinsic.

kitaqgb/lib/scroll.c:27

c
void Scroll_SetWindowY(u8 wy) { __scroll_win_y_set(wy); }
Scroll_SplitCommit

Guarda la visibilidad base de la ventana y prepara el primer evento de línea de la tabla de divisiones.

Sintaxis

c
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

c
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.

Scroll_SplitCommit: DMG
DMG
Scroll_SplitCommit: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_split_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_split_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/scroll.h:92

Notas de la declaración (original)
Publish the pending split configuration through the compiler runtime.

kitaqgb/lib/scroll.c:66

c
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

c
void Scroll_SplitPush(u8 ly, u8 scx, u8 scy);

Parámetros

ly

Nú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.

scx

Desplazamiento horizontal del fondo, de 0 a 255 píxeles; al aumentarlo, el fondo se mueve a la izquierda.

scy

Desplazamiento 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

c
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.

Scroll_SplitPush: DMG
DMG
Scroll_SplitPush: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_split_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_split_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/scroll.h:85

Notas de la declaración (original)
Append a background-scroll split directly. Use Raster_Push when caller-side
scanline ordering and capacity validation are desired.

kitaqgb/lib/scroll.c:53

c
void Scroll_SplitPush(u8 ly, u8 scx, u8 scy) { __scroll_split_push(ly, scx, scy); }
Scroll_SplitPushBgColor0

Añade un evento que cambia el color cero de la paleta cero del fondo de CGB.

Sintaxis

c
void Scroll_SplitPushBgColor0(u8 ly, u16 rgb15);

Parámetros

ly

Nú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.

rgb15

Color 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

c
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.

Scroll_SplitPushBgColor0: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_split_color.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_split_color.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/scroll.h:90

Notas de la declaración (original)
Reuse the two background-scroll fields to carry the low/high RGB15 bytes
for a split whose operation flag selects background color zero.

kitaqgb/lib/scroll.c:61

c
void Scroll_SplitPushBgColor0(u8 ly, u16 rgb15)
{
    __scroll_split_push_ex(ly, (u8)rgb15, (u8)(rgb15 >> 8), 0, 0, KQ_SCROLL_SPLIT_BG_COLOR0);
}
Scroll_SplitPushEx

Añade una división cuyos indicadores seleccionan operaciones de fondo, ventana, visibilidad o color cero del fondo.

Sintaxis

c
void Scroll_SplitPushEx(u8 ly, u8 scx, u8 scy, u8 wx, u8 wy, u8 flags);

Parámetros

ly

Nú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.

scx

Desplazamiento horizontal del fondo, de 0 a 255 píxeles; al aumentarlo, el fondo se mueve a la izquierda.

scy

Desplazamiento vertical del fondo, de 0 a 255 píxeles; al aumentarlo, el fondo se mueve hacia arriba.

wx

Byte WX sin ajustar, de 0 a 255: suma 7 a la X de pantalla deseada; el borde izquierdo usa 7.

wy

Parte superior de la ventana en píxeles Y de pantalla, de 0 a 255; las líneas visibles van de 0 a 143.

flags

Bits 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

c
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.

Scroll_SplitPushEx: DMG
DMG
Scroll_SplitPushEx: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_split_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_split_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/scroll.h:87

Notas de la declaración (original)
Append an extended split with raw background/window fields and operation flags.

kitaqgb/lib/scroll.c:55

c
void Scroll_SplitPushEx(u8 ly, u8 scx, u8 scy, u8 wx, u8 wy, u8 flags)
{
    __scroll_split_push_ex(ly, scx, scy, wx, wy, flags);
}
Scroll_SplitReset

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

c
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

c
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.

Scroll_SplitReset: DMG
DMG
Scroll_SplitReset: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_split_wrappers.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_split_wrappers.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/scroll.h:82

Notas de la declaración (original)
Clear the pending split table before building a new raster configuration.

kitaqgb/lib/scroll.c:50

c
void Scroll_SplitReset() { __scroll_split_reset(); }
Scroll_WindowAdd

Suma desplazamientos con signo a las coordenadas registradas de la ventana y los aplica de inmediato.

Sintaxis

c
void Scroll_WindowAdd(s8 dx, s8 dy);

Parámetros

dx

Desplazamiento horizontal con signo en píxeles, de −128 a 127.

dy

Desplazamiento 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

c
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.

Scroll_WindowAdd: DMG
DMG
Scroll_WindowAdd: CGB
CGB

Programa de ejemplo completo

Comando de compilación

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

Ejemplo de uso

c
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.

Scroll_WindowAdd: DMG
DMG
Scroll_WindowAdd: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/scroll.h:75

Notas de la declaración (original)
Apply signed deltas to the byte-sized hardware window coordinates.

kitaqgb/lib/scroll.c:43

c
void Scroll_WindowAdd(s8 dx, s8 dy) { __scroll_win_add(dx, dy); }
Scroll_WindowHide

Desactiva el bit de ventana de LCDC y el estado registrado de visibilidad de la ventana.

Sintaxis

c
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

c
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.

Scroll_WindowHide: DMG
DMG
Scroll_WindowHide: CGB
CGB

Programa de ejemplo completo

Comando de compilación

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

Ejemplo de uso

c
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.

Scroll_WindowHide: DMG
DMG
Scroll_WindowHide: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/scroll.h:79

Notas de la declaración (original)
Request that the window be hidden through the compiler intrinsic.

kitaqgb/lib/scroll.c:47

c
void Scroll_WindowHide() { __scroll_win_hide(); }
Scroll_WindowShow

Activa el bit de ventana de LCDC y el estado registrado de visibilidad de la ventana.

Sintaxis

c
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

c
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.

Scroll_WindowShow: DMG
DMG
Scroll_WindowShow: CGB
CGB

Programa de ejemplo completo

Comando de compilación

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

Ejemplo de uso

c
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.

Scroll_WindowShow: DMG
DMG
Scroll_WindowShow: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_camera_view.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_camera_view.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/scroll.h:77

Notas de la declaración (original)
Request window visibility through the compiler intrinsic.

kitaqgb/lib/scroll.c:45

c
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

c
void slg_board_clear(SLGBoard* board, u8 value);

Parámetros

board

SLGBoard sobre el que operar; la inicialización requiere almacenamiento no NULL.

value

Valor 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

c
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.

slg_board_clear: DMG
DMG
slg_board_clear: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_board.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_board.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/slg.h:33

Notas de la declaración (original)
Fill every cell with value; a null board is ignored. A valid board must own
enough accessible cell storage for its declared dimensions.

kitaqgb/lib/slg_board.c:36

c
void slg_board_clear(SLGBoard* board, u8 value)
{
    u16 total;
    u16 i;
    u8* p;
    if (board == 0) return;
    total = (u16)((u16)board->width * (u16)board->height);
    i = 0;
    p = board->cells;
    while (i < total) {
        *p = value;
        p++;
        i++;
    }
}
slg_board_get

Lee una celda; devuelve cero si el tablero es NULL o la coordenada está fuera de rango.

Sintaxis

c
u8 slg_board_get(const SLGBoard* board, u8 x, u8 y);

Parámetros

board

SLGBoard sobre el que operar; la inicialización requiere almacenamiento no NULL.

x

Columna de la celda desde la izquierda, empezando en cero; registrar una jugada no comprueba los límites del tablero.

y

Fila 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

c
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.

slg_board_get: DMG
DMG
slg_board_get: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_board.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_board.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/slg.h:36

Notas de la declaración (original)
Return zero for a null board or out-of-range coordinate; otherwise read the
cell. Zero therefore cannot distinguish an invalid lookup from an empty cell.

kitaqgb/lib/slg_board.c:54

c
u8 slg_board_get(const SLGBoard* board, u8 x, u8 y)
{
    u8* p;
    if (board == 0) return 0;
    if (x >= board->width || y >= board->height) return 0;
    p = slg_cell_ptr((SLGBoard*)board, x, y);
    return *p;
}
slg_board_init

Asocia las dimensiones de un tablero y un array de celdas, conservando su contenido.

Sintaxis

c
void slg_board_init(SLGBoard* board, u8 width, u8 height, u8* cells);

Parámetros

board

SLGBoard sobre el que operar; la inicialización requiere almacenamiento no NULL.

width

Ancho del tablero en celdas; también es el paso entre filas.

height

Número de filas del tablero.

cells

Array accesible para escritura, ordenado por filas, de al menos width*height bytes 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

c
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.

slg_board_init: DMG
DMG
slg_board_init: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_board.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_board.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/slg.h:30

Notas de la declaración (original)
Attach width * height bytes of caller-owned cell storage without clearing it.

kitaqgb/lib/slg_board.c:27

c
void slg_board_init(SLGBoard* board, u8 width, u8 height, u8* cells)
{
    board->width = width;
    board->height = height;
    board->cells = cells;
}
slg_board_set

Escribe en una celda válida del tablero; ignora un tablero NULL o una coordenada fuera de rango.

Sintaxis

c
void slg_board_set(SLGBoard* board, u8 x, u8 y, u8 value);

Parámetros

board

SLGBoard sobre el que operar; la inicialización requiere almacenamiento no NULL.

x

Columna de la celda desde la izquierda, empezando en cero; registrar una jugada no comprueba los límites del tablero.

y

Fila de la celda desde arriba, empezando en cero; registrar una jugada no comprueba los límites del tablero.

value

Valor 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

c
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.

slg_board_set: DMG
DMG
slg_board_set: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_board.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_board.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/slg.h:38

Notas de la declaración (original)
Write a cell only when the board and coordinate are valid.

kitaqgb/lib/slg_board.c:64

c
void slg_board_set(SLGBoard* board, u8 x, u8 y, u8 value)
{
    u8* p;
    if (board == 0) return;
    if (x >= board->width || y >= board->height) return;
    p = slg_cell_ptr(board, x, y);
    *p = value;
}
slg_move_list_clear

Restablece el número de jugadas sin borrar los registros guardados.

Sintaxis

c
void slg_move_list_clear(SLGMoveList* list);

Parámetros

list

Lista 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

c
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.

slg_move_list_clear: DMG
DMG
slg_move_list_clear: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_board.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_board.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/slg.h:42

Notas de la declaración (original)
Forget the moves without erasing their storage; a null list is ignored.

kitaqgb/lib/slg_board.c:83

c
void slg_move_list_clear(SLGMoveList* list)
{
    if (list == 0) return;
    list->count = 0;
}
slg_move_list_init

Asocia el almacenamiento de jugadas y su capacidad, y pone el contador a cero.

Sintaxis

c
void slg_move_list_init(SLGMoveList* list, SLGMove* items, u8 capacity);

Parámetros

list

Lista de jugadas sobre la que operar; la inicialización requiere un puntero no NULL.

items

Array propiedad del código que llama, con espacio para al menos capacity registros SLGMove.

capacity

Nú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

c
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.

slg_move_list_init: DMG
DMG
slg_move_list_init: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_board.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_board.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/slg.h:40

Notas de la declaración (original)
Attach caller-owned move storage and reset the list length.

kitaqgb/lib/slg_board.c:75

c
void slg_move_list_init(SLGMoveList* list, SLGMove* items, u8 capacity)
{
    list->items = items;
    list->capacity = capacity;
    list->count = 0;
}
slg_move_list_push

Añade unas coordenadas y un valor a la lista de jugadas sin modificar el tablero.

Sintaxis

c
u8 slg_move_list_push(SLGMoveList* list, u8 x, u8 y, u8 value);

Parámetros

list

Lista de jugadas sobre la que operar; la inicialización requiere un puntero no NULL.

x

Columna de la celda desde la izquierda, empezando en cero; registrar una jugada no comprueba los límites del tablero.

y

Fila de la celda desde arriba, empezando en cero; registrar una jugada no comprueba los límites del tablero.

value

Valor 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

c
result[6]=slg_move_list_push(&moves,1,1,7);result[7]=slg_move_list_push(&moves,2,1,8);result[8]=slg_move_list_push(&moves,3,1,9);result[9]=moves.count;

Este fragmento 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.

slg_move_list_push: DMG
DMG
slg_move_list_push: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_board.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_board.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/slg.h:45

Notas de la declaración (original)
Append coordinates and a value to the bounded move list. Return zero on a
null/full list without replacing any existing move.

kitaqgb/lib/slg_board.c:91

c
u8 slg_move_list_push(SLGMoveList* list, u8 x, u8 y, u8 value)
{
    SLGMove* move;
    if (list == 0) return 0;
    if (list->count >= list->capacity) return 0;
    move = &list->items[(__safe_index u8)list->count];
    move->x = x;
    move->y = y;
    move->value = value;
    list->count++;
    return 1;
}
slg_undo_init

Asocia el almacenamiento para deshacer y su capacidad, empezando con una pila vacía.

Sintaxis

c
void slg_undo_init(SLGUndoStack* stack, SLGMove* items, u8 capacity);

Parámetros

stack

Pila para deshacer sobre la que operar; la inicialización requiere un puntero no NULL.

items

Array propiedad del código que llama, con espacio para al menos capacity registros SLGMove.

capacity

Nú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

c
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.

slg_undo_init: DMG
DMG
slg_undo_init: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_board.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_board.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/slg.h:47

Notas de la declaración (original)
Attach caller-owned undo records and initialize an empty stack.

kitaqgb/lib/slg_board.c:106

c
void slg_undo_init(SLGUndoStack* stack, SLGMove* items, u8 capacity)
{
    stack->items = items;
    stack->capacity = capacity;
    stack->count = 0;
}
slg_undo_pop

Extrae el registro más reciente para deshacer; el código que llama lo aplica al tablero.

Sintaxis

c
u8 slg_undo_pop(SLGUndoStack* stack, SLGMove* out_move);

Parámetros

stack

Pila para deshacer sobre la que operar; la inicialización requiere un puntero no NULL.

out_move

Destino 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

c
result[15]=slg_undo_pop(&undo,&old);result[16]=old.value;result[17]=slg_board_get(&board,1,1);slg_undo_pop(&undo,&old);slg_board_set(&board,old.x,old.y,old.value);result[18]=slg_board_get(&board,1,1);result[19]=slg_undo_pop(&undo,&old);

Este fragmento 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.

slg_undo_pop: DMG
DMG
slg_undo_pop: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_board.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_board.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/slg.h:53

Notas de la declaración (original)
Remove the newest undo record and optionally copy it out. A null output
still discards the record; a null or empty stack returns zero.

kitaqgb/lib/slg_board.c:128

c
u8 slg_undo_pop(SLGUndoStack* stack, SLGMove* out_move)
{
    if (stack == 0) return 0;
    if (stack->count == 0) return 0;
    stack->count--;
    if (out_move != 0) {
        out_move->x = stack->items[stack->count].x;
        out_move->y = stack->items[stack->count].y;
        out_move->value = stack->items[stack->count].value;
    }
    return 1;
}
slg_undo_push

Apila el valor anterior de una celda en la pila para deshacer sin modificar el tablero.

Sintaxis

c
u8 slg_undo_push(SLGUndoStack* stack, u8 x, u8 y, u8 old_value);

Parámetros

stack

Pila para deshacer sobre la que operar; la inicialización requiere un puntero no NULL.

x

Columna de la celda desde la izquierda, empezando en cero; registrar una jugada no comprueba los límites del tablero.

y

Fila de la celda desde arriba, empezando en cero; registrar una jugada no comprueba los límites del tablero.

old_value

Valor 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

c
result[13]=slg_undo_push(&undo,1,1,slg_board_get(&board,1,1));slg_board_set(&board,1,1,8);slg_undo_push(&undo,1,1,8);result[14]=slg_undo_push(&undo,0,0,9);

Este fragmento 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.

slg_undo_push: DMG
DMG
slg_undo_push: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch2_board.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch2_board.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/slg.h:50

Notas de la declaración (original)
Record a cell's previous value for later undo. Return zero if the stack is
null or full; this function does not change the board itself.

kitaqgb/lib/slg_board.c:115

c
u8 slg_undo_push(SLGUndoStack* stack, u8 x, u8 y, u8 old_value)
{
    if (stack == 0) return 0;
    if (stack->count >= stack->capacity) return 0;
    stack->items[stack->count].x = x;
    stack->items[stack->count].y = y;
    stack->items[stack->count].value = old_value;
    stack->count++;
    return 1;
}

sprite.h — 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

c
u8 anim_update(SpriteAnim* anim);

Parámetros

anim

Estado 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

c
sprite_example_animation.first_tile=128;sprite_example_animation.frame_count=2;
sprite_example_animation.frame=0;sprite_example_animation.ticks=0;
sprite_example_animation.ticks_per_frame=2;
sprite_example_expect(anim_update(&sprite_example_animation)==128);
tile=anim_update(&sprite_example_animation);
sprite_example_expect(tile==129);sprite_set_tile(5,tile);

Este fragmento 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.

anim_update: DMG
DMG
anim_update: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/sprite.h:86

Notas de la declaración (original)
Advance animation ticks/frame with wrapping frame selection and return the
resulting tile. Zero ticks-per-frame freezes animation; null state returns zero.

kitaqgb/lib/sprite.c:211

c
u8 anim_update(SpriteAnim* anim)
{
    if (anim == 0) return 0;
    if (anim->frame_count == 0) return anim->first_tile;
    if (anim->ticks_per_frame == 0) return (u8)(anim->first_tile + anim->frame);

    anim->ticks++;
    if (anim->ticks >= anim->ticks_per_frame) {
        anim->ticks = 0;
        anim->frame++;
        if (anim->frame >= anim->frame_count) anim->frame = 0;
    }
    return (u8)(anim->first_tile + anim->frame);
}
metasprite_draw

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

c
u8 metasprite_draw(u8 first_id, u8 x, u8 y, const MetaSpritePart* parts, u8 count);

Parámetros

first_id

ID 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.

x

Posición horizontal en píxeles, expresada como byte sin signo; no es una coordenada de patrón.

y

Coordenada Y de pantalla en píxeles. La función de GB suma 16 antes de guardarla en OAM.

parts

Array legible de al menos count registros MetaSpritePart. Cada registro de cuatro bytes contiene dx/dy con signo, patrón y atributos; no lleva terminador.

count

Nú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

c
sprite_example_expect(metasprite_draw(10,88,SPRITE_EXAMPLE_Y(64),sprite_example_pair,2)==2);
sprite_example_expect(sprite_count_used()==9); // Sparse IDs count actual active slots.

Este fragmento 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.

metasprite_draw: DMG
DMG
metasprite_draw: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/sprite.h:83

Notas de la declaración (original)
Place consecutive parts, counting each newly activated slot once. Existing
active slots are overwritten without increasing the allocation count. Return
the number written; an invalid first slot or zero count writes nothing.

kitaqgb/lib/sprite.c:191

c
u8 metasprite_draw(u8 first_id, u8 x, u8 y, const MetaSpritePart* parts, u8 count)
{
    u8 i = 0;
    while (i < count) {
        u8 id = (u8)(first_id + i);
        if (id >= SPRITE_MAX) return i;
        if (kq_sprite_active[id] == 0) {
            kq_sprite_active[id] = 1;
            kq_sprite_used = (u8)(kq_sprite_used + 1);
        }
        sprite_set_pos(id, (u8)(x + parts[i].dx), (u8)(y + parts[i].dy));
        sprite_set_tile(id, parts[i].tile);
        sprite_set_flags(id, parts[i].flags);
        i++;
    }
    return count;
}
sprite_alloc

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

c
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

c
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.

sprite_alloc: DMG
DMG
sprite_alloc: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/sprite.h:53

Notas de la declaración (original)
Claim the first free slot, hide it, and return its ID; return 0xFF when full.
Previously stored tile/flag bytes are retained until the caller replaces them.

kitaqgb/lib/sprite.c:60

c
u8 sprite_alloc()
{
    u8 i = 0;
    while (i < SPRITE_MAX) {
        if (kq_sprite_active[i] == 0) {
            kq_sprite_active[i] = 1;
            kq_sprite_used++;
            sprite_hide(i);
            return i;
        }
        i++;
    }
    return 0xFF;
}
sprite_count_used

Devuelve el número de entradas reservadas, incluidas las ocultas y las activadas por metasprite_draw. Cuenta reservas, no sprites visibles.

Sintaxis

c
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

c
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.

sprite_count_used: DMG
DMG
sprite_count_used: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/sprite.h:73

Notas de la declaración (original)
Return the number of active slots, including slots activated by metasprite_draw.
Hidden allocated slots remain active until sprite_free releases them.

kitaqgb/lib/sprite.c:148

c
u8 sprite_count_used()
{
    return kq_sprite_used;
}
sprite_flush_oam

Espera VBlank y transfiere la copia de OAM mediante sprite_flush_oam_now.

Sintaxis

c
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

c
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.

sprite_flush_oam: DMG
DMG
sprite_flush_oam: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/sprite.h:70

Notas de la declaración (original)
Wait for VBlank, then transfer shadow OAM using the immediate DMA routine.

kitaqgb/lib/sprite.c:139

c
void sprite_flush_oam()
{
    __wait_vblank();
    sprite_flush_oam_now();
}
sprite_flush_oam_now

Transfiere inmediatamente la copia de OAM al hardware. No espera un intervalo de vídeo seguro; quien llama decide cuándo ejecutarla.

Sintaxis

c
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

c
// 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.

sprite_flush_oam_now: DMG
DMG
sprite_flush_oam_now: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/sprite.h:68

Notas de la declaración (original)
Install the HRAM stub lazily and execute OAM DMA with interrupts disabled.
This routine does not wait for VBlank and always enables interrupts afterward;
it does not restore the caller's previous interrupt-enable state.

kitaqgb/lib/sprite.c:122

c
void sprite_flush_oam_now()
{
    SpriteDmaRoutine dma;
    if (kq_sprite_dma_ready == 0) {
        sprite_install_dma_stub();
    }
    dma = (SpriteDmaRoutine)kq_sprite_dma_stub;
    __asm {
        DI
    }
    dma();
    __asm {
        EI
    }
}
sprite_free

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

c
void sprite_free(u8 id);

Parámetros

id

ID 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

c
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.

sprite_free: DMG
DMG
sprite_free: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/sprite.h:55

Notas de la declaración (original)
Release an allocated valid slot and hide it. Repeated frees do not decrement the count.

kitaqgb/lib/sprite.c:78

c
void sprite_free(u8 id)
{
    if (sprite_valid(id) == 0) return;
    if (kq_sprite_active[id] == 0) return;
    kq_sprite_active[id] = 0;
    if (kq_sprite_used != 0) kq_sprite_used--;
    sprite_hide(id);
}
sprite_hide

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

c
void sprite_hide(u8 id);

Parámetros

id

ID 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

c
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.

sprite_hide: DMG
DMG
sprite_hide: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/sprite.h:64

Notas de la declaración (original)
Move a valid shadow slot off screen without freeing it.

kitaqgb/lib/sprite.c:112

c
void sprite_hide(u8 id)
{
    if (sprite_valid(id) == 0) return;
    kq_sprite_oam[id].y = 0;
    kq_sprite_oam[id].x = 0;
}
sprite_init

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

c
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

c
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.

sprite_init: DMG
DMG
sprite_init: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/sprite.h:50

Notas de la declaración (original)
Clear allocation and shadow OAM state and reset the DMA-stub installation flag.
The default height is eight pixels; the hardware display mode is configured elsewhere.

kitaqgb/lib/sprite.c:22

c
void sprite_init()
{
    u8 i = 0;
    kq_sprite_used = 0;
    kq_sprite_height = 8;
    kq_sprite_dma_ready = 0;
    while (i < SPRITE_MAX) {
        kq_sprite_active[i] = 0;
        kq_sprite_oam[i].y = 0;
        kq_sprite_oam[i].x = 0;
        kq_sprite_oam[i].tile = 0;
        kq_sprite_oam[i].flags = 0;
        i++;
    }
}
sprite_max_scanline_count

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

c
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

c
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.

sprite_max_scanline_count: DMG
DMG
sprite_max_scanline_count: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/sprite.h:79

Notas de la declaración (original)
Estimate the largest overlap of active, non-hidden shadow sprites across
visible scanlines using the configured sprite height. This is a software
overlap count, not a rendered-pixel or hardware-priority simulation.

kitaqgb/lib/sprite.c:158

c
u8 sprite_max_scanline_count()
{
    u8 line = 0;
    u8 best = 0;
    while (line < 144) {
        u8 i = 0;
        u8 count = 0;
        u8 ly_oam = (u8)(line + 16);
        while (i < SPRITE_MAX) {
            u8 sy = kq_sprite_oam[i].y;
            if (kq_sprite_active[i] != 0 && sy != 0) {
                if (ly_oam >= sy && ly_oam < (u8)(sy + kq_sprite_height)) {
                    count++;
                }
            }
            i++;
        }
        if (count > best) best = count;
        line++;
    }
    return best;
}
sprite_set_flags

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

c
void sprite_set_flags(u8 id, u8 flags);

Parámetros

id

ID 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.

flags

Byte 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

c
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.

sprite_set_flags: DMG
DMG
sprite_set_flags: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/sprite.h:62

Notas de la declaración (original)
Replace a valid shadow slot's complete hardware attribute byte.

kitaqgb/lib/sprite.c:105

c
void sprite_set_flags(u8 id, u8 flags)
{
    if (sprite_valid(id) == 0) return;
    kq_sprite_oam[id].flags = flags;
}
sprite_set_pos

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

c
void sprite_set_pos(u8 id, u8 x, u8 y);

Parámetros

id

ID 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.

x

Posición horizontal en píxeles, expresada como byte sin signo; no es una coordenada de patrón.

y

Coordenada 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

c
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.

sprite_set_pos: DMG
DMG
sprite_set_pos: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/sprite.h:58

Notas de la declaración (original)
Convert screen coordinates to OAM coordinates by adding X=8 and Y=16.
The byte additions wrap; this updates shadow storage even for an unallocated slot.

kitaqgb/lib/sprite.c:89

c
void sprite_set_pos(u8 id, u8 x, u8 y)
{
    if (sprite_valid(id) == 0) return;
    kq_sprite_oam[id].x = (u8)(x + 8);
    kq_sprite_oam[id].y = (u8)(y + 16);
}
sprite_set_tile

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

c
void sprite_set_tile(u8 id, u8 tile);

Parámetros

id

ID 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.

tile

Nú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

c
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.

sprite_set_tile: DMG
DMG
sprite_set_tile: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/sprite.h:60

Notas de la declaración (original)
Set a valid shadow slot's tile byte; allocation and hardware transfer are separate.

kitaqgb/lib/sprite.c:98

c
void sprite_set_tile(u8 id, u8 tile)
{
    if (sprite_valid(id) == 0) return;
    kq_sprite_oam[id].tile = tile;
}
sprite_warn_scanline_overflow

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

c
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

c
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.

sprite_warn_scanline_overflow: DMG
DMG
sprite_warn_scanline_overflow: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/sprite.h:75

Notas de la declaración (original)
Report whether the software overlap estimate exceeds ten sprites on a scanline.

kitaqgb/lib/sprite.c:182

c
u8 sprite_warn_scanline_overflow()
{
    return (u8)(sprite_max_scanline_count() > 10);
}

sprite_order.h — 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

c
void sprite_order_begin(SpriteOrder* order);

Parámetros

order

Dirección de un SpriteOrder propiedad 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

c
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.

sprite_order_begin: DMG / fase 04 — 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.
DMG / fase 04 — 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.
sprite_order_begin: CGB / fase 04 — 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.
CGB / fase 04 — 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.
sprite_order_begin: CGB / fase 08 — 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.
CGB / fase 08 — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_order_demo.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_order_demo.gb --cgb=cgb --profile=dev --rst-disable --stack-bank=fixed --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/sprite_order.h:42

Notas de la declaración (original)
Discard this frame's submissions while preserving storage, height and phase.
A null state is ignored. Call once before submitting the next frame's sprites.

kitaqgb/lib/sprite_order.c:24

c
void sprite_order_begin(SpriteOrder* order)
{
    if (order != 0) order->count = 0;
}
sprite_order_build

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

c
u8 sprite_order_build(SpriteOrder* order, SpriteOrderOamEntry* output, u8 limit);

Parámetros

order

Dirección de un SpriteOrder propiedad del código que llama. Inicialízalo antes de usarlo y actualízalo desde el código principal.

output

Array escribible de 40 SpriteOrderOamEntry. Escribe los 160 bytes aunque limit sea cero o menor que 40.

limit

Má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

c
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.

sprite_order_build: DMG / fase 04 — 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.
DMG / fase 04 — 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.
sprite_order_build: CGB / fase 04 — 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.
CGB / fase 04 — 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.
sprite_order_build: CGB / fase 08 — 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.
CGB / fase 08 — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_order_demo.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_order_demo.gb --cgb=cgb --profile=dev --rst-disable --stack-bank=fixed --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/sprite_order.h:62

Notas de la declaración (original)
Write a complete 160-byte shadow OAM: ascending priority, then cyclic order
within each priority. Clamp limit to 40, return the number emitted and zero
all unused entries (including Y) so they cannot consume scanline slots.
Advance phase once for a nonempty valid queue, even when limit is zero.
Empty queues reset phase to zero. Null/disabled/corrupt state or null output
returns 0 without modifying output or phase.
Output must provide 40 entries and must not overlap item/state storage.
This only writes RAM. Build in foreground, then transfer during VBlank.
DMG overlap priority also depends on X: this cannot override that hardware
rule. OAM order chooses the first ten sprites per scanline on both DMG/CGB.
It neither updates sprite_alloc's bookkeeping nor performs OAM DMA.

kitaqgb/lib/sprite_order.c:57

c
u8 sprite_order_build(SpriteOrder* order, SpriteOrderOamEntry* output, u8 limit)
{
    u8 i;
    u8 count;
    u8 phase;
    u8 priority;
    u8 visited;
    u8 written;
    SpriteOrderItem* item;
    if (order == 0 || output == 0) return 0;
    if (order->items == 0 || order->capacity == 0) return 0;
    if (order->count > order->capacity) return 0;
    if (order->height != 8 && order->height != 16) return 0;
    // Clear all hardware slots regardless of the requested emission limit.
    for (i = 0; i < SPRITE_ORDER_OAM_COUNT; i++) {
        output[i].y = 0;
        output[i].x = 0;
        output[i].tile = 0;
        output[i].flags = 0;
    }
    count = order->count;
    if (count == 0) {
        order->phase = 0;
        return 0;
    }
    if (limit > SPRITE_ORDER_OAM_COUNT) limit = SPRITE_ORDER_OAM_COUNT;
    phase = order->phase;
    while (phase >= count) phase = (u8)(phase - count);
    written = 0;
    for (priority = 0; priority < SPRITE_ORDER_LEVELS && written < limit; priority++) {
        i = phase;
        visited = 0;
        while (visited < count && written < limit) {
            item = &order->items[i];
            if (item->priority == priority) {
                output[written].y = item->oam.y;
                output[written].x = item->oam.x;
                output[written].tile = item->oam.tile;
                output[written].flags = item->oam.flags;
                written++;
            }
            visited++;
            i++;
            if (i >= count) i = 0;
        }
    }
    phase++;
    if (phase >= count) phase = 0;
    order->phase = phase;
    return written;
}
sprite_order_init

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

c
u8 sprite_order_init(SpriteOrder* order, SpriteOrderItem* items, u8 capacity, u8 height);

Parámetros

order

Dirección de un SpriteOrder propiedad del código que llama. Inicialízalo antes de usarlo y actualízalo desde el código principal.

items

Array SpriteOrderItem escribible, cinco bytes por elemento. Reserva capacity elementos y mantén la memoria válida durante su uso.

capacity

Capacidad del array, de 1 a 255 elementos; no bytes ni ranuras de hardware.

height

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.

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

c
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.

sprite_order_init: DMG / fase 04 — 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.
DMG / fase 04 — 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.
sprite_order_init: CGB / fase 04 — 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.
CGB / fase 04 — 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.
sprite_order_init: CGB / fase 08 — 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.
CGB / fase 08 — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_order_demo.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_order_demo.gb --cgb=cgb --profile=dev --rst-disable --stack-bank=fixed --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/sprite_order.h:38

Notas de la declaración (original)
Bind writable item storage and select the hardware sprite height (8 or 16).
Return 1 on success. Invalid storage, zero capacity or another height returns
0 and leaves a non-null state disabled. A null state returns 0 without writes.

kitaqgb/lib/sprite_order.c:6

c
u8 sprite_order_init(SpriteOrder* order, SpriteOrderItem* items, u8 capacity, u8 height)
{
    if (order == 0) return 0;
    order->items = 0;
    order->capacity = 0;
    order->count = 0;
    order->height = 8;
    order->phase = 0;
    if (items == 0 || capacity == 0) return 0;
    if (height != 8 && height != 16) return 0;
    order->items = items;
    order->capacity = capacity;
    order->height = height;
    return 1;
}
sprite_order_push

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

c
u8 sprite_order_push(SpriteOrder* order, s16 x, s16 y, u8 tile, u8 flags, u8 priority);

Parámetros

order

Dirección de un SpriteOrder propiedad del código que llama. Inicialízalo antes de usarlo y actualízalo desde el código principal.

x

X 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.

y

Y 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.

tile

Número de tile de 0 a 255, guardado sin cambios. Consulta las notas de altura para 8×16.

flags

Byte de atributos de hardware sin cambios: volteos, prioridad detrás del fondo, paleta DMG/CGB y banco VRAM CGB conservan sus significados habituales.

priority

Prioridad 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

c
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.

sprite_order_push: DMG / fase 04 — 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.
DMG / fase 04 — 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.
sprite_order_push: CGB / fase 04 — 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.
CGB / fase 04 — 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.
sprite_order_push: CGB / fase 08 — 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.
CGB / fase 08 — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\sprite_order_demo.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\sprite_order_demo.gb --cgb=cgb --profile=dev --rst-disable --stack-bank=fixed --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/sprite_order.h:49

Notas de la declaración (original)
Submit one sprite at signed, top-left SCREEN pixel coordinates. Preserve the
tile and attribute bytes; use priority 0 (first) through 3 (last). Fully
off-screen sprites, invalid priorities, disabled state and full storage return
0 without consuming a slot. Partly visible sprites are accepted. Return 1 on
acceptance. Hardware 8x16 mode still ignores the tile index's low bit.

kitaqgb/lib/sprite_order.c:31

c
u8 sprite_order_push(SpriteOrder* order, s16 x, s16 y, u8 tile, u8 flags, u8 priority)
{
    SpriteOrderItem* item;
    if (order == 0) return 0;
    if (order->items == 0 || order->capacity == 0) return 0;
    if (order->height != 8 && order->height != 16) return 0;
    if (order->count >= order->capacity || priority >= SPRITE_ORDER_LEVELS) return 0;
    if (x <= -8 || x >= 160 || y >= 144) return 0;
    if (order->height == 16) {
        if (y <= -16) return 0;
    } else {
        if (y <= -8) return 0;
    }
    item = &order->items[order->count];
    item->oam.y = (u8)(y + 16);
    item->oam.x = (u8)(x + 8);
    item->oam.tile = tile;
    item->oam.flags = flags;
    item->priority = priority;
    order->count++;
    return 1;
}

system.h — 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

c
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.

system_disable_interrupts

Ejemplo de uso

c
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.

gb_disable_interrupts: DMG
DMG
gb_disable_interrupts: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\system_aliases.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\system_aliases.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/system.h:32

c
#define gb_disable_interrupts system_disable_interrupts

kitaqgb/lib/system.c:52

c
void system_disable_interrupts()
{
    __asm {
        DI
        RET
    }
}
gb_enable_interrupts

gb_enable_interrupts es un alias de system_enable_interrupts. Habilita las interrupciones de CPU en GB.

Activa las interrupciones enmascarables de la CPU.

Sintaxis

c
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.

system_enable_interrupts

Ejemplo de uso

c
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.

gb_enable_interrupts: DMG
DMG
gb_enable_interrupts: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\system_aliases.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\system_aliases.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/system.h:31

c
#define gb_enable_interrupts system_enable_interrupts

kitaqgb/lib/system.c:43

c
void system_enable_interrupts()
{
    __asm {
        EI
        RET
    }
}
gb_frame_count

gb_frame_count 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

c
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.

system_get_frame

Ejemplo de uso

c
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.

gb_frame_count: DMG
DMG
gb_frame_count: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\system_aliases.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\system_aliases.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/system.h:30

c
#define gb_frame_count system_get_frame

kitaqgb/lib/system.c:31

c
u16 system_get_frame()
{
    return kq_system_frame;
}
gb_init

gb_init 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

c
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.

system_init

Ejemplo de uso

c
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.

gb_init: DMG
DMG
gb_init: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\system_aliases.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\system_aliases.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/system.h:27

c
#define gb_init system_init

kitaqgb/lib/system.c:7

c
void system_init()
{
    kq_system_frame = 0;
    system_vblank_callback = 0;
}
gb_set_vblank_callback

gb_set_vblank_callback 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

c
void gb_set_vblank_callback(SystemCallback callback);

Parámetros

callback

Funció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.

system_set_vblank_callback

Ejemplo de uso

c
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.

gb_set_vblank_callback: DMG
DMG
gb_set_vblank_callback: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\system_aliases.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\system_aliases.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/system.h:29

c
#define gb_set_vblank_callback system_set_vblank_callback

kitaqgb/lib/system.c:25

c
void system_set_vblank_callback(SystemCallback callback)
{
    system_vblank_callback = callback;
}
gb_wait_vblank

gb_wait_vblank 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

c
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.

system_wait_vblank

Ejemplo de uso

c
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.

gb_wait_vblank: DMG
DMG
gb_wait_vblank: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\system_aliases.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\system_aliases.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/system.h:28

c
#define gb_wait_vblank system_wait_vblank

kitaqgb/lib/system.c:15

c
void system_wait_vblank()
{
    __wait_vblank();
    kq_system_frame++;
    if (system_vblank_callback != 0) {
        system_vblank_callback();
    }
}
system_disable_interrupts

Desactiva las interrupciones enmascarables de la CPU.

Sintaxis

c
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

c
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.

system_disable_interrupts: DMG
DMG
system_disable_interrupts: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_services.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_services.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/system.h:25

Notas de la declaración (original)
Disable CPU interrupts and return; callers must explicitly re-enable them later.

kitaqgb/lib/system.c:52

c
void system_disable_interrupts()
{
    __asm {
        DI
        RET
    }
}
system_enable_interrupts

Activa las interrupciones enmascarables de la CPU.

Sintaxis

c
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

c
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.

system_enable_interrupts: DMG
DMG
system_enable_interrupts: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_services.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_services.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/system.h:23

Notas de la declaración (original)
Enable CPU interrupts and return using the inline-assembly function body.

kitaqgb/lib/system.c:43

c
void system_enable_interrupts()
{
    __asm {
        EI
        RET
    }
}
system_get_frame

Lee el contador de 16 bits de la función de espera de fotograma.

Sintaxis

c
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

c
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.

system_get_frame: DMG
DMG
system_get_frame: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_services.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_services.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/system.h:19

Notas de la declaración (original)
Read the software count of completed system_wait_vblank calls.

kitaqgb/lib/system.c:31

c
u16 system_get_frame()
{
    return kq_system_frame;
}
system_get_frame8

Lee los ocho bits menos significativos del contador de fotogramas para intervalos cortos y repetitivos.

Sintaxis

c
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

c
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.

system_get_frame8: DMG
DMG
system_get_frame8: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_services.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_services.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/system.h:21

Notas de la declaración (original)
Return the low byte of the software frame counter for wrapping 8-bit timing.

kitaqgb/lib/system.c:37

c
u8 system_get_frame8()
{
    return (u8)kq_system_frame;
}
system_init

Inicializa la gestión de fotogramas poniendo a cero el contador y eliminando la función de retorno registrada.

Sintaxis

c
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

c
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.

system_init: DMG
DMG
system_init: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_services.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_services.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/system.h:12

Notas de la declaración (original)
Reset the software frame counter and remove any registered callback.

kitaqgb/lib/system.c:7

c
void system_init()
{
    kq_system_frame = 0;
    system_vblank_callback = 0;
}
system_set_vblank_callback

Registra, sustituye o elimina la función que se llama después de esperar un fotograma.

Sintaxis

c
void system_set_vblank_callback(SystemCallback callback);

Parámetros

callback

Funció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

c
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.

system_set_vblank_callback: DMG
DMG
system_set_vblank_callback: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_services.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_services.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/system.h:17

Notas de la declaración (original)
Replace the callback used by system_wait_vblank; null disables the callback.

kitaqgb/lib/system.c:25

c
void system_set_vblank_callback(SystemCallback callback)
{
    system_vblank_callback = callback;
}
system_wait_vblank

Espera al siguiente fotograma, incrementa el contador e invoca la función de retorno registrada.

Sintaxis

c
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

c
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.

system_wait_vblank: DMG
DMG
system_wait_vblank: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\batch_services.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\batch_services.gb --no-cache --no-disasm --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --cart=mbc5 --romsize=64k
Implementación y código fuente

kitaqgb/lib/system.h:15

Notas de la declaración (original)
Wait for VBlank, count this wrapper call, then invoke the callback synchronously.
The counter wraps at 16 bits and is not an independent hardware frame clock.

kitaqgb/lib/system.c:15

c
void system_wait_vblank()
{
    __wait_vblank();
    kq_system_frame++;
    if (system_vblank_callback != 0) {
        system_vblank_callback();
    }
}

vram.h — 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

c
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

c
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.

vram_clear_queue: DMG
DMG
vram_clear_queue: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\vram.c .\kitaq-docs\samples\api-examples\gb\vram_queue_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/vram.h:41

Notas de la declaración (original)
Discard pending commands and clear the latched overflow flag without writing VRAM.

kitaqgb/lib/vram.c:41

c
void vram_clear_queue()
{
    kq_vram_queue_used = 0;
    kq_vram_queue_overflowed = 0;
}
vram_flush

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

c
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

c
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.

vram_flush: DMG
DMG
vram_flush: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\vram.c .\kitaq-docs\samples\api-examples\gb\vram_queue_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/vram.h:64

Notas de la declaración (original)
Wait for VBlank before executing the queue. Waiting once does not itself limit
the queued workload to the available VBlank duration.

kitaqgb/lib/vram.c:148

c
void vram_flush()
{
    __wait_vblank();
    vram_flush_now();
}
vram_flush_now

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

c
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

c
// Rendering is stopped here. On FC, commit readiness before direct execution.

vram_flush_now();
after_flush=vram_get_queue_used();
if (after_flush!=0) failures++;

Este fragmento 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.

vram_flush_now: DMG
DMG
vram_flush_now: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\vram.c .\kitaq-docs\samples\api-examples\gb\vram_queue_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/vram.h:61

Notas de la declaración (original)
Execute pending commands in insertion order without waiting for VBlank here.
The caller must arrange suitable VRAM access timing and a sufficient transfer budget.
Only the used count is cleared; overflow stays latched until an explicit reset.

kitaqgb/lib/vram.c:125

c
void vram_flush_now()
{
    u8 i = 0;
    while (i < kq_vram_queue_used) {
        VramCommand* cmd = &kq_vram_queue[(__safe_index u8)i];
        if (cmd->kind == VRAM_CMD_BG_TILE) {
            __settile_xy(cmd->x, cmd->y, cmd->value);
        } else if (cmd->kind == VRAM_CMD_BG_RECT) {
            __settile_rect(cmd->x, cmd->y, cmd->w, cmd->h, cmd->value);
        } else if (cmd->kind == VRAM_CMD_BG_BLOCK) {
            __settilemap_rect(cmd->dst, cmd->x, cmd->y, cmd->w, cmd->h, cmd->src);
        } else if (cmd->kind == VRAM_CMD_MEMCPY) {
            __vram_copy(cmd->dst, cmd->src, cmd->len);
        } else if (cmd->kind == VRAM_CMD_MEMSET) {
            __vram_fill(cmd->dst, cmd->value, cmd->len);
        }
        i++;
    }
    kq_vram_queue_used = 0;
}
vram_get_overflowed

Lee la marca de desbordamiento sin borrarla; puede reflejar un fallo anterior.

Sintaxis

c
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

c
overflow_seen=vram_get_overflowed();
if (overflow_seen!=1) failures++;
// Reading the latch again does not clear it.
if (vram_get_overflowed()!=1) failures++;

Este fragmento 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.

vram_get_overflowed: DMG
DMG
vram_get_overflowed: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\vram.c .\kitaq-docs\samples\api-examples\gb\vram_queue_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/vram.h:73

Notas de la declaración (original)
Read the overflow latch without clearing it.

kitaqgb/lib/vram.c:175

c
u8 vram_get_overflowed()
{
    return kq_vram_queue_overflowed;
}
vram_get_queue_capacity

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

c
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

c
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.

vram_get_queue_capacity: DMG
DMG
vram_get_queue_capacity: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\vram.c .\kitaq-docs\samples\api-examples\gb\vram_queue_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/vram.h:69

Notas de la declaración (original)
Return the total number of command slots, independent of queue usage.
This is command-buffer capacity, not free space in hardware VRAM.

kitaqgb/lib/vram.c:162

c
u8 vram_get_queue_capacity()
{
    return VRAM_QUEUE_MAX;
}
vram_get_queue_free

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

c
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

c
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.

vram_get_queue_free: DMG
DMG
vram_get_queue_free: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\vram.c .\kitaq-docs\samples\api-examples\gb\vram_queue_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/vram.h:71

Notas de la declaración (original)
Return the remaining command-slot capacity.

kitaqgb/lib/vram.c:169

c
u8 vram_get_queue_free()
{
    return (u8)(VRAM_QUEUE_MAX - kq_vram_queue_used);
}
vram_get_queue_used

Devuelve el espacio del búfer ocupado por los comandos pendientes, no los bytes que se escribirán en memoria de vídeo.

Sintaxis

c
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

c
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.

vram_get_queue_used: DMG
DMG
vram_get_queue_used: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\vram.c .\kitaq-docs\samples\api-examples\gb\vram_queue_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/vram.h:66

Notas de la declaración (original)
Return the number of queued commands, not the number of transfer bytes.

kitaqgb/lib/vram.c:155

c
u8 vram_get_queue_used()
{
    return kq_vram_queue_used;
}
vram_init

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

c
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

c
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.

vram_init: DMG
DMG
vram_init: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\vram.c .\kitaq-docs\samples\api-examples\gb\vram_queue_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/vram.h:39

Notas de la declaración (original)
Start with an empty command queue and a clear overflow flag.

kitaqgb/lib/vram.c:34

c
void vram_init()
{
    kq_vram_queue_used = 0;
    kq_vram_queue_overflowed = 0;
}
vram_queue_bg_block

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

c
u8 vram_queue_bg_block(u16 base, u8 x, u8 y, u8 w, u8 h, const u8* src);

Parámetros

base

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.

x, y

Coordenadas superiores izquierdas en tiles de 8×8, no píxeles. No hay recorte. Mantén x + w <= 32 y y + h <= 32 en GB, o <= 30 en el área de tiles de una nametable FC. Un tile individual tiene ancho y alto 1.

w, h

Ancho y alto en tiles como bytes sin signo. El bloque fuente contiene w * h bytes por filas. Dimensiones cero no producen escrituras visibles, pero el consumo de cola sigue las reglas de la plataforma.

src

Puntero 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

c
check_result=vram_queue_bg_block(MAP_BASE,10,4,3,2,block);
block[0]=1; // The queued pointer sees this change when the queue executes.
if (check_result!=1) failures++;

Este fragmento 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.

vram_queue_bg_block: DMG
DMG
vram_queue_bg_block: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\vram.c .\kitaq-docs\samples\api-examples\gb\vram_queue_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/vram.h:50

Notas de la declaración (original)
Queue a tile-map rectangle while retaining src rather than copying its bytes.
Keep the source data and its ROM bank accessible until the queue is flushed.

kitaqgb/lib/vram.c:79

c
u8 vram_queue_bg_block(u16 base, u8 x, u8 y, u8 w, u8 h, const u8* src)
{
    VramCommand* cmd = vram_push(VRAM_CMD_BG_BLOCK);
    if (cmd == 0) return 0;
    cmd->dst = base;
    cmd->x = x;
    cmd->y = y;
    cmd->w = w;
    cmd->h = h;
    cmd->src = src;
    return 1;
}
vram_queue_bg_rect

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

c
u8 vram_queue_bg_rect(u8 x, u8 y, u8 w, u8 h, u8 tile);

Parámetros

x, y

Coordenadas superiores izquierdas en tiles de 8×8, no píxeles. No hay recorte. Mantén x + w <= 32 y y + h <= 32 en GB, o <= 30 en el área de tiles de una nametable FC. Un tile individual tiene ancho y alto 1.

w, h

Ancho y alto en tiles como bytes sin signo. El bloque fuente contiene w * h bytes por filas. Dimensiones cero no producen escrituras visibles, pero el consumo de cola sigue las reglas de la plataforma.

tile

Byte 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

c
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.

vram_queue_bg_rect: DMG
DMG
vram_queue_bg_rect: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\vram.c .\kitaq-docs\samples\api-examples\gb\vram_queue_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/vram.h:47

Notas de la declaración (original)
Queue a rectangle filled with one tile value; coordinates and dimensions are in tiles.

kitaqgb/lib/vram.c:65

c
u8 vram_queue_bg_rect(u8 x, u8 y, u8 w, u8 h, u8 tile)
{
    VramCommand* cmd = vram_push(VRAM_CMD_BG_RECT);
    if (cmd == 0) return 0;
    cmd->x = x;
    cmd->y = y;
    cmd->w = w;
    cmd->h = h;
    cmd->value = tile;
    return 1;
}
vram_queue_bg_tile

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

c
u8 vram_queue_bg_tile(u8 x, u8 y, u8 tile);

Parámetros

x, y

Coordenadas superiores izquierdas en tiles de 8×8, no píxeles. No hay recorte. Mantén x + w <= 32 y y + h <= 32 en GB, o <= 30 en el área de tiles de una nametable FC. Un tile individual tiene ancho y alto 1.

tile

Byte 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

c
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.

vram_queue_bg_tile: DMG
DMG
vram_queue_bg_tile: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\vram.c .\kitaq-docs\samples\api-examples\gb\vram_queue_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/vram.h:43

Notas de la declaración (original)
Queue a single background tile write; return zero if no command slot is available.

kitaqgb/lib/vram.c:48

c
u8 vram_queue_bg_tile(u8 x, u8 y, u8 tile)
{
    VramCommand* cmd = vram_push(VRAM_CMD_BG_TILE);
    if (cmd == 0) return 0;
    cmd->x = x;
    cmd->y = y;
    cmd->value = tile;
    return 1;
}
vram_queue_memcpy

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

c
u8 vram_queue_memcpy(u16 dst, const void* src, u16 len);

Parámetros

dst

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.

src

Puntero 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.

len

Nú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

c
check_result=vram_queue_memcpy(MAP_BASE+8*32+2,strip,3);
if (check_result!=1) failures++; // Copy three map bytes, not three tile patterns.

Este fragmento 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.

vram_queue_memcpy: DMG
DMG
vram_queue_memcpy: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\vram.c .\kitaq-docs\samples\api-examples\gb\vram_queue_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/vram.h:53

Notas de la declaración (original)
Queue a byte transfer and retain the source pointer. The source must remain
valid and visible until flush; len is measured in bytes, not tiles.

kitaqgb/lib/vram.c:94

c
u8 vram_queue_memcpy(u16 dst, const void* src, u16 len)
{
    VramCommand* cmd = vram_push(VRAM_CMD_MEMCPY);
    if (cmd == 0) return 0;
    cmd->dst = dst;
    cmd->src = (const u8*)src;
    cmd->len = len;
    return 1;
}
vram_queue_memset

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

c
u8 vram_queue_memset(u16 dst, u8 value, u16 len);

Parámetros

dst

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.

value

Un 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.

len

Nú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

c
check_result=vram_queue_memset(MAP_BASE+8*32+10,1,5);
if (check_result!=1) failures++; // Five solid tiles form a 40x8 horizontal bar.

Este fragmento 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.

vram_queue_memset: DMG
DMG
vram_queue_memset: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\vram.c .\kitaq-docs\samples\api-examples\gb\vram_queue_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/vram.h:57

Notas de la declaración (original)
Queue a byte fill and return zero if the command queue is full.

kitaqgb/lib/vram.c:111

c
u8 vram_queue_memset(u16 dst, u8 value, u16 len)
{
    VramCommand* cmd = vram_push(VRAM_CMD_MEMSET);
    if (cmd == 0) return 0;
    cmd->dst = dst;
    cmd->value = value;
    cmd->len = len;
    return 1;
}
vram_queue_tile

vram_queue_tile 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

c
u8 vram_queue_tile(u8 x, u8 y, u8 tile);

Parámetros

x, y

Coordenadas superiores izquierdas en tiles de 8×8, no píxeles. No hay recorte. Mantén x + w <= 32 y y + h <= 32 en GB, o <= 30 en el área de tiles de una nametable FC. Un tile individual tiene ancho y alto 1.

tile

Byte 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

c
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.

vram_queue_tile: DMG
DMG
vram_queue_tile: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\vram.c .\kitaq-docs\samples\api-examples\gb\vram_queue_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/vram.h:45

Notas de la declaración (original)
Provide the short alias for a queued background tile write.

kitaqgb/lib/vram.c:59

c
u8 vram_queue_tile(u8 x, u8 y, u8 tile)
{
    return vram_queue_bg_tile(x, y, tile);
}
vram_queue_tiles

vram_queue_tiles 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

c
u8 vram_queue_tiles(u16 dst, const void* src, u16 len);

Parámetros

dst

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.

src

Puntero 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.

len

Nú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

c
check_result=vram_queue_tiles(MAP_BASE+8*32+6,strip+1,2);
if (check_result!=1) failures++; // This alias also measures length in bytes.

Este fragmento 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.

vram_queue_tiles: DMG
DMG
vram_queue_tiles: CGB
CGB

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaqgb\lib\vram.c .\kitaq-docs\samples\api-examples\gb\vram_queue_shapes.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\vram_queue_shapes.gb --profile=dev --rst-disable --stack-bank=fixed --cgb=cgb --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/vram.h:55

Notas de la declaración (original)
Alias the queued byte-copy operation; this does not convert a tile count to bytes.

kitaqgb/lib/vram.c:105

c
u8 vram_queue_tiles(u16 dst, const void* src, u16 len)
{
    return vram_queue_memcpy(dst, src, len);
}

wire3d.h — 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

c
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

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    Wire3D_SetCamera(8,0,0,0,0,0);
    result[1]=Wire3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=Wire3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    Wire3D_SetCamera(0,0,0,0,0,0);
    Wire3D_BeginFrame();
    Wire3D_DrawLine2D(8,8,56,8);
    Wire3D_DrawLine2D(56,8,56,40);
    Wire3D_DrawLine2D(56,40,8,40);
    Wire3D_DrawLine2D(8,40,8,8);
    Wire3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    Wire3D_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    Wire3D_PutBgTile(18,1,157);
    Wire3D_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

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.

Wire3D_BeginFrame: DMG — 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.
DMG — 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.
Wire3D_BeginFrame: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_raster.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d.h:34

Notas de la declaración (original)
WIRE3D_DMG_HEIGHT = 96.
Clear staged pixels and occlusion mask and disable occlusion filtering.
This leaves the displayed VRAM frame and pending BG tile queue unchanged.

kitaqgb/lib/wire3d_dmg.c:2641

c
void Wire3DDMG_BeginFrame()
{

    w3ddmg_clear_stage_asm();
    w3ddmg_clear_occlusion_mask();




    w3ddmg_occlusion_active = 0;
}
Wire3D_DrawLine2D

Dibuja en el área de preparación una línea de pantalla con conectividad de cuatro vecinos, incluidos los extremos.

Sintaxis

c
void Wire3D_DrawLine2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by);

Parámetros

ax

Coordenada X del vértice A en píxeles de la ventana gráfica.

ay

Coordenada Y del vértice A en píxeles de la ventana gráfica.

bx

Coordenada X del vértice B en píxeles de la ventana gráfica.

by

Coordenada 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

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    Wire3D_SetCamera(8,0,0,0,0,0);
    result[1]=Wire3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=Wire3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    Wire3D_SetCamera(0,0,0,0,0,0);
    Wire3D_BeginFrame();
    Wire3D_DrawLine2D(8,8,56,8);
    Wire3D_DrawLine2D(56,8,56,40);
    Wire3D_DrawLine2D(56,40,8,40);
    Wire3D_DrawLine2D(8,40,8,8);
    Wire3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    Wire3D_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    Wire3D_PutBgTile(18,1,157);
    Wire3D_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

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.

Wire3D_DrawLine2D: DMG — 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.
DMG — 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.
Wire3D_DrawLine2D: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_raster.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d.h:35

Notas de la declaración (original)
WIRE3D_DMG_HEIGHT = 96.
Draw a connected line into the 128x96 stage, including endpoints. During
DrawScene, use the coarse five-sample occlusion rejection; otherwise draw directly.
Supply viewport coordinates. VRAM is updated only by EndFrame.

kitaqgb/lib/wire3d_dmg.c:2685

c
void Wire3DDMG_DrawLine2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by)
{




    if (w3ddmg_occlusion_active)
    {
        w3ddmg_line_stage_masked_c(ax, ay, bx, by);
        return;
    }

    w3ddmg_line_x0 = ax;
    w3ddmg_line_y0 = ay;
    w3ddmg_line_x1 = bx;
    w3ddmg_line_y1 = by;
    if (ax < 128 && bx < 128 && ay < WIRE3D_DMG_SCREEN_H && by < WIRE3D_DMG_SCREEN_H)
        w3ddmg_line_inside_asm();
    else
        w3ddmg_line_stage_asm();
}
Wire3D_DrawLine3D

Proyecta dos extremos en coordenadas del mundo y dibuja una línea entre ellos.

Sintaxis

c
void Wire3D_DrawLine3D(w3ddmg_i16 ax, w3ddmg_i16 ay, w3ddmg_i16 az, w3ddmg_i16 bx, w3ddmg_i16 by, w3ddmg_i16 bz);

Parámetros

ax

Componente X del punto inicial en coordenadas del mundo.

ay

Componente Y del punto inicial en coordenadas del mundo.

az

Componente Z del punto inicial en coordenadas del mundo.

bx

Componente X del punto final en coordenadas del mundo.

by

Componente Y del punto final en coordenadas del mundo.

bz

Componente 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

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    Wire3D_SetCamera(8,0,0,0,0,0);
    result[1]=Wire3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=Wire3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    Wire3D_SetCamera(0,0,0,0,0,0);
    Wire3D_BeginFrame();
    Wire3D_DrawLine2D(8,8,56,8);
    Wire3D_DrawLine2D(56,8,56,40);
    Wire3D_DrawLine2D(56,40,8,40);
    Wire3D_DrawLine2D(8,40,8,8);
    Wire3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    Wire3D_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    Wire3D_PutBgTile(18,1,157);
    Wire3D_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

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.

Wire3D_DrawLine3D: DMG — 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.
DMG — 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.
Wire3D_DrawLine3D: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_raster.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d.h:36

Notas de la declaración (original)
WIRE3D_DMG_HEIGHT = 96.
Project both world endpoints and draw only when both pass the depth range.
Do not intersect a crossing segment with near/far planes; projected endpoints
are independently clamped to the screen edges.

kitaqgb/lib/wire3d_dmg.c:2808

c
void Wire3DDMG_DrawLine3D(w3ddmg_i16 ax, w3ddmg_i16 ay, w3ddmg_i16 az, w3ddmg_i16 bx, w3ddmg_i16 by, w3ddmg_i16 bz)
{
    w3ddmg_u8 sx0;
    w3ddmg_u8 sy0;
    w3ddmg_u8 sx1;
    w3ddmg_u8 sy1;

    if (w3ddmg_project_world(ax, ay, az, &sx0, &sy0) == 0) return;
    if (w3ddmg_project_world(bx, by, bz, &sx1, &sy1) == 0) return;
    Wire3DDMG_DrawLine2D(sx0, sy0, sx1, sy1);
}
Wire3D_DrawModel

Dibuja un modelo de vértices y aristas en la posición y con la rotación indicadas, a escala unitaria.

Sintaxis

c
void Wire3D_DrawModel(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz);

Parámetros

model

Modelo que contiene los arrays de vértices, aristas y caras y sus cantidades; las tablas deben permanecer legibles durante la llamada.

x

Componente X del punto o del origen del objeto en coordenadas del mundo.

y

Componente Y del punto o del origen del objeto en coordenadas del mundo.

z

Componente Z del punto o del origen del objeto en coordenadas del mundo.

rx

Rotación alrededor de X; dieciséis pasos forman una vuelta completa.

ry

Rotación alrededor de Y; dieciséis pasos forman una vuelta completa.

rz

Rotació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

c
#pragma bank 0
// Compare direct model scaling with an object-array scene.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3D_Vec3 vertices[8]={{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}};
__prg_rom Wire3D_Edge edges[12]={{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}};
Wire3D_Model cube;
Wire3D_Object objects[2];
u16 masks[2];
void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;

    cube.vertices=vertices;cube.edges=edges;cube.faces=0;cube.edge_faces=0;
    cube.vertex_count=8;cube.edge_count=12;cube.face_count=0;cube.flags=0;
    cube.edge_masks=0; cube.edge_mask_count=0;
    Wire3D_BeginFrame();
    // Upper pair: direct model calls at unity and half scale.
    Wire3D_DrawModel(&cube,-32,32,96,0,0,0);
    Wire3D_DrawModelScaled(&cube,32,32,96,0,0,0,128);
    // Lower pair: the caller owns both object records and the model tables.
    for(i=0;i<2;i++) {
        objects[i].model=&cube;objects[i].x=-32+(s16)i*64;
        objects[i].y=-32;objects[i].z=96;
        objects[i].rx=0;objects[i].ry=0;objects[i].rz=0;
        objects[i].scale_q8=256-(s16)i*128;objects[i].visible=1;
    }
    Wire3D_DrawScene(objects,2);
    // Numeric checks cover the operation supplied by this viewport profile.
    masks[0]=3;masks[1]=12;cube.edge_masks=masks; cube.edge_mask_count=2;
    result[1]=Wire3D_SelectEdgeMask(&cube,0,0,0);
    result[2]=Wire3D_SelectEdgeMask(&cube,0,8,0);
    Wire3D_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

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.

Wire3D_DrawModel: DMG — 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.
DMG — 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.
Wire3D_DrawModel: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_models.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d.h:37

Notas de la declaración (original)
WIRE3D_DMG_HEIGHT = 96.
Draw an unscaled model by delegating to DrawModelScaled with scale 256.

kitaqgb/lib/wire3d_dmg.c:2825

c
void Wire3DDMG_DrawModel(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz)



{
    Wire3DDMG_DrawModelScaled(model, x, y, z, rx, ry, rz, 256);
}
Wire3D_DrawModelScaled

Escala un modelo, lo rota en orden Y/X/Z, traslada y proyecta sus vértices y dibuja las aristas.

Sintaxis

c
void Wire3D_DrawModelScaled(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz, w3ddmg_i16 scale_q8);

Parámetros

model

Modelo que contiene los arrays de vértices, aristas y caras y sus cantidades; las tablas deben permanecer legibles durante la llamada.

x

Componente X del punto o del origen del objeto en coordenadas del mundo.

y

Componente Y del punto o del origen del objeto en coordenadas del mundo.

z

Componente Z del punto o del origen del objeto en coordenadas del mundo.

rx

Rotación alrededor de X; dieciséis pasos forman una vuelta completa.

ry

Rotación alrededor de Y; dieciséis pasos forman una vuelta completa.

rz

Rotación alrededor de Z; dieciséis pasos forman una vuelta completa.

scale_q8

Escala 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

c
#pragma bank 0
// Compare direct model scaling with an object-array scene.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3D_Vec3 vertices[8]={{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}};
__prg_rom Wire3D_Edge edges[12]={{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}};
Wire3D_Model cube;
Wire3D_Object objects[2];
u16 masks[2];
void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;

    cube.vertices=vertices;cube.edges=edges;cube.faces=0;cube.edge_faces=0;
    cube.vertex_count=8;cube.edge_count=12;cube.face_count=0;cube.flags=0;
    cube.edge_masks=0; cube.edge_mask_count=0;
    Wire3D_BeginFrame();
    // Upper pair: direct model calls at unity and half scale.
    Wire3D_DrawModel(&cube,-32,32,96,0,0,0);
    Wire3D_DrawModelScaled(&cube,32,32,96,0,0,0,128);
    // Lower pair: the caller owns both object records and the model tables.
    for(i=0;i<2;i++) {
        objects[i].model=&cube;objects[i].x=-32+(s16)i*64;
        objects[i].y=-32;objects[i].z=96;
        objects[i].rx=0;objects[i].ry=0;objects[i].rz=0;
        objects[i].scale_q8=256-(s16)i*128;objects[i].visible=1;
    }
    Wire3D_DrawScene(objects,2);
    // Numeric checks cover the operation supplied by this viewport profile.
    masks[0]=3;masks[1]=12;cube.edge_masks=masks; cube.edge_mask_count=2;
    result[1]=Wire3D_SelectEdgeMask(&cube,0,0,0);
    result[2]=Wire3D_SelectEdgeMask(&cube,0,8,0);
    Wire3D_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

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.

Wire3D_DrawModelScaled: DMG — 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.
DMG — 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.
Wire3D_DrawModelScaled: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_models.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d.h:38

Notas de la declaración (original)
WIRE3D_DMG_HEIGHT = 96.
Scale, rotate in Y/X/Z order, translate and project at most 24 vertices;
then draw up to 16 edges filtered by yaw masks and optional front-facing faces.
Nonpositive scale becomes unity (256). Null model/vertex/edge pointers are
ignored; referenced tables must remain readable. Keep scale products and
translations in signed 16-bit range. Depth-crossing edges are dropped, not clipped.

kitaqgb/lib/wire3d_dmg.c:2965

c
void Wire3DDMG_DrawModelScaled(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz, w3ddmg_i16 scale_q8)








{
    w3ddmg_u8 i;
    w3ddmg_u8 count;
    w3ddmg_u8 edge_count;
    w3ddmg_u8 face_count;

    if (model == 0) return;
    if (model->vertices == 0) return;
    if (model->edges == 0) return;
    if (scale_q8 <= 0) scale_q8 = 256;

    count = model->vertex_count;
    if (count > WIRE3D_DMG_MODEL_VERTEX_LIMIT) count = WIRE3D_DMG_MODEL_VERTEX_LIMIT;

    i = 0;
    while (i < count)
    {
        const Wire3DDMG_Vec3* v;
        w3ddmg_i16 vx;
        w3ddmg_i16 vy;
        w3ddmg_i16 vz;
        w3ddmg_u8 sx;
        w3ddmg_u8 sy;

        v = &model->vertices[(__safe_index w3ddmg_u8)i];
        vx = (w3ddmg_i16)((v->x * scale_q8) >> 8);
        vy = (w3ddmg_i16)((v->y * scale_q8) >> 8);
        vz = (w3ddmg_i16)((v->z * scale_q8) >> 8);


        w3ddmg_rotate_y(&vx, &vz, (w3ddmg_i8)ry);
        w3ddmg_rotate_x(&vy, &vz, (w3ddmg_i8)rx);
        w3ddmg_rotate_z(&vx, &vy, (w3ddmg_i8)rz);






        vx = (w3ddmg_i16)(vx + x);
        vy = (w3ddmg_i16)(vy + y);
        vz = (w3ddmg_i16)(vz + z);

        if (w3ddmg_project_world(vx, vy, vz, &sx, &sy))
        {
            w3ddmg_screen_x[(__safe_index w3ddmg_u8)i] = sx;
            w3ddmg_screen_y[(__safe_index w3ddmg_u8)i] = sy;
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 1;
        }
        else
        {
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 0;
        }
        i = (w3ddmg_u8)(i + 1);
    }

    face_count = model->face_count;
    if (face_count > WIRE3D_DMG_MODEL_FACE_LIMIT) face_count = WIRE3D_DMG_MODEL_FACE_LIMIT;
    if ((model->flags & WIRE3D_DMG_MODEL_HIDDEN_LINES) && (model->faces != 0) && (model->edge_faces != 0))
    {
        w3ddmg_build_face_visibility(model, count, face_count);
    }

    edge_count = model->edge_count;

    if (edge_count > WIRE3D_DMG_MODEL_EDGE_LIMIT) edge_count = WIRE3D_DMG_MODEL_EDGE_LIMIT;
    w3ddmg_build_edge_flags(model, edge_count, face_count, rx, ry, rz);

    i = 0;
    while (i < edge_count)
    {
        const Wire3DDMG_Edge* e;
        e = &model->edges[(__safe_index w3ddmg_u8)i];
        if ((e->a < count) && (e->b < count))
        {
            if (w3ddmg_screen_visible[(__safe_index w3ddmg_u8)e->a] &&
                w3ddmg_screen_visible[(__safe_index w3ddmg_u8)e->b] &&

                w3ddmg_edge_flags[(__safe_index w3ddmg_u8)i])



            {
                Wire3DDMG_DrawLine2D(
                    w3ddmg_screen_x[(__safe_index w3ddmg_u8)e->a],
                    w3ddmg_screen_y[(__safe_index w3ddmg_u8)e->a],
                    w3ddmg_screen_x[(__safe_index w3ddmg_u8)e->b],
                    w3ddmg_screen_y[(__safe_index w3ddmg_u8)e->b]);
            }
        }
        i = (w3ddmg_u8)(i + 1);
    }
}
Wire3D_DrawScene

Dibuja hasta ocho objetos de cerca a lejos, usando las caras cercanas para ocultar las aristas posteriores.

Sintaxis

c
void Wire3D_DrawScene(Wire3DDMG_Object* objects, w3ddmg_u8 count);

Parámetros

objects

Array de objetos con posiciones, rotaciones, escalas e indicadores de visibilidad.

count

Cantidad 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

c
#pragma bank 0
// Compare direct model scaling with an object-array scene.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3D_Vec3 vertices[8]={{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}};
__prg_rom Wire3D_Edge edges[12]={{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}};
Wire3D_Model cube;
Wire3D_Object objects[2];
u16 masks[2];
void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;

    cube.vertices=vertices;cube.edges=edges;cube.faces=0;cube.edge_faces=0;
    cube.vertex_count=8;cube.edge_count=12;cube.face_count=0;cube.flags=0;
    cube.edge_masks=0; cube.edge_mask_count=0;
    Wire3D_BeginFrame();
    // Upper pair: direct model calls at unity and half scale.
    Wire3D_DrawModel(&cube,-32,32,96,0,0,0);
    Wire3D_DrawModelScaled(&cube,32,32,96,0,0,0,128);
    // Lower pair: the caller owns both object records and the model tables.
    for(i=0;i<2;i++) {
        objects[i].model=&cube;objects[i].x=-32+(s16)i*64;
        objects[i].y=-32;objects[i].z=96;
        objects[i].rx=0;objects[i].ry=0;objects[i].rz=0;
        objects[i].scale_q8=256-(s16)i*128;objects[i].visible=1;
    }
    Wire3D_DrawScene(objects,2);
    // Numeric checks cover the operation supplied by this viewport profile.
    masks[0]=3;masks[1]=12;cube.edge_masks=masks; cube.edge_mask_count=2;
    result[1]=Wire3D_SelectEdgeMask(&cube,0,0,0);
    result[2]=Wire3D_SelectEdgeMask(&cube,0,8,0);
    Wire3D_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

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.

Wire3D_DrawScene: DMG — 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.
DMG — 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.
Wire3D_DrawScene: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_models.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d.h:39

Notas de la declaración (original)
WIRE3D_DMG_HEIGHT = 96.
Process at most the first eight objects, sorted near to far by transformed
origin depth. Draw visible valid models, then mark their front-face bounding
rectangles to reject fully sampled later lines. This approximates inter-object
occlusion, not a depth buffer. It clears its mask but retains existing staged
pixels. Null arrays are ignored; objects and their data must remain readable.

kitaqgb/lib/wire3d_dmg.c:2723

c
void Wire3DDMG_DrawScene(Wire3DDMG_Object* objects, w3ddmg_u8 count)
{
    w3ddmg_u8 scene_count;
    w3ddmg_u8 i;

    if (objects == 0) return;

    scene_count = count;
    if (scene_count > WIRE3D_DMG_SCENE_OBJECT_LIMIT) scene_count = WIRE3D_DMG_SCENE_OBJECT_LIMIT;




    i = 0;
    while (i < scene_count)
    {
        w3ddmg_scene_order[(__safe_index w3ddmg_u8)i] = i;
        w3ddmg_scene_depth[(__safe_index w3ddmg_u8)i] = w3ddmg_scene_object_depth(&objects[(__safe_index w3ddmg_u8)i]);
        i = (w3ddmg_u8)(i + 1);
    }

    i = 0;
    while (i < scene_count)
    {
        w3ddmg_u8 j;
        j = (w3ddmg_u8)(i + 1);
        while (j < scene_count)
        {
            w3ddmg_u8 oi;
            w3ddmg_u8 oj;
            oi = w3ddmg_scene_order[(__safe_index w3ddmg_u8)i];
            oj = w3ddmg_scene_order[(__safe_index w3ddmg_u8)j];


            // Put the nearer origin first so its face bounds can suppress later lines.
            // The array itself stays in caller order; only the scratch index list is sorted.

            if (w3ddmg_scene_depth[(__safe_index w3ddmg_u8)oj] < w3ddmg_scene_depth[(__safe_index w3ddmg_u8)oi])
            {
                w3ddmg_scene_order[(__safe_index w3ddmg_u8)i] = oj;
                w3ddmg_scene_order[(__safe_index w3ddmg_u8)j] = oi;
            }
            j = (w3ddmg_u8)(j + 1);
        }
        i = (w3ddmg_u8)(i + 1);
    }

    w3ddmg_clear_occlusion_mask();

    w3ddmg_occlusion_active = 1;




    i = 0;
    while (i < scene_count)
    {
        Wire3DDMG_Object* obj;
        obj = &objects[(__safe_index w3ddmg_u8)w3ddmg_scene_order[(__safe_index w3ddmg_u8)i]];
        if ((obj->visible != 0) && (obj->model != 0))
        {

            Wire3DDMG_DrawModelScaled(obj->model, obj->x, obj->y, obj->z, (w3ddmg_i8)obj->rx, (w3ddmg_i8)obj->ry, (w3ddmg_i8)obj->rz, obj->scale_q8);
            w3ddmg_mark_model_occluder(obj->model);








        }
        i = (w3ddmg_u8)(i + 1);
    }

    w3ddmg_occlusion_active = 0;
}
Wire3D_EndFrame

Envía a VRAM las escrituras del fondo pendientes y el dibujo preparado.

Sintaxis

c
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

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    Wire3D_SetCamera(8,0,0,0,0,0);
    result[1]=Wire3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=Wire3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    Wire3D_SetCamera(0,0,0,0,0,0);
    Wire3D_BeginFrame();
    Wire3D_DrawLine2D(8,8,56,8);
    Wire3D_DrawLine2D(56,8,56,40);
    Wire3D_DrawLine2D(56,40,8,40);
    Wire3D_DrawLine2D(8,40,8,8);
    Wire3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    Wire3D_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    Wire3D_PutBgTile(18,1,157);
    Wire3D_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

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.

Wire3D_EndFrame: DMG — 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.
DMG — 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.
Wire3D_EndFrame: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_raster.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d.h:42

Notas de la declaración (original)
WIRE3D_DMG_HEIGHT = 96.
Wait for the next VBlank, flush pending BG map writes, then copy the stage
to VRAM while polling access windows. Copying consumes the staged pixels.
The transfer may extend beyond VBlank; this is not an atomic frame swap.

kitaqgb/lib/wire3d_dmg.c:3081

c
void Wire3DDMG_EndFrame()
{
    w3ddmg_wait_vblank_start();
    w3ddmg_flush_bg_queue();

    w3ddmg_transfer_stage_asm();














}
Wire3D_EraseModelFaces

Proyecta los triángulos frontales del modelo y borra los píxeles preparados de su interior.

Sintaxis

c
void Wire3D_EraseModelFaces(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz, w3ddmg_i16 scale_q8);

Parámetros

model

Modelo que contiene los arrays de vértices, aristas y caras y sus cantidades; las tablas deben permanecer legibles durante la llamada.

x

Componente X del punto o del origen del objeto en coordenadas del mundo.

y

Componente Y del punto o del origen del objeto en coordenadas del mundo.

z

Componente Z del punto o del origen del objeto en coordenadas del mundo.

rx

Rotación alrededor de X; dieciséis pasos forman una vuelta completa.

ry

Rotación alrededor de Y; dieciséis pasos forman una vuelta completa.

rz

Rotación alrededor de Z; dieciséis pasos forman una vuelta completa.

scale_q8

Escala 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

c
#pragma bank 0
// Erase a screen triangle and a projected model face from separate filled panels.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3D_Vec3 vertices[4]={{-24,-24,0},{24,-24,0},{24,24,0},{-24,24,0}};
__prg_rom Wire3D_Edge edges[4]={{0,1},{1,2},{2,3},{3,0}};
__prg_rom Wire3D_Face faces[2]={{0,2,1},{0,3,2}};
Wire3D_Model plane;

void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
        plane.vertices=vertices;plane.edges=edges;plane.faces=faces;plane.edge_faces=0;
    plane.vertex_count=4;plane.edge_count=4;plane.face_count=2;plane.flags=1;plane.edge_masks=0;plane.edge_mask_count=0;
    Wire3D_BeginFrame();
    // Separate panels show a direct screen triangle and a projected square face.
    for(i=8;i<=32;i++) Wire3D_DrawLine2D(8,i,32,i);
    for(i=24;i<=72;i++) Wire3D_DrawLine2D(40,i,88,i);
    Wire3D_EraseTriangle2D(12,12,28,12,12,28);
    Wire3D_EraseModelFaces(&plane,0,0,64,0,0,0,256);

    Wire3D_EndFrame(); result[7]=0xA55A; while(1) {}
}

Resultado esperado

Las caras proyectadas borran una región rellena y permiten distinguir las zonas conservadas de las borradas.

Wire3D_EraseModelFaces: DMG — Las caras proyectadas borran una región rellena y permiten distinguir las zonas conservadas de las borradas.
DMG — Las caras proyectadas borran una región rellena y permiten distinguir las zonas conservadas de las borradas.
Wire3D_EraseModelFaces: CGB — Las caras proyectadas borran una región rellena y permiten distinguir las zonas conservadas de las borradas.
CGB — Las caras proyectadas borran una región rellena y permiten distinguir las zonas conservadas de las borradas.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_faces.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_faces.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d.h:43

Notas de la declaración (original)
WIRE3D_DMG_HEIGHT = 96.
Project up to 24 vertices and erase front-facing triangle interiors from
the stage for a model with hidden-line flags and face data. Nonpositive scale
means 256 (unity). Up to 16 faces are considered; depth-crossing faces are
skipped. This also replaces shared projection caches, but does not update VRAM.

kitaqgb/lib/wire3d_dmg.c:2841

c
void Wire3DDMG_EraseModelFaces(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz, w3ddmg_i16 scale_q8)



{
    w3ddmg_u8 i;
    w3ddmg_u8 count;
    w3ddmg_u8 face_count;

    if (model == 0) return;
    if (model->vertices == 0) return;
    if (model->faces == 0) return;
    if ((model->flags & WIRE3D_DMG_MODEL_HIDDEN_LINES) == 0) return;
    if (scale_q8 <= 0) scale_q8 = 256;

    count = model->vertex_count;
    if (count > WIRE3D_DMG_MODEL_VERTEX_LIMIT) count = WIRE3D_DMG_MODEL_VERTEX_LIMIT;

    i = 0;
    while (i < count)
    {
        const Wire3DDMG_Vec3* v;
        w3ddmg_i16 vx;
        w3ddmg_i16 vy;
        w3ddmg_i16 vz;
        w3ddmg_u8 sx;
        w3ddmg_u8 sy;

        v = &model->vertices[(__safe_index w3ddmg_u8)i];
        vx = (w3ddmg_i16)((v->x * scale_q8) >> 8);
        vy = (w3ddmg_i16)((v->y * scale_q8) >> 8);
        vz = (w3ddmg_i16)((v->z * scale_q8) >> 8);


        w3ddmg_rotate_y(&vx, &vz, (w3ddmg_i8)ry);
        w3ddmg_rotate_x(&vy, &vz, (w3ddmg_i8)rx);
        w3ddmg_rotate_z(&vx, &vy, (w3ddmg_i8)rz);






        vx = (w3ddmg_i16)(vx + x);
        vy = (w3ddmg_i16)(vy + y);
        vz = (w3ddmg_i16)(vz + z);

        if (w3ddmg_project_world(vx, vy, vz, &sx, &sy))
        {
            w3ddmg_screen_x[(__safe_index w3ddmg_u8)i] = sx;
            w3ddmg_screen_y[(__safe_index w3ddmg_u8)i] = sy;
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 1;
        }
        else
        {
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 0;
        }
        i = (w3ddmg_u8)(i + 1);
    }

    face_count = model->face_count;
    if (face_count > WIRE3D_DMG_MODEL_FACE_LIMIT) face_count = WIRE3D_DMG_MODEL_FACE_LIMIT;
    w3ddmg_build_face_visibility(model, count, face_count);

    i = 0;
    while (i < face_count)
    {
        const Wire3DDMG_Face* f;
        f = &model->faces[(__safe_index w3ddmg_u8)i];
        if (w3ddmg_face_visible[(__safe_index w3ddmg_u8)i] &&
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)f->a] &&
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)f->b] &&
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)f->c])
        {
            w3ddmg_clear_triangle(
                w3ddmg_screen_x[(__safe_index w3ddmg_u8)f->a],
                w3ddmg_screen_y[(__safe_index w3ddmg_u8)f->a],
                w3ddmg_screen_x[(__safe_index w3ddmg_u8)f->b],
                w3ddmg_screen_y[(__safe_index w3ddmg_u8)f->b],
                w3ddmg_screen_x[(__safe_index w3ddmg_u8)f->c],
                w3ddmg_screen_y[(__safe_index w3ddmg_u8)f->c]);
        }
        i = (w3ddmg_u8)(i + 1);
    }
}
Wire3D_EraseSpan2D

Borra un tramo horizontal, con ambos extremos incluidos, de una fila preparada.

Sintaxis

c
void Wire3D_EraseSpan2D(w3ddmg_u8 y, w3ddmg_u8 x0, w3ddmg_u8 x1);

Parámetros

y

Coordenada Y en píxeles de la fila que se va a borrar.

x0

Extremo X inferior, en píxeles de la ventana gráfica; el orden y el recorte siguen las notas de esta operación.

x1

Extremo 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

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    Wire3D_SetCamera(8,0,0,0,0,0);
    result[1]=Wire3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=Wire3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    Wire3D_SetCamera(0,0,0,0,0,0);
    Wire3D_BeginFrame();
    Wire3D_DrawLine2D(8,8,56,8);
    Wire3D_DrawLine2D(56,8,56,40);
    Wire3D_DrawLine2D(56,40,8,40);
    Wire3D_DrawLine2D(8,40,8,8);
    Wire3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    Wire3D_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    Wire3D_PutBgTile(18,1,157);
    Wire3D_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

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.

Wire3D_EraseSpan2D: DMG — 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.
DMG — 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.
Wire3D_EraseSpan2D: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_raster.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d.h:44

Notas de la declaración (original)
WIRE3D_DMG_HEIGHT = 96.
Order the X endpoints and erase the inclusive staged span. Both endpoints
must be in 0..127; invalid Y is ignored. The routine does not clip X for you.

kitaqgb/lib/wire3d_dmg.c:2943

c
void Wire3DDMG_EraseSpan2D(w3ddmg_u8 y, w3ddmg_u8 x0, w3ddmg_u8 x1)
{
    w3ddmg_u8 tx;

    if (x0 > x1)
    {
        tx = x0;
        x0 = x1;
        x1 = tx;
    }
    w3ddmg_stage_clear_span(y, x0, x1);
}
Wire3D_EraseTriangle2D

Borra un triángulo de pantalla del área de preparación mediante tramos horizontales de líneas de barrido.

Sintaxis

c
void Wire3D_EraseTriangle2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by, w3ddmg_u8 cx, w3ddmg_u8 cy);

Parámetros

ax

Coordenada X del vértice A en píxeles de la ventana gráfica.

ay

Coordenada Y del vértice A en píxeles de la ventana gráfica.

bx

Coordenada X del vértice B en píxeles de la ventana gráfica.

by

Coordenada Y del vértice B en píxeles de la ventana gráfica.

cx

Coordenada X del vértice C en píxeles de la ventana gráfica.

cy

Coordenada 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

c
#pragma bank 0
// Erase a screen triangle and a projected model face from separate filled panels.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3D_Vec3 vertices[4]={{-24,-24,0},{24,-24,0},{24,24,0},{-24,24,0}};
__prg_rom Wire3D_Edge edges[4]={{0,1},{1,2},{2,3},{3,0}};
__prg_rom Wire3D_Face faces[2]={{0,2,1},{0,3,2}};
Wire3D_Model plane;

void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
        plane.vertices=vertices;plane.edges=edges;plane.faces=faces;plane.edge_faces=0;
    plane.vertex_count=4;plane.edge_count=4;plane.face_count=2;plane.flags=1;plane.edge_masks=0;plane.edge_mask_count=0;
    Wire3D_BeginFrame();
    // Separate panels show a direct screen triangle and a projected square face.
    for(i=8;i<=32;i++) Wire3D_DrawLine2D(8,i,32,i);
    for(i=24;i<=72;i++) Wire3D_DrawLine2D(40,i,88,i);
    Wire3D_EraseTriangle2D(12,12,28,12,12,28);
    Wire3D_EraseModelFaces(&plane,0,0,64,0,0,0,256);

    Wire3D_EndFrame(); result[7]=0xA55A; while(1) {}
}

Resultado esperado

Las caras proyectadas borran una región rellena y permiten distinguir las zonas conservadas de las borradas.

Wire3D_EraseTriangle2D: DMG — Las caras proyectadas borran una región rellena y permiten distinguir las zonas conservadas de las borradas.
DMG — Las caras proyectadas borran una región rellena y permiten distinguir las zonas conservadas de las borradas.
Wire3D_EraseTriangle2D: CGB — Las caras proyectadas borran una región rellena y permiten distinguir las zonas conservadas de las borradas.
CGB — Las caras proyectadas borran una región rellena y permiten distinguir las zonas conservadas de las borradas.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_faces.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_faces.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d.h:45

Notas de la declaración (original)
WIRE3D_DMG_HEIGHT = 96.
Erase a triangle from staged pixels using integer scanline intersections.
Supply viewport coordinates. Degenerate triangles are ignored; the occlusion
mask and VRAM are unchanged.

kitaqgb/lib/wire3d_dmg.c:2933

c
void Wire3DDMG_EraseTriangle2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by, w3ddmg_u8 cx, w3ddmg_u8 cy)
{
    w3ddmg_clear_triangle(ax, ay, bx, by, cx, cy);
}
Wire3D_Init

Inicializa el LCD, los tiles y el mapa del fondo para una ventana gráfica de alambre monocroma.

Sintaxis

c
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

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    Wire3D_SetCamera(8,0,0,0,0,0);
    result[1]=Wire3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=Wire3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    Wire3D_SetCamera(0,0,0,0,0,0);
    Wire3D_BeginFrame();
    Wire3D_DrawLine2D(8,8,56,8);
    Wire3D_DrawLine2D(56,8,56,40);
    Wire3D_DrawLine2D(56,40,8,40);
    Wire3D_DrawLine2D(8,40,8,8);
    Wire3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    Wire3D_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    Wire3D_PutBgTile(18,1,157);
    Wire3D_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

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.

Wire3D_Init: DMG — 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.
DMG — 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.
Wire3D_Init: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_raster.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d.h:47

Notas de la declaración (original)
WIRE3D_DMG_HEIGHT = 96.
Take over the LCD: wait for VBlank, switch it off, clear 6144 tile bytes and
the BG map, install HUD tiles and the 128x96 signed-tile viewport, then enable
BG display with scroll zero and BGP=0xB4. Reset camera, BG queue and stage.
Reserve 0xD000..0xDFFF for staging and retain its WRAM bank mapping.
Call BeginFrame before drawing to initialize the occlusion state as well.

kitaqgb/lib/wire3d_dmg.c:2572

c
void Wire3DDMG_Init()
{
    w3ddmg_u8 row;
    w3ddmg_u8 col;
    w3ddmg_u8 tid;
    w3ddmg_u16 off;

    w3ddmg_wait_vblank_start();
    w3ddmg_reg_lcdc = 0;

    w3ddmg_clear_vram_asm();

    w3ddmg_load_hud_tiles();

    w3ddmg_fill_bg_map_asm();

    row = 0;
    tid = 0x90;
    while (row < WIRE3D_DMG_TILE_H)
    {

        off = (w3ddmg_u16)((w3ddmg_u16)row << 5);



        col = 0;
        while (col < WIRE3D_DMG_TILE_W)
        {
            w3ddmg_bg_map_9800[(w3ddmg_u16)(off + (w3ddmg_u16)col)] = tid;
            tid = (w3ddmg_u8)(tid + WIRE3D_DMG_TILE_H);
            col = (w3ddmg_u8)(col + 1);
        }
        row = (w3ddmg_u8)(row + 1);
        tid = (w3ddmg_u8)(0x90 + row);
    }


    w3ddmg_reg_scx = 0;



    w3ddmg_reg_scy = 0;
    w3ddmg_reg_bgp = 0xB4;
    w3ddmg_reg_lcdc = 0x81;
    w3ddmg_bgq_count = 0;





    Wire3DDMG_SetCamera(0, 0, 0, 0, 0, 0);
    w3ddmg_clear_stage_asm();




}
Wire3D_ProjectPoint

Proyecta un punto del mundo mediante la cámara a coordenadas de la ventana gráfica.

Sintaxis

c
w3ddmg_u8 Wire3D_ProjectPoint(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8* sx, w3ddmg_u8* sy);

Parámetros

x

Componente X del punto o del origen del objeto en coordenadas del mundo.

y

Componente Y del punto o del origen del objeto en coordenadas del mundo.

z

Componente Z del punto o del origen del objeto en coordenadas del mundo.

sx

Puntero u8 válido y escribible que recibe la coordenada X proyectada.

sy

Puntero 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

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    Wire3D_SetCamera(8,0,0,0,0,0);
    result[1]=Wire3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=Wire3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    Wire3D_SetCamera(0,0,0,0,0,0);
    Wire3D_BeginFrame();
    Wire3D_DrawLine2D(8,8,56,8);
    Wire3D_DrawLine2D(56,8,56,40);
    Wire3D_DrawLine2D(56,40,8,40);
    Wire3D_DrawLine2D(8,40,8,8);
    Wire3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    Wire3D_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    Wire3D_PutBgTile(18,1,157);
    Wire3D_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

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.

Wire3D_ProjectPoint: DMG — 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.
DMG — 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.
Wire3D_ProjectPoint: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_raster.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d.h:50

Notas de la declaración (original)
WIRE3D_DMG_HEIGHT = 96.
Project a world point with the current camera. Return zero for rejected
depth, leaving outputs unchanged; success writes clamped 128x96 coordinates.
Output pointers must be valid. Screen clamping is not geometric clipping.

kitaqgb/lib/wire3d_dmg.c:549

c
w3ddmg_u8 Wire3DDMG_ProjectPoint(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8* sx, w3ddmg_u8* sy)
{
    return w3ddmg_project_world(x, y, z, sx, sy);
}
Wire3D_PutBgTile

Encola una escritura de número de tile en una celda del mapa del fondo.

Sintaxis

c
void Wire3D_PutBgTile(w3ddmg_u8 x, w3ddmg_u8 y, w3ddmg_u8 tile);

Parámetros

x

Coordenada X de tile en el mapa del fondo de 32×32.

y

Coordenada Y de tile en el mapa del fondo de 32×32.

tile

Nú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

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    Wire3D_SetCamera(8,0,0,0,0,0);
    result[1]=Wire3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=Wire3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    Wire3D_SetCamera(0,0,0,0,0,0);
    Wire3D_BeginFrame();
    Wire3D_DrawLine2D(8,8,56,8);
    Wire3D_DrawLine2D(56,8,56,40);
    Wire3D_DrawLine2D(56,40,8,40);
    Wire3D_DrawLine2D(8,40,8,8);
    Wire3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    Wire3D_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    Wire3D_PutBgTile(18,1,157);
    Wire3D_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

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.

Wire3D_PutBgTile: DMG — 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.
DMG — 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.
Wire3D_PutBgTile: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_raster.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d.h:51

Notas de la declaración (original)
WIRE3D_DMG_HEIGHT = 96.
Queue a tile write to the 32x32 map at 0x9800 for EndFrame. Invalid map
coordinates and submissions beyond 48 pending writes are silently ignored.
This queue is separate from the general vram library queue.

kitaqgb/lib/wire3d_dmg.c:582

c
void Wire3DDMG_PutBgTile(w3ddmg_u8 x, w3ddmg_u8 y, w3ddmg_u8 tile)
{
    if (x >= 32) return;
    if (y >= 32) return;
    if (w3ddmg_bgq_count >= WIRE3D_DMG_BG_QUEUE_LIMIT) return;
    w3ddmg_bgq_x[(__safe_index w3ddmg_u8)w3ddmg_bgq_count] = x;
    w3ddmg_bgq_y[(__safe_index w3ddmg_u8)w3ddmg_bgq_count] = y;
    w3ddmg_bgq_tile[(__safe_index w3ddmg_u8)w3ddmg_bgq_count] = tile;
    w3ddmg_bgq_count = (w3ddmg_u8)(w3ddmg_bgq_count + 1);
}
Wire3D_SelectEdgeMask

Selecciona una máscara precalculada de visibilidad de aristas según la guiñada del objeto.

Sintaxis

c
w3ddmg_u16 Wire3D_SelectEdgeMask(const Wire3DDMG_Model* model, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz);

Parámetros

model

Modelo que contiene los arrays de vértices, aristas y caras y sus cantidades; las tablas deben permanecer legibles durante la llamada.

rx

Rotación alrededor de X; dieciséis pasos forman una vuelta completa.

ry

Rotación alrededor de Y; dieciséis pasos forman una vuelta completa.

rz

Rotació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

c
#pragma bank 0
// Compare direct model scaling with an object-array scene.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3D_Vec3 vertices[8]={{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}};
__prg_rom Wire3D_Edge edges[12]={{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}};
Wire3D_Model cube;
Wire3D_Object objects[2];
u16 masks[2];
void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;

    cube.vertices=vertices;cube.edges=edges;cube.faces=0;cube.edge_faces=0;
    cube.vertex_count=8;cube.edge_count=12;cube.face_count=0;cube.flags=0;
    cube.edge_masks=0; cube.edge_mask_count=0;
    Wire3D_BeginFrame();
    // Upper pair: direct model calls at unity and half scale.
    Wire3D_DrawModel(&cube,-32,32,96,0,0,0);
    Wire3D_DrawModelScaled(&cube,32,32,96,0,0,0,128);
    // Lower pair: the caller owns both object records and the model tables.
    for(i=0;i<2;i++) {
        objects[i].model=&cube;objects[i].x=-32+(s16)i*64;
        objects[i].y=-32;objects[i].z=96;
        objects[i].rx=0;objects[i].ry=0;objects[i].rz=0;
        objects[i].scale_q8=256-(s16)i*128;objects[i].visible=1;
    }
    Wire3D_DrawScene(objects,2);
    // Numeric checks cover the operation supplied by this viewport profile.
    masks[0]=3;masks[1]=12;cube.edge_masks=masks; cube.edge_mask_count=2;
    result[1]=Wire3D_SelectEdgeMask(&cube,0,0,0);
    result[2]=Wire3D_SelectEdgeMask(&cube,0,8,0);
    Wire3D_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

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.

Wire3D_SelectEdgeMask: DMG — 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.
DMG — 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.
Wire3D_SelectEdgeMask: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_models.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d.h:52

Notas de la declaración (original)
WIRE3D_DMG_HEIGHT = 96.
Select a precomputed mask from the low four bits of object yaw; pitch,
roll and camera orientation are ignored. Use 16, 8, 4 or 2 bins; other positive
counts select entry zero (counts >=16 use the first 16). Missing data returns
0xFFFF. Keep the mask table readable through the current data-pointer mapping.

kitaqgb/lib/wire3d_dmg.c:1109

c
w3ddmg_u16 Wire3DDMG_SelectEdgeMask(const Wire3DDMG_Model* model, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz)
{
    w3ddmg_u8 count;
    w3ddmg_u8 bin;

    if (model == 0) return 0xFFFF;
    if (model->edge_masks == 0) return 0xFFFF;
    count = model->edge_mask_count;
    if (count == 0) return 0xFFFF;

    (void)rx;
    (void)rz;

    bin = (w3ddmg_u8)(((w3ddmg_u8)ry) & 15);
    if (count >= 16) return model->edge_masks[(__safe_index w3ddmg_u8)bin];
    if (count == 8) bin = (w3ddmg_u8)(bin >> 1);
    else if (count == 4) bin = (w3ddmg_u8)(bin >> 2);
    else if (count == 2) bin = (w3ddmg_u8)(bin >> 3);
    else bin = 0;

    if (bin >= count) bin = (w3ddmg_u8)(count - 1);
    return model->edge_masks[(__safe_index w3ddmg_u8)bin];
}
Wire3D_SetCamera

Guarda la posición y la orientación de la cámara para las proyecciones posteriores.

Sintaxis

c
void Wire3D_SetCamera(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 pitch, w3ddmg_i8 yaw, w3ddmg_i8 roll);

Parámetros

x

Componente X de la cámara en coordenadas del mundo.

y

Componente Y de la cámara en coordenadas del mundo.

z

Componente Z de la cámara en coordenadas del mundo.

pitch

Rotación alrededor de X; dieciséis pasos forman una vuelta completa.

yaw

Rotación alrededor de Y; dieciséis pasos forman una vuelta completa.

roll

Rotació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

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    Wire3D_SetCamera(8,0,0,0,0,0);
    result[1]=Wire3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=Wire3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    Wire3D_SetCamera(0,0,0,0,0,0);
    Wire3D_BeginFrame();
    Wire3D_DrawLine2D(8,8,56,8);
    Wire3D_DrawLine2D(56,8,56,40);
    Wire3D_DrawLine2D(56,40,8,40);
    Wire3D_DrawLine2D(8,40,8,8);
    Wire3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    Wire3D_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    Wire3D_PutBgTile(18,1,157);
    Wire3D_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

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.

Wire3D_SetCamera: DMG — 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.
DMG — 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.
Wire3D_SetCamera: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_raster.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d.h:53

Notas de la declaración (original)
WIRE3D_DMG_HEIGHT = 96.
Store camera position and angles for later draws; a full turn is 16 angle
steps. No existing drawing is reprojected and no input range validation occurs.

kitaqgb/lib/wire3d_dmg.c:2659

c
void Wire3DDMG_SetCamera(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 pitch, w3ddmg_i8 yaw, w3ddmg_i8 roll)



{
    w3ddmg_cam_x = x;
    w3ddmg_cam_y = y;
    w3ddmg_cam_z = z;
    w3ddmg_cam_pitch = pitch;
    w3ddmg_cam_yaw = yaw;
    w3ddmg_cam_roll = roll;
}
Wire3D_SetPalette

Escribe la correspondencia de cuatro tonos en el registro de paleta del fondo monocromo BGP.

Sintaxis

c
void Wire3D_SetPalette(w3ddmg_u8 bgp);

Parámetros

bgp

Valor 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

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3D_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3D_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    Wire3D_SetCamera(8,0,0,0,0,0);
    result[1]=Wire3D_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=Wire3D_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    Wire3D_SetCamera(0,0,0,0,0,0);
    Wire3D_BeginFrame();
    Wire3D_DrawLine2D(8,8,56,8);
    Wire3D_DrawLine2D(56,8,56,40);
    Wire3D_DrawLine2D(56,40,8,40);
    Wire3D_DrawLine2D(8,40,8,8);
    Wire3D_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    Wire3D_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    Wire3D_PutBgTile(18,1,157);
    Wire3D_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

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.

Wire3D_SetPalette: DMG — 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.
DMG — 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.
Wire3D_SetPalette: CGB — 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.
CGB — 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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_wire3d_raster.c .\kitaqgb\lib\wire3d.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_wire3d_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d.h:54

Notas de la declaración (original)
WIRE3D_DMG_HEIGHT = 96.
Write the raw DMG BGP palette encoding immediately; no frame synchronization occurs.

kitaqgb/lib/wire3d_dmg.c:597

c
void Wire3DDMG_SetPalette(w3ddmg_u8 bgp)
{
    w3ddmg_reg_bgp = bgp;
}

wire3d_cgb.h — 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

c
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

c
#pragma bank 0
// CGB raster paths: a red frame, blue diagonal, green marker and clipped line.
// Build this source together with lib/wire3d_cgb.c in an MBC5 256 KB CGB ROM.
#include "wire3d_cgb.h"
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4D) u8 sample_key1;
__location(0xC110) u16 result[8];
__prg_rom u8 lower_lines[8]={80,56,112,56,112,56,112,80};

void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DCGB_EnableDoubleSpeed();
    Wire3DCGB_Init(); // Already at double speed: its internal request is a no-op.
    result[2]=(u8)(sample_key1&128);
    // Palette writes are performed with the LCD off, after entering VBlank.
    while(sample_ly>=144) {} while(sample_ly<144) {}
    sample_lcdc=0;
    Wire3DCGB_SetPaletteRGB15(WIRE3DCGB_RGB15(0,0,0),WIRE3DCGB_RGB15(31,0,0),WIRE3DCGB_RGB15(0,0,31),WIRE3DCGB_RGB15(0,31,0));
    sample_lcdc=0x81;
    Wire3DCGB_SetScreenOffset(0,0);
    Wire3DCGB_SetCamera(0,0,0,0,0,0);
    Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawLine2D(8,8,56,8);
    Wire3DCGB_DrawLine2D(56,8,56,40);
    Wire3DCGB_DrawLine2D(56,40,8,40);
    Wire3DCGB_DrawLine2D(8,40,8,8);
    Wire3DCGB_DrawLine2DColor(8,40,56,8,2);
    result[0]=Wire3DCGB_GetLineColor(); // Temporary blue restores red.
    Wire3DCGB_SetLineColor(3);
    Wire3DCGB_DrawPoint2D(64,48);
    Wire3DCGB_DrawLineClipped2D(-10,72,140,72,3);
    Wire3DCGB_DrawLineList2DColor(lower_lines,2,2);
    result[1]=Wire3DCGB_GetLineColor(); // The blue line list restores green.
    Wire3DCGB_PutBgTile(18,1,0x80); // Queue the supplied zero glyph outside the viewport.
    Wire3DCGB_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_raster.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:122

kitaqgb/lib/wire3d_cgb.c:8154

c
void Wire3DCGB_BeginFrame()
{
    if (w3dcgb_full_mode != 0)
    {
        w3dcgb_full_begin_asm();
        return;
    }
    w3dcgb_full_frame_transfer = 1;
    w3dcgb_clear_stage_asm();
    w3dcgb_clear_occlusion_mask_asm();
    w3dcgb_occ_min_x = (w3dcgb_u8)(WIRE3DCGB_SCREEN_W - 1);
    w3dcgb_occ_min_y = (w3dcgb_u8)(WIRE3DCGB_SCREEN_H - 1);
    w3dcgb_occ_max_x = 0;
    w3dcgb_occ_max_y = 0;
    w3dcgb_occlusion_active = 0;
}
Wire3DCGB_BeginFrameFast

Inicia un fotograma limpio e invalida los rangos parciales anteriores para cubrir toda la ventana gráfica.

Sintaxis

c
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

c
#pragma bank 0
// Reuse both VRAM banks and remove old geometry while presenting sparse frames.
#include "wire_cgb_example.h"
void main() {
    wire_results_clear(); Wire3DCGB_Init();
    Wire3DCGB_ClearFrameTiles();
    Wire3DCGB_EnableAtomicMaps(); wire_colors();
    // First frame: red on the left. Fast begin invalidates both bank histories.
    Wire3DCGB_BeginFrameFast(); wire_frame(8,8,32,32,1);
    Wire3DCGB_EndFrameFast();
    // Second frame: blue in the middle, with the old red frame removed.
    Wire3DCGB_BeginFrameSparse(); wire_frame(40,40,64,64,2);
    Wire3DCGB_EndFrameSparse();
    // Third frame: explicitly clearing a stage discards its first green point.
    Wire3DCGB_BeginFrameSparse();
    Wire3DCGB_SetLineColor(3); Wire3DCGB_DrawPoint2D(4,4);
    Wire3DCGB_ClearSparseStageFast();
    // The final image contains only this green frame on the right.
    wire_frame(80,8,112,32,3);
    Wire3DCGB_MarkDirtyRect2D(80,8,112,32);
    Wire3DCGB_InvalidateFrameHistory();
    Wire3DCGB_EndFrameSparseNow();
    result[0]=Wire3DCGB_GetLineColor();
    result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_sparse.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_sparse.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:123

kitaqgb/lib/wire3d_cgb.c:8175

c
void Wire3DCGB_BeginFrameFast()
{
    w3dcgb_older_dirty_min_tile = 0;
    w3dcgb_older_dirty_max_tile = (w3dcgb_u8)(WIRE3DCGB_TILE_COUNT - 1);
    w3dcgb_prev_dirty_min_tile = 0;
    w3dcgb_prev_dirty_max_tile = (w3dcgb_u8)(WIRE3DCGB_TILE_COUNT - 1);
    if (w3dcgb_full_mode != 0)
    {
        w3dcgb_full_begin_asm();
        return;
    }
    w3dcgb_full_frame_transfer = 1;
    w3dcgb_clear_stage_asm();
    w3dcgb_clear_occlusion_mask_asm();
    w3dcgb_occ_min_x = (w3dcgb_u8)(WIRE3DCGB_SCREEN_W - 1);
    w3dcgb_occ_min_y = (w3dcgb_u8)(WIRE3DCGB_SCREEN_H - 1);
    w3dcgb_occ_max_x = 0;
    w3dcgb_occ_max_y = 0;
    w3dcgb_occlusion_active = 0;
}
Wire3DCGB_BeginFrameSparse

Inicia un fotograma para transferir rangos parciales.

Sintaxis

c
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

c
#pragma bank 0
// Reuse both VRAM banks and remove old geometry while presenting sparse frames.
#include "wire_cgb_example.h"
void main() {
    wire_results_clear(); Wire3DCGB_Init();
    Wire3DCGB_ClearFrameTiles();
    Wire3DCGB_EnableAtomicMaps(); wire_colors();
    // First frame: red on the left. Fast begin invalidates both bank histories.
    Wire3DCGB_BeginFrameFast(); wire_frame(8,8,32,32,1);
    Wire3DCGB_EndFrameFast();
    // Second frame: blue in the middle, with the old red frame removed.
    Wire3DCGB_BeginFrameSparse(); wire_frame(40,40,64,64,2);
    Wire3DCGB_EndFrameSparse();
    // Third frame: explicitly clearing a stage discards its first green point.
    Wire3DCGB_BeginFrameSparse();
    Wire3DCGB_SetLineColor(3); Wire3DCGB_DrawPoint2D(4,4);
    Wire3DCGB_ClearSparseStageFast();
    // The final image contains only this green frame on the right.
    wire_frame(80,8,112,32,3);
    Wire3DCGB_MarkDirtyRect2D(80,8,112,32);
    Wire3DCGB_InvalidateFrameHistory();
    Wire3DCGB_EndFrameSparseNow();
    result[0]=Wire3DCGB_GetLineColor();
    result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_sparse.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_sparse.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:124

kitaqgb/lib/wire3d_cgb.c:8200

c
void Wire3DCGB_BeginFrameSparse()
{
    if (w3dcgb_full_mode != 0)
    {
        w3dcgb_full_begin_asm();
        return;
    }
    w3dcgb_full_frame_transfer = 0;
    w3dcgb_dirty_count = 0;
    /* One ASM pass is faster than repeated range-growth clears and guarantees
       that newly exposed dirty tiles can never copy stale stage pixels. */
    w3dcgb_clear_stage_asm();
#ifndef WIRE3DCGB_PAINTER_ONLY
    /* A Z-sorted painter erases silhouettes directly in the stage and never
       reads the separate front-to-back coverage mask. */
    w3dcgb_clear_occlusion_mask_asm();
#endif
    w3dcgb_occ_min_x = (w3dcgb_u8)(WIRE3DCGB_SCREEN_W - 1);
    w3dcgb_occ_min_y = (w3dcgb_u8)(WIRE3DCGB_SCREEN_H - 1);
    w3dcgb_occ_max_x = 0;
    w3dcgb_occ_max_y = 0;
    w3dcgb_occlusion_active = 0;
}
Wire3DCGB_ClearFrameTiles

Borra los tiles del fotograma visible de 128×96 y el área de preparación.

Sintaxis

c
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

c
#pragma bank 0
// Reuse both VRAM banks and remove old geometry while presenting sparse frames.
#include "wire_cgb_example.h"
void main() {
    wire_results_clear(); Wire3DCGB_Init();
    Wire3DCGB_ClearFrameTiles();
    Wire3DCGB_EnableAtomicMaps(); wire_colors();
    // First frame: red on the left. Fast begin invalidates both bank histories.
    Wire3DCGB_BeginFrameFast(); wire_frame(8,8,32,32,1);
    Wire3DCGB_EndFrameFast();
    // Second frame: blue in the middle, with the old red frame removed.
    Wire3DCGB_BeginFrameSparse(); wire_frame(40,40,64,64,2);
    Wire3DCGB_EndFrameSparse();
    // Third frame: explicitly clearing a stage discards its first green point.
    Wire3DCGB_BeginFrameSparse();
    Wire3DCGB_SetLineColor(3); Wire3DCGB_DrawPoint2D(4,4);
    Wire3DCGB_ClearSparseStageFast();
    // The final image contains only this green frame on the right.
    wire_frame(80,8,112,32,3);
    Wire3DCGB_MarkDirtyRect2D(80,8,112,32);
    Wire3DCGB_InvalidateFrameHistory();
    Wire3DCGB_EndFrameSparseNow();
    result[0]=Wire3DCGB_GetLineColor();
    result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_sparse.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_sparse.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:121

kitaqgb/lib/wire3d_cgb.c:8240

c
void Wire3DCGB_ClearFrameTiles()
{
    w3dcgb_u8 i;

    w3dcgb_wait_vblank_start();
    w3dcgb_reg_lcdc = 0;
    w3dcgb_clear_stage_asm();
    w3dcgb_clear_frame_tiles_vram_asm();
    w3dcgb_fill_attr_map_asm();
    w3dcgb_reg_lcdc = 0x81;

    i = 0;
    while (i < W3DCGB_DIRTY_TILE_LIMIT)
    {
        w3dcgb_dirty_flags[(__safe_index w3dcgb_u8)i] = 0;
        w3dcgb_prev_dirty_flags[(__safe_index w3dcgb_u8)i] = 0;
        i = (w3dcgb_u8)(i + 1);
    }
    w3dcgb_dirty_count = 0;
    w3dcgb_prev_dirty_count = 0;
}
Wire3DCGB_ClearOcclusionMask

Borra el mapa de bits de oclusión o el historial de tramos de pantalla completa.

Sintaxis

c
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

c
#pragma bank 0
// Red/blue scanlines stop inside masks; green outlines identify the triangle.
#include "wire_cgb_example.h"
__prg_rom u8 silhouette[5]={0x73,0x74,0xFF,0x75,0x73};
void main() {
    u8 y;
    wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    // Clearing this first test mask must leave the upper-left scanline intact.
    Wire3DCGB_MarkTriangle2D(8,8,16,8,8,16);
    Wire3DCGB_ClearOcclusionMask();
    Wire3DCGB_MarkTriangle2D(32,16,64,16,32,48);
    Wire3DCGB_MarkPackedSilhouette2D(silhouette,5,-2,104,32);
    Wire3DCGB_SetOcclusionActive(1);
    for(y=8;y<=56;y=y+4) Wire3DCGB_DrawLine2DColor(8,y,88,y,1);
    for(y=28;y<=36;y++) Wire3DCGB_DrawLine2DColor(92,y,120,y,2);
    Wire3DCGB_SetOcclusionActive(0);
    Wire3DCGB_DrawLine2DColor(32,16,64,16,3);
    Wire3DCGB_DrawLine2DColor(64,16,32,48,3);
    Wire3DCGB_DrawLine2DColor(32,48,32,16,3);
    Wire3DCGB_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_mask.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_mask.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:148

kitaqgb/lib/wire3d_cgb.c:1962

c
void Wire3DCGB_ClearOcclusionMask()
{
    if (w3dcgb_full_mode != 0) w3dcgb_full_clear_spans_asm();
    else w3dcgb_clear_occlusion_mask();
}
Wire3DCGB_ClearSparseStageFast

Borra toda el área de preparación y marca para transferencia la ventana gráfica completa de 128×96.

Sintaxis

c
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

c
#pragma bank 0
// Reuse both VRAM banks and remove old geometry while presenting sparse frames.
#include "wire_cgb_example.h"
void main() {
    wire_results_clear(); Wire3DCGB_Init();
    Wire3DCGB_ClearFrameTiles();
    Wire3DCGB_EnableAtomicMaps(); wire_colors();
    // First frame: red on the left. Fast begin invalidates both bank histories.
    Wire3DCGB_BeginFrameFast(); wire_frame(8,8,32,32,1);
    Wire3DCGB_EndFrameFast();
    // Second frame: blue in the middle, with the old red frame removed.
    Wire3DCGB_BeginFrameSparse(); wire_frame(40,40,64,64,2);
    Wire3DCGB_EndFrameSparse();
    // Third frame: explicitly clearing a stage discards its first green point.
    Wire3DCGB_BeginFrameSparse();
    Wire3DCGB_SetLineColor(3); Wire3DCGB_DrawPoint2D(4,4);
    Wire3DCGB_ClearSparseStageFast();
    // The final image contains only this green frame on the right.
    wire_frame(80,8,112,32,3);
    Wire3DCGB_MarkDirtyRect2D(80,8,112,32);
    Wire3DCGB_InvalidateFrameHistory();
    Wire3DCGB_EndFrameSparseNow();
    result[0]=Wire3DCGB_GetLineColor();
    result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_sparse.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_sparse.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:125

kitaqgb/lib/wire3d_cgb.c:8227

c
void Wire3DCGB_ClearSparseStageFast()
{
    w3dcgb_clear_stage_asm();
    w3dcgb_mark_dirty_rect(0, 0,
                           (w3dcgb_u8)(WIRE3DCGB_SCREEN_W - 1),
                           (w3dcgb_u8)(WIRE3DCGB_SCREEN_H - 1));
}
Wire3DCGB_DrawEdgeList2D

Dibuja hasta 64 aristas a partir de desplazamientos de vértices preproyectados de tipo byte con signo.

Sintaxis

c
void Wire3DCGB_DrawEdgeList2D(const Wire3DCGB_Edge* edges, w3dcgb_u8 edge_count, const w3dcgb_i8* vertex_x, const w3dcgb_i8* vertex_y, w3dcgb_u8 x, w3dcgb_u8 y, w3dcgb_u8 color);

Parámetros

edges

Índices de los vértices de cada arista, en el formato declarado de estructura o de pares de bytes.

edge_count

Cantidad de aristas.

vertex_x

Array de desplazamientos X de los vértices preproyectados.

vertex_y

Array de desplazamientos Y de los vértices preproyectados.

x

Coordenada X del centro en píxeles de la ventana gráfica.

y

Coordenada 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

c
#pragma bank 0
// Preprojected edge arrays, a clipped square, a tiny marker and a projectile.
#include "wire_cgb_example.h"
__prg_rom Wire3DCGB_Edge edges[4]={{0,1},{1,2},{2,3},{3,0}};
__prg_rom s8 vx8[4]={-8,8,8,-8};
__prg_rom s8 vy8[4]={-8,-8,8,8};
__prg_rom s16 vx16[4]={-12,12,12,-12};
__prg_rom s16 vy16[4]={-8,-8,8,8};
__prg_rom u8 mask[1]={5};
Wire3DCGB_Model shape;
void main() {
    wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    shape.vertices=0;shape.edges=edges;shape.faces=0;shape.edge_faces=0;
    shape.vertex_count=4;shape.edge_count=4;shape.face_count=0;shape.flags=0;
    Wire3DCGB_SetLineColor(2);
    Wire3DCGB_DrawMaskedModel2D(&shape,vx8,vy8,mask,24,24,1);
    Wire3DCGB_DrawEdgeList2D(edges,4,vx8,vy8,64,24,2);
    Wire3DCGB_DrawEdgeListClipped2D(edges,4,vx16,vy16,4,4,64,3);
    Wire3DCGB_DrawTinyModel2D(104,24,16,3);
    result[0]=Wire3DCGB_ProjectAxis48(48,96);
    result[1]=Wire3DCGB_ProjectAxis48(-48,96);
    Wire3DCGB_DrawFastProjectile(96,64,64,0,1);
    result[2]=Wire3DCGB_GetLineColor();
    Wire3DCGB_EndFrame();result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_lists.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_lists.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:183

kitaqgb/lib/wire3d_cgb.c:8524

c
void Wire3DCGB_DrawEdgeList2D(const Wire3DCGB_Edge* edges, w3dcgb_u8 edge_count,
                             const w3dcgb_i8* vertex_x, const w3dcgb_i8* vertex_y,
                             w3dcgb_u8 x, w3dcgb_u8 y, w3dcgb_u8 color)
{
    w3dcgb_u8 i;
    w3dcgb_u8 a;
    w3dcgb_u8 b;
    w3dcgb_u8 old_color;

    if (edges == 0) return;
    if (vertex_x == 0) return;
    if (vertex_y == 0) return;
    if (edge_count > WIRE3DCGB_MODEL_EDGE_LIMIT) edge_count = WIRE3DCGB_MODEL_EDGE_LIMIT;

    old_color = w3dcgb_line_color;
    w3dcgb_line_color = (w3dcgb_u8)(color & 3);
    if (w3dcgb_full_mode == 0)
    {
        w3dcgb_edge_list_ptr = edges;
        w3dcgb_edge_x_ptr = vertex_x;
        w3dcgb_edge_y_ptr = vertex_y;
        w3dcgb_edge_remaining = edge_count;
        w3dcgb_edge_center_x = x;
        w3dcgb_edge_center_y = y;
        w3dcgb_edge_list_asm();
        w3dcgb_line_color = old_color;
        return;
    }
    i = 0;
    while (i < edge_count)
    {
        a = edges[(__safe_index w3dcgb_u8)i].a;
        b = edges[(__safe_index w3dcgb_u8)i].b;
        w3dcgb_line_x0 = (w3dcgb_u8)((w3dcgb_i16)x + (w3dcgb_i16)vertex_x[(__safe_index w3dcgb_u8)a]);
        w3dcgb_line_y0 = (w3dcgb_u8)((w3dcgb_i16)y + (w3dcgb_i16)vertex_y[(__safe_index w3dcgb_u8)a]);
        w3dcgb_line_x1 = (w3dcgb_u8)((w3dcgb_i16)x + (w3dcgb_i16)vertex_x[(__safe_index w3dcgb_u8)b]);
        w3dcgb_line_y1 = (w3dcgb_u8)((w3dcgb_i16)y + (w3dcgb_i16)vertex_y[(__safe_index w3dcgb_u8)b]);
        if (w3dcgb_full_mode != 0) w3dcgb_full_line_fast_asm();
        else w3dcgb_line_stage_asm();
        i = (w3dcgb_u8)(i + 1);
    }
    w3dcgb_line_color = old_color;
}
Wire3DCGB_DrawEdgeListClipped2D

Valida los vértices proyectados con signo y las aristas, y después recorta y dibuja la lista de aristas.

Sintaxis

c
void Wire3DCGB_DrawEdgeListClipped2D(const Wire3DCGB_Edge* edges, w3dcgb_u8 edge_count, const w3dcgb_i16* vx, const w3dcgb_i16* vy, w3dcgb_u8 vertex_count, w3dcgb_i16 cx, w3dcgb_i16 cy, w3dcgb_u8 color);

Parámetros

edges

Índices de los vértices de cada arista, en el formato declarado de estructura o de pares de bytes.

edge_count

Cantidad de aristas.

vx

Array de desplazamientos X de 16 bits con signo antes del recorte.

vy

Array de desplazamientos Y de 16 bits con signo antes del recorte.

vertex_count

Cantidad de entradas del array de vértices.

cx

Coordenada X del centro en píxeles de la ventana gráfica.

cy

Coordenada 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

c
#pragma bank 0
// Preprojected edge arrays, a clipped square, a tiny marker and a projectile.
#include "wire_cgb_example.h"
__prg_rom Wire3DCGB_Edge edges[4]={{0,1},{1,2},{2,3},{3,0}};
__prg_rom s8 vx8[4]={-8,8,8,-8};
__prg_rom s8 vy8[4]={-8,-8,8,8};
__prg_rom s16 vx16[4]={-12,12,12,-12};
__prg_rom s16 vy16[4]={-8,-8,8,8};
__prg_rom u8 mask[1]={5};
Wire3DCGB_Model shape;
void main() {
    wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    shape.vertices=0;shape.edges=edges;shape.faces=0;shape.edge_faces=0;
    shape.vertex_count=4;shape.edge_count=4;shape.face_count=0;shape.flags=0;
    Wire3DCGB_SetLineColor(2);
    Wire3DCGB_DrawMaskedModel2D(&shape,vx8,vy8,mask,24,24,1);
    Wire3DCGB_DrawEdgeList2D(edges,4,vx8,vy8,64,24,2);
    Wire3DCGB_DrawEdgeListClipped2D(edges,4,vx16,vy16,4,4,64,3);
    Wire3DCGB_DrawTinyModel2D(104,24,16,3);
    result[0]=Wire3DCGB_ProjectAxis48(48,96);
    result[1]=Wire3DCGB_ProjectAxis48(-48,96);
    Wire3DCGB_DrawFastProjectile(96,64,64,0,1);
    result[2]=Wire3DCGB_GetLineColor();
    Wire3DCGB_EndFrame();result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_lists.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_lists.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:138

kitaqgb/lib/wire3d_cgb.c:9806

c
void Wire3DCGB_DrawEdgeListClipped2D(const Wire3DCGB_Edge* edges, w3dcgb_u8 edge_count,
    const w3dcgb_i16* vx, const w3dcgb_i16* vy, w3dcgb_u8 vertex_count,
    w3dcgb_i16 cx, w3dcgb_i16 cy, w3dcgb_u8 color)
{
    w3dcgb_u8 i;
    w3dcgb_u8 a;
    w3dcgb_u8 b;
    w3dcgb_u8 inside;
    w3dcgb_i16 x;
    w3dcgb_i16 y;
    w3dcgb_i16 min_x;
    w3dcgb_i16 min_y;
    w3dcgb_i16 max_x;
    w3dcgb_i16 max_y;
    if ((edges == 0) || (vx == 0) || (vy == 0)) return;
    if ((cx < -2047) || (cx > 2047) || (cy < -2047) || (cy > 2047)) return;
    if ((vertex_count == 0) || (vertex_count > WIRE3DCGB_MODEL_VERTEX_LIMIT) ||
        (edge_count > WIRE3DCGB_MODEL_EDGE_LIMIT)) return;
    i = 0;
    while (i < edge_count)
    {
        if ((edges[(__safe_index w3dcgb_u8)i].a >= vertex_count) ||
            (edges[(__safe_index w3dcgb_u8)i].b >= vertex_count)) return;
        i = (w3dcgb_u8)(i + 1);
    }
    min_x = 32767;
    min_y = 32767;
    max_x = -32767;
    max_y = -32767;
    inside = 1;
    i = 0;
    while (i < vertex_count)
    {
        if ((vx[(__safe_index w3dcgb_u8)i] < -2047) ||
            (vx[(__safe_index w3dcgb_u8)i] > 2047) ||
            (vy[(__safe_index w3dcgb_u8)i] < -2047) ||
            (vy[(__safe_index w3dcgb_u8)i] > 2047)) return;
        x = (w3dcgb_i16)(cx + vx[(__safe_index w3dcgb_u8)i]);
        y = (w3dcgb_i16)(cy + vy[(__safe_index w3dcgb_u8)i]);
        if (x < min_x) min_x = x;
        if (x > max_x) max_x = x;
        if (y < min_y) min_y = y;
        if (y > max_y) max_y = y;
        /* Reuse projected-vertex scratch; drawing is non-reentrant. */
        w3dcgb_screen_x[(__safe_index w3dcgb_u8)i] = (w3dcgb_u8)(x - 64);
        w3dcgb_screen_y[(__safe_index w3dcgb_u8)i] = (w3dcgb_u8)(y - 48);
        i = (w3dcgb_u8)(i + 1);
    }
    if ((w3dcgb_clip_outcode(min_x, min_y) | w3dcgb_clip_outcode(max_x, max_y)) != 0) inside = 0;
    if (inside != 0)
    {
        if (w3dcgb_full_mode == 0) w3dcgb_mark_dirty_rect((w3dcgb_u8)min_x,
            (w3dcgb_u8)min_y, (w3dcgb_u8)max_x, (w3dcgb_u8)max_y);
        Wire3DCGB_DrawEdgeList2D(edges, edge_count, (const w3dcgb_i8*)w3dcgb_screen_x,
            (const w3dcgb_i8*)w3dcgb_screen_y, 64, 48, color);
        return;
    }
    i = 0;
    while (i < edge_count)
    {
        a = edges[(__safe_index w3dcgb_u8)i].a;
        b = edges[(__safe_index w3dcgb_u8)i].b;
        Wire3DCGB_DrawLineClipped2D((w3dcgb_i16)(cx + vx[(__safe_index w3dcgb_u8)a]),
            (w3dcgb_i16)(cy + vy[(__safe_index w3dcgb_u8)a]),
            (w3dcgb_i16)(cx + vx[(__safe_index w3dcgb_u8)b]),
            (w3dcgb_i16)(cy + vy[(__safe_index w3dcgb_u8)b]), color);
        i = (w3dcgb_u8)(i + 1);
    }
}
Wire3DCGB_DrawFastCubeFrame

Sustituye el fotograma anterior de patrones de cubo y transfiere hasta tres patrones junto con los indicadores de estado.

Sintaxis

c
void Wire3DCGB_DrawFastCubeFrame(Wire3DCGB_FastCube* cubes, w3dcgb_u8 count, w3dcgb_u8 hidden_enabled, w3dcgb_u8 selected);

Parámetros

cubes

Array de posiciones, ángulos y colores para dibujar cubos de forma rápida.

count

Cantidad de entradas proporcionadas; consulta el límite de procesamiento de cada operación.

hidden_enabled

Cero 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

c
#pragma bank 0
// A complete cube-stamp frame removes the preceding stamp's old map cells.
#include "wire_cgb_example.h"
Wire3DCGB_FastCube cube[1];
void main() {
    u8 bank;
    wire_results_clear(); Wire3DCGB_Init(); wire_colors();
    cube[0].x=-24;cube[0].y=0;cube[0].z=96;
    cube[0].rx=0;cube[0].ry=0;cube[0].rz=0;cube[0].color=1;
    bank=sample_svbk;sample_svbk=2;
    Wire3DCGB_DrawFastCubeFrame(cube,1,1,0);
    cube[0].x=24;
    Wire3DCGB_DrawFastCubeFrame(cube,1,1,0);
    sample_svbk=bank;result[0]=cube[0].x;result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_stamp.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_stamp.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:158

kitaqgb/lib/wire3d_cgb.c:10800

c
void Wire3DCGB_DrawFastCubeFrame(Wire3DCGB_FastCube* cubes, w3dcgb_u8 count, w3dcgb_u8 hidden_enabled, w3dcgb_u8 selected)
{
    w3dcgb_u8 i;
    w3dcgb_u8 scene_count;
    w3dcgb_u8 a;
    w3dcgb_u8 b;
    w3dcgb_u8 c;
    w3dcgb_u8 x;

    if (cubes == 0) return;
    scene_count = count;
    if (scene_count > 3) scene_count = 3;

    w3dcgb_fast_map_prepare();

    i = 0;
    while (i < w3dcgb_fast_prev_count)
    {
        w3dcgb_fast_map_clear_rect(
            w3dcgb_fast_prev_x[(__safe_index w3dcgb_u8)i],
            w3dcgb_fast_prev_y[(__safe_index w3dcgb_u8)i],
            w3dcgb_fast_prev_w[(__safe_index w3dcgb_u8)i],
            w3dcgb_fast_prev_h[(__safe_index w3dcgb_u8)i]);
        i = (w3dcgb_u8)(i + 1);
    }
    w3dcgb_fast_map_clear_rect(0, 0, 4, 1);
    w3dcgb_fast_map_clear_rect(14, 0, 2, 1);

    if (scene_count == 0)
    {
        w3dcgb_fast_prev_count = 0;
        w3dcgb_wait_vblank_start();
        w3dcgb_fast_map_flush_gdma_asm();
        return;
    }

    a = 0;
    b = 1;
    c = 2;
    if (scene_count == 1)
    {
        w3dcgb_fast_map_draw_cube_one(&cubes[0], hidden_enabled, (w3dcgb_u8)(selected == 0), 0);
        w3dcgb_fast_prev_count = 1;
    }
    else if (scene_count == 2)
    {
        if (cubes[0].z < cubes[1].z)
        {
            w3dcgb_fast_map_draw_cube_one(&cubes[1], hidden_enabled, (w3dcgb_u8)(selected == 1), 1);
            w3dcgb_fast_map_draw_cube_one(&cubes[0], hidden_enabled, (w3dcgb_u8)(selected == 0), 0);
        }
        else
        {
            w3dcgb_fast_map_draw_cube_one(&cubes[0], hidden_enabled, (w3dcgb_u8)(selected == 0), 0);
            w3dcgb_fast_map_draw_cube_one(&cubes[1], hidden_enabled, (w3dcgb_u8)(selected == 1), 1);
        }
        w3dcgb_fast_prev_count = 2;
    }
    else
    {
        if (cubes[a].z < cubes[b].z)
        {
            w3dcgb_u8 t;
            t = a;
            a = b;
            b = t;
        }
        if (cubes[b].z < cubes[c].z)
        {
            w3dcgb_u8 t;
            t = b;
            b = c;
            c = t;
        }
        if (cubes[a].z < cubes[b].z)
        {
            w3dcgb_u8 t;
            t = a;
            a = b;
            b = t;
        }
        w3dcgb_fast_map_draw_cube_one(&cubes[a], hidden_enabled, (w3dcgb_u8)(selected == a), a);
        w3dcgb_fast_map_draw_cube_one(&cubes[b], hidden_enabled, (w3dcgb_u8)(selected == b), b);
        w3dcgb_fast_map_draw_cube_one(&cubes[c], hidden_enabled, (w3dcgb_u8)(selected == c), c);
        w3dcgb_fast_prev_count = 3;
    }

    x = (w3dcgb_u8)(selected & 3);
    w3dcgb_fast_map_or_cell((w3dcgb_i16)x, (w3dcgb_i16)0, WIRE3DCGB_COLOR_HIGH, 15);
    if (hidden_enabled != 0) w3dcgb_fast_map_or_cell((w3dcgb_i16)15, (w3dcgb_i16)0, WIRE3DCGB_COLOR_HIGH, 15);
    else w3dcgb_fast_map_or_cell((w3dcgb_i16)14, (w3dcgb_i16)0, WIRE3DCGB_COLOR_LOW, 15);

    w3dcgb_wait_vblank_start();
    w3dcgb_fast_map_flush_gdma_asm();
}
Wire3DCGB_DrawFastCubes

Dibuja hasta tres cubos como contornos 2D cuyo tamaño depende de la profundidad.

Sintaxis

c
void Wire3DCGB_DrawFastCubes(Wire3DCGB_FastCube* cubes, w3dcgb_u8 count, w3dcgb_u8 hidden_enabled, w3dcgb_u8 selected);

Parámetros

cubes

Array de posiciones, ángulos y colores para dibujar cubos de forma rápida.

count

Cantidad de entradas proporcionadas; consulta el límite de procesamiento de cada operación.

hidden_enabled

Cero 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

c
#pragma bank 0
// Fast cube approximations use screen offsets and depth size bands, not a camera.
#include "wire_cgb_example.h"
Wire3DCGB_FastCube cubes[2];
void main() {
    u8 i;
    wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    for(i=0;i<2;i++){cubes[i].rx=0;cubes[i].ry=0;cubes[i].rz=0;}
    cubes[0].x=-32;cubes[0].y=-8;cubes[0].z=90;cubes[0].color=1;
    cubes[1].x=32;cubes[1].y=8;cubes[1].z=160;cubes[1].color=2;
    Wire3DCGB_SetCamera(100,0,0,4,4,4); // FastCubes intentionally ignores this.
    Wire3DCGB_DrawFastCubes(cubes,2,1,0);
    Wire3DCGB_DrawFastStatus(1,0);
    result[0]=Wire3DCGB_GetLineColor();
    result[1]=cubes[0].z;result[2]=cubes[1].z;
    Wire3DCGB_EndFrame();result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_cubes.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_cubes.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:156

kitaqgb/lib/wire3d_cgb.c:8765

c
void Wire3DCGB_DrawFastCubes(Wire3DCGB_FastCube* cubes, w3dcgb_u8 count, w3dcgb_u8 hidden_enabled, w3dcgb_u8 selected)
{
    w3dcgb_u8 scene_count;
    w3dcgb_u8 a;
    w3dcgb_u8 b;
    w3dcgb_u8 c;
    w3dcgb_u8 x;

    if (cubes == 0) return;
    scene_count = count;
    if (scene_count == 0) return;
    if (scene_count > 3) scene_count = 3;

    a = 0;
    b = 1;
    c = 2;
    if (scene_count == 1)
    {
        w3dcgb_draw_fast_cube_one(&cubes[0], hidden_enabled, (w3dcgb_u8)(selected == 0));
        return;
    }

    if (scene_count == 2)
    {
        if (cubes[0].z < cubes[1].z)
        {
            w3dcgb_draw_fast_cube_one(&cubes[1], hidden_enabled, (w3dcgb_u8)(selected == 1));
            w3dcgb_draw_fast_cube_one(&cubes[0], hidden_enabled, (w3dcgb_u8)(selected == 0));
        }
        else
        {
            w3dcgb_draw_fast_cube_one(&cubes[0], hidden_enabled, (w3dcgb_u8)(selected == 0));
            w3dcgb_draw_fast_cube_one(&cubes[1], hidden_enabled, (w3dcgb_u8)(selected == 1));
        }
        return;
    }

    if (cubes[a].z < cubes[b].z)
    {
        w3dcgb_u8 t;
        t = a;
        a = b;
        b = t;
    }
    if (cubes[b].z < cubes[c].z)
    {
        w3dcgb_u8 t;
        t = b;
        b = c;
        c = t;
    }
    if (cubes[a].z < cubes[b].z)
    {
        w3dcgb_u8 t;
        t = a;
        a = b;
        b = t;
    }

    w3dcgb_draw_fast_cube_one(&cubes[a], hidden_enabled, (w3dcgb_u8)(selected == a));
    w3dcgb_draw_fast_cube_one(&cubes[b], hidden_enabled, (w3dcgb_u8)(selected == b));
    w3dcgb_draw_fast_cube_one(&cubes[c], hidden_enabled, (w3dcgb_u8)(selected == c));
}
Wire3DCGB_DrawFastProjectile

Dibuja un proyectil de seis aristas en un centro ya proyectado, con tamaño y orientación elegidos por profundidad y fase.

Sintaxis

c
void Wire3DCGB_DrawFastProjectile(w3dcgb_u8 x, w3dcgb_u8 y, w3dcgb_i16 z, w3dcgb_u8 phase, w3dcgb_u8 color);

Parámetros

x

Coordenada X del centro en píxeles de la ventana gráfica.

y

Coordenada Y del centro en píxeles de la ventana gráfica.

z

Profundidad usada para elegir el tamaño o calcular la proyección.

phase

Fase 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

c
#pragma bank 0
// Preprojected edge arrays, a clipped square, a tiny marker and a projectile.
#include "wire_cgb_example.h"
__prg_rom Wire3DCGB_Edge edges[4]={{0,1},{1,2},{2,3},{3,0}};
__prg_rom s8 vx8[4]={-8,8,8,-8};
__prg_rom s8 vy8[4]={-8,-8,8,8};
__prg_rom s16 vx16[4]={-12,12,12,-12};
__prg_rom s16 vy16[4]={-8,-8,8,8};
__prg_rom u8 mask[1]={5};
Wire3DCGB_Model shape;
void main() {
    wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    shape.vertices=0;shape.edges=edges;shape.faces=0;shape.edge_faces=0;
    shape.vertex_count=4;shape.edge_count=4;shape.face_count=0;shape.flags=0;
    Wire3DCGB_SetLineColor(2);
    Wire3DCGB_DrawMaskedModel2D(&shape,vx8,vy8,mask,24,24,1);
    Wire3DCGB_DrawEdgeList2D(edges,4,vx8,vy8,64,24,2);
    Wire3DCGB_DrawEdgeListClipped2D(edges,4,vx16,vy16,4,4,64,3);
    Wire3DCGB_DrawTinyModel2D(104,24,16,3);
    result[0]=Wire3DCGB_ProjectAxis48(48,96);
    result[1]=Wire3DCGB_ProjectAxis48(-48,96);
    Wire3DCGB_DrawFastProjectile(96,64,64,0,1);
    result[2]=Wire3DCGB_GetLineColor();
    Wire3DCGB_EndFrame();result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_lists.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_lists.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:159

kitaqgb/lib/wire3d_cgb.c:8833

c
void Wire3DCGB_DrawFastProjectile(w3dcgb_u8 x, w3dcgb_u8 y, w3dcgb_i16 z,
                                  w3dcgb_u8 phase, w3dcgb_u8 color)
{
    w3dcgb_u8 radius;
    w3dcgb_u8 half;
    w3dcgb_u8 depth;
    w3dcgb_u8 ax;
    w3dcgb_u8 ay;
    w3dcgb_u8 bx;
    w3dcgb_u8 by;
    w3dcgb_u8 cx;
    w3dcgb_u8 cy;
    w3dcgb_u8 dx;
    w3dcgb_u8 dy;
    w3dcgb_u8 spin;

    if ((x < 10) || (x > 117) || (y < 10) || (y > 85)) return;
    radius = 3;
    depth = 1;
    if (z <= 160) { radius = 4; depth = 2; }
    if (z <= 112) { radius = 5; depth = 3; }
    if (z <= 64) { radius = 7; depth = 4; }
    half = (w3dcgb_u8)(radius >> 1);

    ax = x;
    ay = (w3dcgb_u8)(y - radius);
    bx = (w3dcgb_u8)(x - radius);
    by = (w3dcgb_u8)(y + half);
    cx = (w3dcgb_u8)(x + radius);
    cy = by;
    spin = (w3dcgb_u8)((phase >> 3) & 3);
    dx = (w3dcgb_u8)(x + depth);
    dy = (w3dcgb_u8)(y - depth);
    if (spin == 1) dy = (w3dcgb_u8)(y + depth);
    else if (spin == 2)
    {
        dx = (w3dcgb_u8)(x - depth);
        dy = (w3dcgb_u8)(y + depth);
    }
    else if (spin == 3) dx = (w3dcgb_u8)(x - depth);

    w3dcgb_mark_dirty_rect((w3dcgb_u8)(x - radius), (w3dcgb_u8)(y - radius),
                           (w3dcgb_u8)(x + radius), (w3dcgb_u8)(y + radius));
    w3dcgb_line_color = color;
    w3dcgb_draw_line_raw(ax, ay, bx, by);
    w3dcgb_draw_line_raw(bx, by, cx, cy);
    w3dcgb_draw_line_raw(cx, cy, ax, ay);
    w3dcgb_draw_line_raw(ax, ay, dx, dy);
    w3dcgb_draw_line_raw(bx, by, dx, dy);
    w3dcgb_draw_line_raw(cx, cy, dx, dy);
}
Wire3DCGB_DrawFastStatus

Dibuja pequeños indicadores de líneas para la selección de objetos y el modo de líneas ocultas.

Sintaxis

c
void Wire3DCGB_DrawFastStatus(w3dcgb_u8 hidden_enabled, w3dcgb_u8 selected);

Parámetros

hidden_enabled

Cero 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

c
#pragma bank 0
// Fast cube approximations use screen offsets and depth size bands, not a camera.
#include "wire_cgb_example.h"
Wire3DCGB_FastCube cubes[2];
void main() {
    u8 i;
    wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    for(i=0;i<2;i++){cubes[i].rx=0;cubes[i].ry=0;cubes[i].rz=0;}
    cubes[0].x=-32;cubes[0].y=-8;cubes[0].z=90;cubes[0].color=1;
    cubes[1].x=32;cubes[1].y=8;cubes[1].z=160;cubes[1].color=2;
    Wire3DCGB_SetCamera(100,0,0,4,4,4); // FastCubes intentionally ignores this.
    Wire3DCGB_DrawFastCubes(cubes,2,1,0);
    Wire3DCGB_DrawFastStatus(1,0);
    result[0]=Wire3DCGB_GetLineColor();
    result[1]=cubes[0].z;result[2]=cubes[1].z;
    Wire3DCGB_EndFrame();result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_cubes.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_cubes.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:157

kitaqgb/lib/wire3d_cgb.c:8888

c
void Wire3DCGB_DrawFastStatus(w3dcgb_u8 hidden_enabled, w3dcgb_u8 selected)
{
    w3dcgb_u8 x;

    w3dcgb_mark_dirty_rect(0, 0, 31, 7);
    w3dcgb_mark_dirty_rect(116, 0, 127, 7);

    x = (w3dcgb_u8)(4 + (selected * 8));
    w3dcgb_line_color = WIRE3DCGB_COLOR_HIGH;
    w3dcgb_draw_line_raw(x, 3, (w3dcgb_u8)(x + 5), 3);
    w3dcgb_draw_line_raw(x, 6, (w3dcgb_u8)(x + 5), 6);
    if (hidden_enabled != 0)
    {
        w3dcgb_draw_line_raw(118, 3, 124, 3);
        w3dcgb_draw_line_raw(118, 6, 124, 6);
    }
    else
    {
        w3dcgb_draw_line_raw(118, 3, 124, 6);
        w3dcgb_draw_line_raw(118, 6, 124, 3);
    }
}
Wire3DCGB_DrawLine2D

Dibuja una línea en coordenadas de pantalla, incluidos ambos extremos, con el renderizador activo.

Sintaxis

c
void Wire3DCGB_DrawLine2D(w3dcgb_u8 ax, w3dcgb_u8 ay, w3dcgb_u8 bx, w3dcgb_u8 by);

Parámetros

ax

Coordenada X del vértice A en píxeles de la ventana gráfica.

ay

Coordenada Y del vértice A en píxeles de la ventana gráfica.

bx

Coordenada X del vértice B en píxeles de la ventana gráfica.

by

Coordenada 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

c
#pragma bank 0
// CGB raster paths: a red frame, blue diagonal, green marker and clipped line.
// Build this source together with lib/wire3d_cgb.c in an MBC5 256 KB CGB ROM.
#include "wire3d_cgb.h"
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4D) u8 sample_key1;
__location(0xC110) u16 result[8];
__prg_rom u8 lower_lines[8]={80,56,112,56,112,56,112,80};

void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DCGB_EnableDoubleSpeed();
    Wire3DCGB_Init(); // Already at double speed: its internal request is a no-op.
    result[2]=(u8)(sample_key1&128);
    // Palette writes are performed with the LCD off, after entering VBlank.
    while(sample_ly>=144) {} while(sample_ly<144) {}
    sample_lcdc=0;
    Wire3DCGB_SetPaletteRGB15(WIRE3DCGB_RGB15(0,0,0),WIRE3DCGB_RGB15(31,0,0),WIRE3DCGB_RGB15(0,0,31),WIRE3DCGB_RGB15(0,31,0));
    sample_lcdc=0x81;
    Wire3DCGB_SetScreenOffset(0,0);
    Wire3DCGB_SetCamera(0,0,0,0,0,0);
    Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawLine2D(8,8,56,8);
    Wire3DCGB_DrawLine2D(56,8,56,40);
    Wire3DCGB_DrawLine2D(56,40,8,40);
    Wire3DCGB_DrawLine2D(8,40,8,8);
    Wire3DCGB_DrawLine2DColor(8,40,56,8,2);
    result[0]=Wire3DCGB_GetLineColor(); // Temporary blue restores red.
    Wire3DCGB_SetLineColor(3);
    Wire3DCGB_DrawPoint2D(64,48);
    Wire3DCGB_DrawLineClipped2D(-10,72,140,72,3);
    Wire3DCGB_DrawLineList2DColor(lower_lines,2,2);
    result[1]=Wire3DCGB_GetLineColor(); // The blue line list restores green.
    Wire3DCGB_PutBgTile(18,1,0x80); // Queue the supplied zero glyph outside the viewport.
    Wire3DCGB_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_raster.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:177

kitaqgb/lib/wire3d_cgb.c:8363

c
void Wire3DCGB_DrawLine2D(w3dcgb_u8 ax, w3dcgb_u8 ay, w3dcgb_u8 bx, w3dcgb_u8 by)
{
    w3dcgb_line_x0 = ax;
    w3dcgb_line_y0 = ay;
    w3dcgb_line_x1 = bx;
    w3dcgb_line_y1 = by;
    if (w3dcgb_full_mode != 0) w3dcgb_full_line_fast_asm();
    else w3dcgb_line_stage_asm();
}
Wire3DCGB_DrawLine2DColor

Dibuja una línea en coordenadas de pantalla con un color temporal, conservando el color seleccionado.

Sintaxis

c
void Wire3DCGB_DrawLine2DColor(w3dcgb_u8 ax, w3dcgb_u8 ay, w3dcgb_u8 bx, w3dcgb_u8 by, w3dcgb_u8 color);

Parámetros

ax

Coordenada X del vértice A en píxeles de la ventana gráfica.

ay

Coordenada Y del vértice A en píxeles de la ventana gráfica.

bx

Coordenada X del vértice B en píxeles de la ventana gráfica.

by

Coordenada 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

c
#pragma bank 0
// CGB raster paths: a red frame, blue diagonal, green marker and clipped line.
// Build this source together with lib/wire3d_cgb.c in an MBC5 256 KB CGB ROM.
#include "wire3d_cgb.h"
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4D) u8 sample_key1;
__location(0xC110) u16 result[8];
__prg_rom u8 lower_lines[8]={80,56,112,56,112,56,112,80};

void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DCGB_EnableDoubleSpeed();
    Wire3DCGB_Init(); // Already at double speed: its internal request is a no-op.
    result[2]=(u8)(sample_key1&128);
    // Palette writes are performed with the LCD off, after entering VBlank.
    while(sample_ly>=144) {} while(sample_ly<144) {}
    sample_lcdc=0;
    Wire3DCGB_SetPaletteRGB15(WIRE3DCGB_RGB15(0,0,0),WIRE3DCGB_RGB15(31,0,0),WIRE3DCGB_RGB15(0,0,31),WIRE3DCGB_RGB15(0,31,0));
    sample_lcdc=0x81;
    Wire3DCGB_SetScreenOffset(0,0);
    Wire3DCGB_SetCamera(0,0,0,0,0,0);
    Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawLine2D(8,8,56,8);
    Wire3DCGB_DrawLine2D(56,8,56,40);
    Wire3DCGB_DrawLine2D(56,40,8,40);
    Wire3DCGB_DrawLine2D(8,40,8,8);
    Wire3DCGB_DrawLine2DColor(8,40,56,8,2);
    result[0]=Wire3DCGB_GetLineColor(); // Temporary blue restores red.
    Wire3DCGB_SetLineColor(3);
    Wire3DCGB_DrawPoint2D(64,48);
    Wire3DCGB_DrawLineClipped2D(-10,72,140,72,3);
    Wire3DCGB_DrawLineList2DColor(lower_lines,2,2);
    result[1]=Wire3DCGB_GetLineColor(); // The blue line list restores green.
    Wire3DCGB_PutBgTile(18,1,0x80); // Queue the supplied zero glyph outside the viewport.
    Wire3DCGB_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_raster.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:178

kitaqgb/lib/wire3d_cgb.c:8376

c
void Wire3DCGB_DrawLine2DColor(w3dcgb_u8 ax, w3dcgb_u8 ay, w3dcgb_u8 bx, w3dcgb_u8 by, w3dcgb_u8 color)
{
    w3dcgb_u8 old_color;
    old_color = w3dcgb_line_color;
    Wire3DCGB_SetLineColor(color);
    Wire3DCGB_DrawLine2D(ax, ay, bx, by);
    w3dcgb_line_color = old_color;
}
Wire3DCGB_DrawLine3D

Proyecta los extremos del mundo mediante la cámara y dibuja una línea con el color actual.

Sintaxis

c
void Wire3DCGB_DrawLine3D(w3dcgb_i16 ax, w3dcgb_i16 ay, w3dcgb_i16 az, w3dcgb_i16 bx, w3dcgb_i16 by, w3dcgb_i16 bz);

Parámetros

ax

Componente X del punto inicial en coordenadas del mundo.

ay

Componente Y del punto inicial en coordenadas del mundo.

az

Componente Z del punto inicial en coordenadas del mundo.

bx

Componente X del punto final en coordenadas del mundo.

by

Componente Y del punto final en coordenadas del mundo.

bz

Componente 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

c
#pragma bank 0
// Four cubes compare unity/half scale and persistent/temporary line colors.
#include "wire_cgb_example.h"
__prg_rom Wire3DCGB_Vec3 vertices[8]={
    {-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},
    {-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}
};
__prg_rom Wire3DCGB_Edge edges[12]={
    {0,1},{1,2},{2,3},{3,0},{4,5},{5,6},
    {6,7},{7,4},{0,4},{1,5},{2,6},{3,7}
};
Wire3DCGB_Model cube;
u8 sx;
u8 sy;
void main() {
    wire_results_clear();
    cube.vertices=vertices; cube.edges=edges;
    cube.faces=0; cube.edge_faces=0;
    cube.vertex_count=8; cube.edge_count=12; cube.face_count=0; cube.flags=0;
    Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawModel(&cube,-32,32,96,0,0,0);
    Wire3DCGB_DrawModelScaled(&cube,32,32,96,0,0,0,128);
    Wire3DCGB_DrawModelColor(&cube,-32,-32,96,0,0,0,2);
    Wire3DCGB_DrawModelScaledColor(&cube,32,-32,96,0,0,0,128,3);
    result[0]=Wire3DCGB_GetLineColor();
    Wire3DCGB_DrawLine3D(0,56,96,0,-56,96);
    Wire3DCGB_DrawLine3DColor(-80,0,96,80,0,96,3);
    result[1]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
    result[2]=sx; result[3]=sy;
    // Camera setters affect future projection, leaving the staged cubes intact.
    Wire3DCGB_SetCamera(0,0,0,0,4,0);
    result[4]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
    result[5]=Wire3DCGB_ProjectPointNoRotation(0,0,96,&sx,&sy);
    result[6]=sx;
    Wire3DCGB_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_models.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:172

kitaqgb/lib/wire3d_cgb.c:8992

c
void Wire3DCGB_DrawLine3D(w3dcgb_i16 ax, w3dcgb_i16 ay, w3dcgb_i16 az, w3dcgb_i16 bx, w3dcgb_i16 by, w3dcgb_i16 bz)
{
    w3dcgb_u8 sx0;
    w3dcgb_u8 sy0;
    w3dcgb_u8 sx1;
    w3dcgb_u8 sy1;

    if (w3dcgb_project_world(ax, ay, az, &sx0, &sy0) == 0) return;
    if (w3dcgb_project_world(bx, by, bz, &sx1, &sy1) == 0) return;
    Wire3DCGB_DrawLine2D(sx0, sy0, sx1, sy1);
}
Wire3DCGB_DrawLine3DColor

Dibuja una línea 3D con un color temporal.

Sintaxis

c
void Wire3DCGB_DrawLine3DColor(w3dcgb_i16 ax, w3dcgb_i16 ay, w3dcgb_i16 az, w3dcgb_i16 bx, w3dcgb_i16 by, w3dcgb_i16 bz, w3dcgb_u8 color);

Parámetros

ax

Componente X del punto inicial en coordenadas del mundo.

ay

Componente Y del punto inicial en coordenadas del mundo.

az

Componente Z del punto inicial en coordenadas del mundo.

bx

Componente X del punto final en coordenadas del mundo.

by

Componente Y del punto final en coordenadas del mundo.

bz

Componente 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

c
#pragma bank 0
// Four cubes compare unity/half scale and persistent/temporary line colors.
#include "wire_cgb_example.h"
__prg_rom Wire3DCGB_Vec3 vertices[8]={
    {-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},
    {-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}
};
__prg_rom Wire3DCGB_Edge edges[12]={
    {0,1},{1,2},{2,3},{3,0},{4,5},{5,6},
    {6,7},{7,4},{0,4},{1,5},{2,6},{3,7}
};
Wire3DCGB_Model cube;
u8 sx;
u8 sy;
void main() {
    wire_results_clear();
    cube.vertices=vertices; cube.edges=edges;
    cube.faces=0; cube.edge_faces=0;
    cube.vertex_count=8; cube.edge_count=12; cube.face_count=0; cube.flags=0;
    Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawModel(&cube,-32,32,96,0,0,0);
    Wire3DCGB_DrawModelScaled(&cube,32,32,96,0,0,0,128);
    Wire3DCGB_DrawModelColor(&cube,-32,-32,96,0,0,0,2);
    Wire3DCGB_DrawModelScaledColor(&cube,32,-32,96,0,0,0,128,3);
    result[0]=Wire3DCGB_GetLineColor();
    Wire3DCGB_DrawLine3D(0,56,96,0,-56,96);
    Wire3DCGB_DrawLine3DColor(-80,0,96,80,0,96,3);
    result[1]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
    result[2]=sx; result[3]=sy;
    // Camera setters affect future projection, leaving the staged cubes intact.
    Wire3DCGB_SetCamera(0,0,0,0,4,0);
    result[4]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
    result[5]=Wire3DCGB_ProjectPointNoRotation(0,0,96,&sx,&sy);
    result[6]=sx;
    Wire3DCGB_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_models.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:173

kitaqgb/lib/wire3d_cgb.c:9005

c
void Wire3DCGB_DrawLine3DColor(w3dcgb_i16 ax, w3dcgb_i16 ay, w3dcgb_i16 az, w3dcgb_i16 bx, w3dcgb_i16 by, w3dcgb_i16 bz, w3dcgb_u8 color)
{
    w3dcgb_u8 old_color;
    old_color = w3dcgb_line_color;
    Wire3DCGB_SetLineColor(color);
    Wire3DCGB_DrawLine3D(ax, ay, az, bx, by, bz);
    w3dcgb_line_color = old_color;
}
Wire3DCGB_DrawLineClipped2D

Recorta las coordenadas de pantalla con signo a la ventana gráfica y dibuja una línea con el color solicitado.

Sintaxis

c
void Wire3DCGB_DrawLineClipped2D(w3dcgb_i16 x0, w3dcgb_i16 y0, w3dcgb_i16 x1, w3dcgb_i16 y1, w3dcgb_u8 color);

Parámetros

x0

Extremo X inferior, en píxeles de la ventana gráfica; el orden y el recorte siguen las notas de esta operación.

y0

Extremo Y inferior, en píxeles de la ventana gráfica; el orden y el recorte siguen las notas de esta operación.

x1

Extremo X superior, en píxeles de la ventana gráfica; el orden y el recorte siguen las notas de esta operación.

y1

Extremo 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

c
#pragma bank 0
// CGB raster paths: a red frame, blue diagonal, green marker and clipped line.
// Build this source together with lib/wire3d_cgb.c in an MBC5 256 KB CGB ROM.
#include "wire3d_cgb.h"
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4D) u8 sample_key1;
__location(0xC110) u16 result[8];
__prg_rom u8 lower_lines[8]={80,56,112,56,112,56,112,80};

void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DCGB_EnableDoubleSpeed();
    Wire3DCGB_Init(); // Already at double speed: its internal request is a no-op.
    result[2]=(u8)(sample_key1&128);
    // Palette writes are performed with the LCD off, after entering VBlank.
    while(sample_ly>=144) {} while(sample_ly<144) {}
    sample_lcdc=0;
    Wire3DCGB_SetPaletteRGB15(WIRE3DCGB_RGB15(0,0,0),WIRE3DCGB_RGB15(31,0,0),WIRE3DCGB_RGB15(0,0,31),WIRE3DCGB_RGB15(0,31,0));
    sample_lcdc=0x81;
    Wire3DCGB_SetScreenOffset(0,0);
    Wire3DCGB_SetCamera(0,0,0,0,0,0);
    Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawLine2D(8,8,56,8);
    Wire3DCGB_DrawLine2D(56,8,56,40);
    Wire3DCGB_DrawLine2D(56,40,8,40);
    Wire3DCGB_DrawLine2D(8,40,8,8);
    Wire3DCGB_DrawLine2DColor(8,40,56,8,2);
    result[0]=Wire3DCGB_GetLineColor(); // Temporary blue restores red.
    Wire3DCGB_SetLineColor(3);
    Wire3DCGB_DrawPoint2D(64,48);
    Wire3DCGB_DrawLineClipped2D(-10,72,140,72,3);
    Wire3DCGB_DrawLineList2DColor(lower_lines,2,2);
    result[1]=Wire3DCGB_GetLineColor(); // The blue line list restores green.
    Wire3DCGB_PutBgTile(18,1,0x80); // Queue the supplied zero glyph outside the viewport.
    Wire3DCGB_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_raster.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:136

Notas de la declaración (original)
Signed endpoints, clipped before conversion to the rasterizer's u8 ABI.

kitaqgb/lib/wire3d_cgb.c:9745

c
void Wire3DCGB_DrawLineClipped2D(w3dcgb_i16 x0, w3dcgb_i16 y0,
                               w3dcgb_i16 x1, w3dcgb_i16 y1, w3dcgb_u8 color)
{
    w3dcgb_u8 c0;
    w3dcgb_u8 c1;
    w3dcgb_u8 outside;
    w3dcgb_u8 guard;
    w3dcgb_i16 x;
    w3dcgb_i16 y;
    c0 = 0;
    c1 = 0;
    if ((((x0 | y0 | x1 | y1) & 0xFF80) != 0) || (y0 >= WIRE3DCGB_SCREEN_H) || (y1 >= WIRE3DCGB_SCREEN_H))
    {
        if ((x0 < -2047) || (x0 > 2047) || (y0 < -2047) || (y0 > 2047) ||
            (x1 < -2047) || (x1 > 2047) || (y1 < -2047) || (y1 > 2047)) return;
        c0 = w3dcgb_clip_outcode(x0, y0);
        c1 = w3dcgb_clip_outcode(x1, y1);
    }
    guard = 0;
    while (guard < 8)
    {
        if ((c0 | c1) == 0)
        {
            /* The existing ASM rasterizer handles the hot, in-window path. */
            if (w3dcgb_full_mode == 0) w3dcgb_mark_dirty_line((w3dcgb_u8)x0, (w3dcgb_u8)y0,
                                  (w3dcgb_u8)x1, (w3dcgb_u8)y1);
            Wire3DCGB_DrawLine2DColor((w3dcgb_u8)x0, (w3dcgb_u8)y0,
                                    (w3dcgb_u8)x1, (w3dcgb_u8)y1, color);
            return;
        }
        if ((c0 & c1) != 0) return;
        outside = c0;
        if (outside == 0) outside = c1;
        if ((outside & 12) != 0)
        {
            y = 0;
            if ((outside & 8) != 0) y = WIRE3DCGB_SCREEN_H - 1;
            if (((outside & 8) != 0) && (w3dcgb_full_mode != 0)) y = WIRE3DCGB_FULL_SCREEN_H - 1;
            x = (w3dcgb_i16)(x0 + w3dcgb_clip_muldiv((w3dcgb_i16)(x1 - x0),
                (w3dcgb_i16)(y - y0), (w3dcgb_i16)(y1 - y0)));
        }
        else
        {
            x = 0;
            if ((outside & 2) != 0) x = WIRE3DCGB_SCREEN_W - 1;
            if (((outside & 2) != 0) && (w3dcgb_full_mode != 0)) x = WIRE3DCGB_FULL_SCREEN_W - 1;
            y = (w3dcgb_i16)(y0 + w3dcgb_clip_muldiv((w3dcgb_i16)(y1 - y0),
                (w3dcgb_i16)(x - x0), (w3dcgb_i16)(x1 - x0)));
        }
        if (outside == c0) { x0 = x; y0 = y; c0 = w3dcgb_clip_outcode(x0, y0); }
        else { x1 = x; y1 = y; c1 = w3dcgb_clip_outcode(x1, y1); }
        guard = (w3dcgb_u8)(guard + 1);
    }
}
Wire3DCGB_DrawLineList2DColor

Dibuja una lista de registros de líneas de pantalla de cuatro bytes con el color elegido.

Sintaxis

c
void Wire3DCGB_DrawLineList2DColor(const w3dcgb_u8* line_xy, w3dcgb_u8 line_count, w3dcgb_u8 color);

Parámetros

line_xy

Array de bytes con registros x0,y0,x1,y1.

line_count

Cantidad 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

c
#pragma bank 0
// CGB raster paths: a red frame, blue diagonal, green marker and clipped line.
// Build this source together with lib/wire3d_cgb.c in an MBC5 256 KB CGB ROM.
#include "wire3d_cgb.h"
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4D) u8 sample_key1;
__location(0xC110) u16 result[8];
__prg_rom u8 lower_lines[8]={80,56,112,56,112,56,112,80};

void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DCGB_EnableDoubleSpeed();
    Wire3DCGB_Init(); // Already at double speed: its internal request is a no-op.
    result[2]=(u8)(sample_key1&128);
    // Palette writes are performed with the LCD off, after entering VBlank.
    while(sample_ly>=144) {} while(sample_ly<144) {}
    sample_lcdc=0;
    Wire3DCGB_SetPaletteRGB15(WIRE3DCGB_RGB15(0,0,0),WIRE3DCGB_RGB15(31,0,0),WIRE3DCGB_RGB15(0,0,31),WIRE3DCGB_RGB15(0,31,0));
    sample_lcdc=0x81;
    Wire3DCGB_SetScreenOffset(0,0);
    Wire3DCGB_SetCamera(0,0,0,0,0,0);
    Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawLine2D(8,8,56,8);
    Wire3DCGB_DrawLine2D(56,8,56,40);
    Wire3DCGB_DrawLine2D(56,40,8,40);
    Wire3DCGB_DrawLine2D(8,40,8,8);
    Wire3DCGB_DrawLine2DColor(8,40,56,8,2);
    result[0]=Wire3DCGB_GetLineColor(); // Temporary blue restores red.
    Wire3DCGB_SetLineColor(3);
    Wire3DCGB_DrawPoint2D(64,48);
    Wire3DCGB_DrawLineClipped2D(-10,72,140,72,3);
    Wire3DCGB_DrawLineList2DColor(lower_lines,2,2);
    result[1]=Wire3DCGB_GetLineColor(); // The blue line list restores green.
    Wire3DCGB_PutBgTile(18,1,0x80); // Queue the supplied zero glyph outside the viewport.
    Wire3DCGB_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_raster.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:186

kitaqgb/lib/wire3d_cgb.c:8571

c
void Wire3DCGB_DrawLineList2DColor(const w3dcgb_u8* line_xy,
                                  w3dcgb_u8 line_count, w3dcgb_u8 color)
{
    w3dcgb_u8 i;
    w3dcgb_u8 offset;
    w3dcgb_u8 old_color;
    if (line_xy == 0) return;
    if (line_count > WIRE3DCGB_MODEL_EDGE_LIMIT) line_count = WIRE3DCGB_MODEL_EDGE_LIMIT;

    old_color = w3dcgb_line_color;
    w3dcgb_line_color = (w3dcgb_u8)(color & 3);
    i = 0;
    offset = 0;
    while (i < line_count)
    {
        w3dcgb_line_x0 = line_xy[(__safe_index w3dcgb_u8)offset];
        offset = (w3dcgb_u8)(offset + 1);
        w3dcgb_line_y0 = line_xy[(__safe_index w3dcgb_u8)offset];
        offset = (w3dcgb_u8)(offset + 1);
        w3dcgb_line_x1 = line_xy[(__safe_index w3dcgb_u8)offset];
        offset = (w3dcgb_u8)(offset + 1);
        w3dcgb_line_y1 = line_xy[(__safe_index w3dcgb_u8)offset];
        offset = (w3dcgb_u8)(offset + 1);
        if (w3dcgb_full_mode != 0) w3dcgb_full_line_fast_asm();
        else w3dcgb_line_stage_asm();
        i = (w3dcgb_u8)(i + 1);
    }
    w3dcgb_line_color = old_color;
}
Wire3DCGB_DrawMaskedModel2D

Dibuja las aristas habilitadas a partir de vértices preproyectados y una máscara de bits de aristas.

Sintaxis

c
void Wire3DCGB_DrawMaskedModel2D(const Wire3DCGB_Model* model, const w3dcgb_i8* vertex_x, const w3dcgb_i8* vertex_y, const w3dcgb_u8* edge_mask, w3dcgb_u8 x, w3dcgb_u8 y, w3dcgb_u8 color);

Parámetros

model

Modelo que contiene los arrays de vértices, aristas y caras y sus cantidades; las tablas deben permanecer legibles durante la llamada.

vertex_x

Array de desplazamientos X de los vértices preproyectados.

vertex_y

Array de desplazamientos Y de los vértices preproyectados.

edge_mask

Array de bytes con un bit de visibilidad por arista, empezando por el menos significativo.

x

Coordenada X del centro en píxeles de la ventana gráfica.

y

Coordenada 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

c
#pragma bank 0
// Preprojected edge arrays, a clipped square, a tiny marker and a projectile.
#include "wire_cgb_example.h"
__prg_rom Wire3DCGB_Edge edges[4]={{0,1},{1,2},{2,3},{3,0}};
__prg_rom s8 vx8[4]={-8,8,8,-8};
__prg_rom s8 vy8[4]={-8,-8,8,8};
__prg_rom s16 vx16[4]={-12,12,12,-12};
__prg_rom s16 vy16[4]={-8,-8,8,8};
__prg_rom u8 mask[1]={5};
Wire3DCGB_Model shape;
void main() {
    wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    shape.vertices=0;shape.edges=edges;shape.faces=0;shape.edge_faces=0;
    shape.vertex_count=4;shape.edge_count=4;shape.face_count=0;shape.flags=0;
    Wire3DCGB_SetLineColor(2);
    Wire3DCGB_DrawMaskedModel2D(&shape,vx8,vy8,mask,24,24,1);
    Wire3DCGB_DrawEdgeList2D(edges,4,vx8,vy8,64,24,2);
    Wire3DCGB_DrawEdgeListClipped2D(edges,4,vx16,vy16,4,4,64,3);
    Wire3DCGB_DrawTinyModel2D(104,24,16,3);
    result[0]=Wire3DCGB_ProjectAxis48(48,96);
    result[1]=Wire3DCGB_ProjectAxis48(-48,96);
    Wire3DCGB_DrawFastProjectile(96,64,64,0,1);
    result[2]=Wire3DCGB_GetLineColor();
    Wire3DCGB_EndFrame();result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_lists.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_lists.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:179

kitaqgb/lib/wire3d_cgb.c:8392

c
void Wire3DCGB_DrawMaskedModel2D(const Wire3DCGB_Model* model,
                                 const w3dcgb_i8* vertex_x, const w3dcgb_i8* vertex_y,
                                 const w3dcgb_u8* edge_mask,
                                 w3dcgb_u8 x, w3dcgb_u8 y, w3dcgb_u8 color)
{
    w3dcgb_u8 i;
    w3dcgb_u8 bit;
    w3dcgb_u8 mask_index;
    w3dcgb_u8 mask;
    w3dcgb_u8 a;
    w3dcgb_u8 b;
    w3dcgb_u8 old_color;

    old_color = w3dcgb_line_color;
    w3dcgb_line_color = (w3dcgb_u8)(color & 3);
    i = 0;
    bit = 1;
    mask_index = 0;
    mask = edge_mask[0];
    while (i < model->edge_count)
    {
        if ((mask & bit) != 0)
        {
            a = model->edges[(__safe_index w3dcgb_u8)i].a;
            b = model->edges[(__safe_index w3dcgb_u8)i].b;
            w3dcgb_line_x0 = (w3dcgb_u8)((w3dcgb_i16)x + (w3dcgb_i16)vertex_x[(__safe_index w3dcgb_u8)a]);
            w3dcgb_line_y0 = (w3dcgb_u8)((w3dcgb_i16)y + (w3dcgb_i16)vertex_y[(__safe_index w3dcgb_u8)a]);
            w3dcgb_line_x1 = (w3dcgb_u8)((w3dcgb_i16)x + (w3dcgb_i16)vertex_x[(__safe_index w3dcgb_u8)b]);
            w3dcgb_line_y1 = (w3dcgb_u8)((w3dcgb_i16)y + (w3dcgb_i16)vertex_y[(__safe_index w3dcgb_u8)b]);
            if (w3dcgb_full_mode != 0) w3dcgb_full_line_fast_asm();
            else w3dcgb_line_stage_asm();
        }
        i = (w3dcgb_u8)(i + 1);
        bit = (w3dcgb_u8)(bit << 1);
        if ((bit == 0) && (i < model->edge_count))
        {
            bit = 1;
            mask_index = (w3dcgb_u8)(mask_index + 1);
            mask = edge_mask[(__safe_index w3dcgb_u8)mask_index];
        }
    }
    w3dcgb_line_color = old_color;
}
Wire3DCGB_DrawModel

Dibuja un modelo 3D en la posición y con la rotación indicadas, a escala unitaria.

Sintaxis

c
void Wire3DCGB_DrawModel(const Wire3DCGB_Model* model, w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 rx, w3dcgb_i8 ry, w3dcgb_i8 rz);

Parámetros

model

Modelo que contiene los arrays de vértices, aristas y caras y sus cantidades; las tablas deben permanecer legibles durante la llamada.

x

Componente X del punto o del origen del objeto en coordenadas del mundo.

y

Componente Y del punto o del origen del objeto en coordenadas del mundo.

z

Componente Z del punto o del origen del objeto en coordenadas del mundo.

rx

Rotación alrededor de X; dieciséis pasos forman una vuelta completa.

ry

Rotación alrededor de Y; dieciséis pasos forman una vuelta completa.

rz

Rotació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

c
#pragma bank 0
// Four cubes compare unity/half scale and persistent/temporary line colors.
#include "wire_cgb_example.h"
__prg_rom Wire3DCGB_Vec3 vertices[8]={
    {-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},
    {-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}
};
__prg_rom Wire3DCGB_Edge edges[12]={
    {0,1},{1,2},{2,3},{3,0},{4,5},{5,6},
    {6,7},{7,4},{0,4},{1,5},{2,6},{3,7}
};
Wire3DCGB_Model cube;
u8 sx;
u8 sy;
void main() {
    wire_results_clear();
    cube.vertices=vertices; cube.edges=edges;
    cube.faces=0; cube.edge_faces=0;
    cube.vertex_count=8; cube.edge_count=12; cube.face_count=0; cube.flags=0;
    Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawModel(&cube,-32,32,96,0,0,0);
    Wire3DCGB_DrawModelScaled(&cube,32,32,96,0,0,0,128);
    Wire3DCGB_DrawModelColor(&cube,-32,-32,96,0,0,0,2);
    Wire3DCGB_DrawModelScaledColor(&cube,32,-32,96,0,0,0,128,3);
    result[0]=Wire3DCGB_GetLineColor();
    Wire3DCGB_DrawLine3D(0,56,96,0,-56,96);
    Wire3DCGB_DrawLine3DColor(-80,0,96,80,0,96,3);
    result[1]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
    result[2]=sx; result[3]=sy;
    // Camera setters affect future projection, leaving the staged cubes intact.
    Wire3DCGB_SetCamera(0,0,0,0,4,0);
    result[4]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
    result[5]=Wire3DCGB_ProjectPointNoRotation(0,0,96,&sx,&sy);
    result[6]=sx;
    Wire3DCGB_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_models.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:128

kitaqgb/lib/wire3d_cgb.c:9015

c
void Wire3DCGB_DrawModel(const Wire3DCGB_Model* model, w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 rx, w3dcgb_i8 ry, w3dcgb_i8 rz)
{
    Wire3DCGB_DrawModelScaled(model, x, y, z, rx, ry, rz, 256);
}
Wire3DCGB_DrawModelColor

Dibuja un modelo a escala unitaria con un color temporal.

Sintaxis

c
void Wire3DCGB_DrawModelColor(const Wire3DCGB_Model* model, w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 rx, w3dcgb_i8 ry, w3dcgb_i8 rz, w3dcgb_u8 color);

Parámetros

model

Modelo que contiene los arrays de vértices, aristas y caras y sus cantidades; las tablas deben permanecer legibles durante la llamada.

x

Componente X del punto o del origen del objeto en coordenadas del mundo.

y

Componente Y del punto o del origen del objeto en coordenadas del mundo.

z

Componente Z del punto o del origen del objeto en coordenadas del mundo.

rx

Rotación alrededor de X; dieciséis pasos forman una vuelta completa.

ry

Rotación alrededor de Y; dieciséis pasos forman una vuelta completa.

rz

Rotació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

c
#pragma bank 0
// Four cubes compare unity/half scale and persistent/temporary line colors.
#include "wire_cgb_example.h"
__prg_rom Wire3DCGB_Vec3 vertices[8]={
    {-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},
    {-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}
};
__prg_rom Wire3DCGB_Edge edges[12]={
    {0,1},{1,2},{2,3},{3,0},{4,5},{5,6},
    {6,7},{7,4},{0,4},{1,5},{2,6},{3,7}
};
Wire3DCGB_Model cube;
u8 sx;
u8 sy;
void main() {
    wire_results_clear();
    cube.vertices=vertices; cube.edges=edges;
    cube.faces=0; cube.edge_faces=0;
    cube.vertex_count=8; cube.edge_count=12; cube.face_count=0; cube.flags=0;
    Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawModel(&cube,-32,32,96,0,0,0);
    Wire3DCGB_DrawModelScaled(&cube,32,32,96,0,0,0,128);
    Wire3DCGB_DrawModelColor(&cube,-32,-32,96,0,0,0,2);
    Wire3DCGB_DrawModelScaledColor(&cube,32,-32,96,0,0,0,128,3);
    result[0]=Wire3DCGB_GetLineColor();
    Wire3DCGB_DrawLine3D(0,56,96,0,-56,96);
    Wire3DCGB_DrawLine3DColor(-80,0,96,80,0,96,3);
    result[1]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
    result[2]=sx; result[3]=sy;
    // Camera setters affect future projection, leaving the staged cubes intact.
    Wire3DCGB_SetCamera(0,0,0,0,4,0);
    result[4]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
    result[5]=Wire3DCGB_ProjectPointNoRotation(0,0,96,&sx,&sy);
    result[6]=sx;
    Wire3DCGB_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_models.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:130

kitaqgb/lib/wire3d_cgb.c:9021

c
void Wire3DCGB_DrawModelColor(const Wire3DCGB_Model* model, w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 rx, w3dcgb_i8 ry, w3dcgb_i8 rz, w3dcgb_u8 color)
{
    Wire3DCGB_DrawModelScaledColor(model, x, y, z, rx, ry, rz, 256, color);
}
Wire3DCGB_DrawModelScaled

Escala, rota y proyecta un modelo y dibuja las aristas seleccionadas con el color actual.

Sintaxis

c
void Wire3DCGB_DrawModelScaled(const Wire3DCGB_Model* model, w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 rx, w3dcgb_i8 ry, w3dcgb_i8 rz, w3dcgb_i16 scale_q8);

Parámetros

model

Modelo que contiene los arrays de vértices, aristas y caras y sus cantidades; las tablas deben permanecer legibles durante la llamada.

x

Componente X del punto o del origen del objeto en coordenadas del mundo.

y

Componente Y del punto o del origen del objeto en coordenadas del mundo.

z

Componente Z del punto o del origen del objeto en coordenadas del mundo.

rx

Rotación alrededor de X; dieciséis pasos forman una vuelta completa.

ry

Rotación alrededor de Y; dieciséis pasos forman una vuelta completa.

rz

Rotación alrededor de Z; dieciséis pasos forman una vuelta completa.

scale_q8

Escala 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

c
#pragma bank 0
// Four cubes compare unity/half scale and persistent/temporary line colors.
#include "wire_cgb_example.h"
__prg_rom Wire3DCGB_Vec3 vertices[8]={
    {-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},
    {-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}
};
__prg_rom Wire3DCGB_Edge edges[12]={
    {0,1},{1,2},{2,3},{3,0},{4,5},{5,6},
    {6,7},{7,4},{0,4},{1,5},{2,6},{3,7}
};
Wire3DCGB_Model cube;
u8 sx;
u8 sy;
void main() {
    wire_results_clear();
    cube.vertices=vertices; cube.edges=edges;
    cube.faces=0; cube.edge_faces=0;
    cube.vertex_count=8; cube.edge_count=12; cube.face_count=0; cube.flags=0;
    Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawModel(&cube,-32,32,96,0,0,0);
    Wire3DCGB_DrawModelScaled(&cube,32,32,96,0,0,0,128);
    Wire3DCGB_DrawModelColor(&cube,-32,-32,96,0,0,0,2);
    Wire3DCGB_DrawModelScaledColor(&cube,32,-32,96,0,0,0,128,3);
    result[0]=Wire3DCGB_GetLineColor();
    Wire3DCGB_DrawLine3D(0,56,96,0,-56,96);
    Wire3DCGB_DrawLine3DColor(-80,0,96,80,0,96,3);
    result[1]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
    result[2]=sx; result[3]=sy;
    // Camera setters affect future projection, leaving the staged cubes intact.
    Wire3DCGB_SetCamera(0,0,0,0,4,0);
    result[4]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
    result[5]=Wire3DCGB_ProjectPointNoRotation(0,0,96,&sx,&sy);
    result[6]=sx;
    Wire3DCGB_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_models.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:129

kitaqgb/lib/wire3d_cgb.c:9396

c
void Wire3DCGB_DrawModelScaled(const Wire3DCGB_Model* model, w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 rx, w3dcgb_i8 ry, w3dcgb_i8 rz, w3dcgb_i16 scale_q8)
{
    w3dcgb_u8 i;
    w3dcgb_u8 count;
    w3dcgb_u8 edge_count;
    w3dcgb_u8 face_count;
    w3dcgb_u8 camera_unrotated;
    w3dcgb_u8 unit_scale;

    if (model == 0) return;
    if (model->vertices == 0) return;
    if (model->edges == 0) return;
    if (scale_q8 <= 0) scale_q8 = 256;

    count = model->vertex_count;
    if (count > WIRE3DCGB_MODEL_VERTEX_LIMIT) count = WIRE3DCGB_MODEL_VERTEX_LIMIT;
    unit_scale = 0;
    if (scale_q8 == 256) unit_scale = 1;
    camera_unrotated = 0;
    if ((w3dcgb_cam_yaw == 0) && (w3dcgb_cam_pitch == 0) && (w3dcgb_cam_roll == 0))
    {
        camera_unrotated = 1;
    }

    i = 0;
    while (i < count)
    {
        const Wire3DCGB_Vec3* v;
        w3dcgb_i16 vx;
        w3dcgb_i16 vy;
        w3dcgb_i16 vz;
        w3dcgb_u8 sx;
        w3dcgb_u8 sy;
        w3dcgb_u8 projected;

        v = &model->vertices[(__safe_index w3dcgb_u8)i];
        if (unit_scale != 0)
        {
            vx = v->x;
            vy = v->y;
            vz = v->z;
        }
        else
        {
            vx = (w3dcgb_i16)((v->x * scale_q8) >> 8);
            vy = (w3dcgb_i16)((v->y * scale_q8) >> 8);
            vz = (w3dcgb_i16)((v->z * scale_q8) >> 8);
        }

        if (ry != 0) w3dcgb_rotate_y(&vx, &vz, (w3dcgb_i8)ry);
        if (rx != 0) w3dcgb_rotate_x(&vy, &vz, (w3dcgb_i8)rx);
        if (rz != 0) w3dcgb_rotate_z(&vx, &vy, (w3dcgb_i8)rz);

        vx = (w3dcgb_i16)(vx + x);
        vy = (w3dcgb_i16)(vy + y);
        vz = (w3dcgb_i16)(vz + z);

        if (camera_unrotated != 0)
        {
            vx = (w3dcgb_i16)(vx - w3dcgb_cam_x);
            vy = (w3dcgb_i16)(vy - w3dcgb_cam_y);
            vz = (w3dcgb_i16)(vz - w3dcgb_cam_z);
            projected = w3dcgb_project_camera_space(vx, vy, vz, &sx, &sy);
        }
        else
        {
            projected = w3dcgb_project_world(vx, vy, vz, &sx, &sy);
        }

        if (projected != 0)
        {
            w3dcgb_screen_x[(__safe_index w3dcgb_u8)i] = sx;
            w3dcgb_screen_y[(__safe_index w3dcgb_u8)i] = sy;
            w3dcgb_screen_visible[(__safe_index w3dcgb_u8)i] = 1;
        }
        else
        {
            w3dcgb_screen_visible[(__safe_index w3dcgb_u8)i] = 0;
        }
        i = (w3dcgb_u8)(i + 1);
    }

    face_count = model->face_count;
    if (face_count > WIRE3DCGB_MODEL_FACE_LIMIT) face_count = WIRE3DCGB_MODEL_FACE_LIMIT;
    if ((model->flags & WIRE3DCGB_MODEL_HIDDEN_LINES) && (model->faces != 0) && (model->edge_faces != 0))
    {
        w3dcgb_build_face_visibility(model, count, face_count);
    }

    edge_count = model->edge_count;
    i = 0;
    while (i < edge_count)
    {
        const Wire3DCGB_Edge* e;
        e = &model->edges[(__safe_index w3dcgb_u8)i];
        if ((e->a < count) && (e->b < count))
        {
            if (w3dcgb_screen_visible[(__safe_index w3dcgb_u8)e->a] &&
                w3dcgb_screen_visible[(__safe_index w3dcgb_u8)e->b] &&
                w3dcgb_is_edge_visible(model, i, face_count))
            {
                w3dcgb_draw_model_line(
                    w3dcgb_screen_x[(__safe_index w3dcgb_u8)e->a],
                    w3dcgb_screen_y[(__safe_index w3dcgb_u8)e->a],
                    w3dcgb_screen_x[(__safe_index w3dcgb_u8)e->b],
                    w3dcgb_screen_y[(__safe_index w3dcgb_u8)e->b]);
            }
        }
        i = (w3dcgb_u8)(i + 1);
    }
}
Wire3DCGB_DrawModelScaledColor

Dibuja un modelo con la escala elegida y un color de línea temporal.

Sintaxis

c
void Wire3DCGB_DrawModelScaledColor(const Wire3DCGB_Model* model, w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 rx, w3dcgb_i8 ry, w3dcgb_i8 rz, w3dcgb_i16 scale_q8, w3dcgb_u8 color);

Parámetros

model

Modelo que contiene los arrays de vértices, aristas y caras y sus cantidades; las tablas deben permanecer legibles durante la llamada.

x

Componente X del punto o del origen del objeto en coordenadas del mundo.

y

Componente Y del punto o del origen del objeto en coordenadas del mundo.

z

Componente Z del punto o del origen del objeto en coordenadas del mundo.

rx

Rotación alrededor de X; dieciséis pasos forman una vuelta completa.

ry

Rotación alrededor de Y; dieciséis pasos forman una vuelta completa.

rz

Rotación alrededor de Z; dieciséis pasos forman una vuelta completa.

scale_q8

Escala 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

c
#pragma bank 0
// Four cubes compare unity/half scale and persistent/temporary line colors.
#include "wire_cgb_example.h"
__prg_rom Wire3DCGB_Vec3 vertices[8]={
    {-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},
    {-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}
};
__prg_rom Wire3DCGB_Edge edges[12]={
    {0,1},{1,2},{2,3},{3,0},{4,5},{5,6},
    {6,7},{7,4},{0,4},{1,5},{2,6},{3,7}
};
Wire3DCGB_Model cube;
u8 sx;
u8 sy;
void main() {
    wire_results_clear();
    cube.vertices=vertices; cube.edges=edges;
    cube.faces=0; cube.edge_faces=0;
    cube.vertex_count=8; cube.edge_count=12; cube.face_count=0; cube.flags=0;
    Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawModel(&cube,-32,32,96,0,0,0);
    Wire3DCGB_DrawModelScaled(&cube,32,32,96,0,0,0,128);
    Wire3DCGB_DrawModelColor(&cube,-32,-32,96,0,0,0,2);
    Wire3DCGB_DrawModelScaledColor(&cube,32,-32,96,0,0,0,128,3);
    result[0]=Wire3DCGB_GetLineColor();
    Wire3DCGB_DrawLine3D(0,56,96,0,-56,96);
    Wire3DCGB_DrawLine3DColor(-80,0,96,80,0,96,3);
    result[1]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
    result[2]=sx; result[3]=sy;
    // Camera setters affect future projection, leaving the staged cubes intact.
    Wire3DCGB_SetCamera(0,0,0,0,4,0);
    result[4]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
    result[5]=Wire3DCGB_ProjectPointNoRotation(0,0,96,&sx,&sy);
    result[6]=sx;
    Wire3DCGB_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_models.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:131

kitaqgb/lib/wire3d_cgb.c:9510

c
void Wire3DCGB_DrawModelScaledColor(const Wire3DCGB_Model* model, w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 rx, w3dcgb_i8 ry, w3dcgb_i8 rz, w3dcgb_i16 scale_q8, w3dcgb_u8 color)
{
    w3dcgb_u8 old_color;
    old_color = w3dcgb_line_color;
    Wire3DCGB_SetLineColor(color);
    Wire3DCGB_DrawModelScaled(model, x, y, z, rx, ry, rz, scale_q8);
    w3dcgb_line_color = old_color;
}
Wire3DCGB_DrawPoint2D

Escribe un píxel con el color actual.

Sintaxis

c
void Wire3DCGB_DrawPoint2D(w3dcgb_u8 x, w3dcgb_u8 y);

Parámetros

x

Coordenada X del centro en píxeles de la ventana gráfica.

y

Coordenada 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

c
#pragma bank 0
// CGB raster paths: a red frame, blue diagonal, green marker and clipped line.
// Build this source together with lib/wire3d_cgb.c in an MBC5 256 KB CGB ROM.
#include "wire3d_cgb.h"
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4D) u8 sample_key1;
__location(0xC110) u16 result[8];
__prg_rom u8 lower_lines[8]={80,56,112,56,112,56,112,80};

void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DCGB_EnableDoubleSpeed();
    Wire3DCGB_Init(); // Already at double speed: its internal request is a no-op.
    result[2]=(u8)(sample_key1&128);
    // Palette writes are performed with the LCD off, after entering VBlank.
    while(sample_ly>=144) {} while(sample_ly<144) {}
    sample_lcdc=0;
    Wire3DCGB_SetPaletteRGB15(WIRE3DCGB_RGB15(0,0,0),WIRE3DCGB_RGB15(31,0,0),WIRE3DCGB_RGB15(0,0,31),WIRE3DCGB_RGB15(0,31,0));
    sample_lcdc=0x81;
    Wire3DCGB_SetScreenOffset(0,0);
    Wire3DCGB_SetCamera(0,0,0,0,0,0);
    Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawLine2D(8,8,56,8);
    Wire3DCGB_DrawLine2D(56,8,56,40);
    Wire3DCGB_DrawLine2D(56,40,8,40);
    Wire3DCGB_DrawLine2D(8,40,8,8);
    Wire3DCGB_DrawLine2DColor(8,40,56,8,2);
    result[0]=Wire3DCGB_GetLineColor(); // Temporary blue restores red.
    Wire3DCGB_SetLineColor(3);
    Wire3DCGB_DrawPoint2D(64,48);
    Wire3DCGB_DrawLineClipped2D(-10,72,140,72,3);
    Wire3DCGB_DrawLineList2DColor(lower_lines,2,2);
    result[1]=Wire3DCGB_GetLineColor(); // The blue line list restores green.
    Wire3DCGB_PutBgTile(18,1,0x80); // Queue the supplied zero glyph outside the viewport.
    Wire3DCGB_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_raster.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:174

kitaqgb/lib/wire3d_cgb.c:8283

c
void Wire3DCGB_DrawPoint2D(w3dcgb_u8 x, w3dcgb_u8 y)
{
    w3dcgb_u8 tile;
    if (w3dcgb_full_mode != 0)
    {
        w3dcgb_line_x0 = x;
        w3dcgb_line_y0 = y;
        w3dcgb_line_x1 = x;
        w3dcgb_line_y1 = y;
        w3dcgb_full_line_fast_asm();
        return;
    }
    if (x >= WIRE3DCGB_SCREEN_W) return;
    if (y >= WIRE3DCGB_SCREEN_H) return;
    if (w3dcgb_full_frame_transfer == 0)
    {
        tile = (w3dcgb_u8)(((x >> 3) * W3DCGB_TILE_H) + (y >> 3));
        if (tile < w3dcgb_dirty_min_tile) w3dcgb_dirty_min_tile = tile;
        if (tile > w3dcgb_dirty_max_tile) w3dcgb_dirty_max_tile = tile;
    }
    w3dcgb_plot_x = x;
    w3dcgb_plot_y = y;
    w3dcgb_plot_stage_asm();
}
Wire3DCGB_DrawScene

Dibuja hasta ocho objetos de cerca a lejos, usando las caras anteriores para ocultar las líneas posteriores.

Sintaxis

c
void Wire3DCGB_DrawScene(Wire3DCGB_Object* objects, w3dcgb_u8 count);

Parámetros

objects

Array de objetos con posiciones, rotaciones, escalas e indicadores de visibilidad.

count

Cantidad 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

c
#pragma bank 0
// A near square hides the middle of a farther blue line, regardless of array order.
#include "wire_cgb_example.h"
#include "wire_cgb_plane.h"
__prg_rom Wire3DCGB_Vec3 back_vertices[2]={{-96,0,0},{96,0,0}};
__prg_rom Wire3DCGB_Edge back_edges[1]={{0,1}};
Wire3DCGB_Model back;
Wire3DCGB_Object objects[2];
void main() {
    u8 i;
    wire_results_clear();wire_plane_setup();
    back.vertices=back_vertices;back.edges=back_edges;back.faces=0;back.edge_faces=0;
    back.vertex_count=2;back.edge_count=1;back.face_count=0;back.flags=0;
    for(i=0;i<2;i++) {
        objects[i].x=0;objects[i].y=0;objects[i].rx=0;objects[i].ry=0;objects[i].rz=0;
        objects[i].scale_q8=256;objects[i].visible=1;
    }
    objects[0].model=&back;objects[0].z=128;objects[0].color=2;
    objects[1].model=&plane;objects[1].z=64;objects[1].color=1;
    Wire3DCGB_Init();wire_colors();Wire3DCGB_BeginFrame();Wire3DCGB_SetLineColor(3);
    Wire3DCGB_DrawScene(objects,2);
    result[0]=objects[0].z;result[1]=objects[1].z;result[2]=Wire3DCGB_GetLineColor();
    Wire3DCGB_EndFrame();result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_scene.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_scene.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:155

kitaqgb/lib/wire3d_cgb.c:8918

c
void Wire3DCGB_DrawScene(Wire3DCGB_Object* objects, w3dcgb_u8 count)
{
    w3dcgb_u8 scene_count;
    w3dcgb_u8 i;
    w3dcgb_u8 old_color;

    if (objects == 0) return;

    scene_count = count;
    if (scene_count > WIRE3DCGB_SCENE_OBJECT_LIMIT) scene_count = WIRE3DCGB_SCENE_OBJECT_LIMIT;

    i = 0;
    while (i < scene_count)
    {
        w3dcgb_scene_order[(__safe_index w3dcgb_u8)i] = i;
        w3dcgb_scene_depth[(__safe_index w3dcgb_u8)i] = w3dcgb_scene_object_depth(&objects[(__safe_index w3dcgb_u8)i]);
        i = (w3dcgb_u8)(i + 1);
    }

    i = 0;
    while (i < scene_count)
    {
        w3dcgb_u8 j;
        j = (w3dcgb_u8)(i + 1);
        while (j < scene_count)
        {
            w3dcgb_u8 oi;
            w3dcgb_u8 oj;
            oi = w3dcgb_scene_order[(__safe_index w3dcgb_u8)i];
            oj = w3dcgb_scene_order[(__safe_index w3dcgb_u8)j];

            if (w3dcgb_scene_depth[(__safe_index w3dcgb_u8)oj] < w3dcgb_scene_depth[(__safe_index w3dcgb_u8)oi])
            {
                w3dcgb_scene_order[(__safe_index w3dcgb_u8)i] = oj;
                w3dcgb_scene_order[(__safe_index w3dcgb_u8)j] = oi;
            }
            j = (w3dcgb_u8)(j + 1);
        }
        i = (w3dcgb_u8)(i + 1);
    }

    old_color = w3dcgb_line_color;
    w3dcgb_clear_occlusion_mask();
    w3dcgb_occlusion_active = 0;

    i = 0;
    while (i < scene_count)
    {
        Wire3DCGB_Object* obj;
        obj = &objects[(__safe_index w3dcgb_u8)w3dcgb_scene_order[(__safe_index w3dcgb_u8)i]];
        if ((obj->visible != 0) && (obj->model != 0))
        {
            if (i == 0) w3dcgb_occlusion_active = 0;
            else w3dcgb_occlusion_active = 1;
            if (obj->color != 0) Wire3DCGB_SetLineColor(obj->color);
            Wire3DCGB_DrawModelScaled(obj->model, obj->x, obj->y, obj->z, (w3dcgb_i8)obj->rx, (w3dcgb_i8)obj->ry, (w3dcgb_i8)obj->rz, obj->scale_q8);
            w3dcgb_occlusion_active = 0;
            w3dcgb_mark_model_occluder(obj->model);
        }
        i = (w3dcgb_u8)(i + 1);
    }

    w3dcgb_occlusion_active = 0;
    w3dcgb_line_color = old_color;
}
Wire3DCGB_DrawTinyModel2D

Dibuja un marcador de seis píxeles cuya punta y cola indican la dirección.

Sintaxis

c
void Wire3DCGB_DrawTinyModel2D(w3dcgb_u8 x, w3dcgb_u8 y, w3dcgb_u8 turn, w3dcgb_u8 color);

Parámetros

x

Coordenada X del centro en píxeles de la ventana gráfica.

y

Coordenada Y del centro en píxeles de la ventana gráfica.

turn

Valor 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

c
#pragma bank 0
// Preprojected edge arrays, a clipped square, a tiny marker and a projectile.
#include "wire_cgb_example.h"
__prg_rom Wire3DCGB_Edge edges[4]={{0,1},{1,2},{2,3},{3,0}};
__prg_rom s8 vx8[4]={-8,8,8,-8};
__prg_rom s8 vy8[4]={-8,-8,8,8};
__prg_rom s16 vx16[4]={-12,12,12,-12};
__prg_rom s16 vy16[4]={-8,-8,8,8};
__prg_rom u8 mask[1]={5};
Wire3DCGB_Model shape;
void main() {
    wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    shape.vertices=0;shape.edges=edges;shape.faces=0;shape.edge_faces=0;
    shape.vertex_count=4;shape.edge_count=4;shape.face_count=0;shape.flags=0;
    Wire3DCGB_SetLineColor(2);
    Wire3DCGB_DrawMaskedModel2D(&shape,vx8,vy8,mask,24,24,1);
    Wire3DCGB_DrawEdgeList2D(edges,4,vx8,vy8,64,24,2);
    Wire3DCGB_DrawEdgeListClipped2D(edges,4,vx16,vy16,4,4,64,3);
    Wire3DCGB_DrawTinyModel2D(104,24,16,3);
    result[0]=Wire3DCGB_ProjectAxis48(48,96);
    result[1]=Wire3DCGB_ProjectAxis48(-48,96);
    Wire3DCGB_DrawFastProjectile(96,64,64,0,1);
    result[2]=Wire3DCGB_GetLineColor();
    Wire3DCGB_EndFrame();result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_lists.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_lists.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:175

kitaqgb/lib/wire3d_cgb.c:8313

c
void Wire3DCGB_DrawTinyModel2D(w3dcgb_u8 x, w3dcgb_u8 y,
                               w3dcgb_u8 turn, w3dcgb_u8 color)
{
    w3dcgb_u8 nose_x;
    w3dcgb_u8 tail_x;
    w3dcgb_u8 old_color;
    if ((x < 3) || (x > 124) || (y < 3) || (y > (w3dcgb_u8)(WIRE3DCGB_SCREEN_H - 4))) return;

    nose_x = x;
    tail_x = x;
    turn = (w3dcgb_u8)(turn & 31);
    if (turn < 12)
    {
        nose_x = (w3dcgb_u8)(x + 1);
        tail_x = (w3dcgb_u8)(x - 1);
    }
    else if (turn >= 20)
    {
        nose_x = (w3dcgb_u8)(x - 1);
        tail_x = (w3dcgb_u8)(x + 1);
    }

    old_color = w3dcgb_line_color;
    w3dcgb_line_color = (w3dcgb_u8)(color & 3);
    w3dcgb_plot_x = nose_x;
    w3dcgb_plot_y = (w3dcgb_u8)(y - 2);
    w3dcgb_plot_stage_asm();
    w3dcgb_plot_x = x;
    w3dcgb_plot_y = (w3dcgb_u8)(y - 1);
    w3dcgb_plot_stage_asm();
    w3dcgb_plot_x = (w3dcgb_u8)(x - 2);
    w3dcgb_plot_y = (w3dcgb_u8)(y + 1);
    w3dcgb_plot_stage_asm();
    w3dcgb_plot_x = (w3dcgb_u8)(x + 2);
    w3dcgb_plot_stage_asm();
    w3dcgb_plot_x = x;
    w3dcgb_plot_y = y;
    w3dcgb_plot_stage_asm();
    w3dcgb_plot_x = tail_x;
    w3dcgb_plot_y = (w3dcgb_u8)(y + 2);
    w3dcgb_plot_stage_asm();
    w3dcgb_line_color = old_color;
}
Wire3DCGB_DrawWhiteBorderFast

Dibuja un borde de un píxel con índice de color 2 alrededor del área de preparación de 128×96.

Sintaxis

c
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

c
#pragma bank 0
// A cleared 24-pixel strip and a palette-index-2 border have distinct purposes.
#include "wire_cgb_example.h"
void main() {
    u8 y;
    wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    for(y=0;y<96;y++) Wire3DCGB_DrawLine2D(0,y,31,y);
    Wire3DCGB_EraseLeftGuard24Fast();
    // With this example's palette, color index 2 is blue rather than white.
    Wire3DCGB_DrawWhiteBorderFast();
    Wire3DCGB_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_guard.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_guard.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:147

kitaqgb/lib/wire3d_cgb.c:9369

c
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

c
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

c
#pragma bank 0
// Reuse both VRAM banks and remove old geometry while presenting sparse frames.
#include "wire_cgb_example.h"
void main() {
    wire_results_clear(); Wire3DCGB_Init();
    Wire3DCGB_ClearFrameTiles();
    Wire3DCGB_EnableAtomicMaps(); wire_colors();
    // First frame: red on the left. Fast begin invalidates both bank histories.
    Wire3DCGB_BeginFrameFast(); wire_frame(8,8,32,32,1);
    Wire3DCGB_EndFrameFast();
    // Second frame: blue in the middle, with the old red frame removed.
    Wire3DCGB_BeginFrameSparse(); wire_frame(40,40,64,64,2);
    Wire3DCGB_EndFrameSparse();
    // Third frame: explicitly clearing a stage discards its first green point.
    Wire3DCGB_BeginFrameSparse();
    Wire3DCGB_SetLineColor(3); Wire3DCGB_DrawPoint2D(4,4);
    Wire3DCGB_ClearSparseStageFast();
    // The final image contains only this green frame on the right.
    wire_frame(80,8,112,32,3);
    Wire3DCGB_MarkDirtyRect2D(80,8,112,32);
    Wire3DCGB_InvalidateFrameHistory();
    Wire3DCGB_EndFrameSparseNow();
    result[0]=Wire3DCGB_GetLineColor();
    result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_sparse.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_sparse.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:144

Notas de la declaración (original)
Startup-only: reserves both BG maps; queued HUD tiles are mirrored.

kitaqgb/lib/wire3d_cgb.c:7912

c
void Wire3DCGB_EnableAtomicMaps()
{
    if ((w3dcgb_full_mode != 0) || (w3dcgb_atomic_maps != 0)) return;
    __asm {
w3dam_wait:
        LDH_A_MEM 68
        CP_IMM 144
        JR_C w3dam_wait
        LDH_A_MEM 64
        PUSH_AF
        XOR_A
        LDH_MEM_A 64
        LDH_MEM_A 79
        LD_HL_IMM 0x9800
        LD_DE_IMM 0x9C00
        LD_B_IMM 4
w3dam_copy_page:
        LD_C_IMM 0
w3dam_copy_byte:
        LD_A_HL
        INC_HL
        LD_DE_A
        INC_DE
        DEC_C
        JR_NZ w3dam_copy_byte
        DEC_B
        JR_NZ w3dam_copy_page
        LDH_A_MEM 79
        AND_IMM 1
        JR_NZ w3dam_attrs
        LD_A_IMM 1
        LDH_MEM_A 79
        LD_HL_IMM 0x9800
        LD_DE_IMM 0x9C00
        LD_B_IMM 4
        JR w3dam_copy_page
w3dam_attrs:
        LD_HL_IMM 0x9800
        LD_DE_IMM 0x9C00
        LD_B_IMM 12
w3dam_row:
        LD_C_IMM 16
w3dam_cell:
        XOR_A
        LDI_HL_A
        LD_A_IMM 8
        LD_DE_A
        INC_DE
        DEC_C
        JR_NZ w3dam_cell
        LD_A_L
        ADD_A_IMM 16
        LD_L_A
        JR_NC w3dam_hl_ready
        INC_H
w3dam_hl_ready:
        LD_A_E
        ADD_A_IMM 16
        LD_E_A
        JR_NC w3dam_de_ready
        INC_D
w3dam_de_ready:
        DEC_B
        JR_NZ w3dam_row
        LD_A_IMM 1
        LD_MEM_A w3dcgb_atomic_maps
        XOR_A
        LDH_MEM_A 79
        POP_AF
        OR_IMM 8
        LDH_MEM_A 64
        RET
    }
}
Wire3DCGB_EnableDoubleSpeed

Cambia la CPU de CGB a doble velocidad.

Sintaxis

c
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

c
#pragma bank 0
// CGB raster paths: a red frame, blue diagonal, green marker and clipped line.
// Build this source together with lib/wire3d_cgb.c in an MBC5 256 KB CGB ROM.
#include "wire3d_cgb.h"
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4D) u8 sample_key1;
__location(0xC110) u16 result[8];
__prg_rom u8 lower_lines[8]={80,56,112,56,112,56,112,80};

void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DCGB_EnableDoubleSpeed();
    Wire3DCGB_Init(); // Already at double speed: its internal request is a no-op.
    result[2]=(u8)(sample_key1&128);
    // Palette writes are performed with the LCD off, after entering VBlank.
    while(sample_ly>=144) {} while(sample_ly<144) {}
    sample_lcdc=0;
    Wire3DCGB_SetPaletteRGB15(WIRE3DCGB_RGB15(0,0,0),WIRE3DCGB_RGB15(31,0,0),WIRE3DCGB_RGB15(0,0,31),WIRE3DCGB_RGB15(0,31,0));
    sample_lcdc=0x81;
    Wire3DCGB_SetScreenOffset(0,0);
    Wire3DCGB_SetCamera(0,0,0,0,0,0);
    Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawLine2D(8,8,56,8);
    Wire3DCGB_DrawLine2D(56,8,56,40);
    Wire3DCGB_DrawLine2D(56,40,8,40);
    Wire3DCGB_DrawLine2D(8,40,8,8);
    Wire3DCGB_DrawLine2DColor(8,40,56,8,2);
    result[0]=Wire3DCGB_GetLineColor(); // Temporary blue restores red.
    Wire3DCGB_SetLineColor(3);
    Wire3DCGB_DrawPoint2D(64,48);
    Wire3DCGB_DrawLineClipped2D(-10,72,140,72,3);
    Wire3DCGB_DrawLineList2DColor(lower_lines,2,2);
    result[1]=Wire3DCGB_GetLineColor(); // The blue line list restores green.
    Wire3DCGB_PutBgTile(18,1,0x80); // Queue the supplied zero glyph outside the viewport.
    Wire3DCGB_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_raster.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:116

kitaqgb/lib/wire3d_cgb.c:1081

c
void Wire3DCGB_EnableDoubleSpeed()
{
    if ((w3dcgb_reg_key1 & 0x80) != 0) return;
    w3dcgb_reg_key1 = 1;
    w3dcgb_cgb_speed_switch_asm();
}
Wire3DCGB_EndFrame

Transfiere y presenta el fotograma terminado.

Sintaxis

c
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

c
#pragma bank 0
// CGB raster paths: a red frame, blue diagonal, green marker and clipped line.
// Build this source together with lib/wire3d_cgb.c in an MBC5 256 KB CGB ROM.
#include "wire3d_cgb.h"
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4D) u8 sample_key1;
__location(0xC110) u16 result[8];
__prg_rom u8 lower_lines[8]={80,56,112,56,112,56,112,80};

void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DCGB_EnableDoubleSpeed();
    Wire3DCGB_Init(); // Already at double speed: its internal request is a no-op.
    result[2]=(u8)(sample_key1&128);
    // Palette writes are performed with the LCD off, after entering VBlank.
    while(sample_ly>=144) {} while(sample_ly<144) {}
    sample_lcdc=0;
    Wire3DCGB_SetPaletteRGB15(WIRE3DCGB_RGB15(0,0,0),WIRE3DCGB_RGB15(31,0,0),WIRE3DCGB_RGB15(0,0,31),WIRE3DCGB_RGB15(0,31,0));
    sample_lcdc=0x81;
    Wire3DCGB_SetScreenOffset(0,0);
    Wire3DCGB_SetCamera(0,0,0,0,0,0);
    Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawLine2D(8,8,56,8);
    Wire3DCGB_DrawLine2D(56,8,56,40);
    Wire3DCGB_DrawLine2D(56,40,8,40);
    Wire3DCGB_DrawLine2D(8,40,8,8);
    Wire3DCGB_DrawLine2DColor(8,40,56,8,2);
    result[0]=Wire3DCGB_GetLineColor(); // Temporary blue restores red.
    Wire3DCGB_SetLineColor(3);
    Wire3DCGB_DrawPoint2D(64,48);
    Wire3DCGB_DrawLineClipped2D(-10,72,140,72,3);
    Wire3DCGB_DrawLineList2DColor(lower_lines,2,2);
    result[1]=Wire3DCGB_GetLineColor(); // The blue line list restores green.
    Wire3DCGB_PutBgTile(18,1,0x80); // Queue the supplied zero glyph outside the viewport.
    Wire3DCGB_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_raster.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:189

kitaqgb/lib/wire3d_cgb.c:9881

c
void Wire3DCGB_EndFrame()
{
    if (w3dcgb_full_mode != 0)
    {
        w3dcgb_full_transfer_asm();
        w3dcgb_full_present_asm();
        return;
    }
    if (w3dcgb_bgq_count != 0)
    {
        w3dcgb_wait_vblank_start();
        w3dcgb_flush_bg_queue();
    }
    w3dcgb_transfer_stage_asm();
    w3dcgb_present_stage_asm();
}
Wire3DCGB_EndFrameFast

Transfiere y presenta un fotograma completo sin aplicar las escrituras del fondo en cola.

Sintaxis

c
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

c
#pragma bank 0
// Reuse both VRAM banks and remove old geometry while presenting sparse frames.
#include "wire_cgb_example.h"
void main() {
    wire_results_clear(); Wire3DCGB_Init();
    Wire3DCGB_ClearFrameTiles();
    Wire3DCGB_EnableAtomicMaps(); wire_colors();
    // First frame: red on the left. Fast begin invalidates both bank histories.
    Wire3DCGB_BeginFrameFast(); wire_frame(8,8,32,32,1);
    Wire3DCGB_EndFrameFast();
    // Second frame: blue in the middle, with the old red frame removed.
    Wire3DCGB_BeginFrameSparse(); wire_frame(40,40,64,64,2);
    Wire3DCGB_EndFrameSparse();
    // Third frame: explicitly clearing a stage discards its first green point.
    Wire3DCGB_BeginFrameSparse();
    Wire3DCGB_SetLineColor(3); Wire3DCGB_DrawPoint2D(4,4);
    Wire3DCGB_ClearSparseStageFast();
    // The final image contains only this green frame on the right.
    wire_frame(80,8,112,32,3);
    Wire3DCGB_MarkDirtyRect2D(80,8,112,32);
    Wire3DCGB_InvalidateFrameHistory();
    Wire3DCGB_EndFrameSparseNow();
    result[0]=Wire3DCGB_GetLineColor();
    result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_sparse.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_sparse.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:190

kitaqgb/lib/wire3d_cgb.c:9902

c
void Wire3DCGB_EndFrameFast()
{
    if (w3dcgb_full_mode != 0)
    {
        w3dcgb_full_transfer_asm();
        w3dcgb_full_present_asm();
        return;
    }
    w3dcgb_transfer_stage_asm();
    w3dcgb_present_stage_asm();
}
Wire3DCGB_EndFrameSparse

Espera a un nuevo VBlank y transfiere y presenta los rangos parciales necesarios.

Sintaxis

c
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

c
#pragma bank 0
// Reuse both VRAM banks and remove old geometry while presenting sparse frames.
#include "wire_cgb_example.h"
void main() {
    wire_results_clear(); Wire3DCGB_Init();
    Wire3DCGB_ClearFrameTiles();
    Wire3DCGB_EnableAtomicMaps(); wire_colors();
    // First frame: red on the left. Fast begin invalidates both bank histories.
    Wire3DCGB_BeginFrameFast(); wire_frame(8,8,32,32,1);
    Wire3DCGB_EndFrameFast();
    // Second frame: blue in the middle, with the old red frame removed.
    Wire3DCGB_BeginFrameSparse(); wire_frame(40,40,64,64,2);
    Wire3DCGB_EndFrameSparse();
    // Third frame: explicitly clearing a stage discards its first green point.
    Wire3DCGB_BeginFrameSparse();
    Wire3DCGB_SetLineColor(3); Wire3DCGB_DrawPoint2D(4,4);
    Wire3DCGB_ClearSparseStageFast();
    // The final image contains only this green frame on the right.
    wire_frame(80,8,112,32,3);
    Wire3DCGB_MarkDirtyRect2D(80,8,112,32);
    Wire3DCGB_InvalidateFrameHistory();
    Wire3DCGB_EndFrameSparseNow();
    result[0]=Wire3DCGB_GetLineColor();
    result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_sparse.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_sparse.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:191

kitaqgb/lib/wire3d_cgb.c:9917

c
void Wire3DCGB_EndFrameSparse()
{
    if (w3dcgb_full_mode != 0)
    {
        w3dcgb_full_transfer_asm();
        w3dcgb_full_present_asm();
        return;
    }
    w3dcgb_wait_vblank_start();
    Wire3DCGB_EndFrameSparseNow();
}
Wire3DCGB_EndFrameSparseNow

Envía las escrituras del fondo y los rangos parciales actuales/N−2 sin la espera inicial a un nuevo VBlank.

Sintaxis

c
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

c
#pragma bank 0
// Reuse both VRAM banks and remove old geometry while presenting sparse frames.
#include "wire_cgb_example.h"
void main() {
    wire_results_clear(); Wire3DCGB_Init();
    Wire3DCGB_ClearFrameTiles();
    Wire3DCGB_EnableAtomicMaps(); wire_colors();
    // First frame: red on the left. Fast begin invalidates both bank histories.
    Wire3DCGB_BeginFrameFast(); wire_frame(8,8,32,32,1);
    Wire3DCGB_EndFrameFast();
    // Second frame: blue in the middle, with the old red frame removed.
    Wire3DCGB_BeginFrameSparse(); wire_frame(40,40,64,64,2);
    Wire3DCGB_EndFrameSparse();
    // Third frame: explicitly clearing a stage discards its first green point.
    Wire3DCGB_BeginFrameSparse();
    Wire3DCGB_SetLineColor(3); Wire3DCGB_DrawPoint2D(4,4);
    Wire3DCGB_ClearSparseStageFast();
    // The final image contains only this green frame on the right.
    wire_frame(80,8,112,32,3);
    Wire3DCGB_MarkDirtyRect2D(80,8,112,32);
    Wire3DCGB_InvalidateFrameHistory();
    Wire3DCGB_EndFrameSparseNow();
    result[0]=Wire3DCGB_GetLineColor();
    result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_sparse.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_sparse.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:192

kitaqgb/lib/wire3d_cgb.c:9935

c
void Wire3DCGB_EndFrameSparseNow()
{
#ifndef WIRE3DCGB_MINIMAL_RUNTIME
    if (w3dcgb_full_mode != 0)
    {
        w3dcgb_full_transfer_asm();
        w3dcgb_full_present_asm();
        return;
    }
#endif
    /* Atomic mode never writes a displayed tile and does not need a
       frame-long VBlank wait before starting an off-screen upload. */
    if (w3dcgb_atomic_maps == 0) w3dcgb_restore_hud_blank_tile_asm();
    if (w3dcgb_bgq_count != 0) w3dcgb_flush_bg_queue();
    w3dcgb_transfer_dirty_tiles();
    w3dcgb_present_stage_asm();
}
Wire3DCGB_EraseLeftGuard24Fast

Borra las 24 columnas más a la izquierda del área de preparación normal.

Sintaxis

c
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

c
#pragma bank 0
// A cleared 24-pixel strip and a palette-index-2 border have distinct purposes.
#include "wire_cgb_example.h"
void main() {
    u8 y;
    wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    for(y=0;y<96;y++) Wire3DCGB_DrawLine2D(0,y,31,y);
    Wire3DCGB_EraseLeftGuard24Fast();
    // With this example's palette, color index 2 is blue rather than white.
    Wire3DCGB_DrawWhiteBorderFast();
    Wire3DCGB_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_guard.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_guard.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:146

kitaqgb/lib/wire3d_cgb.c:9200

c
void Wire3DCGB_EraseLeftGuard24Fast()
{
    w3dcgb_erase_left_guard24_asm();
}
Wire3DCGB_EraseModelFaces

Borra los píxeles preparados dentro de las caras frontales proyectadas del modelo.

Sintaxis

c
void Wire3DCGB_EraseModelFaces(const Wire3DCGB_Model* model, w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 rx, w3dcgb_i8 ry, w3dcgb_i8 rz, w3dcgb_i16 scale_q8);

Parámetros

model

Modelo que contiene los arrays de vértices, aristas y caras y sus cantidades; las tablas deben permanecer legibles durante la llamada.

x

Componente X del punto o del origen del objeto en coordenadas del mundo.

y

Componente Y del punto o del origen del objeto en coordenadas del mundo.

z

Componente Z del punto o del origen del objeto en coordenadas del mundo.

rx

Rotación alrededor de X; dieciséis pasos forman una vuelta completa.

ry

Rotación alrededor de Y; dieciséis pasos forman una vuelta completa.

rz

Rotación alrededor de Z; dieciséis pasos forman una vuelta completa.

scale_q8

Escala 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

c
#pragma bank 0
// Projected model faces erase a square opening; redraw its outline in green.
#include "wire_cgb_example.h"
#include "wire_cgb_plane.h"
void main() {
    u8 y;u8 bank;
    wire_results_clear();wire_plane_setup();Wire3DCGB_Init();wire_colors();Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    for(y=8;y<=88;y++) Wire3DCGB_DrawLine2D(24,y,104,y);
    bank=sample_svbk;sample_svbk=2;
    Wire3DCGB_EraseModelFaces(&plane,0,0,64,0,0,0,256);
    sample_svbk=bank;
    Wire3DCGB_DrawModelColor(&plane,0,0,64,0,0,0,3);
    result[0]=Wire3DCGB_GetLineColor();
    Wire3DCGB_EndFrame();result[7]=0xA55A;
    while(1) {}
}

Resultado esperado

Las caras proyectadas borran una región rellena y permiten distinguir las zonas conservadas de las borradas.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_faces.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_faces.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:132

kitaqgb/lib/wire3d_cgb.c:9033

c
void Wire3DCGB_EraseModelFaces(const Wire3DCGB_Model* model, w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 rx, w3dcgb_i8 ry, w3dcgb_i8 rz, w3dcgb_i16 scale_q8)
{
    w3dcgb_u8 i;
    w3dcgb_u8 count;
    w3dcgb_u8 face_count;

    if (model == 0) return;
    if (model->vertices == 0) return;
    if (model->faces == 0) return;
    if ((model->flags & WIRE3DCGB_MODEL_HIDDEN_LINES) == 0) return;
    if (scale_q8 <= 0) scale_q8 = 256;

    count = model->vertex_count;
    if (count > WIRE3DCGB_MODEL_VERTEX_LIMIT) count = WIRE3DCGB_MODEL_VERTEX_LIMIT;

    i = 0;
    while (i < count)
    {
        const Wire3DCGB_Vec3* v;
        w3dcgb_i16 vx;
        w3dcgb_i16 vy;
        w3dcgb_i16 vz;
        w3dcgb_u8 sx;
        w3dcgb_u8 sy;

        v = &model->vertices[(__safe_index w3dcgb_u8)i];
        vx = (w3dcgb_i16)((v->x * scale_q8) >> 8);
        vy = (w3dcgb_i16)((v->y * scale_q8) >> 8);
        vz = (w3dcgb_i16)((v->z * scale_q8) >> 8);

        w3dcgb_rotate_y(&vx, &vz, (w3dcgb_i8)ry);
        w3dcgb_rotate_x(&vy, &vz, (w3dcgb_i8)rx);
        w3dcgb_rotate_z(&vx, &vy, (w3dcgb_i8)rz);

        vx = (w3dcgb_i16)(vx + x);
        vy = (w3dcgb_i16)(vy + y);
        vz = (w3dcgb_i16)(vz + z);

        if (w3dcgb_project_world(vx, vy, vz, &sx, &sy))
        {
            w3dcgb_screen_x[(__safe_index w3dcgb_u8)i] = sx;
            w3dcgb_screen_y[(__safe_index w3dcgb_u8)i] = sy;
            w3dcgb_screen_visible[(__safe_index w3dcgb_u8)i] = 1;
        }
        else
        {
            w3dcgb_screen_visible[(__safe_index w3dcgb_u8)i] = 0;
        }
        i = (w3dcgb_u8)(i + 1);
    }

    face_count = model->face_count;
    if (face_count > WIRE3DCGB_MODEL_FACE_LIMIT) face_count = WIRE3DCGB_MODEL_FACE_LIMIT;
    w3dcgb_build_face_visibility(model, count, face_count);

    i = 0;
    while (i < face_count)
    {
        const Wire3DCGB_Face* f;
        f = &model->faces[(__safe_index w3dcgb_u8)i];
        if (w3dcgb_face_visible[(__safe_index w3dcgb_u8)i] &&
            w3dcgb_screen_visible[(__safe_index w3dcgb_u8)f->a] &&
            w3dcgb_screen_visible[(__safe_index w3dcgb_u8)f->b] &&
            w3dcgb_screen_visible[(__safe_index w3dcgb_u8)f->c])
        {
            w3dcgb_clear_triangle(
                w3dcgb_screen_x[(__safe_index w3dcgb_u8)f->a],
                w3dcgb_screen_y[(__safe_index w3dcgb_u8)f->a],
                w3dcgb_screen_x[(__safe_index w3dcgb_u8)f->b],
                w3dcgb_screen_y[(__safe_index w3dcgb_u8)f->b],
                w3dcgb_screen_x[(__safe_index w3dcgb_u8)f->c],
                w3dcgb_screen_y[(__safe_index w3dcgb_u8)f->c]);
        }
        i = (w3dcgb_u8)(i + 1);
    }
}
Wire3DCGB_ErasePackedSilhouette2D

Borra una silueta empaquetada de ambos planos de color del área de preparación normal.

Sintaxis

c
void Wire3DCGB_ErasePackedSilhouette2D(const w3dcgb_u8* profile, w3dcgb_u8 count, w3dcgb_i8 y0, w3dcgb_u8 x, w3dcgb_u8 y);

Parámetros

profile

Array de silueta de un byte por fila; 0xFF omite una fila.

count

Cantidad de entradas proporcionadas; consulta el límite de procesamiento de cada operación.

y0

Desplazamiento con signo desde el centro Y hasta la primera fila de la silueta.

x

Coordenada X del centro en píxeles de la ventana gráfica.

y

Coordenada 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

c
#pragma bank 0
// Colored panels expose triangle, span, rectangle and packed-silhouette erasure.
#include "wire_cgb_example.h"
__prg_rom u8 silhouette[5]={0x73,0x74,0xFF,0x75,0x73};
void main() {
    u8 y;
    u8 bank;
    wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    for(y=8;y<=40;y++) Wire3DCGB_DrawLine2DColor(8,y,40,y,1);
    for(y=8;y<=40;y++) Wire3DCGB_DrawLine2DColor(48,y,80,y,2);
    for(y=64;y<=72;y++) Wire3DCGB_DrawLine2DColor(88,y,120,y,3);
    // The C triangle/rectangle clearers access the stage through the current
    // WRAM window. Select bank 2 around them and restore the caller's bank.
    bank=sample_svbk; sample_svbk=2;
    Wire3DCGB_EraseTriangle2D(12,12,36,12,12,36);
    Wire3DCGB_EraseSpan2D(36,40,24);
    Wire3DCGB_EraseRect2D(56,16,72,32);
    Wire3DCGB_ErasePackedSilhouette2D(silhouette,5,-2,104,68);
    sample_svbk=bank;
    Wire3DCGB_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

Resultado esperado

Triángulos, tramos horizontales, rectángulos y siluetas empaquetadas abren huecos negros en paneles rellenos de rojo, azul y verde.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_erase.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_erase.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:153

kitaqgb/lib/wire3d_cgb.c:2038

c
void Wire3DCGB_ErasePackedSilhouette2D(const w3dcgb_u8* profile, w3dcgb_u8 count,
                                      w3dcgb_i8 y0, w3dcgb_u8 x, w3dcgb_u8 y)
{
    w3dcgb_u8 i;
    w3dcgb_u8 packed;
    w3dcgb_u8 half_width;
    w3dcgb_i16 center;
    w3dcgb_i16 left;
    w3dcgb_i16 right;
    w3dcgb_i16 row;

    if (profile == 0) return;
    if (count > 29) count = 29;
    i = 0;
    while (i < count)
    {
        packed = profile[(__safe_index w3dcgb_u8)i];
        if (packed != 0xFF)
        {
            row = (w3dcgb_i16)((w3dcgb_i16)y + (w3dcgb_i16)y0 + (w3dcgb_i16)i);
            if ((row >= 0) && (row < WIRE3DCGB_SCREEN_H))
            {
                center = (w3dcgb_i16)((w3dcgb_i16)x + (w3dcgb_i16)(packed >> 4) - 7);
                half_width = (w3dcgb_u8)(packed & 15);
                left = (w3dcgb_i16)(center - (w3dcgb_i16)half_width - 2);
                right = (w3dcgb_i16)(center + (w3dcgb_i16)half_width + 2);
                if ((right >= 0) && (left < WIRE3DCGB_SCREEN_W))
                {
                    if (left < 0) left = 0;
                    if (right >= WIRE3DCGB_SCREEN_W) right = WIRE3DCGB_SCREEN_W - 1;
                    w3dcgb_mask_span_y = (w3dcgb_u8)row;
                    w3dcgb_mask_span_min_x = (w3dcgb_u8)left;
                    w3dcgb_mask_span_max_x = (w3dcgb_u8)right;
                    w3dcgb_stage_clear_span_asm();
                }
            }
        }
        i = (w3dcgb_u8)(i + 1);
    }
}
Wire3DCGB_EraseRect2D

Borra un rectángulo del área de preparación normal.

Sintaxis

c
void Wire3DCGB_EraseRect2D(w3dcgb_u8 x0, w3dcgb_u8 y0, w3dcgb_u8 x1, w3dcgb_u8 y1);

Parámetros

x0

Extremo X inferior, en píxeles de la ventana gráfica; el orden y el recorte siguen las notas de esta operación.

y0

Extremo Y inferior, en píxeles de la ventana gráfica; el orden y el recorte siguen las notas de esta operación.

x1

Extremo X superior, en píxeles de la ventana gráfica; el orden y el recorte siguen las notas de esta operación.

y1

Extremo 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

c
#pragma bank 0
// Colored panels expose triangle, span, rectangle and packed-silhouette erasure.
#include "wire_cgb_example.h"
__prg_rom u8 silhouette[5]={0x73,0x74,0xFF,0x75,0x73};
void main() {
    u8 y;
    u8 bank;
    wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    for(y=8;y<=40;y++) Wire3DCGB_DrawLine2DColor(8,y,40,y,1);
    for(y=8;y<=40;y++) Wire3DCGB_DrawLine2DColor(48,y,80,y,2);
    for(y=64;y<=72;y++) Wire3DCGB_DrawLine2DColor(88,y,120,y,3);
    // The C triangle/rectangle clearers access the stage through the current
    // WRAM window. Select bank 2 around them and restore the caller's bank.
    bank=sample_svbk; sample_svbk=2;
    Wire3DCGB_EraseTriangle2D(12,12,36,12,12,36);
    Wire3DCGB_EraseSpan2D(36,40,24);
    Wire3DCGB_EraseRect2D(56,16,72,32);
    Wire3DCGB_ErasePackedSilhouette2D(silhouette,5,-2,104,68);
    sample_svbk=bank;
    Wire3DCGB_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

Resultado esperado

Triángulos, tramos horizontales, rectángulos y siluetas empaquetadas abren huecos negros en paneles rellenos de rojo, azul y verde.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_erase.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_erase.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:145

kitaqgb/lib/wire3d_cgb.c:9146

c
void Wire3DCGB_EraseRect2D(w3dcgb_u8 x0, w3dcgb_u8 y0, w3dcgb_u8 x1, w3dcgb_u8 y1)
{
    w3dcgb_u8 t;
    w3dcgb_u8 y;

    if (x0 > x1)
    {
        t = x0;
        x0 = x1;
        x1 = t;
    }
    if (y0 > y1)
    {
        t = y0;
        y0 = y1;
        y1 = t;
    }
    if (x0 >= WIRE3DCGB_SCREEN_W) return;
    if (y0 >= WIRE3DCGB_SCREEN_H) return;
    if (x1 >= WIRE3DCGB_SCREEN_W) x1 = (w3dcgb_u8)(WIRE3DCGB_SCREEN_W - 1);
    if (y1 >= WIRE3DCGB_SCREEN_H) y1 = (w3dcgb_u8)(WIRE3DCGB_SCREEN_H - 1);

    if ((x0 == 0) &&
        (x1 == 15) &&
        (y0 == 0) &&
        (y1 == (w3dcgb_u8)(WIRE3DCGB_SCREEN_H - 1)))
    {
        w3dcgb_erase_left_guard16_asm();
        w3dcgb_mark_dirty_rect(0, 0, 15, (w3dcgb_u8)(WIRE3DCGB_SCREEN_H - 1));
        return;
    }
    if ((x0 == 0) &&
        (x1 == 23) &&
        (y0 == 0) &&
        (y1 == (w3dcgb_u8)(WIRE3DCGB_SCREEN_H - 1)))
    {
        w3dcgb_erase_left_guard24_asm();
        w3dcgb_mark_dirty_rect(0, 0, 23, (w3dcgb_u8)(WIRE3DCGB_SCREEN_H - 1));
        return;
    }

    y = y0;
    while (y <= y1)
    {
        w3dcgb_stage_clear_span(y, x0, x1);
        if (y == y1) break;
        y = (w3dcgb_u8)(y + 1);
    }
}
Wire3DCGB_EraseSpan2D

Borra un tramo horizontal, guardando y restaurando la selección del banco de WRAM.

Sintaxis

c
void Wire3DCGB_EraseSpan2D(w3dcgb_u8 y, w3dcgb_u8 x0, w3dcgb_u8 x1);

Parámetros

y

Coordenada Y en píxeles de la fila que se va a borrar.

x0

Extremo X inferior, en píxeles de la ventana gráfica; el orden y el recorte siguen las notas de esta operación.

x1

Extremo 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

c
#pragma bank 0
// Colored panels expose triangle, span, rectangle and packed-silhouette erasure.
#include "wire_cgb_example.h"
__prg_rom u8 silhouette[5]={0x73,0x74,0xFF,0x75,0x73};
void main() {
    u8 y;
    u8 bank;
    wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    for(y=8;y<=40;y++) Wire3DCGB_DrawLine2DColor(8,y,40,y,1);
    for(y=8;y<=40;y++) Wire3DCGB_DrawLine2DColor(48,y,80,y,2);
    for(y=64;y<=72;y++) Wire3DCGB_DrawLine2DColor(88,y,120,y,3);
    // The C triangle/rectangle clearers access the stage through the current
    // WRAM window. Select bank 2 around them and restore the caller's bank.
    bank=sample_svbk; sample_svbk=2;
    Wire3DCGB_EraseTriangle2D(12,12,36,12,12,36);
    Wire3DCGB_EraseSpan2D(36,40,24);
    Wire3DCGB_EraseRect2D(56,16,72,32);
    Wire3DCGB_ErasePackedSilhouette2D(silhouette,5,-2,104,68);
    sample_svbk=bank;
    Wire3DCGB_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

Resultado esperado

Triángulos, tramos horizontales, rectángulos y siluetas empaquetadas abren huecos negros en paneles rellenos de rojo, azul y verde.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_erase.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_erase.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:134

kitaqgb/lib/wire3d_cgb.c:9123

c
void Wire3DCGB_EraseSpan2D(w3dcgb_u8 y, w3dcgb_u8 x0, w3dcgb_u8 x1)
{
    w3dcgb_u8 tx;

    if (x0 > x1)
    {
        tx = x0;
        x0 = x1;
        x1 = tx;
    }
    if ((y >= WIRE3DCGB_SCREEN_H) || (x0 >= WIRE3DCGB_SCREEN_W)) return;
    if (x1 >= WIRE3DCGB_SCREEN_W) x1 = WIRE3DCGB_SCREEN_W - 1;
    w3dcgb_mark_dirty_rect(x0, y, x1, y);
    w3dcgb_mask_span_y = y;
    w3dcgb_mask_span_min_x = x0;
    w3dcgb_mask_span_max_x = x1;
    w3dcgb_stage_clear_span_asm();
}
Wire3DCGB_EraseTriangle2D

Borra un triángulo de ambos planos de color del área de preparación normal.

Sintaxis

c
void Wire3DCGB_EraseTriangle2D(w3dcgb_u8 ax, w3dcgb_u8 ay, w3dcgb_u8 bx, w3dcgb_u8 by, w3dcgb_u8 cx, w3dcgb_u8 cy);

Parámetros

ax

Coordenada X del vértice A en píxeles de la ventana gráfica.

ay

Coordenada Y del vértice A en píxeles de la ventana gráfica.

bx

Coordenada X del vértice B en píxeles de la ventana gráfica.

by

Coordenada Y del vértice B en píxeles de la ventana gráfica.

cx

Coordenada X del vértice C en píxeles de la ventana gráfica.

cy

Coordenada 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

c
#pragma bank 0
// Colored panels expose triangle, span, rectangle and packed-silhouette erasure.
#include "wire_cgb_example.h"
__prg_rom u8 silhouette[5]={0x73,0x74,0xFF,0x75,0x73};
void main() {
    u8 y;
    u8 bank;
    wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    for(y=8;y<=40;y++) Wire3DCGB_DrawLine2DColor(8,y,40,y,1);
    for(y=8;y<=40;y++) Wire3DCGB_DrawLine2DColor(48,y,80,y,2);
    for(y=64;y<=72;y++) Wire3DCGB_DrawLine2DColor(88,y,120,y,3);
    // The C triangle/rectangle clearers access the stage through the current
    // WRAM window. Select bank 2 around them and restore the caller's bank.
    bank=sample_svbk; sample_svbk=2;
    Wire3DCGB_EraseTriangle2D(12,12,36,12,12,36);
    Wire3DCGB_EraseSpan2D(36,40,24);
    Wire3DCGB_EraseRect2D(56,16,72,32);
    Wire3DCGB_ErasePackedSilhouette2D(silhouette,5,-2,104,68);
    sample_svbk=bank;
    Wire3DCGB_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

Resultado esperado

Triángulos, tramos horizontales, rectángulos y siluetas empaquetadas abren huecos negros en paneles rellenos de rojo, azul y verde.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_erase.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_erase.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:133

kitaqgb/lib/wire3d_cgb.c:9113

c
void Wire3DCGB_EraseTriangle2D(w3dcgb_u8 ax, w3dcgb_u8 ay, w3dcgb_u8 bx, w3dcgb_u8 by, w3dcgb_u8 cx, w3dcgb_u8 cy)
{
    w3dcgb_clear_triangle(ax, ay, bx, by, cx, cy);
}
Wire3DCGB_FastMapBegin

Borra los números de tile y los atributos de la ventana gráfica FastMap de 16×12.

Sintaxis

c
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

c
#pragma bank 0
// FastMap uses precomputed outline tiles rather than a pixel stage upload.
#include "wire_cgb_example.h"
void main() {
    u8 bank;
    wire_results_clear(); Wire3DCGB_InitFastMapLite(); wire_colors();
    bank=sample_svbk;sample_svbk=2;
    Wire3DCGB_FastMapBegin();
    Wire3DCGB_FastMapCell(1,1,1,15); // This first red square must disappear.
    Wire3DCGB_FastMapFlush();
    Wire3DCGB_FastMapBeginTilesOnly();
    Wire3DCGB_FastMapCell(13,1,1,1);
    Wire3DCGB_FastMapCell(13,1,1,4); // Same-color top and left sides combine.
    Wire3DCGB_FastMapRect(4,2,9,7,2,15);
    Wire3DCGB_FastMapCell(2,9,3,15);
    Wire3DCGB_FastMapFlushTilesOnly();
    sample_svbk=bank;result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_fastmap.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_fastmap.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:160

kitaqgb/lib/wire3d_cgb.c:10137

c
void Wire3DCGB_FastMapBegin()
{
    w3dcgb_fast_map_ready = 1;
    w3dcgb_fast_map_clear_rect(0, 0, 16, 12);
}
Wire3DCGB_FastMapBeginTilesOnly

Borra solo los números de tile de la ventana gráfica FastMap de 16×12.

Sintaxis

c
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

c
#pragma bank 0
// FastMap uses precomputed outline tiles rather than a pixel stage upload.
#include "wire_cgb_example.h"
void main() {
    u8 bank;
    wire_results_clear(); Wire3DCGB_InitFastMapLite(); wire_colors();
    bank=sample_svbk;sample_svbk=2;
    Wire3DCGB_FastMapBegin();
    Wire3DCGB_FastMapCell(1,1,1,15); // This first red square must disappear.
    Wire3DCGB_FastMapFlush();
    Wire3DCGB_FastMapBeginTilesOnly();
    Wire3DCGB_FastMapCell(13,1,1,1);
    Wire3DCGB_FastMapCell(13,1,1,4); // Same-color top and left sides combine.
    Wire3DCGB_FastMapRect(4,2,9,7,2,15);
    Wire3DCGB_FastMapCell(2,9,3,15);
    Wire3DCGB_FastMapFlushTilesOnly();
    sample_svbk=bank;result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_fastmap.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_fastmap.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:161

kitaqgb/lib/wire3d_cgb.c:10146

c
void Wire3DCGB_FastMapBeginTilesOnly()
{
    w3dcgb_fast_map_ready = 1;
    w3dcgb_fm_x0 = 0;
    w3dcgb_fm_y0 = 0;
    w3dcgb_fm_count_x = 16;
    w3dcgb_fm_count_y = 12;
    w3dcgb_fast_map_clear_rect_asm();
}
Wire3DCGB_FastMapCell

Añade a una celda del mapa los lados de contorno elegidos entre arriba, abajo, izquierda y derecha.

Sintaxis

c
void Wire3DCGB_FastMapCell(w3dcgb_u8 tx, w3dcgb_u8 ty, w3dcgb_u8 color, w3dcgb_u8 mask);

Parámetros

tx

Posición X en coordenadas de tile.

ty

Posición Y en coordenadas de tile.

color

Índice de color de dibujo; las paletas de ejemplo usan 1=rojo, 2=azul y 3=verde.

mask

Má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

c
#pragma bank 0
// FastMap uses precomputed outline tiles rather than a pixel stage upload.
#include "wire_cgb_example.h"
void main() {
    u8 bank;
    wire_results_clear(); Wire3DCGB_InitFastMapLite(); wire_colors();
    bank=sample_svbk;sample_svbk=2;
    Wire3DCGB_FastMapBegin();
    Wire3DCGB_FastMapCell(1,1,1,15); // This first red square must disappear.
    Wire3DCGB_FastMapFlush();
    Wire3DCGB_FastMapBeginTilesOnly();
    Wire3DCGB_FastMapCell(13,1,1,1);
    Wire3DCGB_FastMapCell(13,1,1,4); // Same-color top and left sides combine.
    Wire3DCGB_FastMapRect(4,2,9,7,2,15);
    Wire3DCGB_FastMapCell(2,9,3,15);
    Wire3DCGB_FastMapFlushTilesOnly();
    sample_svbk=bank;result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_fastmap.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_fastmap.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:162

kitaqgb/lib/wire3d_cgb.c:10160

c
void Wire3DCGB_FastMapCell(w3dcgb_u8 tx, w3dcgb_u8 ty, w3dcgb_u8 color, w3dcgb_u8 mask)
{
    w3dcgb_fast_map_or_cell((w3dcgb_i16)tx, (w3dcgb_i16)ty, color, mask);
}
Wire3DCGB_FastMapFlush

Transfiere a VRAM las primeras doce filas completas de números de tile y atributos de la copia de trabajo.

Sintaxis

c
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

c
#pragma bank 0
// FastMap uses precomputed outline tiles rather than a pixel stage upload.
#include "wire_cgb_example.h"
void main() {
    u8 bank;
    wire_results_clear(); Wire3DCGB_InitFastMapLite(); wire_colors();
    bank=sample_svbk;sample_svbk=2;
    Wire3DCGB_FastMapBegin();
    Wire3DCGB_FastMapCell(1,1,1,15); // This first red square must disappear.
    Wire3DCGB_FastMapFlush();
    Wire3DCGB_FastMapBeginTilesOnly();
    Wire3DCGB_FastMapCell(13,1,1,1);
    Wire3DCGB_FastMapCell(13,1,1,4); // Same-color top and left sides combine.
    Wire3DCGB_FastMapRect(4,2,9,7,2,15);
    Wire3DCGB_FastMapCell(2,9,3,15);
    Wire3DCGB_FastMapFlushTilesOnly();
    sample_svbk=bank;result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_fastmap.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_fastmap.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:164

kitaqgb/lib/wire3d_cgb.c:10208

c
void Wire3DCGB_FastMapFlush()
{
    w3dcgb_wait_vblank_start();
    w3dcgb_fast_map_flush_gdma_asm();
}
Wire3DCGB_FastMapFlushTilesOnly

Transfiere solo los números de tile de las primeras doce filas completas del mapa de trabajo.

Sintaxis

c
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

c
#pragma bank 0
// FastMap uses precomputed outline tiles rather than a pixel stage upload.
#include "wire_cgb_example.h"
void main() {
    u8 bank;
    wire_results_clear(); Wire3DCGB_InitFastMapLite(); wire_colors();
    bank=sample_svbk;sample_svbk=2;
    Wire3DCGB_FastMapBegin();
    Wire3DCGB_FastMapCell(1,1,1,15); // This first red square must disappear.
    Wire3DCGB_FastMapFlush();
    Wire3DCGB_FastMapBeginTilesOnly();
    Wire3DCGB_FastMapCell(13,1,1,1);
    Wire3DCGB_FastMapCell(13,1,1,4); // Same-color top and left sides combine.
    Wire3DCGB_FastMapRect(4,2,9,7,2,15);
    Wire3DCGB_FastMapCell(2,9,3,15);
    Wire3DCGB_FastMapFlushTilesOnly();
    sample_svbk=bank;result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_fastmap.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_fastmap.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:165

kitaqgb/lib/wire3d_cgb.c:10217

c
void Wire3DCGB_FastMapFlushTilesOnly()
{
    w3dcgb_wait_vblank_start();
    w3dcgb_fast_map_flush_tiles_gdma_asm();
}
Wire3DCGB_FastMapRect

Coloca los lados de contorno elegidos alrededor de un rectángulo en coordenadas de tile.

Sintaxis

c
void Wire3DCGB_FastMapRect(w3dcgb_u8 tx0, w3dcgb_u8 ty0, w3dcgb_u8 tx1, w3dcgb_u8 ty1, w3dcgb_u8 color, w3dcgb_u8 sides);

Parámetros

tx0

Posición X en coordenadas de tile.

ty0

Posición Y en coordenadas de tile.

tx1

Posición X en coordenadas de tile.

ty1

Posición Y en coordenadas de tile.

color

Índice de color de dibujo; las paletas de ejemplo usan 1=rojo, 2=azul y 3=verde.

sides

Má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

c
#pragma bank 0
// FastMap uses precomputed outline tiles rather than a pixel stage upload.
#include "wire_cgb_example.h"
void main() {
    u8 bank;
    wire_results_clear(); Wire3DCGB_InitFastMapLite(); wire_colors();
    bank=sample_svbk;sample_svbk=2;
    Wire3DCGB_FastMapBegin();
    Wire3DCGB_FastMapCell(1,1,1,15); // This first red square must disappear.
    Wire3DCGB_FastMapFlush();
    Wire3DCGB_FastMapBeginTilesOnly();
    Wire3DCGB_FastMapCell(13,1,1,1);
    Wire3DCGB_FastMapCell(13,1,1,4); // Same-color top and left sides combine.
    Wire3DCGB_FastMapRect(4,2,9,7,2,15);
    Wire3DCGB_FastMapCell(2,9,3,15);
    Wire3DCGB_FastMapFlushTilesOnly();
    sample_svbk=bank;result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_fastmap.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_fastmap.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:163

kitaqgb/lib/wire3d_cgb.c:10170

c
void Wire3DCGB_FastMapRect(w3dcgb_u8 tx0, w3dcgb_u8 ty0, w3dcgb_u8 tx1, w3dcgb_u8 ty1, w3dcgb_u8 color, w3dcgb_u8 sides)
{
    w3dcgb_u8 t;

    if (tx0 > tx1)
    {
        t = tx0;
        tx0 = tx1;
        tx1 = t;
    }
    if (ty0 > ty1)
    {
        t = ty0;
        ty0 = ty1;
        ty1 = t;
    }
    if (tx0 >= 16) return;
    if (ty0 >= 12) return;
    if (tx1 >= 16) tx1 = 15;
    if (ty1 >= 12) ty1 = 11;
    if (color == 0) color = WIRE3DCGB_COLOR_MAIN;
    if (color > 3) color = 3;

    w3dcgb_fm_x0 = tx0;
    w3dcgb_fm_y0 = ty0;
    w3dcgb_fm_x1 = tx1;
    w3dcgb_fm_y1 = ty1;
    w3dcgb_fm_count_x = (w3dcgb_u8)(tx1 - tx0 + 1);
    w3dcgb_fm_count_y = (w3dcgb_u8)(ty1 - ty0 + 1);
    w3dcgb_fm_tile_base = (w3dcgb_u8)(W3DCGB_FAST_TILE_BASE + ((color - 1) << 4));
    w3dcgb_fm_sides = (w3dcgb_u8)(sides & 15);
    w3dcgb_fast_map_rect_asm();
}
Wire3DCGB_GetFullScreenOverflow

Informa de una coordenada inválida o del agotamiento de tiles al dibujar a pantalla completa.

Sintaxis

c
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

c
#pragma bank 0
// One point per tile exposes the 127-tile limit without relying on text alone.
#include "wire_cgb_example.h"
void main() {
    u8 i;
    wire_results_clear();
    Wire3DCGB_InitFullScreen(); wire_colors();
    Wire3DCGB_BeginFrame(); Wire3DCGB_SetLineColor(3);
    for(i=0;i<128;i++) Wire3DCGB_DrawPoint2D((i%20)*8+4,(i/20)*8+4);
    result[0]=Wire3DCGB_GetFullScreenTileCount();
    result[1]=Wire3DCGB_GetFullScreenOverflow();
    Wire3DCGB_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_capacity.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_capacity.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:194

kitaqgb/lib/wire3d_cgb.c:9965

c
w3dcgb_u8 Wire3DCGB_GetFullScreenOverflow()
{
    return w3dcgb_full_overflow;
}
Wire3DCGB_GetFullScreenTileCount

Devuelve la cantidad de tiles de pantalla completa asignados en el fotograma actual.

Sintaxis

c
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

c
#pragma bank 0
// One point per tile exposes the 127-tile limit without relying on text alone.
#include "wire_cgb_example.h"
void main() {
    u8 i;
    wire_results_clear();
    Wire3DCGB_InitFullScreen(); wire_colors();
    Wire3DCGB_BeginFrame(); Wire3DCGB_SetLineColor(3);
    for(i=0;i<128;i++) Wire3DCGB_DrawPoint2D((i%20)*8+4,(i/20)*8+4);
    result[0]=Wire3DCGB_GetFullScreenTileCount();
    result[1]=Wire3DCGB_GetFullScreenOverflow();
    Wire3DCGB_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_capacity.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_capacity.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:193

kitaqgb/lib/wire3d_cgb.c:9956

c
w3dcgb_u8 Wire3DCGB_GetFullScreenTileCount()
{
    return w3dcgb_full_tile_count;
}
Wire3DCGB_GetLineColor

Lee el índice de color de línea guardado actualmente.

Sintaxis

c
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

c
#pragma bank 0
// CGB raster paths: a red frame, blue diagonal, green marker and clipped line.
// Build this source together with lib/wire3d_cgb.c in an MBC5 256 KB CGB ROM.
#include "wire3d_cgb.h"
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4D) u8 sample_key1;
__location(0xC110) u16 result[8];
__prg_rom u8 lower_lines[8]={80,56,112,56,112,56,112,80};

void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DCGB_EnableDoubleSpeed();
    Wire3DCGB_Init(); // Already at double speed: its internal request is a no-op.
    result[2]=(u8)(sample_key1&128);
    // Palette writes are performed with the LCD off, after entering VBlank.
    while(sample_ly>=144) {} while(sample_ly<144) {}
    sample_lcdc=0;
    Wire3DCGB_SetPaletteRGB15(WIRE3DCGB_RGB15(0,0,0),WIRE3DCGB_RGB15(31,0,0),WIRE3DCGB_RGB15(0,0,31),WIRE3DCGB_RGB15(0,31,0));
    sample_lcdc=0x81;
    Wire3DCGB_SetScreenOffset(0,0);
    Wire3DCGB_SetCamera(0,0,0,0,0,0);
    Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawLine2D(8,8,56,8);
    Wire3DCGB_DrawLine2D(56,8,56,40);
    Wire3DCGB_DrawLine2D(56,40,8,40);
    Wire3DCGB_DrawLine2D(8,40,8,8);
    Wire3DCGB_DrawLine2DColor(8,40,56,8,2);
    result[0]=Wire3DCGB_GetLineColor(); // Temporary blue restores red.
    Wire3DCGB_SetLineColor(3);
    Wire3DCGB_DrawPoint2D(64,48);
    Wire3DCGB_DrawLineClipped2D(-10,72,140,72,3);
    Wire3DCGB_DrawLineList2DColor(lower_lines,2,2);
    result[1]=Wire3DCGB_GetLineColor(); // The blue line list restores green.
    Wire3DCGB_PutBgTile(18,1,0x80); // Queue the supplied zero glyph outside the viewport.
    Wire3DCGB_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_raster.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:120

kitaqgb/lib/wire3d_cgb.c:1147

c
w3dcgb_u8 Wire3DCGB_GetLineColor()
{
    return w3dcgb_line_color;
}
Wire3DCGB_Init

Inicializa el renderizador de píxeles de 128×96 para CGB.

Sintaxis

c
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

c
#pragma bank 0
// CGB raster paths: a red frame, blue diagonal, green marker and clipped line.
// Build this source together with lib/wire3d_cgb.c in an MBC5 256 KB CGB ROM.
#include "wire3d_cgb.h"
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4D) u8 sample_key1;
__location(0xC110) u16 result[8];
__prg_rom u8 lower_lines[8]={80,56,112,56,112,56,112,80};

void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DCGB_EnableDoubleSpeed();
    Wire3DCGB_Init(); // Already at double speed: its internal request is a no-op.
    result[2]=(u8)(sample_key1&128);
    // Palette writes are performed with the LCD off, after entering VBlank.
    while(sample_ly>=144) {} while(sample_ly<144) {}
    sample_lcdc=0;
    Wire3DCGB_SetPaletteRGB15(WIRE3DCGB_RGB15(0,0,0),WIRE3DCGB_RGB15(31,0,0),WIRE3DCGB_RGB15(0,0,31),WIRE3DCGB_RGB15(0,31,0));
    sample_lcdc=0x81;
    Wire3DCGB_SetScreenOffset(0,0);
    Wire3DCGB_SetCamera(0,0,0,0,0,0);
    Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawLine2D(8,8,56,8);
    Wire3DCGB_DrawLine2D(56,8,56,40);
    Wire3DCGB_DrawLine2D(56,40,8,40);
    Wire3DCGB_DrawLine2D(8,40,8,8);
    Wire3DCGB_DrawLine2DColor(8,40,56,8,2);
    result[0]=Wire3DCGB_GetLineColor(); // Temporary blue restores red.
    Wire3DCGB_SetLineColor(3);
    Wire3DCGB_DrawPoint2D(64,48);
    Wire3DCGB_DrawLineClipped2D(-10,72,140,72,3);
    Wire3DCGB_DrawLineList2DColor(lower_lines,2,2);
    result[1]=Wire3DCGB_GetLineColor(); // The blue line list restores green.
    Wire3DCGB_PutBgTile(18,1,0x80); // Queue the supplied zero glyph outside the viewport.
    Wire3DCGB_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_raster.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:113

kitaqgb/lib/wire3d_cgb.c:7994

c
void Wire3DCGB_Init()
{
    w3dcgb_u8 row;
    w3dcgb_u8 col;
    w3dcgb_u8 tid;
    w3dcgb_u8 tile_index;
    w3dcgb_u16 off;

    w3dcgb_full_mode = 0;
    w3dcgb_atomic_maps = 0;
    Wire3DCGB_EnableDoubleSpeed();
    w3dcgb_wait_vblank_start();
    w3dcgb_reg_lcdc = 0;

    w3dcgb_clear_vram_asm();
    w3dcgb_load_hud_tiles();
#ifndef WIRE3DCGB_MINIMAL_RUNTIME
    w3dcgb_load_fast_map_tiles();
    w3dcgb_load_fast_stamp_tiles();
#endif
    w3dcgb_fill_bg_map_asm();
    w3dcgb_fill_attr_map_asm();

    row = 0;
    while (row < W3DCGB_TILE_H)
    {
        off = (w3dcgb_u16)((w3dcgb_u16)row << 5);
        tile_index = row;
        col = 0;
        while (col < W3DCGB_TILE_W)
        {
            if (tile_index < 112) tid = (w3dcgb_u8)(0x90 + tile_index);
            else tid = (w3dcgb_u8)(tile_index - 112);
            w3dcgb_bg_map_9800[(w3dcgb_u16)(off + (w3dcgb_u16)col)] = tid;
            tile_index = (w3dcgb_u8)(tile_index + W3DCGB_TILE_H);
            col = (w3dcgb_u8)(col + 1);
        }
        row = (w3dcgb_u8)(row + 1);
    }

    w3dcgb_select_blank_render_bank_asm();

    w3dcgb_reg_scx = 0;
    w3dcgb_reg_scy = 0;
    w3dcgb_reg_bgp = 0xB4;
    Wire3DCGB_SetPaletteRGB15(
        WIRE3DCGB_RGB15(0, 0, 2),
        WIRE3DCGB_RGB15(10, 20, 31),
        WIRE3DCGB_RGB15(31, 31, 31),
        WIRE3DCGB_RGB15(31, 14, 4));
    w3dcgb_line_color = WIRE3DCGB_COLOR_DEFAULT;
    w3dcgb_reg_lcdc = 0x81;
    w3dcgb_bgq_count = 0;
    w3dcgb_dirty_count = 0;
    w3dcgb_prev_dirty_count = 0;
    w3dcgb_dirty_min_tile = 0xFF;
    w3dcgb_dirty_max_tile = 0;
    // Both back banks may contain generated fast-map/stamp tiles. Refresh
    // the whole pixel viewport on their first sparse use, including empty rows.
    w3dcgb_prev_dirty_min_tile = 0;
    w3dcgb_prev_dirty_max_tile = (w3dcgb_u8)(WIRE3DCGB_TILE_COUNT - 1);
    w3dcgb_older_dirty_min_tile = 0;
    w3dcgb_older_dirty_max_tile = (w3dcgb_u8)(WIRE3DCGB_TILE_COUNT - 1);
    w3dcgb_display_tile_bank = 1;
    w3dcgb_pending_tile_bank = 1;

    Wire3DCGB_SetCamera((w3dcgb_i16)0, (w3dcgb_i16)0, (w3dcgb_i16)0, 0, 0, 0);
    w3dcgb_clear_stage_asm();
}
Wire3DCGB_InitFastMapLite

Inicializa el renderizado FastMap con tiles de contorno precalculados.

Sintaxis

c
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

c
#pragma bank 0
// FastMap uses precomputed outline tiles rather than a pixel stage upload.
#include "wire_cgb_example.h"
void main() {
    u8 bank;
    wire_results_clear(); Wire3DCGB_InitFastMapLite(); wire_colors();
    bank=sample_svbk;sample_svbk=2;
    Wire3DCGB_FastMapBegin();
    Wire3DCGB_FastMapCell(1,1,1,15); // This first red square must disappear.
    Wire3DCGB_FastMapFlush();
    Wire3DCGB_FastMapBeginTilesOnly();
    Wire3DCGB_FastMapCell(13,1,1,1);
    Wire3DCGB_FastMapCell(13,1,1,4); // Same-color top and left sides combine.
    Wire3DCGB_FastMapRect(4,2,9,7,2,15);
    Wire3DCGB_FastMapCell(2,9,3,15);
    Wire3DCGB_FastMapFlushTilesOnly();
    sample_svbk=bank;result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_fastmap.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_fastmap.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:115

kitaqgb/lib/wire3d_cgb.c:8108

c
void Wire3DCGB_InitFastMapLite()
{
    w3dcgb_atomic_maps = 0;
    w3dcgb_full_mode = 0;
    Wire3DCGB_EnableDoubleSpeed();
    w3dcgb_wait_vblank_start();
    w3dcgb_reg_lcdc = 0;

    w3dcgb_clear_vram_asm();
    w3dcgb_load_hud_tiles();
    w3dcgb_load_fast_map_tiles_lite_asm();
    w3dcgb_fill_bg_map_asm();
    w3dcgb_fill_attr_map_asm();

    w3dcgb_reg_scx = 0;
    w3dcgb_reg_scy = 0;
    w3dcgb_reg_bgp = 0xB4;
    Wire3DCGB_SetPaletteRGB15(
        WIRE3DCGB_RGB15(0, 0, 2),
        WIRE3DCGB_RGB15(10, 20, 31),
        WIRE3DCGB_RGB15(31, 31, 31),
        WIRE3DCGB_RGB15(31, 14, 4));
    w3dcgb_line_color = WIRE3DCGB_COLOR_DEFAULT;
    w3dcgb_reg_lcdc = 0x81;
    w3dcgb_bgq_count = 0;
    w3dcgb_dirty_count = 0;
    w3dcgb_prev_dirty_count = 0;
    w3dcgb_dirty_min_tile = 0xFF;
    w3dcgb_dirty_max_tile = 0;
    w3dcgb_prev_dirty_min_tile = 0xFF;
    w3dcgb_prev_dirty_max_tile = 0;
    w3dcgb_fast_map_ready = 0;
    w3dcgb_display_tile_bank = 0;
    w3dcgb_pending_tile_bank = 0;

    Wire3DCGB_SetCamera((w3dcgb_i16)0, (w3dcgb_i16)0, (w3dcgb_i16)0, 0, 0, 0);
    w3dcgb_clear_stage_asm();
}
Wire3DCGB_InitFullScreen

Inicializa un renderizador de 160×144 que asigna tiles a medida que dibuja píxeles.

Sintaxis

c
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

c
#pragma bank 0
// A large frame demonstrates the 160x144 renderer and its allocated-tile count.
#include "wire_cgb_example.h"
void main() {
    wire_results_clear();
    Wire3DCGB_InitFullScreen(); wire_colors();
    Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawLine2D(8,8,151,8);
    Wire3DCGB_DrawLine2D(8,8,8,135);
    Wire3DCGB_DrawLine2DColor(8,135,151,135,2);
    Wire3DCGB_DrawLine2DColor(151,8,151,135,3);
    result[0]=Wire3DCGB_GetFullScreenTileCount();
    result[1]=Wire3DCGB_GetFullScreenOverflow();
    Wire3DCGB_EndFrameFast();
    result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_full.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_full.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:114

kitaqgb/lib/wire3d_cgb.c:8070

c
void Wire3DCGB_InitFullScreen()
{
    w3dcgb_atomic_maps = 0;
    Wire3DCGB_EnableDoubleSpeed();
    w3dcgb_wait_vblank_start();
    w3dcgb_reg_lcdc = 0;

    w3dcgb_clear_vram_asm();
    w3dcgb_full_clear_map_asm();
    w3dcgb_reg_scx = 0;
    w3dcgb_reg_scy = 0;
    w3dcgb_reg_bgp = 0xB4;
    Wire3DCGB_SetPaletteRGB15(
        WIRE3DCGB_RGB15(0, 0, 2),
        WIRE3DCGB_RGB15(10, 20, 31),
        WIRE3DCGB_RGB15(31, 31, 31),
        WIRE3DCGB_RGB15(31, 14, 4));
    w3dcgb_line_color = WIRE3DCGB_COLOR_DEFAULT;
    w3dcgb_bgq_count = 0;
    w3dcgb_dirty_count = 0;
    w3dcgb_prev_dirty_count = 0;
    w3dcgb_display_tile_bank = 0;
    w3dcgb_pending_tile_bank = 0;
    w3dcgb_full_tile_count = 0;
    w3dcgb_full_prev_tile_count = 0;
    w3dcgb_full_overflow = 0;
    w3dcgb_full_mode = 1;

    Wire3DCGB_SetCamera((w3dcgb_i16)0, (w3dcgb_i16)0, (w3dcgb_i16)0, 0, 0, 0);
    w3dcgb_full_begin_asm();
    w3dcgb_reg_lcdc = 0x91;
}
Wire3DCGB_InvalidateFrameHistory

Amplía el rango de transferencia actual y los dos anteriores a los 192 tiles del modo normal.

Sintaxis

c
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

c
#pragma bank 0
// Reuse both VRAM banks and remove old geometry while presenting sparse frames.
#include "wire_cgb_example.h"
void main() {
    wire_results_clear(); Wire3DCGB_Init();
    Wire3DCGB_ClearFrameTiles();
    Wire3DCGB_EnableAtomicMaps(); wire_colors();
    // First frame: red on the left. Fast begin invalidates both bank histories.
    Wire3DCGB_BeginFrameFast(); wire_frame(8,8,32,32,1);
    Wire3DCGB_EndFrameFast();
    // Second frame: blue in the middle, with the old red frame removed.
    Wire3DCGB_BeginFrameSparse(); wire_frame(40,40,64,64,2);
    Wire3DCGB_EndFrameSparse();
    // Third frame: explicitly clearing a stage discards its first green point.
    Wire3DCGB_BeginFrameSparse();
    Wire3DCGB_SetLineColor(3); Wire3DCGB_DrawPoint2D(4,4);
    Wire3DCGB_ClearSparseStageFast();
    // The final image contains only this green frame on the right.
    wire_frame(80,8,112,32,3);
    Wire3DCGB_MarkDirtyRect2D(80,8,112,32);
    Wire3DCGB_InvalidateFrameHistory();
    Wire3DCGB_EndFrameSparseNow();
    result[0]=Wire3DCGB_GetLineColor();
    result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_sparse.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_sparse.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:142

kitaqgb/lib/wire3d_cgb.c:9712

c
void Wire3DCGB_InvalidateFrameHistory()
{
    w3dcgb_dirty_min_tile = 0;
    w3dcgb_dirty_max_tile = (w3dcgb_u8)(WIRE3DCGB_TILE_COUNT - 1);
    w3dcgb_prev_dirty_min_tile = 0;
    w3dcgb_prev_dirty_max_tile = (w3dcgb_u8)(WIRE3DCGB_TILE_COUNT - 1);
    w3dcgb_older_dirty_min_tile = 0;
    w3dcgb_older_dirty_max_tile = (w3dcgb_u8)(WIRE3DCGB_TILE_COUNT - 1);
}
Wire3DCGB_MarkDirtyRect2D

Añade un rectángulo de píxeles al rango que habrá que transferir después.

Sintaxis

c
void Wire3DCGB_MarkDirtyRect2D(w3dcgb_u8 min_x, w3dcgb_u8 min_y, w3dcgb_u8 max_x, w3dcgb_u8 max_y);

Parámetros

min_x

Extremo X inferior, en píxeles de la ventana gráfica; el orden y el recorte siguen las notas de esta operación.

min_y

Extremo Y inferior, en píxeles de la ventana gráfica; el orden y el recorte siguen las notas de esta operación.

max_x

Extremo X superior, en píxeles de la ventana gráfica; el orden y el recorte siguen las notas de esta operación.

max_y

Extremo 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

c
#pragma bank 0
// Reuse both VRAM banks and remove old geometry while presenting sparse frames.
#include "wire_cgb_example.h"
void main() {
    wire_results_clear(); Wire3DCGB_Init();
    Wire3DCGB_ClearFrameTiles();
    Wire3DCGB_EnableAtomicMaps(); wire_colors();
    // First frame: red on the left. Fast begin invalidates both bank histories.
    Wire3DCGB_BeginFrameFast(); wire_frame(8,8,32,32,1);
    Wire3DCGB_EndFrameFast();
    // Second frame: blue in the middle, with the old red frame removed.
    Wire3DCGB_BeginFrameSparse(); wire_frame(40,40,64,64,2);
    Wire3DCGB_EndFrameSparse();
    // Third frame: explicitly clearing a stage discards its first green point.
    Wire3DCGB_BeginFrameSparse();
    Wire3DCGB_SetLineColor(3); Wire3DCGB_DrawPoint2D(4,4);
    Wire3DCGB_ClearSparseStageFast();
    // The final image contains only this green frame on the right.
    wire_frame(80,8,112,32,3);
    Wire3DCGB_MarkDirtyRect2D(80,8,112,32);
    Wire3DCGB_InvalidateFrameHistory();
    Wire3DCGB_EndFrameSparseNow();
    result[0]=Wire3DCGB_GetLineColor();
    result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_sparse.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_sparse.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:126

kitaqgb/lib/wire3d_cgb.c:1288

c
void Wire3DCGB_MarkDirtyRect2D(w3dcgb_u8 min_x, w3dcgb_u8 min_y, w3dcgb_u8 max_x, w3dcgb_u8 max_y)
{
    w3dcgb_mark_dirty_rect(min_x, min_y, max_x, max_y);
}
Wire3DCGB_MarkPackedSilhouette2D

Marca una silueta empaquetada por filas en el mapa de bits de oclusión de 128×96.

Sintaxis

c
void Wire3DCGB_MarkPackedSilhouette2D(const w3dcgb_u8* profile, w3dcgb_u8 count, w3dcgb_i8 y0, w3dcgb_u8 x, w3dcgb_u8 y);

Parámetros

profile

Array de silueta de un byte por fila; 0xFF omite una fila.

count

Cantidad de entradas proporcionadas; consulta el límite de procesamiento de cada operación.

y0

Desplazamiento con signo desde el centro Y hasta la primera fila de la silueta.

x

Coordenada X del centro en píxeles de la ventana gráfica.

y

Coordenada 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

c
#pragma bank 0
// Red/blue scanlines stop inside masks; green outlines identify the triangle.
#include "wire_cgb_example.h"
__prg_rom u8 silhouette[5]={0x73,0x74,0xFF,0x75,0x73};
void main() {
    u8 y;
    wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    // Clearing this first test mask must leave the upper-left scanline intact.
    Wire3DCGB_MarkTriangle2D(8,8,16,8,8,16);
    Wire3DCGB_ClearOcclusionMask();
    Wire3DCGB_MarkTriangle2D(32,16,64,16,32,48);
    Wire3DCGB_MarkPackedSilhouette2D(silhouette,5,-2,104,32);
    Wire3DCGB_SetOcclusionActive(1);
    for(y=8;y<=56;y=y+4) Wire3DCGB_DrawLine2DColor(8,y,88,y,1);
    for(y=28;y<=36;y++) Wire3DCGB_DrawLine2DColor(92,y,120,y,2);
    Wire3DCGB_SetOcclusionActive(0);
    Wire3DCGB_DrawLine2DColor(32,16,64,16,3);
    Wire3DCGB_DrawLine2DColor(64,16,32,48,3);
    Wire3DCGB_DrawLine2DColor(32,48,32,16,3);
    Wire3DCGB_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_mask.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_mask.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:151

kitaqgb/lib/wire3d_cgb.c:1991

c
void Wire3DCGB_MarkPackedSilhouette2D(const w3dcgb_u8* profile, w3dcgb_u8 count,
                                     w3dcgb_i8 y0, w3dcgb_u8 x, w3dcgb_u8 y)
{
    w3dcgb_u8 i;
    w3dcgb_u8 packed;
    w3dcgb_u8 half_width;
    w3dcgb_i16 center;
    w3dcgb_i16 left;
    w3dcgb_i16 right;
    w3dcgb_i16 row;

    if (profile == 0) return;
    if (count > 29) count = 29;
    i = 0;
    while (i < count)
    {
        packed = profile[(__safe_index w3dcgb_u8)i];
        if (packed != 0xFF)
        {
            row = (w3dcgb_i16)((w3dcgb_i16)y + (w3dcgb_i16)y0 + (w3dcgb_i16)i);
            if ((row >= 0) && (row < WIRE3DCGB_SCREEN_H))
            {
                center = (w3dcgb_i16)((w3dcgb_i16)x + (w3dcgb_i16)(packed >> 4) - 7);
                half_width = (w3dcgb_u8)(packed & 15);
                /* Two-pixel guard covers rasterized endpoints at 22.5-degree views. */
                left = (w3dcgb_i16)(center - (w3dcgb_i16)half_width - 2);
                right = (w3dcgb_i16)(center + (w3dcgb_i16)half_width + 2);
                if ((right >= 0) && (left < WIRE3DCGB_SCREEN_W))
                {
                    if (left < 0) left = 0;
                    if (right >= WIRE3DCGB_SCREEN_W) right = WIRE3DCGB_SCREEN_W - 1;
                    w3dcgb_mask_span_y = (w3dcgb_u8)row;
                    w3dcgb_mask_span_min_x = (w3dcgb_u8)left;
                    w3dcgb_mask_span_max_x = (w3dcgb_u8)right;
                    w3dcgb_mask_set_span_asm();
                }
            }
        }
        i = (w3dcgb_u8)(i + 1);
    }
}
Wire3DCGB_MarkTriangle2D

Registra un triángulo como zona que puede ocultar las líneas dibujadas después.

Sintaxis

c
void Wire3DCGB_MarkTriangle2D(w3dcgb_u8 ax, w3dcgb_u8 ay, w3dcgb_u8 bx, w3dcgb_u8 by, w3dcgb_u8 cx, w3dcgb_u8 cy);

Parámetros

ax

Coordenada X del vértice A en píxeles de la ventana gráfica.

ay

Coordenada Y del vértice A en píxeles de la ventana gráfica.

bx

Coordenada X del vértice B en píxeles de la ventana gráfica.

by

Coordenada Y del vértice B en píxeles de la ventana gráfica.

cx

Coordenada X del vértice C en píxeles de la ventana gráfica.

cy

Coordenada 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

c
#pragma bank 0
// Red/blue scanlines stop inside masks; green outlines identify the triangle.
#include "wire_cgb_example.h"
__prg_rom u8 silhouette[5]={0x73,0x74,0xFF,0x75,0x73};
void main() {
    u8 y;
    wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    // Clearing this first test mask must leave the upper-left scanline intact.
    Wire3DCGB_MarkTriangle2D(8,8,16,8,8,16);
    Wire3DCGB_ClearOcclusionMask();
    Wire3DCGB_MarkTriangle2D(32,16,64,16,32,48);
    Wire3DCGB_MarkPackedSilhouette2D(silhouette,5,-2,104,32);
    Wire3DCGB_SetOcclusionActive(1);
    for(y=8;y<=56;y=y+4) Wire3DCGB_DrawLine2DColor(8,y,88,y,1);
    for(y=28;y<=36;y++) Wire3DCGB_DrawLine2DColor(92,y,120,y,2);
    Wire3DCGB_SetOcclusionActive(0);
    Wire3DCGB_DrawLine2DColor(32,16,64,16,3);
    Wire3DCGB_DrawLine2DColor(64,16,32,48,3);
    Wire3DCGB_DrawLine2DColor(32,48,32,16,3);
    Wire3DCGB_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_mask.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_mask.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:150

kitaqgb/lib/wire3d_cgb.c:1980

c
void Wire3DCGB_MarkTriangle2D(w3dcgb_u8 ax, w3dcgb_u8 ay, w3dcgb_u8 bx, w3dcgb_u8 by, w3dcgb_u8 cx, w3dcgb_u8 cy)
{
    w3dcgb_mark_triangle(ax, ay, bx, by, cx, cy);
}
Wire3DCGB_ProjectAxis48

Aproxima un desplazamiento proyectado con una distancia focal de 48.

Sintaxis

c
w3dcgb_i16 Wire3DCGB_ProjectAxis48(w3dcgb_i16 value, w3dcgb_i16 z);

Parámetros

value

Componente de 16 bits con signo que se va a proyectar.

z

Profundidad 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

c
#pragma bank 0
// Preprojected edge arrays, a clipped square, a tiny marker and a projectile.
#include "wire_cgb_example.h"
__prg_rom Wire3DCGB_Edge edges[4]={{0,1},{1,2},{2,3},{3,0}};
__prg_rom s8 vx8[4]={-8,8,8,-8};
__prg_rom s8 vy8[4]={-8,-8,8,8};
__prg_rom s16 vx16[4]={-12,12,12,-12};
__prg_rom s16 vy16[4]={-8,-8,8,8};
__prg_rom u8 mask[1]={5};
Wire3DCGB_Model shape;
void main() {
    wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    shape.vertices=0;shape.edges=edges;shape.faces=0;shape.edge_faces=0;
    shape.vertex_count=4;shape.edge_count=4;shape.face_count=0;shape.flags=0;
    Wire3DCGB_SetLineColor(2);
    Wire3DCGB_DrawMaskedModel2D(&shape,vx8,vy8,mask,24,24,1);
    Wire3DCGB_DrawEdgeList2D(edges,4,vx8,vy8,64,24,2);
    Wire3DCGB_DrawEdgeListClipped2D(edges,4,vx16,vy16,4,4,64,3);
    Wire3DCGB_DrawTinyModel2D(104,24,16,3);
    result[0]=Wire3DCGB_ProjectAxis48(48,96);
    result[1]=Wire3DCGB_ProjectAxis48(-48,96);
    Wire3DCGB_DrawFastProjectile(96,64,64,0,1);
    result[2]=Wire3DCGB_GetLineColor();
    Wire3DCGB_EndFrame();result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_lists.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_lists.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:141

kitaqgb/lib/wire3d_cgb.c:9702

c
w3dcgb_i16 Wire3DCGB_ProjectAxis48(w3dcgb_i16 value, w3dcgb_i16 z)
{
    w3dcgb_projection_value = value;
    w3dcgb_projection_z = z;
    w3dcgb_project_axis48_asm();
    return w3dcgb_projection_result;
}
Wire3DCGB_ProjectPoint

Proyecta un punto del mundo mediante la cámara a la ventana gráfica de 128×96.

Sintaxis

c
w3dcgb_u8 Wire3DCGB_ProjectPoint(w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_u8* sx, w3dcgb_u8* sy);

Parámetros

x

Componente X del punto o del origen del objeto en coordenadas del mundo.

y

Componente Y del punto o del origen del objeto en coordenadas del mundo.

z

Componente Z del punto o del origen del objeto en coordenadas del mundo.

sx

Puntero u8 válido y escribible que recibe la coordenada X proyectada.

sy

Puntero 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

c
#pragma bank 0
// Four cubes compare unity/half scale and persistent/temporary line colors.
#include "wire_cgb_example.h"
__prg_rom Wire3DCGB_Vec3 vertices[8]={
    {-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},
    {-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}
};
__prg_rom Wire3DCGB_Edge edges[12]={
    {0,1},{1,2},{2,3},{3,0},{4,5},{5,6},
    {6,7},{7,4},{0,4},{1,5},{2,6},{3,7}
};
Wire3DCGB_Model cube;
u8 sx;
u8 sy;
void main() {
    wire_results_clear();
    cube.vertices=vertices; cube.edges=edges;
    cube.faces=0; cube.edge_faces=0;
    cube.vertex_count=8; cube.edge_count=12; cube.face_count=0; cube.flags=0;
    Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawModel(&cube,-32,32,96,0,0,0);
    Wire3DCGB_DrawModelScaled(&cube,32,32,96,0,0,0,128);
    Wire3DCGB_DrawModelColor(&cube,-32,-32,96,0,0,0,2);
    Wire3DCGB_DrawModelScaledColor(&cube,32,-32,96,0,0,0,128,3);
    result[0]=Wire3DCGB_GetLineColor();
    Wire3DCGB_DrawLine3D(0,56,96,0,-56,96);
    Wire3DCGB_DrawLine3DColor(-80,0,96,80,0,96,3);
    result[1]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
    result[2]=sx; result[3]=sy;
    // Camera setters affect future projection, leaving the staged cubes intact.
    Wire3DCGB_SetCamera(0,0,0,0,4,0);
    result[4]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
    result[5]=Wire3DCGB_ProjectPointNoRotation(0,0,96,&sx,&sy);
    result[6]=sx;
    Wire3DCGB_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_models.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:169

kitaqgb/lib/wire3d_cgb.c:589

c
w3dcgb_u8 Wire3DCGB_ProjectPoint(w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_u8* sx, w3dcgb_u8* sy)
{
    return w3dcgb_project_world(x, y, z, sx, sy);
}
Wire3DCGB_ProjectPointNoRotation

Proyecta un punto tras restar la posición de cámara, sin rotación de cámara.

Sintaxis

c
w3dcgb_u8 Wire3DCGB_ProjectPointNoRotation(w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_u8* sx, w3dcgb_u8* sy);

Parámetros

x

Componente X del punto o del origen del objeto en coordenadas del mundo.

y

Componente Y del punto o del origen del objeto en coordenadas del mundo.

z

Componente Z del punto o del origen del objeto en coordenadas del mundo.

sx

Puntero u8 válido y escribible que recibe la coordenada X proyectada.

sy

Puntero 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

c
#pragma bank 0
// Four cubes compare unity/half scale and persistent/temporary line colors.
#include "wire_cgb_example.h"
__prg_rom Wire3DCGB_Vec3 vertices[8]={
    {-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},
    {-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}
};
__prg_rom Wire3DCGB_Edge edges[12]={
    {0,1},{1,2},{2,3},{3,0},{4,5},{5,6},
    {6,7},{7,4},{0,4},{1,5},{2,6},{3,7}
};
Wire3DCGB_Model cube;
u8 sx;
u8 sy;
void main() {
    wire_results_clear();
    cube.vertices=vertices; cube.edges=edges;
    cube.faces=0; cube.edge_faces=0;
    cube.vertex_count=8; cube.edge_count=12; cube.face_count=0; cube.flags=0;
    Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawModel(&cube,-32,32,96,0,0,0);
    Wire3DCGB_DrawModelScaled(&cube,32,32,96,0,0,0,128);
    Wire3DCGB_DrawModelColor(&cube,-32,-32,96,0,0,0,2);
    Wire3DCGB_DrawModelScaledColor(&cube,32,-32,96,0,0,0,128,3);
    result[0]=Wire3DCGB_GetLineColor();
    Wire3DCGB_DrawLine3D(0,56,96,0,-56,96);
    Wire3DCGB_DrawLine3DColor(-80,0,96,80,0,96,3);
    result[1]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
    result[2]=sx; result[3]=sy;
    // Camera setters affect future projection, leaving the staged cubes intact.
    Wire3DCGB_SetCamera(0,0,0,0,4,0);
    result[4]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
    result[5]=Wire3DCGB_ProjectPointNoRotation(0,0,96,&sx,&sy);
    result[6]=sx;
    Wire3DCGB_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_models.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:171

Notas de la declaración (original)
Fast path for games whose camera pitch, yaw, and roll stay at zero.

kitaqgb/lib/wire3d_cgb.c:598

c
w3dcgb_u8 Wire3DCGB_ProjectPointNoRotation(w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z,
                                            w3dcgb_u8* sx, w3dcgb_u8* sy)
{
    return w3dcgb_project_camera_space((w3dcgb_i16)(x - w3dcgb_cam_x),
                                        (w3dcgb_i16)(y - w3dcgb_cam_y),
                                        (w3dcgb_i16)(z - w3dcgb_cam_z), sx, sy);
}
Wire3DCGB_PutBgTile

Encola un cambio de número de tile del fondo para EndFrame.

Sintaxis

c
void Wire3DCGB_PutBgTile(w3dcgb_u8 x, w3dcgb_u8 y, w3dcgb_u8 tile);

Parámetros

x

Coordenada X de tile en el mapa del fondo de 32×32.

y

Coordenada Y de tile en el mapa del fondo de 32×32.

tile

Nú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

c
#pragma bank 0
// CGB raster paths: a red frame, blue diagonal, green marker and clipped line.
// Build this source together with lib/wire3d_cgb.c in an MBC5 256 KB CGB ROM.
#include "wire3d_cgb.h"
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4D) u8 sample_key1;
__location(0xC110) u16 result[8];
__prg_rom u8 lower_lines[8]={80,56,112,56,112,56,112,80};

void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DCGB_EnableDoubleSpeed();
    Wire3DCGB_Init(); // Already at double speed: its internal request is a no-op.
    result[2]=(u8)(sample_key1&128);
    // Palette writes are performed with the LCD off, after entering VBlank.
    while(sample_ly>=144) {} while(sample_ly<144) {}
    sample_lcdc=0;
    Wire3DCGB_SetPaletteRGB15(WIRE3DCGB_RGB15(0,0,0),WIRE3DCGB_RGB15(31,0,0),WIRE3DCGB_RGB15(0,0,31),WIRE3DCGB_RGB15(0,31,0));
    sample_lcdc=0x81;
    Wire3DCGB_SetScreenOffset(0,0);
    Wire3DCGB_SetCamera(0,0,0,0,0,0);
    Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawLine2D(8,8,56,8);
    Wire3DCGB_DrawLine2D(56,8,56,40);
    Wire3DCGB_DrawLine2D(56,40,8,40);
    Wire3DCGB_DrawLine2D(8,40,8,8);
    Wire3DCGB_DrawLine2DColor(8,40,56,8,2);
    result[0]=Wire3DCGB_GetLineColor(); // Temporary blue restores red.
    Wire3DCGB_SetLineColor(3);
    Wire3DCGB_DrawPoint2D(64,48);
    Wire3DCGB_DrawLineClipped2D(-10,72,140,72,3);
    Wire3DCGB_DrawLineList2DColor(lower_lines,2,2);
    result[1]=Wire3DCGB_GetLineColor(); // The blue line list restores green.
    Wire3DCGB_PutBgTile(18,1,0x80); // Queue the supplied zero glyph outside the viewport.
    Wire3DCGB_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_raster.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:188

kitaqgb/lib/wire3d_cgb.c:1067

c
void Wire3DCGB_PutBgTile(w3dcgb_u8 x, w3dcgb_u8 y, w3dcgb_u8 tile)
{
    if (x >= 32) return;
    if (y >= 32) return;
    if (w3dcgb_bgq_count >= W3DCGB_BG_QUEUE_LIMIT) return;
    w3dcgb_bgq_x[(__safe_index w3dcgb_u8)w3dcgb_bgq_count] = x;
    w3dcgb_bgq_y[(__safe_index w3dcgb_u8)w3dcgb_bgq_count] = y;
    w3dcgb_bgq_tile[(__safe_index w3dcgb_u8)w3dcgb_bgq_count] = tile;
    w3dcgb_bgq_count = (w3dcgb_u8)(w3dcgb_bgq_count + 1);
}
WIRE3DCGB_RGB15

Empaqueta los canales rojo, verde y azul de cinco bits en un color CGB de 15 bits.

Sintaxis

c
#define WIRE3DCGB_RGB15(r5, g5, b5) ((w3dcgb_u16)((w3dcgb_u16)((r5) & 31) | ((w3dcgb_u16)((g5) & 31) << 5) | ((w3dcgb_u16)((b5) & 31) << 10)))

Parámetros

r5

Canal rojo, 0..31.

g5

Canal verde, 0..31.

b5

Canal 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

c
#pragma bank 0
// CGB raster paths: a red frame, blue diagonal, green marker and clipped line.
// Build this source together with lib/wire3d_cgb.c in an MBC5 256 KB CGB ROM.
#include "wire3d_cgb.h"
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4D) u8 sample_key1;
__location(0xC110) u16 result[8];
__prg_rom u8 lower_lines[8]={80,56,112,56,112,56,112,80};

void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DCGB_EnableDoubleSpeed();
    Wire3DCGB_Init(); // Already at double speed: its internal request is a no-op.
    result[2]=(u8)(sample_key1&128);
    // Palette writes are performed with the LCD off, after entering VBlank.
    while(sample_ly>=144) {} while(sample_ly<144) {}
    sample_lcdc=0;
    Wire3DCGB_SetPaletteRGB15(WIRE3DCGB_RGB15(0,0,0),WIRE3DCGB_RGB15(31,0,0),WIRE3DCGB_RGB15(0,0,31),WIRE3DCGB_RGB15(0,31,0));
    sample_lcdc=0x81;
    Wire3DCGB_SetScreenOffset(0,0);
    Wire3DCGB_SetCamera(0,0,0,0,0,0);
    Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawLine2D(8,8,56,8);
    Wire3DCGB_DrawLine2D(56,8,56,40);
    Wire3DCGB_DrawLine2D(56,40,8,40);
    Wire3DCGB_DrawLine2D(8,40,8,8);
    Wire3DCGB_DrawLine2DColor(8,40,56,8,2);
    result[0]=Wire3DCGB_GetLineColor(); // Temporary blue restores red.
    Wire3DCGB_SetLineColor(3);
    Wire3DCGB_DrawPoint2D(64,48);
    Wire3DCGB_DrawLineClipped2D(-10,72,140,72,3);
    Wire3DCGB_DrawLineList2DColor(lower_lines,2,2);
    result[1]=Wire3DCGB_GetLineColor(); // The blue line list restores green.
    Wire3DCGB_PutBgTile(18,1,0x80); // Queue the supplied zero glyph outside the viewport.
    Wire3DCGB_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_raster.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementació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

c
void Wire3DCGB_SetCamera(w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 pitch, w3dcgb_i8 yaw, w3dcgb_i8 roll);

Parámetros

x

Componente X de la cámara en coordenadas del mundo.

y

Componente Y de la cámara en coordenadas del mundo.

z

Componente Z de la cámara en coordenadas del mundo.

pitch

Rotación alrededor de X; dieciséis pasos forman una vuelta completa.

yaw

Rotación alrededor de Y; dieciséis pasos forman una vuelta completa.

roll

Rotació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

c
#pragma bank 0
// Four cubes compare unity/half scale and persistent/temporary line colors.
#include "wire_cgb_example.h"
__prg_rom Wire3DCGB_Vec3 vertices[8]={
    {-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},
    {-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}
};
__prg_rom Wire3DCGB_Edge edges[12]={
    {0,1},{1,2},{2,3},{3,0},{4,5},{5,6},
    {6,7},{7,4},{0,4},{1,5},{2,6},{3,7}
};
Wire3DCGB_Model cube;
u8 sx;
u8 sy;
void main() {
    wire_results_clear();
    cube.vertices=vertices; cube.edges=edges;
    cube.faces=0; cube.edge_faces=0;
    cube.vertex_count=8; cube.edge_count=12; cube.face_count=0; cube.flags=0;
    Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawModel(&cube,-32,32,96,0,0,0);
    Wire3DCGB_DrawModelScaled(&cube,32,32,96,0,0,0,128);
    Wire3DCGB_DrawModelColor(&cube,-32,-32,96,0,0,0,2);
    Wire3DCGB_DrawModelScaledColor(&cube,32,-32,96,0,0,0,128,3);
    result[0]=Wire3DCGB_GetLineColor();
    Wire3DCGB_DrawLine3D(0,56,96,0,-56,96);
    Wire3DCGB_DrawLine3DColor(-80,0,96,80,0,96,3);
    result[1]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
    result[2]=sx; result[3]=sy;
    // Camera setters affect future projection, leaving the staged cubes intact.
    Wire3DCGB_SetCamera(0,0,0,0,4,0);
    result[4]=Wire3DCGB_ProjectPoint(0,0,96,&sx,&sy);
    result[5]=Wire3DCGB_ProjectPointNoRotation(0,0,96,&sx,&sy);
    result[6]=sx;
    Wire3DCGB_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_models.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:127

kitaqgb/lib/wire3d_cgb.c:8266

c
void Wire3DCGB_SetCamera(w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 pitch, w3dcgb_i8 yaw, w3dcgb_i8 roll)
{
    w3dcgb_cam_x = x;
    w3dcgb_cam_y = y;
    w3dcgb_cam_z = z;
    w3dcgb_cam_pitch = pitch;
    w3dcgb_cam_yaw = yaw;
    w3dcgb_cam_roll = roll;
}
Wire3DCGB_SetLineColor

Selecciona el índice de color para las líneas que se dibujen a continuación.

Sintaxis

c
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

c
#pragma bank 0
// CGB raster paths: a red frame, blue diagonal, green marker and clipped line.
// Build this source together with lib/wire3d_cgb.c in an MBC5 256 KB CGB ROM.
#include "wire3d_cgb.h"
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4D) u8 sample_key1;
__location(0xC110) u16 result[8];
__prg_rom u8 lower_lines[8]={80,56,112,56,112,56,112,80};

void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DCGB_EnableDoubleSpeed();
    Wire3DCGB_Init(); // Already at double speed: its internal request is a no-op.
    result[2]=(u8)(sample_key1&128);
    // Palette writes are performed with the LCD off, after entering VBlank.
    while(sample_ly>=144) {} while(sample_ly<144) {}
    sample_lcdc=0;
    Wire3DCGB_SetPaletteRGB15(WIRE3DCGB_RGB15(0,0,0),WIRE3DCGB_RGB15(31,0,0),WIRE3DCGB_RGB15(0,0,31),WIRE3DCGB_RGB15(0,31,0));
    sample_lcdc=0x81;
    Wire3DCGB_SetScreenOffset(0,0);
    Wire3DCGB_SetCamera(0,0,0,0,0,0);
    Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawLine2D(8,8,56,8);
    Wire3DCGB_DrawLine2D(56,8,56,40);
    Wire3DCGB_DrawLine2D(56,40,8,40);
    Wire3DCGB_DrawLine2D(8,40,8,8);
    Wire3DCGB_DrawLine2DColor(8,40,56,8,2);
    result[0]=Wire3DCGB_GetLineColor(); // Temporary blue restores red.
    Wire3DCGB_SetLineColor(3);
    Wire3DCGB_DrawPoint2D(64,48);
    Wire3DCGB_DrawLineClipped2D(-10,72,140,72,3);
    Wire3DCGB_DrawLineList2DColor(lower_lines,2,2);
    result[1]=Wire3DCGB_GetLineColor(); // The blue line list restores green.
    Wire3DCGB_PutBgTile(18,1,0x80); // Queue the supplied zero glyph outside the viewport.
    Wire3DCGB_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_raster.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:119

kitaqgb/lib/wire3d_cgb.c:1140

c
void Wire3DCGB_SetLineColor(w3dcgb_u8 color)
{
    w3dcgb_line_color = (w3dcgb_u8)(color & 3);
}
Wire3DCGB_SetOcclusionActive

Activa o desactiva la prueba de oclusión para las líneas posteriores.

Sintaxis

c
void Wire3DCGB_SetOcclusionActive(w3dcgb_u8 active);

Parámetros

active

Cero 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

c
#pragma bank 0
// Red/blue scanlines stop inside masks; green outlines identify the triangle.
#include "wire_cgb_example.h"
__prg_rom u8 silhouette[5]={0x73,0x74,0xFF,0x75,0x73};
void main() {
    u8 y;
    wire_results_clear(); Wire3DCGB_Init(); wire_colors(); Wire3DCGB_BeginFrame();
    // Clearing this first test mask must leave the upper-left scanline intact.
    Wire3DCGB_MarkTriangle2D(8,8,16,8,8,16);
    Wire3DCGB_ClearOcclusionMask();
    Wire3DCGB_MarkTriangle2D(32,16,64,16,32,48);
    Wire3DCGB_MarkPackedSilhouette2D(silhouette,5,-2,104,32);
    Wire3DCGB_SetOcclusionActive(1);
    for(y=8;y<=56;y=y+4) Wire3DCGB_DrawLine2DColor(8,y,88,y,1);
    for(y=28;y<=36;y++) Wire3DCGB_DrawLine2DColor(92,y,120,y,2);
    Wire3DCGB_SetOcclusionActive(0);
    Wire3DCGB_DrawLine2DColor(32,16,64,16,3);
    Wire3DCGB_DrawLine2DColor(64,16,32,48,3);
    Wire3DCGB_DrawLine2DColor(32,48,32,16,3);
    Wire3DCGB_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_mask.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_mask.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:149

kitaqgb/lib/wire3d_cgb.c:1970

c
void Wire3DCGB_SetOcclusionActive(w3dcgb_u8 active)
{
    if (active == 0) w3dcgb_occlusion_active = 0;
    else w3dcgb_occlusion_active = 1;
}
Wire3DCGB_SetPaletteRGB15

Configura los cuatro colores de dibujo y las paletas del fondo que dan color a los patrones.

Sintaxis

c
void Wire3DCGB_SetPaletteRGB15(w3dcgb_u16 color0, w3dcgb_u16 color1, w3dcgb_u16 color2, w3dcgb_u16 color3);

Parámetros

color0

Color RGB15 de la entrada 0 de la paleta.

color1

Color RGB15 de la entrada 1 de la paleta.

color2

Color RGB15 de la entrada 2 de la paleta.

color3

Color 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

c
#pragma bank 0
// CGB raster paths: a red frame, blue diagonal, green marker and clipped line.
// Build this source together with lib/wire3d_cgb.c in an MBC5 256 KB CGB ROM.
#include "wire3d_cgb.h"
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4D) u8 sample_key1;
__location(0xC110) u16 result[8];
__prg_rom u8 lower_lines[8]={80,56,112,56,112,56,112,80};

void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DCGB_EnableDoubleSpeed();
    Wire3DCGB_Init(); // Already at double speed: its internal request is a no-op.
    result[2]=(u8)(sample_key1&128);
    // Palette writes are performed with the LCD off, after entering VBlank.
    while(sample_ly>=144) {} while(sample_ly<144) {}
    sample_lcdc=0;
    Wire3DCGB_SetPaletteRGB15(WIRE3DCGB_RGB15(0,0,0),WIRE3DCGB_RGB15(31,0,0),WIRE3DCGB_RGB15(0,0,31),WIRE3DCGB_RGB15(0,31,0));
    sample_lcdc=0x81;
    Wire3DCGB_SetScreenOffset(0,0);
    Wire3DCGB_SetCamera(0,0,0,0,0,0);
    Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawLine2D(8,8,56,8);
    Wire3DCGB_DrawLine2D(56,8,56,40);
    Wire3DCGB_DrawLine2D(56,40,8,40);
    Wire3DCGB_DrawLine2D(8,40,8,8);
    Wire3DCGB_DrawLine2DColor(8,40,56,8,2);
    result[0]=Wire3DCGB_GetLineColor(); // Temporary blue restores red.
    Wire3DCGB_SetLineColor(3);
    Wire3DCGB_DrawPoint2D(64,48);
    Wire3DCGB_DrawLineClipped2D(-10,72,140,72,3);
    Wire3DCGB_DrawLineList2DColor(lower_lines,2,2);
    result[1]=Wire3DCGB_GetLineColor(); // The blue line list restores green.
    Wire3DCGB_PutBgTile(18,1,0x80); // Queue the supplied zero glyph outside the viewport.
    Wire3DCGB_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_raster.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:118

kitaqgb/lib/wire3d_cgb.c:1112

c
void Wire3DCGB_SetPaletteRGB15(w3dcgb_u16 color0, w3dcgb_u16 color1, w3dcgb_u16 color2, w3dcgb_u16 color3)
{
    w3dcgb_write_bg_color(0, color0);
    w3dcgb_write_bg_color(1, color1);
    w3dcgb_write_bg_color(2, color2);
    w3dcgb_write_bg_color(3, color3);

    w3dcgb_write_bg_color(4, color0);
    w3dcgb_write_bg_color(5, color1);
    w3dcgb_write_bg_color(6, color1);
    w3dcgb_write_bg_color(7, color1);

    w3dcgb_write_bg_color(8, color0);
    w3dcgb_write_bg_color(9, color2);
    w3dcgb_write_bg_color(10, color2);
    w3dcgb_write_bg_color(11, color2);

    w3dcgb_write_bg_color(12, color0);
    w3dcgb_write_bg_color(13, color3);
    w3dcgb_write_bg_color(14, color3);
    w3dcgb_write_bg_color(15, color3);
}
Wire3DCGB_SetScreenOffset

Configura directamente los registros de desplazamiento SCX y SCY del LCD.

Sintaxis

c
void Wire3DCGB_SetScreenOffset(w3dcgb_u8 scx, w3dcgb_u8 scy);

Parámetros

scx

Desplazamiento en píxeles que se escribe en SCX.

scy

Desplazamiento 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

c
#pragma bank 0
// CGB raster paths: a red frame, blue diagonal, green marker and clipped line.
// Build this source together with lib/wire3d_cgb.c in an MBC5 256 KB CGB ROM.
#include "wire3d_cgb.h"
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4D) u8 sample_key1;
__location(0xC110) u16 result[8];
__prg_rom u8 lower_lines[8]={80,56,112,56,112,56,112,80};

void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DCGB_EnableDoubleSpeed();
    Wire3DCGB_Init(); // Already at double speed: its internal request is a no-op.
    result[2]=(u8)(sample_key1&128);
    // Palette writes are performed with the LCD off, after entering VBlank.
    while(sample_ly>=144) {} while(sample_ly<144) {}
    sample_lcdc=0;
    Wire3DCGB_SetPaletteRGB15(WIRE3DCGB_RGB15(0,0,0),WIRE3DCGB_RGB15(31,0,0),WIRE3DCGB_RGB15(0,0,31),WIRE3DCGB_RGB15(0,31,0));
    sample_lcdc=0x81;
    Wire3DCGB_SetScreenOffset(0,0);
    Wire3DCGB_SetCamera(0,0,0,0,0,0);
    Wire3DCGB_BeginFrame();
    Wire3DCGB_SetLineColor(1);
    Wire3DCGB_DrawLine2D(8,8,56,8);
    Wire3DCGB_DrawLine2D(56,8,56,40);
    Wire3DCGB_DrawLine2D(56,40,8,40);
    Wire3DCGB_DrawLine2D(8,40,8,8);
    Wire3DCGB_DrawLine2DColor(8,40,56,8,2);
    result[0]=Wire3DCGB_GetLineColor(); // Temporary blue restores red.
    Wire3DCGB_SetLineColor(3);
    Wire3DCGB_DrawPoint2D(64,48);
    Wire3DCGB_DrawLineClipped2D(-10,72,140,72,3);
    Wire3DCGB_DrawLineList2DColor(lower_lines,2,2);
    result[1]=Wire3DCGB_GetLineColor(); // The blue line list restores green.
    Wire3DCGB_PutBgTile(18,1,0x80); // Queue the supplied zero glyph outside the viewport.
    Wire3DCGB_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_cgb_raster.c .\kitaqgb\lib\wire3d_cgb.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_cgb_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:117

kitaqgb/lib/wire3d_cgb.c:1091

c
void Wire3DCGB_SetScreenOffset(w3dcgb_u8 scx, w3dcgb_u8 scy)
{
    w3dcgb_reg_scx = scx;
    w3dcgb_reg_scy = scy;
}

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

PerfilfpsMediana / peor (fotogramas PPU)Plazos excedidos / 47
clocked_dmg_88_sparse13.8524.449 / 4.73235
clocked_dmg_96_sparse13.1864.669 / 4.89139
clocked_dmg_120_sparse13.4344.453 / 7.17635
clocked_cgb_88_sparse15.0124.000 / 5.00028
clocked_cgb_96_sparse15.0924.000 / 5.00026
clocked_cgb_88_full12.5325.000 / 6.00041
clocked_cgb_96_full12.5885.000 / 5.02041
Original DMG box and bar gauge
DMG 128×88 · 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.
Original CGB box and bar gauge
CGB 128×88 · 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.
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

c
w3ddmg_u8 Wire3DDMG_ProjectCameraPoint(w3ddmg_i16 x,w3ddmg_i16 y,w3ddmg_i16 z,w3ddmg_u8* sx,w3ddmg_u8* sy);

Parámetros

x

X/Y/Z de cámara con signo de 16 bits. sx y sy deben ser punteros u8 válidos y escribibles.

y

X/Y/Z de cámara con signo de 16 bits. sx y sy deben ser punteros u8 válidos y escribibles.

z

X/Y/Z de cámara con signo de 16 bits. sx y sy deben ser punteros u8 válidos y escribibles.

sx

X/Y/Z de cámara con signo de 16 bits. sx y sy deben ser punteros u8 válidos y escribibles.

sy

X/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

c
#define WIRE3D_DMG_HEIGHT 88
#include "wire3d_dmg.h"
void project_one() {
    u8 sx; u8 sy;
    if (Wire3DDMG_ProjectCameraPoint(-24, 20, 96, &sx, &sy)) {
        // Use the projected coordinates in a main-thread drawing routine.
    }
}

Este fragmento 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.

Programa de ejemplo completo

renderer_dmg_88.c

hardware.c

audio_glue.c

README.md

Implementación y código fuente

kitaqgb/lib/wire3d_dmg.h:146

Notas de la declaración (original)
Validate depth and project coordinates already in camera space.

kitaqgb/lib/wire3d_dmg.c:720

c
w3ddmg_u8 Wire3DDMG_ProjectCameraPoint(w3ddmg_i16 x,w3ddmg_i16 y,w3ddmg_i16 z,w3ddmg_u8* sx,w3ddmg_u8* sy)
{
 return w3ddmg_project_camera_space(x,y,z,sx,sy);
}
Wire3DCGB_ProjectCameraPoint

ProjectCameraPoint 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

c
w3dcgb_u8 Wire3DCGB_ProjectCameraPoint(w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_u8* sx, w3dcgb_u8* sy);

Parámetros

x

X/Y/Z de cámara con signo de 16 bits. sx y sy deben ser punteros u8 válidos y escribibles.

y

X/Y/Z de cámara con signo de 16 bits. sx y sy deben ser punteros u8 válidos y escribibles.

z

X/Y/Z de cámara con signo de 16 bits. sx y sy deben ser punteros u8 válidos y escribibles.

sx

X/Y/Z de cámara con signo de 16 bits. sx y sy deben ser punteros u8 válidos y escribibles.

sy

X/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

c
#define WIRE3DCGB_HEIGHT 88
#include "wire3d_cgb.h"
void project_one() {
    u8 sx; u8 sy;
    if (Wire3DCGB_ProjectCameraPoint(-24, 20, 96, &sx, &sy)) {
        // Use the projected coordinates in a main-thread drawing routine.
    }
}

Este fragmento 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.

Programa de ejemplo completo

renderer_cgb_88.c

hardware.c

audio_glue.c

README.md

Implementación y código fuente

kitaqgb/lib/wire3d_cgb.h:168

Notas de la declaración (original)
Project camera-space coordinates without subtracting/rotating the camera.
Depth 8..255; outputs unchanged on rejection. Shared scratch: no ISR calls.

kitaqgb/lib/wire3d_cgb.c:552

c
w3dcgb_u8 Wire3DCGB_ProjectCameraPoint(w3dcgb_i16 x,w3dcgb_i16 y,w3dcgb_i16 z,w3dcgb_u8* sx,w3dcgb_u8* sy)
{
    return w3dcgb_project_camera_space(x,y,z,sx,sy);
}
Wire3DDMG_EndFrameNow

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

c
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

c
#define WIRE3D_DMG_HEIGHT 88
#include "wire3d_dmg.h"
void draw_one() {
    Wire3DDMG_BeginFrame();
    Wire3DDMG_DrawLine2D(8,8,32,32);
    Wire3DDMG_PutBgTile(18,16,128);
    Wire3DDMG_EndFrameNow();
}

Este fragmento 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.

Programa de ejemplo completo

renderer_dmg_88.c

hardware.c

audio_glue.c

README.md

Implementación y código fuente

kitaqgb/lib/wire3d_dmg.h:289

Notas de la declaración (original)
Same queue/gate/history lifecycle, without the initial fresh-VBlank wait.
Synchronous STAT-safe upload; not an atomic swap. LCD must remain enabled.

kitaqgb/lib/wire3d_dmg.c:3826

c
void Wire3DDMG_EndFrameNow()
{
    w3ddmg_flush_bg_queue();



    if (w3ddmg_aux_transfer_enabled)
    {
        w3ddmg_transfer_stage_aux_asm();
    }
    if (w3ddmg_dirty_transfer_enabled)
    {
        w3ddmg_transfer_dirty_stage();
    }
    else
    {
        w3ddmg_transfer_stage_asm();
    }

}

wire3d_dmg.h — 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

c
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

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DDMG_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    Wire3DDMG_SetCamera(8,0,0,0,0,0);
    result[1]=Wire3DDMG_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=Wire3DDMG_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    Wire3DDMG_SetCamera(0,0,0,0,0,0);
    Wire3DDMG_BeginFrame();
    Wire3DDMG_DrawLine2D(8,8,56,8);
    Wire3DDMG_DrawLine2D(56,8,56,40);
    Wire3DDMG_DrawLine2D(56,40,8,40);
    Wire3DDMG_DrawLine2D(8,40,8,8);
    Wire3DDMG_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    Wire3DDMG_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    Wire3DDMG_PutBgTile(1,1,160);
    Wire3DDMG_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_raster.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_dmg.h:144

Notas de la declaración (original)
Disable occlusion filtering only. Stage clearing normally happens during
transfer, and Init supplies the first clean stage. This does not discard an
unsubmitted frame, clear the mask, or reset pending BG writes/dirty flags.

kitaqgb/lib/wire3d_dmg.c:3379

c
void Wire3DDMG_BeginFrame()
{




    /* The consuming stage transfer clears D000 as it uploads, so BeginFrame only
       resets draw state. Wire3DDMG_Init supplies the first clean buffer. */

    w3ddmg_occlusion_active = 0;
}
Wire3DDMG_DrawIndexedEdges

Dibuja un modelo de líneas con escala entera a partir de vértices y pares de índices de arista de dos bytes.

Sintaxis

c
void Wire3DDMG_DrawIndexedEdges(const Wire3DDMG_Vec3* vertices, w3ddmg_u8 vertex_count, const w3ddmg_u8* edges, w3ddmg_u8 edge_count, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 scale);

Parámetros

vertices

Array de vértices 3D.

vertex_count

Cantidad 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_count

Cantidad de aristas.

x

Componente X del punto o del origen del objeto en coordenadas del mundo.

y

Componente Y del punto o del origen del objeto en coordenadas del mundo.

z

Componente Z del punto o del origen del objeto en coordenadas del mundo.

scale

Escala 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

c
#pragma bank 0
// Upload a main line and an auxiliary block separately; verify source consumption.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3DDMG_Vec3 vertices[2]={{-32,0,0},{32,0,0}};
__prg_rom u8 edge_pairs[2]={0,1};
u8* stage_byte;

void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DDMG_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
        Wire3DDMG_BeginFrame();
    Wire3DDMG_DrawIndexedEdges(vertices,2,edge_pairs,1,-64,104,96,1);
    Wire3DDMG_TransferMainNow();
    // Direct auxiliary transfer writes a separate tile after the main upload.
    for(i=24;i<=31;i++) Wire3DDMG_DrawLine2D(40,i,47,i);
    stage_byte=(u8*)0xD518;result[1]=*stage_byte;
    Wire3DDMG_TransferAuxNow();result[2]=*stage_byte;

    // Do not upload the consumed stage again.
    result[7]=0xA55A; while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_direct.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_direct.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_dmg.h:253

Notas de la declaración (original)
Draw byte-pair edge indices after integer scaling and translation; scale
zero means one, and there is no object rotation or face filtering. Project at
most 24 vertices. Supply at most 128 edge pairs because byte offsets wrap
after 255. Invalid vertex IDs/depth-rejected endpoints are skipped; null arrays
are ignored. Keep coordinate products/sums representable as s16.

kitaqgb/lib/wire3d_dmg.c:4568

c
void Wire3DDMG_DrawIndexedEdges(const Wire3DDMG_Vec3* vertices, w3ddmg_u8 vertex_count, const w3ddmg_u8* edges, w3ddmg_u8 edge_count, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 scale)
{
    w3ddmg_u8 i;
    w3ddmg_u8 count;

    if (vertices == 0) return;
    if (edges == 0) return;

    count = vertex_count;
    if (count > WIRE3D_DMG_MODEL_VERTEX_LIMIT) count = WIRE3D_DMG_MODEL_VERTEX_LIMIT;
    if (scale == 0) scale = 1;

    i = 0;
    while (i < count)
    {
        const Wire3DDMG_Vec3* v;
        w3ddmg_i16 vx;
        w3ddmg_i16 vy;
        w3ddmg_i16 vz;
        w3ddmg_u8 sx;
        w3ddmg_u8 sy;

        v = &vertices[(__safe_index w3ddmg_u8)i];
        vx = (w3ddmg_i16)(x + (w3ddmg_i16)(v->x * scale));
        vy = (w3ddmg_i16)(y + (w3ddmg_i16)(v->y * scale));
        vz = (w3ddmg_i16)(z + (w3ddmg_i16)(v->z * scale));

        if (w3ddmg_project_world(vx, vy, vz, &sx, &sy))
        {
            w3ddmg_screen_x[(__safe_index w3ddmg_u8)i] = sx;
            w3ddmg_screen_y[(__safe_index w3ddmg_u8)i] = sy;
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 1;
        }
        else
        {
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 0;
        }

        i = (w3ddmg_u8)(i + 1);
    }

    i = 0;
    while (i < edge_count)
    {
        w3ddmg_u8 a;
        w3ddmg_u8 b;

        a = edges[(__safe_index w3ddmg_u8)((w3ddmg_u8)(i << 1))];
        b = edges[(__safe_index w3ddmg_u8)((w3ddmg_u8)((i << 1) + 1))];
        if ((a < count) && (b < count) &&
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)a] &&
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)b])
        {
            Wire3DDMG_DrawLine2D(
                w3ddmg_screen_x[(__safe_index w3ddmg_u8)a],
                w3ddmg_screen_y[(__safe_index w3ddmg_u8)a],
                w3ddmg_screen_x[(__safe_index w3ddmg_u8)b],
                w3ddmg_screen_y[(__safe_index w3ddmg_u8)b]);
        }

        i = (w3ddmg_u8)(i + 1);
    }
}
Wire3DDMG_DrawLine2D

Dibuja en el área de preparación una línea de pantalla con conectividad de cuatro vecinos, incluidos los extremos.

Sintaxis

c
void Wire3DDMG_DrawLine2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by);

Parámetros

ax

Coordenada X del vértice A en píxeles de la ventana gráfica.

ay

Coordenada Y del vértice A en píxeles de la ventana gráfica.

bx

Coordenada X del vértice B en píxeles de la ventana gráfica.

by

Coordenada 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

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DDMG_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    Wire3DDMG_SetCamera(8,0,0,0,0,0);
    result[1]=Wire3DDMG_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=Wire3DDMG_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    Wire3DDMG_SetCamera(0,0,0,0,0,0);
    Wire3DDMG_BeginFrame();
    Wire3DDMG_DrawLine2D(8,8,56,8);
    Wire3DDMG_DrawLine2D(56,8,56,40);
    Wire3DDMG_DrawLine2D(56,40,8,40);
    Wire3DDMG_DrawLine2D(8,40,8,8);
    Wire3DDMG_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    Wire3DDMG_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    Wire3DDMG_PutBgTile(1,1,160);
    Wire3DDMG_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_raster.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_dmg.h:237

Notas de la declaración (original)
Mark the bounding tile rectangle when dirty transfer is enabled, then draw
a connected staged line. Scene drawing may reject it using five mask samples.
Supply 128x120 viewport endpoints; low-level pixel bounds checks do not clip
the segment geometrically.

kitaqgb/lib/wire3d_dmg.c:3423

c
void Wire3DDMG_DrawLine2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by)
{

    w3ddmg_mark_line_dirty(ax, ay, bx, by);


    if (w3ddmg_occlusion_active)
    {
        w3ddmg_line_stage_masked_c(ax, ay, bx, by);
        return;
    }

    w3ddmg_line_x0 = ax;
    w3ddmg_line_y0 = ay;
    w3ddmg_line_x1 = bx;
    w3ddmg_line_y1 = by;
    if (ax < 128 && bx < 128 && ay < WIRE3D_DMG_SCREEN_H && by < WIRE3D_DMG_SCREEN_H)
        w3ddmg_line_inside_asm();
    else
        w3ddmg_line_stage_asm();
}
Wire3DDMG_DrawLine3D

Proyecta dos extremos en coordenadas del mundo y dibuja una línea entre ellos.

Sintaxis

c
void Wire3DDMG_DrawLine3D(w3ddmg_i16 ax, w3ddmg_i16 ay, w3ddmg_i16 az, w3ddmg_i16 bx, w3ddmg_i16 by, w3ddmg_i16 bz);

Parámetros

ax

Componente X del punto inicial en coordenadas del mundo.

ay

Componente Y del punto inicial en coordenadas del mundo.

az

Componente Z del punto inicial en coordenadas del mundo.

bx

Componente X del punto final en coordenadas del mundo.

by

Componente Y del punto final en coordenadas del mundo.

bz

Componente 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

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DDMG_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    Wire3DDMG_SetCamera(8,0,0,0,0,0);
    result[1]=Wire3DDMG_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=Wire3DDMG_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    Wire3DDMG_SetCamera(0,0,0,0,0,0);
    Wire3DDMG_BeginFrame();
    Wire3DDMG_DrawLine2D(8,8,56,8);
    Wire3DDMG_DrawLine2D(56,8,56,40);
    Wire3DDMG_DrawLine2D(56,40,8,40);
    Wire3DDMG_DrawLine2D(8,40,8,8);
    Wire3DDMG_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    Wire3DDMG_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    Wire3DDMG_PutBgTile(1,1,160);
    Wire3DDMG_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_raster.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_dmg.h:226

Notas de la declaración (original)
Project both world endpoints and draw only when both pass the depth range.
Do not intersect a crossing segment with near/far planes; projected endpoints
are independently clamped to the screen edges.

kitaqgb/lib/wire3d_dmg.c:3546

c
void Wire3DDMG_DrawLine3D(w3ddmg_i16 ax, w3ddmg_i16 ay, w3ddmg_i16 az, w3ddmg_i16 bx, w3ddmg_i16 by, w3ddmg_i16 bz)
{
    w3ddmg_u8 sx0;
    w3ddmg_u8 sy0;
    w3ddmg_u8 sx1;
    w3ddmg_u8 sy1;

    if (w3ddmg_project_world(ax, ay, az, &sx0, &sy0) == 0) return;
    if (w3ddmg_project_world(bx, by, bz, &sx1, &sy1) == 0) return;
    Wire3DDMG_DrawLine2D(sx0, sy0, sx1, sy1);
}
Wire3DDMG_DrawModel

Dibuja un modelo de vértices y aristas en la posición y con la rotación indicadas, a escala unitaria.

Sintaxis

c
void Wire3DDMG_DrawModel(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz);

Parámetros

model

Modelo que contiene los arrays de vértices, aristas y caras y sus cantidades; las tablas deben permanecer legibles durante la llamada.

x

Componente X del punto o del origen del objeto en coordenadas del mundo.

y

Componente Y del punto o del origen del objeto en coordenadas del mundo.

z

Componente Z del punto o del origen del objeto en coordenadas del mundo.

rx

Rotación alrededor de X; dieciséis pasos forman una vuelta completa.

ry

Rotación alrededor de Y; dieciséis pasos forman una vuelta completa.

rz

Rotació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

c
#pragma bank 0
// Compare direct model scaling with an object-array scene.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3DDMG_Vec3 vertices[8]={{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}};
__prg_rom Wire3DDMG_Edge edges[12]={{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}};
Wire3DDMG_Model cube;
Wire3DDMG_Object objects[2];
s16 px; s16 py; s16 pz;
void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DDMG_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;

    cube.vertices=vertices;cube.edges=edges;cube.faces=0;cube.edge_faces=0;
    cube.vertex_count=8;cube.edge_count=12;cube.face_count=0;cube.flags=0;

    Wire3DDMG_BeginFrame();
    // Upper pair: direct model calls at unity and half scale.
    Wire3DDMG_DrawModel(&cube,-32,32,96,0,0,0);
    Wire3DDMG_DrawModelScaled(&cube,32,32,96,0,0,0,128);
    // Lower pair: the caller owns both object records and the model tables.
    for(i=0;i<2;i++) {
        objects[i].model=&cube;objects[i].x=-32+(s16)i*64;
        objects[i].y=-32;objects[i].z=96;
        objects[i].rx=0;objects[i].ry=0;objects[i].rz=0;
        objects[i].scale_q8=256-(s16)i*128;objects[i].visible=1;
    }
    Wire3DDMG_DrawScene(objects,2);
    // Numeric checks cover the operation supplied by this viewport profile.
    px=16;py=0;pz=0;Wire3DDMG_RotatePoint(&px,&py,&pz,0,4,0);
    result[1]=px; result[2]=py; result[3]=pz;
    Wire3DDMG_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_models.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_dmg.h:164

Notas de la declaración (original)
Draw an unscaled model by delegating to DrawModelScaled with scale 256.

kitaqgb/lib/wire3d_dmg.c:3565

c
void Wire3DDMG_DrawModel(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz)

{
    Wire3DDMG_DrawModelScaled(model, x, y, z, rx, ry, rz, 256);
}

kitaqgb/lib/wire3d_dmg.c:3563

c
void Wire3DDMG_DrawModel(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz)



{
    Wire3DDMG_DrawModelScaled(model, x, y, z, rx, ry, rz, 256);
}
Wire3DDMG_DrawModelScaled

Escala un modelo, lo rota en orden Y/X/Z, traslada y proyecta sus vértices y dibuja las aristas.

Sintaxis

c
void Wire3DDMG_DrawModelScaled(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz, w3ddmg_i16 scale_q8);

Parámetros

model

Modelo que contiene los arrays de vértices, aristas y caras y sus cantidades; las tablas deben permanecer legibles durante la llamada.

x

Componente X del punto o del origen del objeto en coordenadas del mundo.

y

Componente Y del punto o del origen del objeto en coordenadas del mundo.

z

Componente Z del punto o del origen del objeto en coordenadas del mundo.

rx

Rotación alrededor de X; dieciséis pasos forman una vuelta completa.

ry

Rotación alrededor de Y; dieciséis pasos forman una vuelta completa.

rz

Rotación alrededor de Z; dieciséis pasos forman una vuelta completa.

scale_q8

Escala 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

c
#pragma bank 0
// Compare direct model scaling with an object-array scene.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3DDMG_Vec3 vertices[8]={{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}};
__prg_rom Wire3DDMG_Edge edges[12]={{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}};
Wire3DDMG_Model cube;
Wire3DDMG_Object objects[2];
s16 px; s16 py; s16 pz;
void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DDMG_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;

    cube.vertices=vertices;cube.edges=edges;cube.faces=0;cube.edge_faces=0;
    cube.vertex_count=8;cube.edge_count=12;cube.face_count=0;cube.flags=0;

    Wire3DDMG_BeginFrame();
    // Upper pair: direct model calls at unity and half scale.
    Wire3DDMG_DrawModel(&cube,-32,32,96,0,0,0);
    Wire3DDMG_DrawModelScaled(&cube,32,32,96,0,0,0,128);
    // Lower pair: the caller owns both object records and the model tables.
    for(i=0;i<2;i++) {
        objects[i].model=&cube;objects[i].x=-32+(s16)i*64;
        objects[i].y=-32;objects[i].z=96;
        objects[i].rx=0;objects[i].ry=0;objects[i].rz=0;
        objects[i].scale_q8=256-(s16)i*128;objects[i].visible=1;
    }
    Wire3DDMG_DrawScene(objects,2);
    // Numeric checks cover the operation supplied by this viewport profile.
    px=16;py=0;pz=0;Wire3DDMG_RotatePoint(&px,&py,&pz,0,4,0);
    result[1]=px; result[2]=py; result[3]=pz;
    Wire3DDMG_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_models.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_dmg.h:170

Notas de la declaración (original)
Scale up to 24 vertices, rotate Y/X/Z, translate and project, then traverse
all edge_count entries (a byte count) with optional adjacent-face filtering.
Face scratch is capped at 16; edge tables must contain all declared entries.
Nonpositive scale means 256. Null model/vertex/edge pointers are ignored.
Keep products/translations in signed 16-bit range; depth-crossing edges are dropped.

kitaqgb/lib/wire3d_dmg.c:3710

c
void Wire3DDMG_DrawModelScaled(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz, w3ddmg_i16 scale_q8)

{
    w3ddmg_u8 i;
    w3ddmg_u8 count;
    w3ddmg_u8 edge_count;
    w3ddmg_u8 face_count;

    if (model == 0) return;
    if (model->vertices == 0) return;
    if (model->edges == 0) return;
    if (scale_q8 <= 0) scale_q8 = 256;

    count = model->vertex_count;
    if (count > WIRE3D_DMG_MODEL_VERTEX_LIMIT) count = WIRE3D_DMG_MODEL_VERTEX_LIMIT;

    i = 0;
    while (i < count)
    {
        const Wire3DDMG_Vec3* v;
        w3ddmg_i16 vx;
        w3ddmg_i16 vy;
        w3ddmg_i16 vz;
        w3ddmg_u8 sx;
        w3ddmg_u8 sy;

        v = &model->vertices[(__safe_index w3ddmg_u8)i];
        vx = (w3ddmg_i16)((v->x * scale_q8) >> 8);
        vy = (w3ddmg_i16)((v->y * scale_q8) >> 8);
        vz = (w3ddmg_i16)((v->z * scale_q8) >> 8);






        w3ddmg_rotate_y(&vx, &vz, ry);
        w3ddmg_rotate_x(&vy, &vz, rx);
        w3ddmg_rotate_z(&vx, &vy, rz);


        vx = (w3ddmg_i16)(vx + x);
        vy = (w3ddmg_i16)(vy + y);
        vz = (w3ddmg_i16)(vz + z);

        if (w3ddmg_project_world(vx, vy, vz, &sx, &sy))
        {
            w3ddmg_screen_x[(__safe_index w3ddmg_u8)i] = sx;
            w3ddmg_screen_y[(__safe_index w3ddmg_u8)i] = sy;
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 1;
        }
        else
        {
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 0;
        }
        i = (w3ddmg_u8)(i + 1);
    }

    face_count = model->face_count;
    if (face_count > WIRE3D_DMG_MODEL_FACE_LIMIT) face_count = WIRE3D_DMG_MODEL_FACE_LIMIT;
    if ((model->flags & WIRE3D_DMG_MODEL_HIDDEN_LINES) && (model->faces != 0) && (model->edge_faces != 0))
    {
        w3ddmg_build_face_visibility(model, count, face_count);
    }

    edge_count = model->edge_count;




    i = 0;
    while (i < edge_count)
    {
        const Wire3DDMG_Edge* e;
        e = &model->edges[(__safe_index w3ddmg_u8)i];
        if ((e->a < count) && (e->b < count))
        {
            if (w3ddmg_screen_visible[(__safe_index w3ddmg_u8)e->a] &&
                w3ddmg_screen_visible[(__safe_index w3ddmg_u8)e->b] &&



                w3ddmg_is_edge_visible(model, i, face_count))

            {
                Wire3DDMG_DrawLine2D(
                    w3ddmg_screen_x[(__safe_index w3ddmg_u8)e->a],
                    w3ddmg_screen_y[(__safe_index w3ddmg_u8)e->a],
                    w3ddmg_screen_x[(__safe_index w3ddmg_u8)e->b],
                    w3ddmg_screen_y[(__safe_index w3ddmg_u8)e->b]);
            }
        }
        i = (w3ddmg_u8)(i + 1);
    }
}

kitaqgb/lib/wire3d_dmg.c:3703

c
void Wire3DDMG_DrawModelScaled(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz, w3ddmg_i16 scale_q8)








{
    w3ddmg_u8 i;
    w3ddmg_u8 count;
    w3ddmg_u8 edge_count;
    w3ddmg_u8 face_count;

    if (model == 0) return;
    if (model->vertices == 0) return;
    if (model->edges == 0) return;
    if (scale_q8 <= 0) scale_q8 = 256;

    count = model->vertex_count;
    if (count > WIRE3D_DMG_MODEL_VERTEX_LIMIT) count = WIRE3D_DMG_MODEL_VERTEX_LIMIT;

    i = 0;
    while (i < count)
    {
        const Wire3DDMG_Vec3* v;
        w3ddmg_i16 vx;
        w3ddmg_i16 vy;
        w3ddmg_i16 vz;
        w3ddmg_u8 sx;
        w3ddmg_u8 sy;

        v = &model->vertices[(__safe_index w3ddmg_u8)i];
        vx = (w3ddmg_i16)((v->x * scale_q8) >> 8);
        vy = (w3ddmg_i16)((v->y * scale_q8) >> 8);
        vz = (w3ddmg_i16)((v->z * scale_q8) >> 8);


        w3ddmg_rotate_y(&vx, &vz, (w3ddmg_i8)ry);
        w3ddmg_rotate_x(&vy, &vz, (w3ddmg_i8)rx);
        w3ddmg_rotate_z(&vx, &vy, (w3ddmg_i8)rz);






        vx = (w3ddmg_i16)(vx + x);
        vy = (w3ddmg_i16)(vy + y);
        vz = (w3ddmg_i16)(vz + z);

        if (w3ddmg_project_world(vx, vy, vz, &sx, &sy))
        {
            w3ddmg_screen_x[(__safe_index w3ddmg_u8)i] = sx;
            w3ddmg_screen_y[(__safe_index w3ddmg_u8)i] = sy;
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 1;
        }
        else
        {
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 0;
        }
        i = (w3ddmg_u8)(i + 1);
    }

    face_count = model->face_count;
    if (face_count > WIRE3D_DMG_MODEL_FACE_LIMIT) face_count = WIRE3D_DMG_MODEL_FACE_LIMIT;
    if ((model->flags & WIRE3D_DMG_MODEL_HIDDEN_LINES) && (model->faces != 0) && (model->edge_faces != 0))
    {
        w3ddmg_build_face_visibility(model, count, face_count);
    }

    edge_count = model->edge_count;

    if (edge_count > WIRE3D_DMG_MODEL_EDGE_LIMIT) edge_count = WIRE3D_DMG_MODEL_EDGE_LIMIT;
    w3ddmg_build_edge_flags(model, edge_count, face_count, rx, ry, rz);

    i = 0;
    while (i < edge_count)
    {
        const Wire3DDMG_Edge* e;
        e = &model->edges[(__safe_index w3ddmg_u8)i];
        if ((e->a < count) && (e->b < count))
        {
            if (w3ddmg_screen_visible[(__safe_index w3ddmg_u8)e->a] &&
                w3ddmg_screen_visible[(__safe_index w3ddmg_u8)e->b] &&

                w3ddmg_edge_flags[(__safe_index w3ddmg_u8)i])



            {
                Wire3DDMG_DrawLine2D(
                    w3ddmg_screen_x[(__safe_index w3ddmg_u8)e->a],
                    w3ddmg_screen_y[(__safe_index w3ddmg_u8)e->a],
                    w3ddmg_screen_x[(__safe_index w3ddmg_u8)e->b],
                    w3ddmg_screen_y[(__safe_index w3ddmg_u8)e->b]);
            }
        }
        i = (w3ddmg_u8)(i + 1);
    }
}
Wire3DDMG_DrawScene

Dibuja hasta ocho objetos de cerca a lejos, usando las caras cercanas para ocultar las aristas posteriores.

Sintaxis

c
void Wire3DDMG_DrawScene(Wire3DDMG_Object* objects, w3ddmg_u8 count);

Parámetros

objects

Array de objetos con posiciones, rotaciones, escalas e indicadores de visibilidad.

count

Cantidad 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

c
#pragma bank 0
// Compare direct model scaling with an object-array scene.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3DDMG_Vec3 vertices[8]={{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}};
__prg_rom Wire3DDMG_Edge edges[12]={{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}};
Wire3DDMG_Model cube;
Wire3DDMG_Object objects[2];
s16 px; s16 py; s16 pz;
void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DDMG_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;

    cube.vertices=vertices;cube.edges=edges;cube.faces=0;cube.edge_faces=0;
    cube.vertex_count=8;cube.edge_count=12;cube.face_count=0;cube.flags=0;

    Wire3DDMG_BeginFrame();
    // Upper pair: direct model calls at unity and half scale.
    Wire3DDMG_DrawModel(&cube,-32,32,96,0,0,0);
    Wire3DDMG_DrawModelScaled(&cube,32,32,96,0,0,0,128);
    // Lower pair: the caller owns both object records and the model tables.
    for(i=0;i<2;i++) {
        objects[i].model=&cube;objects[i].x=-32+(s16)i*64;
        objects[i].y=-32;objects[i].z=96;
        objects[i].rx=0;objects[i].ry=0;objects[i].rz=0;
        objects[i].scale_q8=256-(s16)i*128;objects[i].visible=1;
    }
    Wire3DDMG_DrawScene(objects,2);
    // Numeric checks cover the operation supplied by this viewport profile.
    px=16;py=0;pz=0;Wire3DDMG_RotatePoint(&px,&py,&pz,0,4,0);
    result[1]=px; result[2]=py; result[3]=pz;
    Wire3DDMG_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_models.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_dmg.h:201

Notas de la declaración (original)
Sort at most eight object origins by camera depth, near to far. Draw visible
valid models and mark front-face bounding rectangles for later objects. The
first sorted slot bypasses mask tests and the last needs no new occluder.
This is coarse line rejection, not a depth buffer. Null/empty input is ignored;
caller data and the current projection cache must remain valid during traversal.

kitaqgb/lib/wire3d_dmg.c:3461

c
void Wire3DDMG_DrawScene(Wire3DDMG_Object* objects, w3ddmg_u8 count)
{
    w3ddmg_u8 scene_count;
    w3ddmg_u8 i;

    if (objects == 0) return;

    scene_count = count;
    if (scene_count > WIRE3D_DMG_SCENE_OBJECT_LIMIT) scene_count = WIRE3D_DMG_SCENE_OBJECT_LIMIT;

    if (scene_count == 0) return;


    i = 0;
    while (i < scene_count)
    {
        w3ddmg_scene_order[(__safe_index w3ddmg_u8)i] = i;
        w3ddmg_scene_depth[(__safe_index w3ddmg_u8)i] = w3ddmg_scene_object_depth(&objects[(__safe_index w3ddmg_u8)i]);
        i = (w3ddmg_u8)(i + 1);
    }

    i = 0;
    while (i < scene_count)
    {
        w3ddmg_u8 j;
        j = (w3ddmg_u8)(i + 1);
        while (j < scene_count)
        {
            w3ddmg_u8 oi;
            w3ddmg_u8 oj;
            oi = w3ddmg_scene_order[(__safe_index w3ddmg_u8)i];
            oj = w3ddmg_scene_order[(__safe_index w3ddmg_u8)j];





            if (w3ddmg_scene_depth[(__safe_index w3ddmg_u8)oj] < w3ddmg_scene_depth[(__safe_index w3ddmg_u8)oi])
            {
                w3ddmg_scene_order[(__safe_index w3ddmg_u8)i] = oj;
                w3ddmg_scene_order[(__safe_index w3ddmg_u8)j] = oi;
            }
            j = (w3ddmg_u8)(j + 1);
        }
        i = (w3ddmg_u8)(i + 1);
    }

    w3ddmg_clear_occlusion_mask();



    w3ddmg_occlusion_active = 0;


    i = 0;
    while (i < scene_count)
    {
        Wire3DDMG_Object* obj;
        obj = &objects[(__safe_index w3ddmg_u8)w3ddmg_scene_order[(__safe_index w3ddmg_u8)i]];
        if ((obj->visible != 0) && (obj->model != 0))
        {




            w3ddmg_occlusion_active = i == 0 ? 0 : 1;
            Wire3DDMG_DrawModelScaled(obj->model, obj->x, obj->y, obj->z, obj->rx, obj->ry, obj->rz, obj->scale_q8);
            if ((w3ddmg_u8)(i + 1) < scene_count)
            {
                w3ddmg_mark_model_occluder(obj->model);
            }

        }
        i = (w3ddmg_u8)(i + 1);
    }

    w3ddmg_occlusion_active = 0;
}
Wire3DDMG_EndFrame

Envía a VRAM las escrituras del fondo pendientes y el dibujo preparado.

Sintaxis

c
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

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DDMG_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    Wire3DDMG_SetCamera(8,0,0,0,0,0);
    result[1]=Wire3DDMG_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=Wire3DDMG_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    Wire3DDMG_SetCamera(0,0,0,0,0,0);
    Wire3DDMG_BeginFrame();
    Wire3DDMG_DrawLine2D(8,8,56,8);
    Wire3DDMG_DrawLine2D(56,8,56,40);
    Wire3DDMG_DrawLine2D(56,40,8,40);
    Wire3DDMG_DrawLine2D(8,40,8,8);
    Wire3DDMG_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    Wire3DDMG_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    Wire3DDMG_PutBgTile(1,1,160);
    Wire3DDMG_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_raster.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_dmg.h:286

Notas de la declaración (original)
Wait for the next VBlank and flush BG writes, then optionally consume the
auxiliary strips before uploading either dirty tiles or the entire main stage.
Auxiliary/main source overlap makes that ordering significant. STAT polling
continues across access windows; the update need not fit one VBlank.

kitaqgb/lib/wire3d_dmg.c:3819

c
void Wire3DDMG_EndFrame()
{
    w3ddmg_wait_vblank_start();
    Wire3DDMG_EndFrameNow();
}
Wire3DDMG_EraseModelFaces

Proyecta los triángulos frontales del modelo y borra los píxeles preparados de su interior.

Sintaxis

c
void Wire3DDMG_EraseModelFaces(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz, w3ddmg_i16 scale_q8);

Parámetros

model

Modelo que contiene los arrays de vértices, aristas y caras y sus cantidades; las tablas deben permanecer legibles durante la llamada.

x

Componente X del punto o del origen del objeto en coordenadas del mundo.

y

Componente Y del punto o del origen del objeto en coordenadas del mundo.

z

Componente Z del punto o del origen del objeto en coordenadas del mundo.

rx

Rotación alrededor de X; dieciséis pasos forman una vuelta completa.

ry

Rotación alrededor de Y; dieciséis pasos forman una vuelta completa.

rz

Rotación alrededor de Z; dieciséis pasos forman una vuelta completa.

scale_q8

Escala 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

c
#pragma bank 0
// Erase a screen triangle and a projected model face from separate filled panels.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3DDMG_Vec3 vertices[4]={{-24,-24,0},{24,-24,0},{24,24,0},{-24,24,0}};
__prg_rom Wire3DDMG_Edge edges[4]={{0,1},{1,2},{2,3},{3,0}};
__prg_rom Wire3DDMG_Face faces[2]={{0,2,1},{0,3,2}};
Wire3DDMG_Model plane;

void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DDMG_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
        plane.vertices=vertices;plane.edges=edges;plane.faces=faces;plane.edge_faces=0;
    plane.vertex_count=4;plane.edge_count=4;plane.face_count=2;plane.flags=1;
    Wire3DDMG_BeginFrame();
    // Separate panels show a direct screen triangle and a projected square face.
    for(i=8;i<=32;i++) Wire3DDMG_DrawLine2D(8,i,32,i);
    for(i=36;i<=84;i++) Wire3DDMG_DrawLine2D(40,i,88,i);
    Wire3DDMG_EraseTriangle2D(12,12,28,12,12,28);
    Wire3DDMG_EraseModelFaces(&plane,0,0,64,0,0,0,256);

    Wire3DDMG_EndFrame(); result[7]=0xA55A; while(1) {}
}

Resultado esperado

Las caras proyectadas borran una región rellena y permiten distinguir las zonas conservadas de las borradas.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_faces.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_faces.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_dmg.h:179

Notas de la declaración (original)
Project up to 24 vertices and erase front-facing triangle interiors from
the stage for a model with hidden-line flags and face data. Nonpositive scale
means 256 (unity). Up to 16 faces are considered; depth-crossing faces are
skipped. This also replaces shared projection caches, but does not update VRAM.

kitaqgb/lib/wire3d_dmg.c:3581

c
void Wire3DDMG_EraseModelFaces(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz, w3ddmg_i16 scale_q8)

{
    w3ddmg_u8 i;
    w3ddmg_u8 count;
    w3ddmg_u8 face_count;

    if (model == 0) return;
    if (model->vertices == 0) return;
    if (model->faces == 0) return;
    if ((model->flags & WIRE3D_DMG_MODEL_HIDDEN_LINES) == 0) return;
    if (scale_q8 <= 0) scale_q8 = 256;

    count = model->vertex_count;
    if (count > WIRE3D_DMG_MODEL_VERTEX_LIMIT) count = WIRE3D_DMG_MODEL_VERTEX_LIMIT;

    i = 0;
    while (i < count)
    {
        const Wire3DDMG_Vec3* v;
        w3ddmg_i16 vx;
        w3ddmg_i16 vy;
        w3ddmg_i16 vz;
        w3ddmg_u8 sx;
        w3ddmg_u8 sy;

        v = &model->vertices[(__safe_index w3ddmg_u8)i];
        vx = (w3ddmg_i16)((v->x * scale_q8) >> 8);
        vy = (w3ddmg_i16)((v->y * scale_q8) >> 8);
        vz = (w3ddmg_i16)((v->z * scale_q8) >> 8);






        w3ddmg_rotate_y(&vx, &vz, ry);
        w3ddmg_rotate_x(&vy, &vz, rx);
        w3ddmg_rotate_z(&vx, &vy, rz);


        vx = (w3ddmg_i16)(vx + x);
        vy = (w3ddmg_i16)(vy + y);
        vz = (w3ddmg_i16)(vz + z);

        if (w3ddmg_project_world(vx, vy, vz, &sx, &sy))
        {
            w3ddmg_screen_x[(__safe_index w3ddmg_u8)i] = sx;
            w3ddmg_screen_y[(__safe_index w3ddmg_u8)i] = sy;
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 1;
        }
        else
        {
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 0;
        }
        i = (w3ddmg_u8)(i + 1);
    }

    face_count = model->face_count;
    if (face_count > WIRE3D_DMG_MODEL_FACE_LIMIT) face_count = WIRE3D_DMG_MODEL_FACE_LIMIT;
    w3ddmg_build_face_visibility(model, count, face_count);

    i = 0;
    while (i < face_count)
    {
        const Wire3DDMG_Face* f;
        f = &model->faces[(__safe_index w3ddmg_u8)i];
        if (w3ddmg_face_visible[(__safe_index w3ddmg_u8)i] &&
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)f->a] &&
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)f->b] &&
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)f->c])
        {
            w3ddmg_clear_triangle(
                w3ddmg_screen_x[(__safe_index w3ddmg_u8)f->a],
                w3ddmg_screen_y[(__safe_index w3ddmg_u8)f->a],
                w3ddmg_screen_x[(__safe_index w3ddmg_u8)f->b],
                w3ddmg_screen_y[(__safe_index w3ddmg_u8)f->b],
                w3ddmg_screen_x[(__safe_index w3ddmg_u8)f->c],
                w3ddmg_screen_y[(__safe_index w3ddmg_u8)f->c]);
        }
        i = (w3ddmg_u8)(i + 1);
    }
}

kitaqgb/lib/wire3d_dmg.c:3579

c
void Wire3DDMG_EraseModelFaces(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz, w3ddmg_i16 scale_q8)



{
    w3ddmg_u8 i;
    w3ddmg_u8 count;
    w3ddmg_u8 face_count;

    if (model == 0) return;
    if (model->vertices == 0) return;
    if (model->faces == 0) return;
    if ((model->flags & WIRE3D_DMG_MODEL_HIDDEN_LINES) == 0) return;
    if (scale_q8 <= 0) scale_q8 = 256;

    count = model->vertex_count;
    if (count > WIRE3D_DMG_MODEL_VERTEX_LIMIT) count = WIRE3D_DMG_MODEL_VERTEX_LIMIT;

    i = 0;
    while (i < count)
    {
        const Wire3DDMG_Vec3* v;
        w3ddmg_i16 vx;
        w3ddmg_i16 vy;
        w3ddmg_i16 vz;
        w3ddmg_u8 sx;
        w3ddmg_u8 sy;

        v = &model->vertices[(__safe_index w3ddmg_u8)i];
        vx = (w3ddmg_i16)((v->x * scale_q8) >> 8);
        vy = (w3ddmg_i16)((v->y * scale_q8) >> 8);
        vz = (w3ddmg_i16)((v->z * scale_q8) >> 8);


        w3ddmg_rotate_y(&vx, &vz, (w3ddmg_i8)ry);
        w3ddmg_rotate_x(&vy, &vz, (w3ddmg_i8)rx);
        w3ddmg_rotate_z(&vx, &vy, (w3ddmg_i8)rz);






        vx = (w3ddmg_i16)(vx + x);
        vy = (w3ddmg_i16)(vy + y);
        vz = (w3ddmg_i16)(vz + z);

        if (w3ddmg_project_world(vx, vy, vz, &sx, &sy))
        {
            w3ddmg_screen_x[(__safe_index w3ddmg_u8)i] = sx;
            w3ddmg_screen_y[(__safe_index w3ddmg_u8)i] = sy;
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 1;
        }
        else
        {
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)i] = 0;
        }
        i = (w3ddmg_u8)(i + 1);
    }

    face_count = model->face_count;
    if (face_count > WIRE3D_DMG_MODEL_FACE_LIMIT) face_count = WIRE3D_DMG_MODEL_FACE_LIMIT;
    w3ddmg_build_face_visibility(model, count, face_count);

    i = 0;
    while (i < face_count)
    {
        const Wire3DDMG_Face* f;
        f = &model->faces[(__safe_index w3ddmg_u8)i];
        if (w3ddmg_face_visible[(__safe_index w3ddmg_u8)i] &&
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)f->a] &&
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)f->b] &&
            w3ddmg_screen_visible[(__safe_index w3ddmg_u8)f->c])
        {
            w3ddmg_clear_triangle(
                w3ddmg_screen_x[(__safe_index w3ddmg_u8)f->a],
                w3ddmg_screen_y[(__safe_index w3ddmg_u8)f->a],
                w3ddmg_screen_x[(__safe_index w3ddmg_u8)f->b],
                w3ddmg_screen_y[(__safe_index w3ddmg_u8)f->b],
                w3ddmg_screen_x[(__safe_index w3ddmg_u8)f->c],
                w3ddmg_screen_y[(__safe_index w3ddmg_u8)f->c]);
        }
        i = (w3ddmg_u8)(i + 1);
    }
}
Wire3DDMG_EraseSpan2D

Borra un tramo horizontal, con ambos extremos incluidos, de una fila preparada.

Sintaxis

c
void Wire3DDMG_EraseSpan2D(w3ddmg_u8 y, w3ddmg_u8 x0, w3ddmg_u8 x1);

Parámetros

y

Coordenada Y en píxeles de la fila que se va a borrar.

x0

Extremo X inferior, en píxeles de la ventana gráfica; el orden y el recorte siguen las notas de esta operación.

x1

Extremo 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

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DDMG_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    Wire3DDMG_SetCamera(8,0,0,0,0,0);
    result[1]=Wire3DDMG_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=Wire3DDMG_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    Wire3DDMG_SetCamera(0,0,0,0,0,0);
    Wire3DDMG_BeginFrame();
    Wire3DDMG_DrawLine2D(8,8,56,8);
    Wire3DDMG_DrawLine2D(56,8,56,40);
    Wire3DDMG_DrawLine2D(56,40,8,40);
    Wire3DDMG_DrawLine2D(8,40,8,8);
    Wire3DDMG_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    Wire3DDMG_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    Wire3DDMG_PutBgTile(1,1,160);
    Wire3DDMG_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_raster.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_dmg.h:187

Notas de la declaración (original)
Order the X endpoints and erase the inclusive staged span. Both endpoints
must be in 0..127; invalid Y is ignored. The routine does not clip X for you.

kitaqgb/lib/wire3d_dmg.c:3681

c
void Wire3DDMG_EraseSpan2D(w3ddmg_u8 y, w3ddmg_u8 x0, w3ddmg_u8 x1)
{
    w3ddmg_u8 tx;

    if (x0 > x1)
    {
        tx = x0;
        x0 = x1;
        x1 = tx;
    }
    w3ddmg_stage_clear_span(y, x0, x1);
}
Wire3DDMG_EraseTriangle2D

Borra un triángulo de pantalla del área de preparación mediante tramos horizontales de líneas de barrido.

Sintaxis

c
void Wire3DDMG_EraseTriangle2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by, w3ddmg_u8 cx, w3ddmg_u8 cy);

Parámetros

ax

Coordenada X del vértice A en píxeles de la ventana gráfica.

ay

Coordenada Y del vértice A en píxeles de la ventana gráfica.

bx

Coordenada X del vértice B en píxeles de la ventana gráfica.

by

Coordenada Y del vértice B en píxeles de la ventana gráfica.

cx

Coordenada X del vértice C en píxeles de la ventana gráfica.

cy

Coordenada 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

c
#pragma bank 0
// Erase a screen triangle and a projected model face from separate filled panels.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3DDMG_Vec3 vertices[4]={{-24,-24,0},{24,-24,0},{24,24,0},{-24,24,0}};
__prg_rom Wire3DDMG_Edge edges[4]={{0,1},{1,2},{2,3},{3,0}};
__prg_rom Wire3DDMG_Face faces[2]={{0,2,1},{0,3,2}};
Wire3DDMG_Model plane;

void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DDMG_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
        plane.vertices=vertices;plane.edges=edges;plane.faces=faces;plane.edge_faces=0;
    plane.vertex_count=4;plane.edge_count=4;plane.face_count=2;plane.flags=1;
    Wire3DDMG_BeginFrame();
    // Separate panels show a direct screen triangle and a projected square face.
    for(i=8;i<=32;i++) Wire3DDMG_DrawLine2D(8,i,32,i);
    for(i=36;i<=84;i++) Wire3DDMG_DrawLine2D(40,i,88,i);
    Wire3DDMG_EraseTriangle2D(12,12,28,12,12,28);
    Wire3DDMG_EraseModelFaces(&plane,0,0,64,0,0,0,256);

    Wire3DDMG_EndFrame(); result[7]=0xA55A; while(1) {}
}

Resultado esperado

Las caras proyectadas borran una región rellena y permiten distinguir las zonas conservadas de las borradas.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_faces.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_faces.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_dmg.h:184

Notas de la declaración (original)
Erase a triangle from staged pixels using integer scanline intersections.
Supply viewport coordinates. Degenerate triangles are ignored; the occlusion
mask and VRAM are unchanged.

kitaqgb/lib/wire3d_dmg.c:3671

c
void Wire3DDMG_EraseTriangle2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by, w3ddmg_u8 cx, w3ddmg_u8 cy)
{
    w3ddmg_clear_triangle(ax, ay, bx, by, cx, cy);
}
Wire3DDMG_Init

Inicializa el LCD, los tiles y el mapa del fondo para una ventana gráfica de alambre monocroma.

Sintaxis

c
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

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DDMG_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    Wire3DDMG_SetCamera(8,0,0,0,0,0);
    result[1]=Wire3DDMG_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=Wire3DDMG_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    Wire3DDMG_SetCamera(0,0,0,0,0,0);
    Wire3DDMG_BeginFrame();
    Wire3DDMG_DrawLine2D(8,8,56,8);
    Wire3DDMG_DrawLine2D(56,8,56,40);
    Wire3DDMG_DrawLine2D(56,40,8,40);
    Wire3DDMG_DrawLine2D(8,40,8,8);
    Wire3DDMG_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    Wire3DDMG_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    Wire3DDMG_PutBgTile(1,1,160);
    Wire3DDMG_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_raster.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_dmg.h:135

Notas de la declaración (original)
Take over LCD state, clear tile VRAM and the BG map, and install a 16x15
viewport beginning at map tile (3,1). Set scroll (8,0), BGP=0xB4 and BG display.
Reset camera, queues, transfer modes, both dirty tables and stage. Reserve
0xD000..0xDFFF and retain its WRAM mapping; auxiliary storage aliases it.
Call BeginFrame before drawing to establish occlusion state.

kitaqgb/lib/wire3d_dmg.c:3310

c
void Wire3DDMG_Init()
{
    w3ddmg_u8 row;
    w3ddmg_u8 col;
    w3ddmg_u8 tid;
    w3ddmg_u16 off;

    w3ddmg_wait_vblank_start();
    w3ddmg_reg_lcdc = 0;

    w3ddmg_clear_vram_asm();



    w3ddmg_fill_bg_map_asm();

    row = 0;
    tid = 0x90;
    while (row < WIRE3D_DMG_TILE_H)
    {



        off = (w3ddmg_u16)(0x23 + ((w3ddmg_u16)row << 5));

        col = 0;
        while (col < WIRE3D_DMG_TILE_W)
        {
            w3ddmg_bg_map_9800[(w3ddmg_u16)(off + (w3ddmg_u16)col)] = tid;
            tid = (w3ddmg_u8)(tid + WIRE3D_DMG_TILE_H);
            col = (w3ddmg_u8)(col + 1);
        }
        row = (w3ddmg_u8)(row + 1);
        tid = (w3ddmg_u8)(0x90 + row);
    }




    w3ddmg_reg_scx = 8;

    w3ddmg_reg_scy = 0;
    w3ddmg_reg_bgp = 0xB4;
    w3ddmg_reg_lcdc = 0x81;
    w3ddmg_bgq_count = 0;

    w3ddmg_aux_transfer_enabled = 0;
    w3ddmg_dirty_transfer_enabled = 0;


    Wire3DDMG_SetCamera((w3ddmg_i16)0, (w3ddmg_i16)0, (w3ddmg_i16)0, (w3ddmg_u8)0, (w3ddmg_u8)0, (w3ddmg_u8)0);
    w3ddmg_clear_stage_asm();

    w3ddmg_clear_stage_aux_asm();
    w3ddmg_clear_dirty_tables();

}
Wire3DDMG_ProjectPoint

Proyecta un punto del mundo mediante la cámara a coordenadas de la ventana gráfica.

Sintaxis

c
w3ddmg_u8 Wire3DDMG_ProjectPoint(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8* sx, w3ddmg_u8* sy);

Parámetros

x

Componente X del punto o del origen del objeto en coordenadas del mundo.

y

Componente Y del punto o del origen del objeto en coordenadas del mundo.

z

Componente Z del punto o del origen del objeto en coordenadas del mundo.

sx

Puntero u8 válido y escribible que recibe la coordenada X proyectada.

sy

Puntero 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

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DDMG_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    Wire3DDMG_SetCamera(8,0,0,0,0,0);
    result[1]=Wire3DDMG_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=Wire3DDMG_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    Wire3DDMG_SetCamera(0,0,0,0,0,0);
    Wire3DDMG_BeginFrame();
    Wire3DDMG_DrawLine2D(8,8,56,8);
    Wire3DDMG_DrawLine2D(56,8,56,40);
    Wire3DDMG_DrawLine2D(56,40,8,40);
    Wire3DDMG_DrawLine2D(8,40,8,8);
    Wire3DDMG_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    Wire3DDMG_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    Wire3DDMG_PutBgTile(1,1,160);
    Wire3DDMG_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_raster.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_dmg.h:216

Notas de la declaración (original)
Project a world point with the current camera. Return zero for invalid
depth without changing outputs; success writes clamped 128x120 coordinates.
Both output pointers must be valid. Coordinate differences must fit s16.

kitaqgb/lib/wire3d_dmg.c:688

c
w3ddmg_u8 Wire3DDMG_ProjectPoint(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8* sx, w3ddmg_u8* sy)
{
    return w3ddmg_project_world(x, y, z, sx, sy);
}
Wire3DDMG_PutBgTile

Encola una escritura de número de tile en una celda del mapa del fondo.

Sintaxis

c
void Wire3DDMG_PutBgTile(w3ddmg_u8 x, w3ddmg_u8 y, w3ddmg_u8 tile);

Parámetros

x

Coordenada X de tile en el mapa del fondo de 32×32.

y

Coordenada Y de tile en el mapa del fondo de 32×32.

tile

Nú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

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DDMG_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    Wire3DDMG_SetCamera(8,0,0,0,0,0);
    result[1]=Wire3DDMG_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=Wire3DDMG_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    Wire3DDMG_SetCamera(0,0,0,0,0,0);
    Wire3DDMG_BeginFrame();
    Wire3DDMG_DrawLine2D(8,8,56,8);
    Wire3DDMG_DrawLine2D(56,8,56,40);
    Wire3DDMG_DrawLine2D(56,40,8,40);
    Wire3DDMG_DrawLine2D(8,40,8,8);
    Wire3DDMG_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    Wire3DDMG_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    Wire3DDMG_PutBgTile(1,1,160);
    Wire3DDMG_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_raster.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_dmg.h:258

Notas de la declaración (original)
Queue a tile write to the 32x32 map at 0x9800 for EndFrame. Invalid map
coordinates and submissions beyond 48 pending writes are silently ignored.
This queue is separate from the general vram library queue.

kitaqgb/lib/wire3d_dmg.c:731

c
void Wire3DDMG_PutBgTile(w3ddmg_u8 x, w3ddmg_u8 y, w3ddmg_u8 tile)
{
    if (x >= 32) return;
    if (y >= 32) return;
    if (w3ddmg_bgq_count >= WIRE3D_DMG_BG_QUEUE_LIMIT) return;
    w3ddmg_bgq_x[(__safe_index w3ddmg_u8)w3ddmg_bgq_count] = x;
    w3ddmg_bgq_y[(__safe_index w3ddmg_u8)w3ddmg_bgq_count] = y;
    w3ddmg_bgq_tile[(__safe_index w3ddmg_u8)w3ddmg_bgq_count] = tile;
    w3ddmg_bgq_count = (w3ddmg_u8)(w3ddmg_bgq_count + 1);
}
Wire3DDMG_RotatePoint

Rota un punto en sus propias variables según los ángulos indicados.

Sintaxis

c
void Wire3DDMG_RotatePoint(w3ddmg_i16* x, w3ddmg_i16* y, w3ddmg_i16* z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz);

Parámetros

x

Puntero s16 escribible y distinto de los demás para la componente X.

y

Puntero s16 escribible y distinto de los demás para la componente Y.

z

Puntero s16 escribible y distinto de los demás para la componente Z.

rx

Rotación alrededor de X; dieciséis pasos forman una vuelta completa.

ry

Rotación alrededor de Y; dieciséis pasos forman una vuelta completa.

rz

Rotació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

c
#pragma bank 0
// Compare direct model scaling with an object-array scene.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3DDMG_Vec3 vertices[8]={{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}};
__prg_rom Wire3DDMG_Edge edges[12]={{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}};
Wire3DDMG_Model cube;
Wire3DDMG_Object objects[2];
s16 px; s16 py; s16 pz;
void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DDMG_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;

    cube.vertices=vertices;cube.edges=edges;cube.faces=0;cube.edge_faces=0;
    cube.vertex_count=8;cube.edge_count=12;cube.face_count=0;cube.flags=0;

    Wire3DDMG_BeginFrame();
    // Upper pair: direct model calls at unity and half scale.
    Wire3DDMG_DrawModel(&cube,-32,32,96,0,0,0);
    Wire3DDMG_DrawModelScaled(&cube,32,32,96,0,0,0,128);
    // Lower pair: the caller owns both object records and the model tables.
    for(i=0;i<2;i++) {
        objects[i].model=&cube;objects[i].x=-32+(s16)i*64;
        objects[i].y=-32;objects[i].z=96;
        objects[i].rx=0;objects[i].ry=0;objects[i].rz=0;
        objects[i].scale_q8=256-(s16)i*128;objects[i].visible=1;
    }
    Wire3DDMG_DrawScene(objects,2);
    // Numeric checks cover the operation supplied by this viewport profile.
    px=16;py=0;pz=0;Wire3DDMG_RotatePoint(&px,&py,&pz,0,4,0);
    result[1]=px; result[2]=py; result[3]=pz;
    Wire3DDMG_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_models.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_dmg.h:221

Notas de la declaración (original)
Rotate in place in Y/X/Z order using 16 steps per full turn. A null
component pointer makes the whole call a no-op; use distinct pointers.
Each axis rotation clamps its inputs to +/-220.

kitaqgb/lib/wire3d_dmg.c:3865

c
void Wire3DDMG_RotatePoint(w3ddmg_i16* x, w3ddmg_i16* y, w3ddmg_i16* z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz)
{
    if (x == 0) return;
    if (y == 0) return;
    if (z == 0) return;

    w3ddmg_rotate_y(x, z, ry);
    w3ddmg_rotate_x(y, z, rx);
    w3ddmg_rotate_z(x, y, rz);
}
Wire3DDMG_SelectEdgeMask

Selecciona una máscara precalculada de visibilidad de aristas según la guiñada del objeto.

Sintaxis

c
w3ddmg_u16 Wire3DDMG_SelectEdgeMask(const Wire3DDMG_Model* model, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz);

Parámetros

model

Modelo que contiene los arrays de vértices, aristas y caras y sus cantidades; las tablas deben permanecer legibles durante la llamada.

rx

Rotación alrededor de X; dieciséis pasos forman una vuelta completa.

ry

Rotación alrededor de Y; dieciséis pasos forman una vuelta completa.

rz

Rotació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

c
#pragma bank 0
// Compare direct model scaling with an object-array scene.
// The selected 96-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 96
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3DDMG_Vec3 vertices[8]={{-16,-16,-16},{16,-16,-16},{16,16,-16},{-16,16,-16},{-16,-16,16},{16,-16,16},{16,16,16},{-16,16,16}};
__prg_rom Wire3DDMG_Edge edges[12]={{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}};
Wire3DDMG_Model cube;
Wire3DDMG_Object objects[2];
u16 masks[2];
void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DDMG_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;

    cube.vertices=vertices;cube.edges=edges;cube.faces=0;cube.edge_faces=0;
    cube.vertex_count=8;cube.edge_count=12;cube.face_count=0;cube.flags=0;
    cube.edge_masks=0; cube.edge_mask_count=0;
    Wire3DDMG_BeginFrame();
    // Upper pair: direct model calls at unity and half scale.
    Wire3DDMG_DrawModel(&cube,-32,32,96,0,0,0);
    Wire3DDMG_DrawModelScaled(&cube,32,32,96,0,0,0,128);
    // Lower pair: the caller owns both object records and the model tables.
    for(i=0;i<2;i++) {
        objects[i].model=&cube;objects[i].x=-32+(s16)i*64;
        objects[i].y=-32;objects[i].z=96;
        objects[i].rx=0;objects[i].ry=0;objects[i].rz=0;
        objects[i].scale_q8=256-(s16)i*128;objects[i].visible=1;
    }
    Wire3DDMG_DrawScene(objects,2);
    // Numeric checks cover the operation supplied by this viewport profile.
    masks[0]=3;masks[1]=12;cube.edge_masks=masks; cube.edge_mask_count=2;
    result[1]=Wire3DDMG_SelectEdgeMask(&cube,0,0,0);
    result[2]=Wire3DDMG_SelectEdgeMask(&cube,0,8,0);
    Wire3DDMG_EndFrame(); result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg96_models.c .\kitaqgb\lib\wire3d_dmg_96.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg96_models.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_dmg.h:207

Notas de la declaración (original)
Select a precomputed mask from the low four bits of object yaw; pitch,
roll and camera orientation are ignored. Use 16, 8, 4 or 2 bins; other positive
counts select entry zero (counts >=16 use the first 16). Missing data returns
0xFFFF. Keep the mask table readable through the current data-pointer mapping.

kitaqgb/lib/wire3d_dmg.c:1258

c
w3ddmg_u16 Wire3DDMG_SelectEdgeMask(const Wire3DDMG_Model* model, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz)
{
    w3ddmg_u8 count;
    w3ddmg_u8 bin;

    if (model == 0) return 0xFFFF;
    if (model->edge_masks == 0) return 0xFFFF;
    count = model->edge_mask_count;
    if (count == 0) return 0xFFFF;

    (void)rx;
    (void)rz;

    bin = (w3ddmg_u8)(((w3ddmg_u8)ry) & 15);
    if (count >= 16) return model->edge_masks[(__safe_index w3ddmg_u8)bin];
    if (count == 8) bin = (w3ddmg_u8)(bin >> 1);
    else if (count == 4) bin = (w3ddmg_u8)(bin >> 2);
    else if (count == 2) bin = (w3ddmg_u8)(bin >> 3);
    else bin = 0;

    if (bin >= count) bin = (w3ddmg_u8)(count - 1);
    return model->edge_masks[(__safe_index w3ddmg_u8)bin];
}
Wire3DDMG_SetAuxTransfer

Elige si EndFrame también transfiere las franjas auxiliares.

Sintaxis

c
void Wire3DDMG_SetAuxTransfer(w3ddmg_u8 flag);

Parámetros

flag

Cero 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

c
#pragma bank 0
// Use the auxiliary-transfer gate to consume an overlapping stage strip.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;

void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DDMG_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
        Wire3DDMG_SetDirtyTransfer(1); Wire3DDMG_SetAuxTransfer(1);
    Wire3DDMG_BeginFrame();
    for(i=24;i<=31;i++) Wire3DDMG_DrawLine2D(40,i,47,i);
    // Auxiliary upload consumes this source before the dirty main tile is sent.

    Wire3DDMG_EndFrame(); result[7]=0xA55A; while(1) {}
}

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).

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_aux_gate.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_aux_gate.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_dmg.h:268

Notas de la declaración (original)
Store the EndFrame auxiliary-transfer gate; any nonzero value enables it.
No data is copied or cleared here. Auxiliary source bytes alias the main stage.

kitaqgb/lib/wire3d_dmg.c:4639

c
void Wire3DDMG_SetAuxTransfer(w3ddmg_u8 flag)
{
    w3ddmg_aux_transfer_enabled = flag;
}
Wire3DDMG_SetCamera

Guarda la posición y la orientación de la cámara para las proyecciones posteriores.

Sintaxis

c
void Wire3DDMG_SetCamera(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 pitch, w3ddmg_u8 yaw, w3ddmg_u8 roll);

Parámetros

x

Componente X de la cámara en coordenadas del mundo.

y

Componente Y de la cámara en coordenadas del mundo.

z

Componente Z de la cámara en coordenadas del mundo.

pitch

Rotación alrededor de X; dieciséis pasos forman una vuelta completa.

yaw

Rotación alrededor de Y; dieciséis pasos forman una vuelta completa.

roll

Rotació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

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DDMG_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    Wire3DDMG_SetCamera(8,0,0,0,0,0);
    result[1]=Wire3DDMG_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=Wire3DDMG_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    Wire3DDMG_SetCamera(0,0,0,0,0,0);
    Wire3DDMG_BeginFrame();
    Wire3DDMG_DrawLine2D(8,8,56,8);
    Wire3DDMG_DrawLine2D(56,8,56,40);
    Wire3DDMG_DrawLine2D(56,40,8,40);
    Wire3DDMG_DrawLine2D(8,40,8,8);
    Wire3DDMG_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    Wire3DDMG_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    Wire3DDMG_PutBgTile(1,1,160);
    Wire3DDMG_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_raster.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_dmg.h:152

Notas de la declaración (original)
Store camera position and angles for later draws; a full turn is 16 angle
steps. No existing drawing is reprojected and no input range validation occurs.

kitaqgb/lib/wire3d_dmg.c:3399

c
void Wire3DDMG_SetCamera(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 pitch, w3ddmg_u8 yaw, w3ddmg_u8 roll)

{
    w3ddmg_cam_x = x;
    w3ddmg_cam_y = y;
    w3ddmg_cam_z = z;
    w3ddmg_cam_pitch = pitch;
    w3ddmg_cam_yaw = yaw;
    w3ddmg_cam_roll = roll;
}

kitaqgb/lib/wire3d_dmg.c:3397

c
void Wire3DDMG_SetCamera(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 pitch, w3ddmg_i8 yaw, w3ddmg_i8 roll)



{
    w3ddmg_cam_x = x;
    w3ddmg_cam_y = y;
    w3ddmg_cam_z = z;
    w3ddmg_cam_pitch = pitch;
    w3ddmg_cam_yaw = yaw;
    w3ddmg_cam_roll = roll;
}
Wire3DDMG_SetDirtyTransfer

Selecciona la transferencia de tiles modificados para la ventana gráfica principal de 120 filas.

Sintaxis

c
void Wire3DDMG_SetDirtyTransfer(w3ddmg_u8 flag);

Parámetros

flag

Cero 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

c
#pragma bank 0
// Remove the previous frame and upload only the tracked current/previous tiles.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;

void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DDMG_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
        Wire3DDMG_SetDirtyTransfer(1); Wire3DDMG_SetAuxTransfer(0);
    Wire3DDMG_BeginFrame();
    Wire3DDMG_DrawLine2D(8,8,24,8); Wire3DDMG_DrawLine2D(24,8,24,24);
    Wire3DDMG_DrawLine2D(24,24,8,24); Wire3DDMG_DrawLine2D(8,24,8,8);
    Wire3DDMG_EndFrame();
    Wire3DDMG_BeginFrame();
    Wire3DDMG_DrawLine2D(80,80,104,80); Wire3DDMG_DrawLine2D(104,80,104,104);
    Wire3DDMG_DrawLine2D(104,104,80,104); Wire3DDMG_DrawLine2D(80,104,80,80);

    Wire3DDMG_EndFrame(); result[7]=0xA55A; while(1) {}
}

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).

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_dirty.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_dirty.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_dmg.h:272

Notas de la declaración (original)
Store the dirty-transfer gate and clear both dirty histories and the main
stage, even if the value is unchanged. VRAM is retained; enabling this over an
old image can leave unmarked old tiles, so arrange a clean displayed baseline.

kitaqgb/lib/wire3d_dmg.c:4699

c
void Wire3DDMG_SetDirtyTransfer(w3ddmg_u8 flag)
{
    w3ddmg_dirty_transfer_enabled = flag;
    w3ddmg_clear_dirty_tables();
    w3ddmg_clear_stage_asm();
}
Wire3DDMG_SetPalette

Escribe la correspondencia de cuatro tonos en el registro de paleta del fondo monocromo BGP.

Sintaxis

c
void Wire3DDMG_SetPalette(w3ddmg_u8 bgp);

Parámetros

bgp

Valor 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

c
#pragma bank 0
// Draw a frame with a gap, a projected diagonal, and a copied corner tile.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
u8 projected_x;
u8 projected_y;
void main() {
    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DDMG_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
    Wire3DDMG_SetCamera(8,0,0,0,0,0);
    result[1]=Wire3DDMG_ProjectPoint(0,0,96,&projected_x,&projected_y);
    result[2]=projected_x; result[3]=projected_y;
    projected_x=91; projected_y=92;
    result[4]=Wire3DDMG_ProjectPoint(0,0,7,&projected_x,&projected_y);
    result[5]=projected_x; result[6]=projected_y;
    Wire3DDMG_SetCamera(0,0,0,0,0,0);
    Wire3DDMG_BeginFrame();
    Wire3DDMG_DrawLine2D(8,8,56,8);
    Wire3DDMG_DrawLine2D(56,8,56,40);
    Wire3DDMG_DrawLine2D(56,40,8,40);
    Wire3DDMG_DrawLine2D(8,40,8,8);
    Wire3DDMG_EraseSpan2D(8,40,24); // Inclusive endpoints are ordered internally.
    Wire3DDMG_DrawLine3D(-24,-24,96,24,24,96);
    // Copy the viewport's top-left frame corner to a separate map cell.
    Wire3DDMG_PutBgTile(1,1,160);
    Wire3DDMG_EndFrame();
    result[7]=0xA55A;
    while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_raster.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_raster.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_dmg.h:260

Notas de la declaración (original)
Write the raw DMG BGP palette encoding immediately; no frame synchronization occurs.

kitaqgb/lib/wire3d_dmg.c:746

c
void Wire3DDMG_SetPalette(w3ddmg_u8 bgp)
{
    w3ddmg_reg_bgp = bgp;
}
Wire3DDMG_TransferAuxNow

Transfiere inmediatamente seis franjas auxiliares y borra sus bytes fuente.

Sintaxis

c
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

c
#pragma bank 0
// Upload a main line and an auxiliary block separately; verify source consumption.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3DDMG_Vec3 vertices[2]={{-32,0,0},{32,0,0}};
__prg_rom u8 edge_pairs[2]={0,1};
u8* stage_byte;

void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DDMG_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
        Wire3DDMG_BeginFrame();
    Wire3DDMG_DrawIndexedEdges(vertices,2,edge_pairs,1,-64,104,96,1);
    Wire3DDMG_TransferMainNow();
    // Direct auxiliary transfer writes a separate tile after the main upload.
    for(i=24;i<=31;i++) Wire3DDMG_DrawLine2D(40,i,47,i);
    stage_byte=(u8*)0xD518;result[1]=*stage_byte;
    Wire3DDMG_TransferAuxNow();result[2]=*stage_byte;

    // Do not upload the consumed stage again.
    result[7]=0xA55A; while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_direct.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_direct.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_dmg.h:280

Notas de la declaración (original)
Upload and consume auxiliary source strips immediately, independent of the
auxiliary gate. No VBlank-start wait or dirty-history/BG-queue update occurs.
The source overlaps the main stage and must be coordinated with its upload.

kitaqgb/lib/wire3d_dmg.c:4727

c
void Wire3DDMG_TransferAuxNow()
{
    w3ddmg_transfer_stage_aux_asm();
}
Wire3DDMG_TransferMainNow

Transfiere inmediatamente toda el área principal y borra los píxeles fuente consumidos.

Sintaxis

c
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

c
#pragma bank 0
// Upload a main line and an auxiliary block separately; verify source consumption.
// The selected 120-line profile determines the stage layout and camera center.
#define WIRE3D_DMG_HEIGHT 120
#include "wire3d_dmg.h"
__location(0xC110) u16 result[8];
__location(0xFF47) u8 sample_bgp;
__location(0xFF40) u8 sample_lcdc;
__location(0xFF44) u8 sample_ly;
__location(0xFF4F) u8 sample_vbk;
__location(0xFF68) u8 sample_bgpi;
__location(0xFF69) u8 sample_bgpd;
__prg_rom Wire3DDMG_Vec3 vertices[2]={{-32,0,0},{32,0,0}};
__prg_rom u8 edge_pairs[2]={0,1};
u8* stage_byte;

void main() {

    u8 i;
    for(i=0;i<8;i++) result[i]=0;
    Wire3DDMG_Init();
    // A CGB-compatible ROM also needs CGB palette and tile-map attributes.
    if(__cgb_is_cgb()) {
        while(sample_ly>=144) {} while(sample_ly<144) {}
        sample_lcdc=0; sample_vbk=1;
        __vram_memset_unsafe(0x9800,0,1024); sample_vbk=0;
        sample_bgpi=0x80; sample_bgpd=255; sample_bgpd=127;
        for(i=0;i<6;i++) sample_bgpd=0;
        sample_lcdc=0x81;
    }
    Wire3DDMG_SetPalette(0xFC); // White background; every nonzero shade is black.
    result[0]=sample_bgp;
        Wire3DDMG_BeginFrame();
    Wire3DDMG_DrawIndexedEdges(vertices,2,edge_pairs,1,-64,104,96,1);
    Wire3DDMG_TransferMainNow();
    // Direct auxiliary transfer writes a separate tile after the main upload.
    for(i=24;i<=31;i++) Wire3DDMG_DrawLine2D(40,i,47,i);
    stage_byte=(u8*)0xD518;result[1]=*stage_byte;
    Wire3DDMG_TransferAuxNow();result[2]=*stage_byte;

    // Do not upload the consumed stage again.
    result[7]=0xA55A; while(1) {}
}

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.

Programa de ejemplo completo

Comando de compilación

powershell
New-Item -ItemType Directory -Force .\out | Out-Null
.\kitaqgb\kitaqgb.exe .\kitaq-docs\samples\api-examples\gb\wire_dmg120_direct.c .\kitaqgb\lib\wire3d_dmg.c -I .\kitaqgb\lib -I .\kitaq-docs\samples -o .\out\wire_dmg120_direct.gb --profile=dev --stack-bank=fixed --rst-disable --cgb=cgb --cart=mbc5 --romsize=256k --no-cache --no-disasm
Implementación y código fuente

kitaqgb/lib/wire3d_dmg.h:276

Notas de la declaración (original)
Upload and consume the full main stage immediately, polling STAT but not
waiting for the next VBlank. Ignore transfer gates and leave dirty histories
and BG tile queue unchanged; the caller coordinates the frame lifecycle.

kitaqgb/lib/wire3d_dmg.c:4714

c
void Wire3DDMG_TransferMainNow()
{
    w3ddmg_transfer_stage_asm();
}

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
c
#pragma once

#define ASSET_TYPE_RAW   ((u8)0)
#define ASSET_TYPE_TILES ((u8)1)
#define ASSET_TYPE_MAP   ((u8)2)
#define ASSET_TYPE_SONG  ((u8)3)

// Packed ROM descriptor: type tag, payload bank, bank-window address and byte length.
// The table itself may live in a different bank from the payload.
typedef __packed struct {
    u8 type;
    u8 bank;
    const u8* ptr;
    u16 len;
} AssetDesc;

void __farmemcpy(void* dst, u8 bank, const void* src, u16 len);
void __vram_copy(u16 dst, const void* src, u16 len);

// Retain the descriptor table address, bank and count; the table is not copied.
void asset_set_table(u8 bank, const AssetDesc* table, u8 count);
// Copy one descriptor from its ROM bank into caller storage. Return zero for a
// null destination or an out-of-range ID; table validity is the caller's responsibility.
u8 asset_get(u8 asset_id, AssetDesc* out_desc);
// Copy at most max_len bytes using the asset's bank. Success means the ID was
// valid, even when the payload was truncated to fit the supplied limit.
u8 asset_load_raw(u8 asset_id, void* dst, u16 max_len);
// Accept tile/raw descriptors and transfer their bytes to VRAM. This path passes
// the descriptor pointer directly; callers must arrange the correct visible ROM bank.
u8 asset_load_tiles(u8 asset_id, u16 vram_dst);
// Return the descriptor bank, or zero on lookup failure; zero can also be a valid bank.
u8 asset_get_bank(u8 asset_id);
// Return the stored address without switching banks. Use the descriptor bank
// with far-data helpers before dereferencing banked assets; failure returns null.
const u8* asset_get_ptr(u8 asset_id);
// Return the descriptor byte length, or zero if its ID cannot be resolved.
u16 asset_get_len(u8 asset_id);

kitaqgb/lib/asset.h

audio.h — Música, efectos de sonido y control de audio
c
#pragma once

// Shared Game Boy audio driver for KITAQGB projects.
//
// Integration notes:
// - Compile a hardware-register file before audio.c so NR10..NR52 and
//   WAVE0..WAVE15 are already declared.
// - Call Audio_Init() once during startup.
// - Call Audio_Update() once per frame, ideally from your VBlank-driven main loop.
// - audio.c is intended to stay in bank 0.
// - Music streams are banked explicitly with Audio_PlayMusic(bank, song).
// - Audio_PlaySFX(sfx, priority) captures the currently visible ROM bank.
// - Audio_PlaySFXBanked(bank, sfx, priority) safely classifies CH1/CH3 data
//   after switching to the requested bank, so banked SFX can be started from
//   any currently visible ROM bank.
// - GBDAW-Stream v1.2 extends the legacy command set with explicit per-channel
//   automation commands that map more directly from GUI and Python tooling.

// Physical APIs and music-stream commands share zero-based CH1..CH4 IDs.
#define AUDIO_CHANNEL_CH1 ((u8)0)
#define AUDIO_CHANNEL_CH2 ((u8)1)
#define AUDIO_CHANNEL_CH3 ((u8)2)
#define AUDIO_CHANNEL_CH4 ((u8)3)

// Music-stream IDs used by NOTE, SET_INST and STOP_CHANNEL.
#define AUDIO_STREAM_CHANNEL_CH1 AUDIO_CHANNEL_CH1
#define AUDIO_STREAM_CHANNEL_CH2 AUDIO_CHANNEL_CH2
#define AUDIO_STREAM_CHANNEL_CH3 AUDIO_CHANNEL_CH3
#define AUDIO_STREAM_CHANNEL_CH4 AUDIO_CHANNEL_CH4

#define AUDIO_PAN_CENTER ((u8)0)
#define AUDIO_PAN_LEFT ((u8)1)
#define AUDIO_PAN_RIGHT ((u8)2)
#define AUDIO_PAN_MUTE ((u8)3)
#define AUDIO_PAN_INHERIT ((u8)0xFF)

#define AUDIO_WAVE_TRIANGLE ((u8)0)
#define AUDIO_WAVE_SAW ((u8)1)
#define AUDIO_WAVE_VOWEL_A ((u8)2)
#define AUDIO_WAVE_VOWEL_I ((u8)3)
#define AUDIO_WAVE_VOWEL_U ((u8)4)
#define AUDIO_WAVE_VOWEL_E ((u8)5)
#define AUDIO_WAVE_VOWEL_O ((u8)6)
#define AUDIO_WAVE_CUSTOM ((u8)7)

#define AUDIO_CH3_LEVEL_MUTE ((u8)0x00)
#define AUDIO_CH3_LEVEL_100 ((u8)0x20)
#define AUDIO_CH3_LEVEL_50 ((u8)0x40)
#define AUDIO_CH3_LEVEL_25 ((u8)0x60)

#define AUDIO_VOLUME_MIN ((u8)0)
#define AUDIO_VOLUME_MAX ((u8)7)
#define AUDIO_NOTE_MAX ((u8)67)

#define AUDIO_CMD_WAIT ((u8)0x00)
#define AUDIO_CMD_NOTE ((u8)0x10)
#define AUDIO_CMD_SET_INST ((u8)0x11)
#define AUDIO_CMD_SET_PAN ((u8)0x12)
#define AUDIO_CMD_SET_SWEEP ((u8)0x13)
#define AUDIO_CMD_SET_WAVE ((u8)0x14)
#define AUDIO_CMD_SET_CH3_CUSTOM_WAVE ((u8)0x15)
#define AUDIO_CMD_SET_CH4_PARAM ((u8)0x16)
#define AUDIO_CMD_SET_MASTER_VOLUME ((u8)0x17)
#define AUDIO_CMD_SET_CH1_DUTY ((u8)0x18)
#define AUDIO_CMD_SET_CH2_DUTY ((u8)0x19)
#define AUDIO_CMD_SET_CH3_LEVEL ((u8)0x1A)
#define AUDIO_CMD_STOP_CHANNEL ((u8)0x20)
#define AUDIO_CMD_LOOP ((u8)0x30)
#define AUDIO_CMD_STOP ((u8)0x40)

#define AUDIO_SFX_CH3_MARKER ((u8)0xFF)

// Enable the APU and reset software streams, instruments, mix and fade state.
// Load the initial triangle wave, then leave every channel silent. Call at startup
// before concurrent interrupt-driven audio service can access these shared fields.
void Audio_Init();
// Advance the master fade first. Unless paused, service both effect streams
// then the optional legacy music decoder. Call once per frame for frame-based timing.
void Audio_Update();
// Retain the bank and song pointer, reset legacy instruments/cursors, and arm
// playback from the beginning. Supply a valid, persistent song; no bytes are copied
// and null is not checked. Existing effect streams remain active.
void __stackcall Audio_PlayMusic(u8 bank, u8 *song);
// Stop legacy music and clear its resume mask, then silence all physical channels.
// Effect pointers remain active and may produce sound on a later update.
void Audio_StopMusic();
// On pause entry, silence hardware while retaining cursors. On resume, retrigger
// eligible legacy CH1, CH2 and CH4 notes; CH3 is not retriggered here. Updates still
// advance master fades while paused, and effect playback resumes on a later update.
void __stackcall Audio_SetPaused(u8 on);
// Capture the currently mapped ROM bank and start an effect with inherited pan.
// Use the explicit-bank API when the pointer belongs to another bank.
void __stackcall Audio_PlaySFX(u8 *sfx, u8 priority);
// Start a banked effect with the channel's base pan, subject to priority arbitration.
void __stackcall Audio_PlaySFXBanked(u8 bank, u8 *sfx, u8 priority);
// Capture the currently mapped ROM bank and request an effect with a pan override.
// Use the explicit-bank API when the pointer belongs to another bank.
void __stackcall Audio_PlaySFXPanned(u8 *sfx, u8 priority, u8 pan);
// Retain a banked effect stream if its priority equals or exceeds the current
// owner's priority, or that slot is empty. A leading CH3 marker selects the wave
// slot and is skipped; other streams use the pulse slot. Paused requests are ignored.
// Keep stream storage valid until completion; acceptance does not trigger a note.
void __stackcall Audio_PlaySFXPannedBanked(u8 bank, u8 *sfx, u8 priority, u8 pan);
// Clear both effect streams and their pan overrides. When not paused, release
// borrowed channels through the configured legacy or VBlank recovery path.
void Audio_StopSfx();
// Stop a physical channel and clear its legacy resume bit. CH1 also clears the
// pulse effect stream; CH3 clears the wave effect stream. This is the legacy
// channel API and does not clear a VBlank driver's independently latched notes.
void __stackcall Audio_StopChannel(u8 ch);

// Set the music-processing gate. This does not silence notes already playing
// or stop the legacy stream cursor from consuming commands.
void __stackcall Audio_SetMusicEnabled(u8 on);
// Enable effect note writes, or disable them and release both effect streams.
// Disabling follows Audio_StopSfx recovery rules rather than silencing all channels.
void __stackcall Audio_SetSfxEnabled(u8 on);

// Clamp both output levels to 0..7, cancel any fade, and write NR50 immediately.
void __stackcall Audio_SetMasterVolume(u8 left, u8 right);
// Move left/right volume toward clamped targets at the requested Audio_Update
// call interval. An interval of zero applies the levels immediately.
void __stackcall Audio_FadeToMasterVolume(u8 left, u8 right, u8 step_frames);
// Cancel further volume steps, retaining the current cached levels and hardware output.
void Audio_CancelMasterVolumeFade();

// Update the base pan for a physical channel and reapply active effect overrides.
// Unknown channel IDs select CH4; unsupported pan values mute the selected channel.
void __stackcall Audio_SetPan(u8 ch, u8 pan);
// Two bits per channel (CH1 in bits 0-1): center, left, right, mute.
// Applies all four positions with one NR51 update for sequencer automation.
void __stackcall Audio_SetPanPacked(u8 packed);
// Install a named preset or the cached custom wave. Unknown IDs are ignored.
// This does not update Audio_Ch3Wave or trigger a new note.
void __stackcall Audio_LoadWave(u8 wave_id);
// Copy 16 packed sample bytes into the persistent custom cache and wave RAM.
// A null pointer is ignored; the source is needed only for this call.
void __stackcall Audio_LoadCustomWave(const u8 *wave16);

// Cache the low two duty bits for the next CH1 note; do not change the active register.
void __stackcall Audio_SetCh1Duty(u8 duty);
// Cache the low two duty bits for the next CH2 note; do not change the active register.
void __stackcall Audio_SetCh2Duty(u8 duty);
// Cache the raw NR32 level encoding for the next CH3 note without writing hardware.
void __stackcall Audio_SetCh3Level(u8 level);
// Cache the raw noise polynomial encoding for the next CH4 note without writing hardware.
void __stackcall Audio_SetCh4Param(u8 param);

// Trigger CH1 with the cached sweep and the supplied raw envelope. Clamp the
// note index; duty values 0, 1 and 3 select their encodings, and all others use 2.
void __stackcall Audio_Ch1NoteOn(u8 note, u8 vol_env, u8 duty2);
// Trigger CH2 with the supplied raw envelope and a clamped note index. Duty
// values 0, 1 and 3 select their encodings; all other values use duty 2.
void __stackcall Audio_Ch2NoteOn(u8 note, u8 vol_env, u8 duty2);
// Clamp the note index, program the raw NR32 output level, and trigger CH3.
// Wave RAM must already contain the desired waveform; this does not load one.
void __stackcall Audio_Ch3NoteOn(u8 note, u8 level);
// Cache the supplied noise parameter, program the raw envelope and polynomial
// registers, then trigger CH4 with the length-enable bit clear.
void __stackcall Audio_Ch4NoteOn(u8 param, u8 vol_env);

kitaqgb/lib/audio.h

audio_vblank.h — Reproducción musical mediante la interrupción VBlank
c
#pragma once

// Fixed-bank VBlank BGM driver.
//
// Stream format:
//   delay, ch1_note, ch2_note, ch3_note, ch4_noise_param
//   IMMEDIATE, ch1_note, ch2_note, ch3_note, ch4_noise_param
//   CONTROL, command, arg0, arg1, arg2
//
// Notes are 0..67. To stay inside the useful CGB register range, C6..G6
// (60..67) alias C5..G5 (48..55) in the fixed pitch table. REST leaves a
// channel unchanged, while STOP silences it. END stops either playback mode.
// LOOP jumps to MusicLoopPoint only in direct-pointer mode; a queue producer
// must expand loops itself. IMMEDIATE is recognized only in queue mode.
// Direct streams treat 0xFB as an ordinary delay, and queues treat 0xFE as one.

#define AUDIO_VBLANK_REST ((u8)0xFF)
#define AUDIO_VBLANK_END  ((u8)0xFF)
#define AUDIO_VBLANK_LOOP ((u8)0xFE)
#define AUDIO_VBLANK_STOP ((u8)0xFD)
#define AUDIO_VBLANK_CONTROL ((u8)0xFC)
#define AUDIO_VBLANK_IMMEDIATE ((u8)0xFB)
#define AUDIO_VBLANK_CONTROL_RESET ((u8)0x01)

#define AUDIO_VBLANK_W8 ((u8)15)
#define AUDIO_VBLANK_WQ ((u8)30)
#define AUDIO_VBLANK_WH ((u8)60)

#define AUDIO_VBLANK_QUEUE_RECORDS 16
#define AUDIO_VBLANK_QUEUE_BYTES 80

typedef void (*AudioVBlankFrameHook)();

extern __wram u8 AudioVBlank_MusicPlaying;
extern __wram u8 AudioVBlank_MusicEnabled;
extern __wram u8 AudioVBlank_MusicDelay;
extern __wram u8 *AudioVBlank_MusicStart;
extern __wram u8 *AudioVBlank_MusicPointer;
extern __wram u8 *AudioVBlank_MusicLoopPoint;
extern __wram u8 AudioVBlank_Step;
extern __wram u8 AudioVBlank_Ch2Note;
extern __wram u8 AudioVBlank_Ch1Note;
extern __wram u8 AudioVBlank_Ch3Note;
extern __wram u8 AudioVBlank_Ch2LatchedNote;
extern __wram u8 AudioVBlank_Ch1LatchedNote;
extern __wram u8 AudioVBlank_Ch3LatchedNote;
// Sound effects temporarily own CH1/CH2/CH3.  A pending value of 1 means a BGM
// note/stop event was suppressed and must be applied once the effect ends;
// value 2 means release the effect channel without retriggering an old note.
extern __wram u8 AudioVBlank_RestoreCh1Pending;
extern __wram u8 AudioVBlank_RestoreCh3Pending;
extern __wram u8 AudioVBlank_Ch4Param;
extern __wram u8 AudioVBlank_Ch1Envelope;
extern __wram u8 AudioVBlank_Ch2Envelope;
extern __wram u8 AudioVBlank_Ch4Envelope;
extern __wram u8 AudioVBlank_Ch1Duty;
extern __wram u8 AudioVBlank_Ch2Duty;
extern __wram u8 AudioVBlank_Ch1Sweep;
extern __wram u8 AudioVBlank_Ch3Level;
extern __wram u8 AudioVBlank_ControlCommand;
extern __wram u8 AudioVBlank_ControlArg0;
extern __wram u8 AudioVBlank_ControlArg1;
extern __wram u8 AudioVBlank_ControlArg2;
// QueueReset/QueueRefill/QueuePlay provide the foreground producer. The ISR owns
// ReadIndex and decreases Count; use the producer APIs instead of editing the
// indices/count while playback is running. Records contain exactly five bytes.
// MusicPlaying and all enable/pause gates still apply in queue mode.
extern __wram u8 AudioVBlank_QueueMode;
extern __wram u8 AudioVBlank_QueueReadIndex;
extern __wram u8 AudioVBlank_QueueWriteIndex;
extern __wram u8 AudioVBlank_QueueCount;
extern __wram u8 AudioVBlank_QueueUnderruns;
// Queue bytes reside in WRAM bank 1. A producer must select that bank while
// writing and restore the caller bank; publish the record only after all bytes
// are complete. The ISR selects bank 1 itself and restores SVBK before returning.
extern __wramx_bank(1) u8 AudioVBlank_QueueBuffer[AUDIO_VBLANK_QUEUE_BYTES];
// The ISR invokes this hook even when music processing is gated off. It runs
// with SVBK=1 using a direct-address call; keep hook code/data accessible in that
// context and synchronize pointer changes with interrupt execution.
extern __wram AudioVBlankFrameHook AudioVBlank_FrameHook;

// Reset software playback state, queue counters, instruments and the frame hook.
// Call before enabling this ISR; the routine does not mask interrupts or
// initialize the APU registers and cannot synchronize with an active handler.
void AudioVBlank_Init();
// Stop music and select an empty WRAM queue; preserve IE, IME and enable/pause gates.
void AudioVBlank_QueueReset();
// Copy complete records from the currently mapped source; return records accepted.
// Each call attempts at most 16 records and stops when full. Null/zero returns 0.
// Supports ROM and RAM sources, restores SVBK and IE, and never changes IME.
// Single foreground producer only: do not call from an ISR or frame hook.
// LOOP must be expanded by the producer. END occupies a full five-byte record.
u8 __stackcall AudioVBlank_QueueRefill(const u8 *records, u8 count);
// Start/resume queued playback; return 1 on success, 0 for an empty/nonqueue mode.
// Does not enable the interrupt, music gate or clear pause. Queue before starting.
u8 AudioVBlank_QueuePlay();
// Select a directly addressed song and reset its cursors, leaving the playing
// flag unchanged. Song storage must remain accessible to the fixed-bank ISR;
// coordinate this multi-field update with interrupt execution.
void __stackcall AudioVBlank_SetMusic(u8 *song);
// Restart the selected direct song at its beginning, leaving queue mode.
// A null song invokes Stop; this does not enable the music or IRQ gates.
void AudioVBlank_Play();
// Select and restart a directly addressed song. This is not the banked WRAM-queue path.
void __stackcall AudioVBlank_PlayMusic(u8 *song);
// Stop software playback and silence pulse/noise envelopes and the wave DAC.
// Song pointers and the IRQ enable remain unchanged; the routine writes the
// physical channels directly, so coordinate ownership with sound effects.
void AudioVBlank_Stop();
// Gate music processing and clear pending CH1/CH3 recovery on disable.
// No audio register is written here: disabling does not itself silence a note
// already playing or disable the VBlank interrupt.
void __stackcall AudioVBlank_SetEnabled(u8 on);
// Enable the VBlank source in IE and execute EI, enabling CPU interrupts globally.
// Install the correct interrupt vector and initialize driver state first.
void AudioVBlank_EnableIrq();
// Clear only the VBlank bit in IE. Other interrupt sources and current sound remain unchanged.
void AudioVBlank_DisableIrq();
// Recover the borrowed pulse channel (CH1 or CH2) from its latched music event.
// Pending value 2, disabled music, or a non-note latch silences it instead.
// The caller must first establish that the effect has released the channel.
void AudioVBlank_RestoreCh1();
// Recover a latched wave-channel music event after effect release, or disable
// the DAC for a release-only request, disabled music, or a non-note latch.
// The caller owns effect arbitration and clearing the pending flag.
void AudioVBlank_RestoreCh3();
// Request deferred pulse-channel release only when no recovery is pending.
// Preserve value 1, which records a music event suppressed while an effect owned it.
void AudioVBlank_RequestRestoreCh1();
// Request a deferred wave-channel release only if no recovery is pending.
// Preserve value 1, which records a new music event suppressed by the effect.
void AudioVBlank_RequestRestoreCh3();

kitaqgb/lib/audio_vblank.h

bank.h — Acceso a código y datos por bancos
c
#pragma once

// A bank byte accompanies the CPU-visible ROM address; the pointer alone is not a far address.
typedef __packed struct {
    u8 bank;
    const u8* ptr;
} BankPtr;

extern u8 kq_bank_current;

void __bankswitch(u8 bank);
u8 __farpeek8(u8 bank, const void* addr);
u16 __farpeek16(u8 bank, const void* addr);
void __farmemcpy(void* dst, u8 bank, const void* src, u16 len);
void __farcall_ptr(u8 bank, const void* func);

// Update both the library bank record and the compiler shadow used by far
// reads and calls. Invoke this permanent bank change from fixed-bank code.
void bank_switch(u8 bank);
// Return the last bank recorded by bank_switch; this does not read cartridge hardware.
u8 bank_get_current();
// Read one byte through the compiler intrinsic that accepts an explicit ROM bank.
u8 far_data_read8(u8 bank, const void* addr);
// Read a 16-bit value from the supplied bank and address through the far-read intrinsic.
u16 far_data_read16(u8 bank, const void* addr);
// Copy len bytes from banked ROM into caller-owned writable storage.
void far_data_read(u8 bank, const void* addr, void* dst, u16 len);
// Invoke a no-argument callback in its ROM bank, then restore the caller
// bank. The pointer must identify executable code; no arguments are forwarded.
void far_call(u8 bank, const void* func);
// Store a bank/address pair without accessing ROM; a null output pointer is ignored.
void farptr_make(BankPtr* out, u8 bank, const u8* ptr);
// Read one byte using both components of the bank-qualified pointer.
u8 farptr_read8(BankPtr ptr);
// Read a 16-bit value using both components of the bank-qualified pointer.
u16 farptr_read16(BankPtr ptr);
// Copy len bytes from a bank-qualified pointer; dst must have room for the full copy.
void farptr_read(BankPtr ptr, void* dst, u16 len);

kitaqgb/lib/bank.h

camera.h — Coordenadas del mundo y áreas visibles
c
#pragma once

#include "scroll.h"

// All position, target and bound fields use signed Q8.8 (-128 to just below 128 pixels).
// Pass initialized, non-null storage; world/screen conversion arguments use integer pixels.
typedef struct Camera8_8 {
    s16 fx;
    s16 fy;
    s16 target_fx;
    s16 target_fy;
    s16 min_fx;
    s16 min_fy;
    s16 max_fx;
    s16 max_fy;
    u8 use_target;
    u8 use_bounds;
} Camera8_8;

// Zero all position/target/bound fields and disable targeting and bounds.
void Camera_Init(Camera8_8* cam);
// Replace the current Q8.8 position and immediately apply enabled bounds.
void Camera_Set(Camera8_8* cam, s16 fx, s16 fy);
// Store a Q8.8 target and enable subsequent step-toward-target updates.
void Camera_SetTarget(Camera8_8* cam, s16 fx, s16 fy);
// Disable target following without moving the camera or erasing the stored target.
void Camera_ClearTarget(Camera8_8* cam);
// Install ordered Q8.8 bounds, enable them and clamp the current position immediately.
void Camera_SetBounds(Camera8_8* cam, s16 min_fx, s16 min_fy, s16 max_fx, s16 max_fy);
// Disable clamping while retaining the stored bounds and current position.
void Camera_ClearBounds(Camera8_8* cam);
// Add Q8.8 deltas and clamp afterward. Keep the intermediate sums within s16;
// clamping cannot repair arithmetic that already overflowed.
void Camera_Add(Camera8_8* cam, s16 dfx, s16 dfy);
// Move by the signed target delta shifted by 0..7 bits, then apply bounds.
// Quantization can make a small delta produce no movement; only exact equality
// clears targeting, and a target outside the bounds may remain active indefinitely.
void Camera_StepTowardTarget(Camera8_8* cam, u8 shift);
// Discard fractional bits and write the low eight integer bits to background scroll registers.
void Camera_ApplyBg(const Camera8_8* cam);
// Convert the Q8.8 position to byte scroll values and stage them for a later flush.
void Camera_ApplyBgBuffered(const Camera8_8* cam);
// Derive nonnegative camera extents from world minus screen size, then convert
// them to Q8.8 bounds. Extents must fit signed Q8.8; the u16 input type does
// not imply support for arbitrary large worlds.
void Camera_ClampToSize(Camera8_8* cam, u16 world_w_px, u16 world_h_px, u8 screen_w_px, u8 screen_h_px);
// Convert an integer-pixel world X by subtracting the camera's integer X component.
s16 Camera_WorldToScreenX(const Camera8_8* cam, s16 world_x);
// Convert an integer-pixel world Y by subtracting the camera's integer Y component.
s16 Camera_WorldToScreenY(const Camera8_8* cam, s16 world_y);
// Convert integer-pixel screen X back to world X using the camera's integer component.
s16 Camera_ScreenToWorldX(const Camera8_8* cam, s16 screen_x);
// Convert integer-pixel screen Y back to world Y using the camera's integer component.
s16 Camera_ScreenToWorldY(const Camera8_8* cam, s16 screen_y);

// Set the shared camera from integer pixels, converting to the representable Q8.8 range.
void camera_set(s16 x, s16 y);
// Position the shared camera so the world point appears at the requested screen
// anchor. This is an immediate move, not the smoothed target-following path.
void camera_follow_xy(s16 x, s16 y, u8 screen_cx, u8 screen_cy);
// Derive and apply world/screen bounds to the shared convenience camera.
void camera_clamp(u16 world_w_px, u16 world_h_px, u8 screen_w_px, u8 screen_h_px);
// Write the shared camera's current integer position to background scroll registers.
void camera_apply();
// Convert integer-pixel world X using the shared convenience camera.
s16 camera_world_to_screen_x(s16 world_x);
// Convert integer-pixel world Y using the shared convenience camera.
s16 camera_world_to_screen_y(s16 world_y);

kitaqgb/lib/camera.h

cgb_palette.h — Paletas de fondo y OBJ de CGB
c
#pragma once

// High-level CGB palette helpers for KITAQGB.
// Palette writes no-op on DMG; RGB packing works on either hardware model.

// Safe here means CGB hardware gating. Palette data writes still require an accessible
// PPU phase (for example LCD off or a sufficiently short VBlank update).
u8 __cgb_is_cgb();
void __cgb_safe_set_bcps(u8 value);
void __cgb_safe_set_bcpd(u8 value);
void __cgb_safe_set_ocps(u8 value);
void __cgb_safe_set_ocpd(u8 value);

// Mask each component to five bits: red in 0..4, green in 5..9, blue in 10..14.
// These macros wrap oversized components rather than saturating them.
#define CGB_RGB15(r5, g5, b5) ((u16)((u16)((r5) & 31) | ((u16)((g5) & 31) << 5) | ((u16)((b5) & 31) << 10)))

// Pack the red, green and blue components using the public RGB15 macro.
u16 cgb_rgb15(u8 r5, u8 g5, u8 b5);

// Set one background color through the indexed palette wrapper.
void cgb_bg_color(u8 palette_index, u8 color_index, u16 rgb15);
// Set one object color through the indexed palette wrapper.
void cgb_obj_color(u8 palette_index, u8 color_index, u16 rgb15);
// Pack component values and write one background color.
void cgb_bg_rgb(u8 palette_index, u8 color_index, u8 r5, u8 g5, u8 b5);
// Pack component values and write one object color.
void cgb_obj_rgb(u8 palette_index, u8 color_index, u8 r5, u8 g5, u8 b5);

// Write background colors starting at the indexed slot. The range may cross
// palette boundaries and is clamped only at the end of all 32 slots.
void cgb_bg_colors(u8 palette_index, u8 start_color_index, const u16* colors, u8 color_count);
// Write object colors from the indexed slot, potentially crossing into later palettes.
void cgb_obj_colors(u8 palette_index, u8 start_color_index, const u16* colors, u8 color_count);

// Write four consecutive colors for one background palette.
void cgb_bg_palette(u8 palette_index, const u16* colors);
// Write four consecutive colors for one object palette.
void cgb_obj_palette(u8 palette_index, const u16* colors);

// Expose sequential background writes using an absolute color-slot index.
void cgb_bg_colors_raw(u8 start_color_slot, const u16* colors, u8 color_count);
// Expose sequential object writes using an absolute color-slot index.
void cgb_obj_colors_raw(u8 start_color_slot, const u16* colors, u8 color_count);

kitaqgb/lib/cgb_palette.h

cgb_tile.h — Números y atributos de tiles de CGB
c
#pragma once

// Declarations for compiler-intrinsic CGB tile helpers.
// Canonical intrinsic entry points use the "__" prefix.
// Attr writes no-op on DMG. Combined tile+attr writes still write the tile on DMG.

// These helpers emit compiler code; cgb_tile.c has no runtime bodies. Scalar coordinates address 32x32 maps.
// Safe write paths poll VRAM access; LCD-on paths can enable interrupts after writing.
// Use _unsafe/_fast only with caller-managed writable VRAM timing, especially inside an ISR.
// Tile writes use the selected VRAM bank; choose bank zero before combined tile/attribute operations.
#define KQ_CGB_ATTR_PAL_MASK 0x07
#define KQ_CGB_ATTR_BANK1 0x08
#define KQ_CGB_ATTR_XFLIP 0x20
#define KQ_CGB_ATTR_YFLIP 0x40
#define KQ_CGB_ATTR_PRIORITY 0x80

#define KQ_CGB_ATTR_NONE ((u8)0)
#define KQ_CGB_ATTR_PAL(n) ((u8)((n) & KQ_CGB_ATTR_PAL_MASK))
#define KQ_CGB_ATTR_BANK(bank) ((u8)((bank) ? KQ_CGB_ATTR_BANK1 : 0))
#define KQ_CGB_ATTR_XFLIP_IF(enabled) ((u8)((enabled) ? KQ_CGB_ATTR_XFLIP : 0))
#define KQ_CGB_ATTR_YFLIP_IF(enabled) ((u8)((enabled) ? KQ_CGB_ATTR_YFLIP : 0))
#define KQ_CGB_ATTR_PRIORITY_IF(enabled) ((u8)((enabled) ? KQ_CGB_ATTR_PRIORITY : 0))
#define KQ_CGB_ATTR(palette, bank, xflip, yflip, priority) ((u8)(((palette) & KQ_CGB_ATTR_PAL_MASK) | ((bank) ? KQ_CGB_ATTR_BANK1 : 0) | ((xflip) ? KQ_CGB_ATTR_XFLIP : 0) | ((yflip) ? KQ_CGB_ATTR_YFLIP : 0) | ((priority) ? KQ_CGB_ATTR_PRIORITY : 0)))

// Return the compiler/runtime CGB mode test as a byte Boolean.
u8 __cgb_is_cgb();
// Write the VRAM bank selection only on CGB. Safe here means hardware-mode guarded, not PPU-timed.
void __cgb_safe_set_vbk(u8 value);

// Write a tile number to map 9800, waiting for VRAM access when necessary.
void __settile(u8 x, u8 y, u8 tile);
// Write a tile number to map 9800 without waiting for writable VRAM.
void __settile_unsafe(u8 x, u8 y, u8 tile);
// Write at base+32*y+x with VRAM access checks; supply a valid tile-map base.
void __settileat(u16 base, u8 x, u8 y, u8 tile);
// Use an explicit map base without waiting for VRAM access.
void __settileat_unsafe(u16 base, u8 x, u8 y, u8 tile);
// Select the window map from LCDC bit 6, then write a tile with access checks.
void __settilewin(u8 x, u8 y, u8 tile);
// Select the LCDC window map and write without access waits.
void __settilewin_unsafe(u8 x, u8 y, u8 tile);
// Select the background map from LCDC bit 3, then write with access checks.
void __settilebg(u8 x, u8 y, u8 tile);
// Select the LCDC background map and write without access waits.
void __settilebg_unsafe(u8 x, u8 y, u8 tile);

// Copy count sequential bytes to dest using the current VRAM bank and access-checked transfer.
void __settile_bulk(u16 dest, const u8* src, u8 count);
// Copy count sequential bytes to dest without VRAM access waits; retain source-bank visibility.
void __settile_bulk_fast(u16 dest, const u8* src, u8 count);

// Write attributes in bank one at map 9800 on CGB, then leave VBK zero; skip on DMG. Use the access-checked write path.
void __settileattr(u8 x, u8 y, u8 attr);
// Write attributes in bank one at map 9800 on CGB, then leave VBK zero; skip on DMG. No VRAM access waits are inserted.
void __settileattr_unsafe(u8 x, u8 y, u8 attr);
// Write tile and CGB attributes at map 9800; DMG receives only the tile write. Use the access-checked write path.
void __settilecgb(u8 x, u8 y, u8 tile, u8 attr);
// Write tile and CGB attributes at map 9800; DMG receives only the tile write. No VRAM access waits are inserted.
void __settilecgb_unsafe(u8 x, u8 y, u8 tile, u8 attr);

// Write attributes in bank one at the explicit map base on CGB, then leave VBK zero; skip on DMG. Use the access-checked write path.
void __settileatattr(u16 base, u8 x, u8 y, u8 attr);
// Write attributes in bank one at the explicit map base on CGB, then leave VBK zero; skip on DMG. No VRAM access waits are inserted.
void __settileatattr_unsafe(u16 base, u8 x, u8 y, u8 attr);
// Write tile and CGB attributes at the explicit map base; DMG receives only the tile write. Use the access-checked write path.
void __settileatcgb(u16 base, u8 x, u8 y, u8 tile, u8 attr);
// Write tile and CGB attributes at the explicit map base; DMG receives only the tile write. No VRAM access waits are inserted.
void __settileatcgb_unsafe(u16 base, u8 x, u8 y, u8 tile, u8 attr);

// Write attributes in bank one at the LCDC window map on CGB, then leave VBK zero; skip on DMG. Use the access-checked write path.
void __settilewinattr(u8 x, u8 y, u8 attr);
// Write attributes in bank one at the LCDC window map on CGB, then leave VBK zero; skip on DMG. No VRAM access waits are inserted.
void __settilewinattr_unsafe(u8 x, u8 y, u8 attr);
// Write tile and CGB attributes at the LCDC window map; DMG receives only the tile write. Use the access-checked write path.
void __settilewincgb(u8 x, u8 y, u8 tile, u8 attr);
// Write tile and CGB attributes at the LCDC window map; DMG receives only the tile write. No VRAM access waits are inserted.
void __settilewincgb_unsafe(u8 x, u8 y, u8 tile, u8 attr);

// Write attributes in bank one at the LCDC background map on CGB, then leave VBK zero; skip on DMG. Use the access-checked write path.
void __settilebgattr(u8 x, u8 y, u8 attr);
// Write attributes in bank one at the LCDC background map on CGB, then leave VBK zero; skip on DMG. No VRAM access waits are inserted.
void __settilebgattr_unsafe(u8 x, u8 y, u8 attr);
// Write tile and CGB attributes at the LCDC background map; DMG receives only the tile write. Use the access-checked write path.
void __settilebgcgb(u8 x, u8 y, u8 tile, u8 attr);
// Write tile and CGB attributes at the LCDC background map; DMG receives only the tile write. No VRAM access waits are inserted.
void __settilebgcgb_unsafe(u8 x, u8 y, u8 tile, u8 attr);

// Copy count attributes to dest in bank one on CGB, then leave VBK zero; skip on DMG. Transfers use access checks.
void __settileattr_bulk(u16 dest, const u8* src, u8 count);
// Copy count attributes to dest in bank one on CGB, then leave VBK zero; skip on DMG. The caller supplies writable VRAM timing.
void __settileattr_bulk_fast(u16 dest, const u8* src, u8 count);
// Copy tile and attribute streams to dest; DMG receives only tiles. Keep both sources readable. Transfers use access checks.
void __settilecgb_bulk(u16 dest, const u8* tile_src, const u8* attr_src, u8 count);
// Copy tile and attribute streams to dest; DMG receives only tiles. Keep both sources readable. The caller supplies writable VRAM timing.
void __settilecgb_bulk_fast(u16 dest, const u8* tile_src, const u8* attr_src, u8 count);

kitaqgb/lib/cgb_tile.h

chain.h — Búferes circulares para el historial de posiciones
c
#pragma once

typedef __packed struct {
    s16 x;
    s16 y;
} ChainPoint;

typedef __packed struct {
    ChainPoint* points;
    u8 capacity;
    u8 count;
    u8 head;
} Chain;

// Attach caller-owned ring storage and start with no recorded points.
// The storage must remain valid for the lifetime of the chain.
// Use a valid chain pointer and capacity entries of caller-owned storage.
// Capacity at most 128 keeps every head+age sum in the byte range used by the reader.
void chain_init(Chain* chain, ChainPoint* storage, u8 capacity);
// Forget the recorded points without clearing or freeing the backing storage.
void chain_clear(Chain* chain);
// Move the ring head backward and store the newest point. Once full, each push
// replaces the oldest point; zero capacity is a no-op.
void chain_push_head(Chain* chain, s16 x, s16 y);
// Read a point by age, with index zero denoting the newest point. Return zero
// for an invalid request and clear a non-null output first. Keep head + index
// within the 8-bit range: addition is narrowed before the capacity wrap.
u8 chain_get_segment(const Chain* chain, u8 index, ChainPoint* out);
// Return the number of stored points, or zero for a null chain.
u8 chain_get_count(const Chain* chain);

// Return target minus current along the shortest wrapped route.
// Supply size 1..256 and coordinates in 0..size-1; inputs are not normalized.
// Exactly half a field retains the direct displacement sign.
s16 chain_wrap_delta(u8 target, u8 current, u16 size);

// Articulated body: one current pose per joint, including the head at index 0.
// Caller-owned byte arrays keep the inner loop compact on both GB and FC.
// Heading sectors run clockwise: 0=right, 4=down, 8=left, 12=up.
// Coordinates are pixels; each wrapped dimension accepts 1..256 pixels.
typedef __packed struct {
    u8* x;
    u8* y;
    u8* heading;
    u8 capacity;
    u8 count;
    u16 width;
    u16 height;
} ChainBody;

// Attach three non-overlapping capacity-byte arrays. Return 1 on success.
// Invalid storage, zero capacity or dimensions outside 1..256 disable the body.
u8 chain_body_init(ChainBody* body, u8* x, u8* y, u8* heading, u8 capacity, u16 width, u16 height);
// Seed count joints in a straight pose behind the head; count includes the head.
// Return 0 without changing the pose if count is zero or exceeds capacity.
// Coordinates wrap to the playfield and headings are masked to 0..15.
u8 chain_body_reset(ChainBody* body, u8 count, u8 head_x, u8 head_y, u8 heading);
// Install the caller's head pose, then pull joints from front to rear.
// Each joint aims four pixels behind its updated predecessor and receives that
// predecessor's OLD heading. Each axis moves 1 pixel, or 2 when error exceeds 4.
// Call once per simulation tick; this does not advance head physics or render.
void chain_body_step(ChainBody* body, u8 head_x, u8 head_y, u8 heading);
// Append a copy of the current tail; later steps separate the new joint.
// Return 1 on growth, or 0 for an empty, disabled or full body.
u8 chain_body_grow(ChainBody* body);
// Remove all joints while retaining caller-owned storage and playfield settings.
void chain_body_clear(ChainBody* body);

kitaqgb/lib/chain.h

danmaku.h — Grupos de proyectiles, abanicos, impactos y roces
c
#pragma once

// Fixed-capacity, allocation-free bullet field for a 160 x 128 play area.
// Positions/velocities are signed Q12.4 / Q4.4; +Y points down.
// Tile ids 0..15 encode the four 4x4 quadrants of an 8x8 tile.
// Reserve those tiles in VRAM, with a 3x3 bullet centered at (2,2)
// in every set quadrant. Other tile ids in the map are decoration.
#define DANMAKU_MAX 96
#define DANMAKU_MAP_BYTES 576
typedef __packed struct {
    s16 x;
    s16 y;
    s8 vx;
    s8 vy;
    u8 active;
    u8 grazed;
} DanmakuBullet;

extern DanmakuBullet dm_bullets[DANMAKU_MAX];
extern __wram __aligned(16) u8 dm_map[DANMAKU_MAP_BYTES];
extern u8 dm_count;
extern u8 dm_peak;
// Per-step hit is a Boolean latch; graze counts newly grazed bullets this step. Spawn/rejection counters wrap at 65536.
extern u8 dm_hit;
extern u8 dm_graze;
extern u8 dm_player_x;
extern u8 dm_player_y;
extern u8 dm_invulnerable;
extern u16 dm_spawned;
extern u16 dm_rejected;

// Reset pool, peak and lifetime counters; player fields and map contents remain caller-owned state.
void danmaku_reset();
// Deactivate the pool while retaining peak/spawn/rejection counters and the RAM map.
void danmaku_clear();
// Use pixel origins inside 160x128 and signed sixteenth-pixel velocities; return one if a slot was allocated.
u8 danmaku_spawn(u8 x, u8 y, s8 vx, s8 vy);
// Attempt a fan using wrapping 32-step angles; count is capped at 96 and speed at 64.
void danmaku_fan(u8 x, u8 y, u8 direction, u8 step, u8 count, u8 speed);
// 32 directions, 0=right, 8=down, 16=left, 24=up. speed in 1/16 px.
// Clear the 32x18 RAM map before drawing the next frame; no transfer is performed.
void danmaku_clear_map();
// Caller fills decoration after clear_map, then calls step to overlay bullets.
// hit and graze are events for this step. Collision uses rendered centers.
void danmaku_step();
// Requires CGB and LCD off or the beginning of VBlank. VBK restored to 0.
// Transfers 18 rows (32-byte stride) to BG map 9800 with 36-block GDMA.
void danmaku_present_now();

kitaqgb/lib/danmaku.h

debug.h — Registros y aserciones en RAM
c
#pragma once

// Use a capacity from 1 through 255; the length counter is a byte.
// Compile every unit with the same override so the array declaration and storage agree.
#ifndef DEBUG_TRACE_MAX
#define DEBUG_TRACE_MAX 32
#endif

// Each packed entry retains a name pointer and two 16-bit values; name text is not copied.
typedef __packed struct {
    const u8* name;
    u16 value;
    u16 frame;
} DebugTraceEntry;

extern DebugTraceEntry kq_debug_trace_log[DEBUG_TRACE_MAX];
extern u8 kq_debug_trace_count;
extern u16 kq_debug_frame;
extern u16 kq_debug_last_assert;

// Reset log length, frame tag and last assertion code; existing entry bytes are not erased.
void debug_init();
// Set the frame tag copied into subsequently recorded entries.
void debug_set_frame(u16 frame);
// Append a named frame marker using 0xFFFF as its value.
void debug_mark_frame(const u8* label);
// Append an unsigned byte value, widened to the log's 16-bit value field.
void debug_trace_u8(const u8* name, u8 value);
// Append a 16-bit value with the current frame tag.
void debug_trace_u16(const u8* name, u16 value);
// Record the assertion code and attempt to append an ASSERT entry. This helper
// does not halt execution, and the code is retained even if the log is full.
void debug_assert_fail(u16 code);
// Return the number of valid entries in the fixed trace buffer.
u8 debug_get_trace_count();
// Expose the internal trace array for inspection; use the count to bound reads.
const DebugTraceEntry* debug_get_trace_log();
// Read the last recorded assertion code, or the zero value installed by initialization.
u16 debug_get_last_assert();

#define KITAQGB_TRACE_U8(name, value) debug_trace_u8((const u8*)(name), (u8)(value))
#define KITAQGB_TRACE_U16(name, value) debug_trace_u16((const u8*)(name), (u16)(value))
#define KITAQGB_TRACE(name, value) debug_trace_u16((const u8*)(name), (u16)(value))
#define KITAQGB_MARK_FRAME(label) debug_mark_frame((const u8*)(label))
#define KITAQGB_ASSERT(cond) do { if (!(cond)) debug_assert_fail((u16)1); } while (0)
#define KITAQGB_ASSERT_CODE(cond, code) do { if (!(cond)) debug_assert_fail((u16)(code)); } while (0)

kitaqgb/lib/debug.h

dmg3d.h — Gráficos de alambre monocromos de 128×120 para DMG
c
// Compatibility names for the shared wire3d_dmg renderer.
// Select the same profile in every translation unit; compile one renderer entry.
#pragma once
#ifndef WIRE3D_DMG_HEIGHT
#define WIRE3D_DMG_HEIGHT 120
#endif
#if WIRE3D_DMG_HEIGHT != 120
#error Incompatible wire3d_dmg profile
#endif
#include "wire3d_dmg.h"

// The aliases below add no calls or storage. Their contracts are documented at the corresponding wire3d_dmg.h declarations.
#define DMG3D_ANGLE_STEPS WIRE3D_DMG_ANGLE_STEPS
#define DMG3D_AUX_COL_BYTES WIRE3D_DMG_AUX_COL_BYTES
#define DMG3D_AUX_ROWS WIRE3D_DMG_AUX_ROWS
#define DMG3D_BG_QUEUE_LIMIT WIRE3D_DMG_BG_QUEUE_LIMIT
#define DMG3D_BeginFrame Wire3DDMG_BeginFrame
#define DMG3D_CENTER_X WIRE3D_DMG_CENTER_X
#define DMG3D_CENTER_Y WIRE3D_DMG_CENTER_Y
#define DMG3D_DrawIndexedEdges Wire3DDMG_DrawIndexedEdges
#define DMG3D_DrawLine2D Wire3DDMG_DrawLine2D
#define DMG3D_DrawLine3D Wire3DDMG_DrawLine3D
#define DMG3D_DrawModel Wire3DDMG_DrawModel
#define DMG3D_DrawModelScaled Wire3DDMG_DrawModelScaled
#define DMG3D_DrawScene Wire3DDMG_DrawScene
#define DMG3D_Edge Wire3DDMG_Edge
#define DMG3D_EdgeFaces Wire3DDMG_EdgeFaces
#define DMG3D_EndFrame Wire3DDMG_EndFrame
#define DMG3D_EraseModelFaces Wire3DDMG_EraseModelFaces
#define DMG3D_EraseSpan2D Wire3DDMG_EraseSpan2D
#define DMG3D_EraseTriangle2D Wire3DDMG_EraseTriangle2D
#define DMG3D_FACE_NONE WIRE3D_DMG_FACE_NONE
#define DMG3D_FAR_Z WIRE3D_DMG_FAR_Z
#define DMG3D_Face Wire3DDMG_Face
#define DMG3D_Init Wire3DDMG_Init
#define DMG3D_MODEL_FACE_LIMIT WIRE3D_DMG_MODEL_FACE_LIMIT
#define DMG3D_MODEL_HIDDEN_LINES WIRE3D_DMG_MODEL_HIDDEN_LINES
#define DMG3D_MODEL_VERTEX_LIMIT WIRE3D_DMG_MODEL_VERTEX_LIMIT
#define DMG3D_Model Wire3DDMG_Model
#define DMG3D_NEAR_Z WIRE3D_DMG_NEAR_Z
#define DMG3D_Object Wire3DDMG_Object
#define DMG3D_PROJECT_LIMIT WIRE3D_DMG_PROJECT_LIMIT
#define DMG3D_ProjectPoint Wire3DDMG_ProjectPoint
#define DMG3D_PutBgTile Wire3DDMG_PutBgTile
#define DMG3D_ROW_BYTES WIRE3D_DMG_ROW_BYTES
#define DMG3D_RotatePoint Wire3DDMG_RotatePoint
#define DMG3D_SCENE_OBJECT_LIMIT WIRE3D_DMG_SCENE_OBJECT_LIMIT
#define DMG3D_SCREEN_H WIRE3D_DMG_SCREEN_H
#define DMG3D_SCREEN_W WIRE3D_DMG_SCREEN_W
#define DMG3D_SetAuxTransfer Wire3DDMG_SetAuxTransfer
#define DMG3D_SetCamera Wire3DDMG_SetCamera
#define DMG3D_SetDirtyTransfer Wire3DDMG_SetDirtyTransfer
#define DMG3D_SetPalette Wire3DDMG_SetPalette
#define DMG3D_TILE_H WIRE3D_DMG_TILE_H
#define DMG3D_TILE_W WIRE3D_DMG_TILE_W
#define DMG3D_TRANSFORM_LIMIT WIRE3D_DMG_TRANSFORM_LIMIT
#define DMG3D_TransferAuxNow Wire3DDMG_TransferAuxNow
#define DMG3D_TransferMainNow Wire3DDMG_TransferMainNow
#define DMG3D_Vec3 Wire3DDMG_Vec3
// The remaining aliases retain internal identifiers for source compatibility; they do not define an independent renderer.
#define DMG3D_abs_i16 w3ddmg_abs_i16
#define DMG3D_angle_index w3ddmg_angle_index
#define DMG3D_aux_transfer_enabled w3ddmg_aux_transfer_enabled
#define DMG3D_bg_map_9800 w3ddmg_bg_map_9800
#define DMG3D_bgq_addr_hi w3ddmg_bgq_addr_hi
#define DMG3D_bgq_addr_lo w3ddmg_bgq_addr_lo
#define DMG3D_bgq_count w3ddmg_bgq_count
#define DMG3D_bgq_tile w3ddmg_bgq_tile
#define DMG3D_bgq_value w3ddmg_bgq_value
#define DMG3D_bgq_x w3ddmg_bgq_x
#define DMG3D_bgq_y w3ddmg_bgq_y
#define DMG3D_bit_mask w3ddmg_bit_mask
#define DMG3D_build_face_visibility w3ddmg_build_face_visibility
#define DMG3D_cam_pitch w3ddmg_cam_pitch
#define DMG3D_cam_roll w3ddmg_cam_roll
#define DMG3D_cam_x w3ddmg_cam_x
#define DMG3D_cam_y w3ddmg_cam_y
#define DMG3D_cam_yaw w3ddmg_cam_yaw
#define DMG3D_cam_z w3ddmg_cam_z
#define DMG3D_clamp_i16 w3ddmg_clamp_i16
#define DMG3D_clamp_screen w3ddmg_clamp_screen
#define DMG3D_clear_dirty_tables w3ddmg_clear_dirty_tables
#define DMG3D_clear_occlusion_mask w3ddmg_clear_occlusion_mask
#define DMG3D_clear_occlusion_mask_asm w3ddmg_clear_occlusion_mask_asm
#define DMG3D_clear_stage_asm w3ddmg_clear_stage_asm
#define DMG3D_clear_stage_aux_asm w3ddmg_clear_stage_aux_asm
#define DMG3D_clear_triangle w3ddmg_clear_triangle
#define DMG3D_clear_vram_asm w3ddmg_clear_vram_asm
#define DMG3D_cos_q6 w3ddmg_cos_q6
#define DMG3D_dirty_dst_hi w3ddmg_dirty_dst_hi
#define DMG3D_dirty_dst_lo w3ddmg_dirty_dst_lo
#define DMG3D_dirty_src_hi w3ddmg_dirty_src_hi
#define DMG3D_dirty_src_lo w3ddmg_dirty_src_lo
#define DMG3D_dirty_tiles w3ddmg_dirty_tiles
#define DMG3D_dirty_transfer_enabled w3ddmg_dirty_transfer_enabled
#define DMG3D_edge_area w3ddmg_edge_area
#define DMG3D_face_visible w3ddmg_face_visible
#define DMG3D_fill_bg_map_asm w3ddmg_fill_bg_map_asm
#define DMG3D_flush_bg_queue w3ddmg_flush_bg_queue
#define DMG3D_i16 w3ddmg_i16
#define DMG3D_i8 w3ddmg_i8
#define DMG3D_inv_depth w3ddmg_inv_depth
#define DMG3D_is_edge_visible w3ddmg_is_edge_visible
#define DMG3D_line_dx w3ddmg_line_dx
#define DMG3D_line_dy w3ddmg_line_dy
#define DMG3D_line_err w3ddmg_line_err
#define DMG3D_line_stage_asm w3ddmg_line_stage_asm
#define DMG3D_line_stage_masked_c w3ddmg_line_stage_masked_c
#define DMG3D_line_sx w3ddmg_line_sx
#define DMG3D_line_sy w3ddmg_line_sy
#define DMG3D_line_x w3ddmg_line_x
#define DMG3D_line_x0 w3ddmg_line_x0
#define DMG3D_line_x1 w3ddmg_line_x1
#define DMG3D_line_y w3ddmg_line_y
#define DMG3D_line_y0 w3ddmg_line_y0
#define DMG3D_line_y1 w3ddmg_line_y1
#define DMG3D_mark_line_dirty w3ddmg_mark_line_dirty
#define DMG3D_mark_model_occluder w3ddmg_mark_model_occluder
#define DMG3D_mark_rect_dirty w3ddmg_mark_rect_dirty
#define DMG3D_mark_tile_dirty w3ddmg_mark_tile_dirty
#define DMG3D_mark_triangle w3ddmg_mark_triangle
#define DMG3D_mask_get w3ddmg_mask_get
#define DMG3D_mask_offset w3ddmg_mask_offset
#define DMG3D_mask_set w3ddmg_mask_set
#define DMG3D_mask_set_span w3ddmg_mask_set_span
#define DMG3D_neg_angle w3ddmg_neg_angle
#define DMG3D_occlusion_active w3ddmg_occlusion_active
#define DMG3D_occlusion_mask w3ddmg_occlusion_mask
#define DMG3D_plot_stage_asm w3ddmg_plot_stage_asm
#define DMG3D_plot_tx w3ddmg_plot_tx
#define DMG3D_plot_x w3ddmg_plot_x
#define DMG3D_plot_y w3ddmg_plot_y
#define DMG3D_prev_dirty_tiles w3ddmg_prev_dirty_tiles
#define DMG3D_project_camera_space w3ddmg_project_camera_space
#define DMG3D_project_world w3ddmg_project_world
#define DMG3D_put_bg_tile_safe_asm w3ddmg_put_bg_tile_safe_asm
#define DMG3D_reg_bgp w3ddmg_reg_bgp
#define DMG3D_reg_lcdc w3ddmg_reg_lcdc
#define DMG3D_reg_ly w3ddmg_reg_ly
#define DMG3D_reg_scx w3ddmg_reg_scx
#define DMG3D_reg_scy w3ddmg_reg_scy
#define DMG3D_rotate_x w3ddmg_rotate_x
#define DMG3D_rotate_y w3ddmg_rotate_y
#define DMG3D_rotate_z w3ddmg_rotate_z
#define DMG3D_scene_depth w3ddmg_scene_depth
#define DMG3D_scene_object_depth w3ddmg_scene_object_depth
#define DMG3D_scene_order w3ddmg_scene_order
#define DMG3D_screen_delta w3ddmg_screen_delta
#define DMG3D_screen_visible w3ddmg_screen_visible
#define DMG3D_screen_x w3ddmg_screen_x
#define DMG3D_screen_y w3ddmg_screen_y
#define DMG3D_sin_q6 w3ddmg_sin_q6
#define DMG3D_stage w3ddmg_stage
#define DMG3D_stage_clear_pixel w3ddmg_stage_clear_pixel
#define DMG3D_stage_clear_span w3ddmg_stage_clear_span
#define DMG3D_transfer_dirty_stage w3ddmg_transfer_dirty_stage
#define DMG3D_transfer_dirty_tile_asm w3ddmg_transfer_dirty_tile_asm
#define DMG3D_transfer_stage_asm w3ddmg_transfer_stage_asm
#define DMG3D_transfer_stage_aux_asm w3ddmg_transfer_stage_aux_asm
#define DMG3D_u16 w3ddmg_u16
#define DMG3D_u8 w3ddmg_u8
#define DMG3D_vram_tiles w3ddmg_vram_tiles
#define DMG3D_wait_vblank_start w3ddmg_wait_vblank_start
#define dmg3d w3ddmg
#define dmg3d_pair_aux_block w3ddmg_pair_aux_block
#define dmg3d_pair_aux_done w3ddmg_pair_aux_done
#define dmg3d_pair_aux_wait_0 w3ddmg_pair_aux_wait_0
#define dmg3d_pair_aux_wait_1 w3ddmg_pair_aux_wait_1
#define dmg3d_pair_aux_wait_10 w3ddmg_pair_aux_wait_10
#define dmg3d_pair_aux_wait_11 w3ddmg_pair_aux_wait_11
#define dmg3d_pair_aux_wait_12 w3ddmg_pair_aux_wait_12
#define dmg3d_pair_aux_wait_13 w3ddmg_pair_aux_wait_13
#define dmg3d_pair_aux_wait_14 w3ddmg_pair_aux_wait_14
#define dmg3d_pair_aux_wait_15 w3ddmg_pair_aux_wait_15
#define dmg3d_pair_aux_wait_16 w3ddmg_pair_aux_wait_16
#define dmg3d_pair_aux_wait_17 w3ddmg_pair_aux_wait_17
#define dmg3d_pair_aux_wait_18 w3ddmg_pair_aux_wait_18
#define dmg3d_pair_aux_wait_19 w3ddmg_pair_aux_wait_19
#define dmg3d_pair_aux_wait_2 w3ddmg_pair_aux_wait_2
#define dmg3d_pair_aux_wait_20 w3ddmg_pair_aux_wait_20
#define dmg3d_pair_aux_wait_21 w3ddmg_pair_aux_wait_21
#define dmg3d_pair_aux_wait_22 w3ddmg_pair_aux_wait_22
#define dmg3d_pair_aux_wait_23 w3ddmg_pair_aux_wait_23
#define dmg3d_pair_aux_wait_24 w3ddmg_pair_aux_wait_24
#define dmg3d_pair_aux_wait_25 w3ddmg_pair_aux_wait_25
#define dmg3d_pair_aux_wait_26 w3ddmg_pair_aux_wait_26
#define dmg3d_pair_aux_wait_27 w3ddmg_pair_aux_wait_27
#define dmg3d_pair_aux_wait_3 w3ddmg_pair_aux_wait_3
#define dmg3d_pair_aux_wait_4 w3ddmg_pair_aux_wait_4
#define dmg3d_pair_aux_wait_5 w3ddmg_pair_aux_wait_5
#define dmg3d_pair_aux_wait_6 w3ddmg_pair_aux_wait_6
#define dmg3d_pair_aux_wait_7 w3ddmg_pair_aux_wait_7
#define dmg3d_pair_aux_wait_8 w3ddmg_pair_aux_wait_8
#define dmg3d_pair_aux_wait_9 w3ddmg_pair_aux_wait_9
#define dmg3d_pair_main_block w3ddmg_pair_main_block
#define dmg3d_pair_main_wait_0 w3ddmg_pair_main_wait_0
#define dmg3d_pair_main_wait_1 w3ddmg_pair_main_wait_1
#define dmg3d_pair_main_wait_10 w3ddmg_pair_main_wait_10
#define dmg3d_pair_main_wait_11 w3ddmg_pair_main_wait_11
#define dmg3d_pair_main_wait_12 w3ddmg_pair_main_wait_12
#define dmg3d_pair_main_wait_13 w3ddmg_pair_main_wait_13
#define dmg3d_pair_main_wait_14 w3ddmg_pair_main_wait_14
#define dmg3d_pair_main_wait_2 w3ddmg_pair_main_wait_2
#define dmg3d_pair_main_wait_3 w3ddmg_pair_main_wait_3
#define dmg3d_pair_main_wait_4 w3ddmg_pair_main_wait_4
#define dmg3d_pair_main_wait_5 w3ddmg_pair_main_wait_5
#define dmg3d_pair_main_wait_6 w3ddmg_pair_main_wait_6
#define dmg3d_pair_main_wait_7 w3ddmg_pair_main_wait_7
#define dmg3d_pair_main_wait_8 w3ddmg_pair_main_wait_8
#define dmg3d_pair_main_wait_9 w3ddmg_pair_main_wait_9
#define dmg3dac_col w3ddmgac_col
#define dmg3dac_enter w3ddmgac_enter
#define dmg3dac_row w3ddmgac_row
#define dmg3dbg_enter w3ddmgbg_enter
#define dmg3dco_enter w3ddmgco_enter
#define dmg3dco_loop w3ddmgco_loop
#define dmg3dco_page w3ddmgco_page
#define dmg3dcs_enter w3ddmgcs_enter
#define dmg3dcs_inner w3ddmgcs_inner
#define dmg3dcs_outer w3ddmgcs_outer
#define dmg3dcv_enter w3ddmgcv_enter
#define dmg3dcv_loop w3ddmgcv_loop
#define dmg3dcv_page w3ddmgcv_page
#define dmg3ddt_enter w3ddmgdt_enter
#define dmg3ddt_loop w3ddmgdt_loop
#define dmg3dfb_enter w3ddmgfb_enter
#define dmg3dfb_loop w3ddmgfb_loop
#define dmg3dfb_page w3ddmgfb_page
#define dmg3dls_branch w3ddmgls_branch
#define dmg3dls_done w3ddmgls_done
#define dmg3dls_enter w3ddmgls_enter
#define dmg3dls_shallow w3ddmgls_shallow
#define dmg3dls_shallow_loop w3ddmgls_shallow_loop
#define dmg3dls_shallow_skip_bridge w3ddmgls_shallow_skip_bridge
#define dmg3dls_steep w3ddmgls_steep
#define dmg3dls_steep_loop w3ddmgls_steep_loop
#define dmg3dls_steep_skip_bridge w3ddmgls_steep_skip_bridge
#define dmg3dls_x_reverse w3ddmgls_x_reverse
#define dmg3dls_y_reverse w3ddmgls_y_reverse
#define dmg3dls_y_start w3ddmgls_y_start
#define dmg3dps_enter w3ddmgps_enter
#define dmg3dps_ret w3ddmgps_ret

kitaqgb/lib/dmg3d.h

entity.h — Grupos de objetos basados en arrays fijos
c
#pragma once

// Keep capacity in 1..255: IDs and scan counters are bytes and FF is reserved for failure.
// Use the same definition in every compilation unit.
#ifndef ENTITY_MAX
#define ENTITY_MAX ((u8)16)
#endif

// Position, velocity, state and timer units are game-defined; the pool does not advance them.
// The sprite field is only bookkeeping and does not allocate or release OAM entries.
typedef __packed struct {
    u8 active;
    u8 type;
    s16 x;
    s16 y;
    s16 vx;
    s16 vy;
    u8 state;
    u8 timer;
    u8 sprite;
} Entity;

// An entity callback receives a slot ID, not a persistent object handle.
typedef void (*EntityFn)(u8 id);

// Reset every slot before the game starts using the pool.
void entity_init();
// Returns a reusable slot ID, or 0xFF if no slot is free.
u8 entity_create(u8 type, s16 x, s16 y);
// Release a valid slot without clearing its payload. Reallocation resets the payload;
// a saved pointer or ID must not be treated as a persistent entity identity.
void entity_destroy(u8 id);
// Returns null for an invalid or inactive ID; the returned pointer aliases reusable pool storage.
Entity* entity_get(u8 id);
// Call fn for each slot that is active when the scan reaches it; null is a no-op.
// Callbacks may change the pool, so newly activated later slots can run in this pass.
void entity_update_all(EntityFn fn);
// Use the same active-slot traversal for drawing; the callback supplies all rendering.
void entity_draw_all(EntityFn fn);
// Count occupied slots without changing entity state.
u8 entity_count_active();
// Release every entity and restore deterministic defaults, including the no-sprite sentinel.
void entity_clear_all();

kitaqgb/lib/entity.h

fixed.h — Aritmética de punto fijo Q8.8 y rectángulos
c
#pragma once

// Signed Q8.8 uses 256 units per pixel/value: the range is -128 to 127 + 255/256.
typedef s16 fix8;

#define FIX_ONE ((fix8)256)
#define FIX_HALF ((fix8)128)

typedef __packed struct {
    fix8 x;
    fix8 y;
} Vec2;

typedef __packed struct {
    s16 x;
    s16 y;
    s16 w;
    s16 h;
} KQRect;

// Convert an integer to signed 8.8 fixed point by moving it into the high byte.
// The caller must keep the result within the representable 16-bit range.
fix8 fix_from_int(s16 n);
// Discard the eight fractional bits using a signed right shift.
s16 fix_to_int(fix8 x);
// Approximate 8.8 multiplication by discarding four low bits from each operand
// before multiplying. This trades precision for a smaller intermediate product.
fix8 fix_mul(fix8 a, fix8 b);
// Scale the reduced-precision quotient back to 8.8 and return zero for b == 0.
// Callers must also ensure (b >> 4) is nonzero; the explicit check only tests b.
// The intermediate product must fit the compiler's integer arithmetic.
fix8 fix_div(fix8 a, fix8 b);
// Interpolate toward b using a quantized Q0.8 weight. Both shifts discard low
// bits, so small changes may vanish and a weight of 255 need not reach b.
fix8 fix_lerp(fix8 a, fix8 b, u8 t_q8);
// Return the magnitude in s16. The most-negative s16 has no positive s16
// representation and must be excluded by callers needing a nonnegative result.
s16 kq_abs_s16(s16 v);
// Select the smaller signed value.
s16 kq_min_s16(s16 a, s16 b);
// Select the larger signed value.
s16 kq_max_s16(s16 a, s16 b);
// Clamp to an inclusive interval; callers must provide lo <= hi.
s16 kq_clamp_s16(s16 v, s16 lo, s16 hi);
// Test overlap using exclusive right/bottom edges; touching edges do not collide.
// Require positive dimensions and edge sums that fit s16; zero-sized rectangles
// are not explicitly rejected and may be reported as overlapping.
u8 kq_rect_intersect(KQRect a, KQRect b);
// Test a half-open rectangle: left/top edges are included, right/bottom excluded.
// The coordinate-plus-size sums must remain representable as s16.
u8 kq_point_in_rect(s16 x, s16 y, KQRect r);

kitaqgb/lib/fixed.h

input.h — Estado, pulsación, liberación y repetición de botones
c
#pragma once

#define BTN_RIGHT  ((u8)0x01)
#define BTN_LEFT   ((u8)0x02)
#define BTN_UP     ((u8)0x04)
#define BTN_DOWN   ((u8)0x08)
#define BTN_A      ((u8)0x10)
#define BTN_B      ((u8)0x20)
#define BTN_SELECT ((u8)0x40)
#define BTN_START  ((u8)0x80)

// A fresh press pulses immediately. The next pulse occurs DELAY + 1 updates later.
#ifndef INPUT_REPEAT_DELAY
#define INPUT_REPEAT_DELAY ((u8)18)
#endif

// Subsequent pulses are RATE + 1 updates apart; zero repeats on every held update.
#ifndef INPUT_REPEAT_RATE
#define INPUT_REPEAT_RATE ((u8)5)
#endif

extern u8 kq_input_prev_keys;
extern u8 kq_input_keys;
extern u8 kq_input_press_keys;
extern u8 kq_input_release_keys;
extern u8 kq_input_repeat_keys;

u16 __readpadex(u8 prev_keys);

// Clear sampled/edge state and initialize an independent repeat timer for each button.
void input_init();
// Sample input once per game tick and derive press, release and repeat masks.
// Repeat delays are measured in calls to this function, not elapsed wall-clock time.
void input_update();
// Return whether any masked button is currently held.
u8 input_down(u8 mask);
// Return whether any masked button became pressed in the latest sample.
u8 input_pressed(u8 mask);
// Return whether any masked button became released in the latest sample.
u8 input_released(u8 mask);
// Return whether any masked button produced a fresh press or scheduled repeat pulse.
u8 input_repeat(u8 mask);
// Return the complete held-button mask from the latest update.
u8 input_current();
// Return the held-button mask that preceded the latest update.
u8 input_previous();

#define btn_down input_down
#define btn_pressed input_pressed
#define btn_released input_released
#define btn_repeat input_repeat

kitaqgb/lib/input.h

link.h — Comunicación serie y paquetes lógicos
c
#pragma once

// Shared Game Boy serial link library for KITAQGB projects.
//
// Integration notes:
// - Compile a hardware-register file before link.c / link_packet.c so SB, SC,
//   IF_REG, and IE_REG are already declared.
// - Call Link_InitMaster() on the clock-source side and Link_InitSlave() on the
//   other side.
// - Call Link_Poll() or Link_PollPacket() regularly from the main loop.
// - If you enable serial IRQ mode, call Link_OnSerialIRQ() from your own
//   serial interrupt handler at vector 0x0058.
// - The packet layer is intentionally small and one-deep. It works best as a
//   master-driven command/response layer. The low-level byte API remains the
//   escape hatch for custom protocols.

#define LINK_MODE_SLAVE   ((u8)0)
#define LINK_MODE_MASTER  ((u8)1)

#define LINK_CLOCK_NORMAL ((u8)0)
#define LINK_CLOCK_FAST   ((u8)1)

#define LINK_ERR_NONE        ((u8)0)
#define LINK_ERR_BUSY        ((u8)1)
#define LINK_ERR_TIMEOUT     ((u8)2)
#define LINK_ERR_OVERFLOW    ((u8)3)
#define LINK_ERR_PROTOCOL    ((u8)4)
#define LINK_ERR_DISCONNECT  ((u8)5)

#define LINK_PKT_MAX_PAYLOAD ((u8)24)
#define LINK_RX_QUEUE_SIZE   ((u8)8)
#define LINK_TX_QUEUE_SIZE   ((u8)8)

#define LINK4_MODE_NONE      ((u8)0)
#define LINK4_MODE_HOST      ((u8)1)
#define LINK4_MODE_PEER      ((u8)2)
#define LINK4_MAX_PLAYERS    ((u8)4)
#define LINK4_HOST_SLOT      ((u8)0)
#define LINK4_INVALID_SLOT   ((u8)0xFF)

// Reset byte queues, packet mailboxes, cooperative-peer state and errors, then
// disable serial transfers and serial IRQ delivery. Existing data is discarded.
void Link_InitCommon();
// Reset link state and select the internal-clock role for subsequent transfers.
void Link_InitMaster();
// Reset link state and select the external-clock role for subsequent transfers.
void Link_InitSlave();
// Enable or disable serial IRQ delivery and clear its pending flag. Enabling
// does not install the handler. Leaving its outer critical section enables CPU interrupts.
void __stackcall Link_SetUseInterrupt(u8 on);
// Select the fast-clock bit for future master transfers; this does not restart
// an active transfer or verify that the hardware supports CGB fast mode.
void __stackcall Link_SetFastClock(u8 on);

// Poll once before returning busy state, so this query may collect a completed byte.
u8 Link_IsBusy();
// Read the ordinary receive-ready flag without polling hardware.
u8 Link_HasByte();
// Return the latest latched error without clearing it.
u8 Link_LastError();
// Clear the error latch without resetting queues or an active transfer.
void Link_ClearError();

// Start one full-duplex byte exchange, or return BUSY without replacing an
// active transfer. Slave mode arms reception and waits for external clocks.
u8 __stackcall Link_BeginTransfer(u8 out);
// Collect a pending transfer only after hardware clears the SC start bit.
void Link_Poll();
// Stop the hardware transfer under interrupt protection. Queued receive bytes
// and packet-layer state remain available; this is not a full protocol reset.
void Link_Cancel();
// Acknowledge serial IRQ and finish a software-busy transfer. Call this from
// the actual serial interrupt handler, not an unrelated interrupt.
void Link_OnSerialIRQ();

// Pop the ordinary receive queue without waiting or polling hardware; null discards a byte.
u8 __stackcall Link_TryReadByte(u8 *out);
// Pop one byte, returning zero when empty. Use Link_TryReadByte when a received
// zero byte must be distinguished from an empty queue.
u8 Link_ReadByte();
// Require an output pointer, poll immediately, then wait at most timeout_frames
// VBlanks for a byte. Zero timeout still performs the initial poll and read.
u8 __stackcall Link_WaitByte(u16 timeout_frames, u8 *out);

// Validate payload size and idle packet state, copy payload bytes into owned
// storage and schedule transmission. Return success means queued, not acknowledged;
// keep polling to progress the exchange and inspect the error latch.
u8 __stackcall Link_SendPacket(const u8 *data, u8 len, u8 cmd);
// Drain received bytes, advance one outgoing exchange and update the retry
// timer. Timeout ticks count calls without progress, not hardware frames; call
// with a controlled cadence and avoid mixing raw reads with packet consumption.
void Link_PollPacket();
// Inspect the shared completed-packet flag without advancing the protocol.
u8 Link_HasPacket();
// Consume the shared packet mailbox and its matching peer flag. Any output
// may be null; a nonnull destination needs room for the received payload because
// there is no destination-capacity argument.
u8 __stackcall Link_ReadPacket(u8 *cmd, u8 *len, u8 *dst);

// Cooperative 4-player adapter helpers.
//
// This layer models the common host-selected adapter pattern:
// - Slot 0 is always the host.
// - The host selects one active peer slot at a time.
// - Packet mailboxes stay one-deep per peer.
// - The original Link_* API remains available for normal 2-player projects.
// Reset as master, validate slot count and select logical peer one. Invalid configuration still discards old link state.
u8 __stackcall Link4_InitHost(u8 slot_count);
// Reset as slave and validate the local nonzero slot and total slot count.
// An invalid configuration still discards the previous link state.
u8 __stackcall Link4_InitPeer(u8 local_slot, u8 slot_count);
// Return the configured cooperative role; this is not a hardware connection probe.
u8 Link4_GetMode();
// Return the configured zero-based local slot.
u8 Link4_GetLocalSlot();
// Return the configured number of logical slots, not a live connection count.
u8 Link4_GetSlotCount();
// Return the current logical destination, or the invalid-slot sentinel when unset.
u8 Link4_GetSelectedPeer();
// Return the peer attributed to the last completed byte transfer.
u8 Link4_GetLastRxPeer();
// Return the peer attributed when the last byte transfer was started.
u8 Link4_GetLastTxPeer();
// Poll completion, then change the logical destination only while byte and
// packet state are idle. A peer can select only the host. No adapter-routing
// command is sent here; the transport must provide the matching physical route.
u8 __stackcall Link4_SelectPeer(u8 peer_slot);
// Select the logical peer and start a byte exchange, returning the first error.
u8 __stackcall Link4_BeginTransferTo(u8 peer_slot, u8 out);
// Inspect a valid peer ring without polling the hardware.
u8 __stackcall Link4_HasByteFrom(u8 peer_slot);
// Pop one byte from the selected peer ring; null output discards it.
u8 __stackcall Link4_TryReadByteFrom(u8 peer_slot, u8 *out);
// Scan remote rings in increasing slot order and return the first available
// byte. Null output pointers are allowed; lower slots have polling priority.
u8 __stackcall Link4_TryReadByteAny(u8 *peer_slot, u8 *out);
// Select a logical peer, then copy and schedule a packet; return the first error.
u8 __stackcall Link4_SendPacketTo(u8 peer_slot, const u8 *data, u8 len, u8 cmd);
// Advance the shared packet engine; this does not poll every logical peer in turn.
void Link4_PollPacket();
// Inspect the one-packet mailbox for a valid remote slot without consuming it.
u8 __stackcall Link4_HasPacketFrom(u8 peer_slot);
// Consume a peer mailbox, copying to optional outputs. A nonnull destination
// needs room for the entire payload. Clear the shared mailbox only when it
// refers to this same peer.
u8 __stackcall Link4_ReadPacketFrom(u8 peer_slot, u8 *cmd, u8 *len, u8 *dst);

kitaqgb/lib/link.h

link_dmg07.h — Comunicación DMG-07 con reloj externo
c
#pragma once

// Polling driver for the physical Nintendo DMG-07 Four Player Adapter.
//
// The adapter supplies every serial clock.  LinkDmg07_Poll() must therefore be
// called frequently enough to re-arm the serial port between adapter bytes;
// calling it only once per video frame is not sufficient.  Call
// LinkDmg07_TickFrame() exactly once per frame for timeout accounting.
//
// Transmission uses SIZE=1: every adapter packet contains four bytes, one for
// each physical player slot.  A console sends its local byte during byte 0 and
// sends zero during bytes 1..3, except while emitting an aligned FF restart
// packet.  The adapter broadcasts those four submitted bytes in the following
// packet.  The initial broadcast contains undefined adapter data and is
// discarded by this driver.

#define LINK_DMG07_PHASE_PING       ((u8)0)
#define LINK_DMG07_PHASE_REQUEST_AA ((u8)1)
#define LINK_DMG07_PHASE_WAIT_CC    ((u8)2)
#define LINK_DMG07_PHASE_TRANSFER   ((u8)3)

#define LINK_DMG07_MAX_PLAYERS  ((u8)4)
#define LINK_DMG07_PACKET_BYTES ((u8)4)
#define LINK_DMG07_SIZE         ((u8)1)
// Physical slots here are one-based; do not substitute the zero-based Link4 cooperative slot identifiers.
#define LINK_DMG07_NO_SLOT      ((u8)0)

// RATE $10 gives the shortest documented packet period for SIZE=1 while
// retaining the adapter's normal inter-byte pacing.  RATE $00 is not used.
#define LINK_DMG07_DEFAULT_RATE ((u8)0x10)

#ifndef LINK_DMG07_TIMEOUT_FRAMES
#define LINK_DMG07_TIMEOUT_FRAMES ((u8)12)
#endif

#define LINK_DMG07_ERR_NONE        ((u8)0)
#define LINK_DMG07_ERR_STATE       ((u8)1)
#define LINK_DMG07_ERR_NOT_PLAYER1 ((u8)2)
#define LINK_DMG07_ERR_NOT_READY   ((u8)3)
#define LINK_DMG07_ERR_TIMEOUT     ((u8)4)
#define LINK_DMG07_ERR_PROTOCOL    ((u8)5)
#define LINK_DMG07_ERR_OVERFLOW    ((u8)6)

#define LINK_DMG07_RESTART_NONE    ((u8)0)
#define LINK_DMG07_RESTART_PENDING ((u8)1)
#define LINK_DMG07_RESTART_SENDING ((u8)2)

// Initializes polling-only external-clock operation.  A zero RATE is replaced
// with LINK_DMG07_DEFAULT_RATE.  This driver disables only the serial IRQ bit.
void __stackcall LinkDmg07_Init(u8 rate);

// Services at most one completed serial byte and immediately re-arms SC=$80.
// Call continuously from the main loop, including between VBlanks.
void LinkDmg07_Poll();

// Advances saturating frame-based silence and handshake timeout counters.
void LinkDmg07_TickFrame();

// Return the discovery, start-handshake or transfer phase without polling.
u8 LinkDmg07_GetPhase();
// Return the one-based player slot, or LINK_DMG07_NO_SLOT before discovery.
u8 LinkDmg07_GetLocalSlot();

// Normalized mask: bit 0 is player 1, ..., bit 3 is player 4.
u8 LinkDmg07_GetConnectedMask();
// Return the last validated raw adapter status byte.
u8 LinkDmg07_GetLastStatus();
// Read the completed-discovery status flag without clearing it.
u8 LinkDmg07_HasPingStatus();
// Clear and report the completed-discovery flag; return zero if no new status exists.
u8 LinkDmg07_ConsumePingStatus();

// Only physical player 1 may request AA AA AA AA.  The bytes are aligned to
// the next FE/status/status/status ping packet.  All consoles enter transfer
// mode only after receiving four consecutive CC bytes.
u8 LinkDmg07_RequestTransmission();

// Any physical slot may schedule FF FF FF FF at the next four-byte packet
// boundary while remaining in TRANSFER phase.  The driver keeps sending aligned
// FF bytes until it sees the adapter's complete all-FF indicator packet, then
// returns to PING.  A transfer-phase silence timeout schedules the same recovery
// automatically and preserves the current byte position for clocks that resume.
u8 LinkDmg07_RequestRestart();
// Return whether aligned recovery is absent, pending or sending control traffic.
u8 LinkDmg07_GetRestartState();

// Sets the byte sampled when byte 0 of the next adapter packet is armed.
// Set it before the current packet completes (and before requesting start for
// the first submission).  During normal transfer, bytes 1..3 are sent as zero.
void __stackcall LinkDmg07_SetLocalByte(u8 value);

// The first incoming adapter data packet is discarded.  Thereafter ReadPacket
// copies four bytes in physical slot order (players 1..4).
u8 LinkDmg07_IsPipelinePrimed();
// Inspect the one-packet receive mailbox without consuming it.
u8 LinkDmg07_HasPacket();
// Consume the latest four-byte packet. A nonnull destination must hold four
// bytes; null discards the packet. Packet storage remains after the flag clears.
u8 __stackcall LinkDmg07_ReadPacket(u8 *dst);
// Read one cached player byte using a one-based slot. Invalid slots return
// zero; the function neither requires readiness nor consumes the packet.
u8 __stackcall LinkDmg07_GetPacketSlot(u8 player_slot);

// SentSequence increments when this console's packet byte is clocked out.
// PacketSequence labels the returned four-byte packet.  For a valid packet it
// is one less than SentSequence, making the DMG-07 one-packet delay explicit.
u8 LinkDmg07_GetSentSequence();
// Return the modulo-256 sequence associated with the most recently published packet.
u8 LinkDmg07_GetPacketSequence();

// SilenceFrames is reset by every completed serial byte.  TimeoutCount counts
// distinct serial-silence or AA/CC/restart handshake timeouts. DisconnectCount counts
// adapter-silence outages and ping-status membership drops.  All saturate.
u8 LinkDmg07_GetSilenceFrames();
// Return the saturating lifetime timeout count, preserved across protocol restarts.
u8 LinkDmg07_GetTimeoutCount();
// Return the saturating count of removed-player and previously-seen-adapter timeout events.
u8 LinkDmg07_GetDisconnectCount();
// Return the saturating protocol/overflow error count. Timeout and request
// validation paths use separate counters or latches and do not increment this value.
u8 LinkDmg07_GetErrorCount();
// Return the latest error latch without clearing counters or restarting the protocol.
u8 LinkDmg07_LastError();
// Clear only the latest error code, preserving counters and protocol state.
void LinkDmg07_ClearError();

kitaqgb/lib/link_dmg07.h

physics2d.h — Movimiento y colisiones en 2D
c
#pragma once

// Position and velocity use caller-selected integer units with one integration
// step per call; no hidden pixel or time conversion occurs. Keep intermediate
// signed arithmetic in range. World/body storage is owned by the caller.
#include "fixed.h"

// Multiply a signed word by a signed byte; divide by 256, truncating toward zero.
s16 __smul16x8(s16 a, s8 b);

// Lightweight deterministic 2D physics for KITAQGB.
// Integer pixels per step are one possible unit convention; inv_mass is Q8.

typedef struct {
    s16 x;
    s16 y;
    s16 vx;
    s16 vy;
    s16 half_x;
    s16 half_y;
    s16 inv_mass_q8;      // 0 means static body.
    s16 restitution_q8;   // 0..255 (reserved for future tuning).
    u8 active;
} KQBody2D;

typedef struct {
    KQBody2D* bodies;
    u8 body_count;
    s16 gravity_x;
    s16 gravity_y;
    u8 solver_iterations;
    s16 max_speed;
} KQWorld2D;

// Retain the caller-owned body array without initializing its elements.
// Set gravity to (0,32), four contact iterations and a per-axis speed limit of 512.
// A null world is ignored; the array must outlive subsequent world operations.
void kq2d_world_init(KQWorld2D* world, KQBody2D* bodies, u8 body_count);
// Advance active dynamic bodies, then visit each active unordered pair for
// the configured contact passes (zero means one). Static bodies still participate
// as obstacles. The world borrows its array and shares non-reentrant ASM scratch.
// This is discrete integration; fast bodies can pass through thin obstacles.
void kq2d_step(KQWorld2D* world);
// For one active dynamic body, add gravity, clamp each velocity axis and then
// add velocity to position. Null inputs are ignored; no contacts are solved.
// Use a nonnegative speed limit and keep additions in signed 16-bit range.
void kq2d_integrate_body(KQWorld2D* world, KQBody2D* body);
// Test strict overlap of two centered boxes; touching edges return false.
// Both pointers must be valid. Active/mass flags are ignored, and coordinate
// differences and extent sums must fit the signed 16-bit calculations.
u8 kq2d_overlap_aabb(const KQBody2D* a, const KQBody2D* b);
// Initialize an active unit-inverse-mass body at the supplied center and half
// extents, with zero velocity and reserved restitution set to zero. Null is ignored.
void kq2d_body_init(KQBody2D* body, s16 x, s16 y, s16 half_x, s16 half_y);
// Replace the center without altering velocity, extents or activity. Null is ignored.
void kq2d_body_set_pos(KQBody2D* body, s16 x, s16 y);
// Replace velocity without clamping or checking activity/mass. Null is ignored.
void kq2d_body_set_velocity(KQBody2D* body, s16 vx, s16 vy);
// Add gravity and clamp each velocity axis separately for an active dynamic
// body. Null, inactive and static bodies are ignored. Supply a nonnegative limit
// and avoid overflow in the additions before clamping; position is unchanged.
void kq2d_body_apply_gravity(KQBody2D* body, s16 gravity_x, s16 gravity_y, s16 max_speed);
// Scale both velocities through the signed 8-bit coefficient intrinsic.
// Despite the unsigned parameter, values 128..255 become negative coefficients;
// this is not a full-range unsigned Q8 damping helper. Null is ignored.
void kq2d_body_apply_friction(KQBody2D* body, u8 friction_q8);
// Delegate strict rectangle overlap to the fixed-point utility; edge-only
// contact is false. Coordinate-plus-size sums must remain representable as s16.
u8 kq2d_rect_intersect(KQRect a, KQRect b);
// Delegate the half-open point test: include left/top and exclude right/bottom.
// Coordinate-plus-size sums must remain representable as s16.
u8 kq2d_point_in_rect(s16 x, s16 y, KQRect r);

// Opt-in surface solver. Velocities/threshold/kick share the caller's units.
// Normal must be unit length in Q8; coefficients are 0..255.
typedef struct {
    s16 nx_q8;
    s16 ny_q8;
    s16 vx;
    s16 vy;
    s16 bounce_threshold;
    s16 kick;
    u8 restitution_q8;
    u8 friction_q8;
} KQSurface2D;

// Truncates toward zero, including negative values; coefficient is -256..256.
s16 kq2d_scale_q8(s16 value, s16 coefficient);
// Conservative circular bound, with a shared Q8 scale for both components.
// Quantizes toward zero; very small limits relative to input may yield zero.
// Components and positive max_speed must be <= 16383 in magnitude.
void kq2d_body_limit_speed(KQBody2D* body, s16 max_speed);
// Kinematic surface response; returns incoming normal speed, or zero if separating.
// Caller resolves penetration separately. Relative components must fit +/-8191.
s16 kq2d_body_resolve_surface(KQBody2D* body, const KQSurface2D* surface);
// Linear crossing time in Q8 (0..256); positive separation is outside.
// Returns 0 for initial overlap, 256 for no crossing. Gaps must fit +/-8191.
u16 kq2d_surface_toi_q8(s16 start_gap, s16 end_gap);

kitaqgb/lib/physics2d.h

physics2d_circle.h — Física de círculos
c
#pragma once

// Deterministic 2D circle physics for KITAQGB.
// Intended for top-down ball games such as billiards, air hockey, and marbles.

// Use consistent caller-selected units for centers, radii and per-step velocity.
// The implementation uses 16-bit arithmetic: reduced squared-distance sums and
// weight products must fit their types. Reduction to byte-sized components alone
// is insufficient to guarantee this. Body storage remains caller-owned.
typedef struct {
    s16 x;
    s16 y;
    s16 vx;
    s16 vy;
    s16 radius;
    s16 inv_mass_q8;      // 0 means static body.
    u8 restitution_q8;    // 0..255, higher means bouncier.
    u8 friction_q8;       // 0..255, higher removes more tangential motion.
    u8 active;
} KQCircleBody2D;

typedef struct {
    KQCircleBody2D* bodies;
    u8 body_count;
    s16 gravity_x;
    s16 gravity_y;
    u8 solver_iterations;
    s16 max_speed;
    u8 linear_damping_q8;   // 255 is almost no damping, lower values damp faster.
    u8 use_bounds;
    s16 min_x;
    s16 min_y;
    s16 max_x;
    s16 max_y;
    u8 wall_restitution_q8;
    u8 wall_friction_q8;
} KQCircleWorld2D;

// Retain a caller-owned array without initializing bodies. Set zero gravity,
// four contact passes, per-axis limit 768 and damping 252/256; bounds start disabled.
// A null world is ignored. Keep the array alive for subsequent steps.
void kq2dc_world_init(KQCircleWorld2D* world, KQCircleBody2D* bodies, u8 body_count);
// Store and enable bounds without validating their order or fitting bodies
// immediately. Supply extents large enough for body diameters. Null is ignored.
void kq2dc_set_bounds(KQCircleWorld2D* world, s16 min_x, s16 min_y, s16 max_x, s16 max_y);
// Integrate active dynamic bodies, apply bounds, solve contacts, then damp
// velocity and snap components in -1..1 to zero. Zero solver iterations means one.
// Pairs with both velocities zero are skipped, so resting overlaps can remain.
// Bounds can reposition static bodies; null world/array inputs are ignored.
void kq2dc_step(KQCircleWorld2D* world);
// Compare a reduced integer center distance with the reduced radius sum.
// Valid pointers and positive radii are required; activity and mass are ignored.
// This approximate test requires representable differences, radius sums and
// squared-distance sum. Touching at the computed distance returns false.
u8 kq2dc_overlap_circle(const KQCircleBody2D* a, const KQCircleBody2D* b);

kitaqgb/lib/physics2d_circle.h

physics3d.h — Física de cajas AABB en 3D
c
#pragma once

// Lightweight deterministic 3D physics for KITAQGB.
// AABB contacts, acceleration, mass-weighted bounce, and impact state flags.

// The game owns break decisions: the solver records impact speeds but never
// sets this flag or deactivates a body based on break_speed. Positions, extents,
// velocities and acceleration use consistent caller-selected per-step units.
#define KQ3D_BODY_BROKEN ((u8)0x01)

typedef struct {
    s16 x;
    s16 y;
    s16 z;
    s16 vx;
    s16 vy;
    s16 vz;
    s16 ax;
    s16 ay;
    s16 az;
    s16 half_x;
    s16 half_y;
    s16 half_z;
    s16 mass_q8;        // 256 means mass 1.0.
    s16 inv_mass_q8;    // 0 means static body.
    s16 restitution_q8; // 256 means perfectly elastic.
    s16 break_speed;    // Reserved for game-side impact thresholds.
    s16 last_impact_speed;
    u8 active;
    u8 flags;
} KQBody3D;

typedef struct {
    KQBody3D* bodies;
    u8 body_count;
    s16 gravity_x;
    s16 gravity_y;
    s16 gravity_z;
    u8 solver_iterations;
    s16 max_speed;
} KQWorld3D;

// Borrow the body array without initializing it. Set gravity (0,24,0), four
// contact passes and a per-axis speed limit of 512. Null world is ignored;
// the caller retains ownership and must keep the array alive.
void kq3d_world_init(KQWorld3D* world, KQBody3D* bodies, u8 body_count);
// Initialize an active centered box with zero velocity/acceleration,
// restitution 224, cleared impact/flags and mass set through the weight helper.
// The caller supplies valid half extents. Null body is ignored.
void kq3d_body_init(KQBody3D* body, s16 x, s16 y, s16 z, s16 half_x, s16 half_y, s16 half_z, s16 mass_q8);
// Store the requested mass; nonpositive mass makes the body static.
// For positive mass compute inverse weight as max(1,32767/max(mass,64)).
// The stored mass retains the original input; this is a relative solver weight,
// not an exact Q8 reciprocal. Null body is ignored.
void kq3d_body_set_mass(KQBody3D* body, s16 mass_q8);
// Integrate active dynamic bodies and reset their impact values, then solve
// each active unordered pair for the configured passes (zero means one).
// Static bodies retain previous impact maxima until the game clears them.
// Acceleration persists; flags and break thresholds remain game-owned.
// This discrete solver shares non-reentrant ASM scratch and can miss fast crossings.
void kq3d_step(KQWorld3D* world);
// Reset impact for one active dynamic body, add gravity and persistent body
// acceleration, clamp velocity per axis and advance position. Static/inactive
// bodies retain impact state. Null inputs are ignored; no contacts are solved.
// Use a nonnegative speed limit and avoid overflow before clamping.
void kq3d_integrate_body(KQWorld3D* world, KQBody3D* body);
// Test strict overlap on all three axes; face-only contact returns false.
// Valid pointers are required and flags are ignored. Center differences and
// extent sums must fit the signed 16-bit magnitude calculations.
u8 kq3d_overlap_aabb(const KQBody3D* a, const KQBody3D* b);

// Sum three signed products, shifting each by eight bits before addition.
// Coefficients are signed bytes scaled by 1/256; the 16-bit sum is not saturated.
s16 kq3d_dot_q8_8(s16 x, s16 y, s16 z, s8 ax, s8 ay, s8 az);

kitaqgb/lib/physics3d.h

raster.h — Tablas de desplazamiento por franjas y líneas de barrido
c
#pragma once

#include "scroll.h"

// Keep wrapper capacity consistent with the compiler split-table capacity; wrapper checks do not enlarge it.
#define KQ_RASTER_MAX_BANDS 8

#define KQ_RASTER_OK        0
#define KQ_RASTER_FULL      1
#define KQ_RASTER_BAD_LY    2
#define KQ_RASTER_UNSORTED  3
#define KQ_RASTER_BAD_RANGE 4

#define KQ_RASTER_BG        KQ_SCROLL_SPLIT_USE_BG
#define KQ_RASTER_WIN       KQ_SCROLL_SPLIT_USE_WIN
#define KQ_RASTER_WIN_SHOW  KQ_SCROLL_SPLIT_WIN_SHOW
#define KQ_RASTER_WIN_HIDE  KQ_SCROLL_SPLIT_WIN_HIDE
#define KQ_RASTER_BG_COLOR0 KQ_SCROLL_SPLIT_BG_COLOR0
#define KQ_RASTER_FLAG_MASK 0x1F

#define KQ_RASTER_LINE_FLAT        0
#define KQ_RASTER_LINE_X_TITLE     1
#define KQ_RASTER_LINE_TRAVEL_GATE 2

// Caller-owned wave state. Initialize it before use and keep it non-null for every LineX operation.
// frame_counter measures RunFrame calls, not an independent hardware clock.
typedef struct RasterLineX {
    u8 profile;
    u8 base_x;
    u8 phase;
    u8 phase_step;
    u8 frame_divider;
    u8 frame_counter;
} RasterLineX;

// Stop split scheduling, empty the shared table and clear error/count state.
void Raster_Init();
// Stop splits immediately and clear bookkeeping. Build and commit a new table to restart.
void Raster_Clear();
// Commit an empty split table so no raster bands remain active.
void Raster_Disable();

// Read the number of bands currently recorded by this wrapper.
u8 Raster_GetCount();
// Read the last stored status without clearing it.
u8 Raster_GetLastError();

// Append a validated background-scroll band and advance the monotonic-LY
// bookkeeping. A successful append clears the previous error.
u8 Raster_Push(u8 ly, u8 scx, u8 scy);
// Append a validated extended band after masking flags to supported operations.
u8 Raster_PushEx(u8 ly, u8 scx, u8 scy, u8 wx, u8 wy, u8 flags);

// Enable window updates and pass hardware WX/WY values without coordinate conversion.
u8 Raster_PushWindowRaw(u8 ly, u8 wx, u8 wy, u8 flags);
// Convert screen X to hardware WX by adding seven, then queue a window band.
// The byte addition wraps if callers supply an excessive X coordinate.
u8 Raster_PushWindowScreen(u8 ly, u8 screen_x, u8 screen_y, u8 flags);
// Queue both background and window updates, converting window screen X to WX.
u8 Raster_PushBgWindowScreen(u8 ly, u8 scx, u8 scy, u8 screen_x, u8 screen_y, u8 flags);
// Pack a 15-bit color into the extended band's two scroll-byte fields and select
// the color-zero operation, which interprets those fields as color data.
u8 Raster_PushBgColor0(u8 ly, u16 rgb15);

// Publish pending splits and return the stored status. This commits even if an
// earlier append failed; callers should inspect errors while building the table.
u8 Raster_Commit();

// Validate the HUD height, then replace pending splits with a fixed top band
// and scrolling playfield. The new table still requires an explicit commit.
u8 Raster_BuildHudTop(u8 hud_height, u8 camera_x, u8 camera_y);
// Build a scrolling upper playfield and fixed bottom HUD after validating the split.
u8 Raster_BuildHudBottom(u8 hud_y, u8 camera_x, u8 camera_y);

// Build two horizontal-scroll bands sharing one vertical scroll value.
u8 Raster_BuildParallax2(u8 split_y, u8 far_scx, u8 near_scx, u8 scy);
// Build three horizontal-scroll bands at ordered visible split lines. Invalid
// parameters leave the previous pending table intact and set the error status.
u8 Raster_BuildParallax3(u8 y1, u8 y2, u8 scx0, u8 scx1, u8 scx2, u8 scy);

// Initialize a scanline-wave state with phase zero and one phase step per frame.
void Raster_LineXInit(RasterLineX* effect, u8 profile, u8 base_x);
// Change the wave profile and restart its phase/divider counter.
void Raster_LineXSetProfile(RasterLineX* effect, u8 profile);
// Configure the phase increment and frame interval; clamp a zero interval to one.
void Raster_LineXSetSpeed(RasterLineX* effect, u8 phase_step, u8 frame_divider);
// Set the byte phase directly without resetting the frame-divider counter.
void Raster_LineXSetPhase(RasterLineX* effect, u8 phase);
// Look up the selected periodic profile at LY + phase and add base X modulo
// 256. An unknown profile returns the unmodified base X.
u8 Raster_LineXGetOffset(const RasterLineX* effect, u8 ly);
// Render all 144 visible lines with one SCX write per line, then advance phase.
// This foreground renderer masks interrupts during the visible frame. Do game
// and audio work between calls; do not combine it with a STAT raster driver.
// Returns without changing the effect when the LCD is off.
void Raster_LineXRunFrame(RasterLineX* effect);

kitaqgb/lib/raster.h

rpg.h — Números aleatorios, texto, mapas, guardado y servicios RPG/ADV/SLG
c
#pragma once

// The application supplies frame/cursor/font tiles at these indices; these constants do not load graphics.
#ifndef TEXT_TILE_FILL
#define TEXT_TILE_FILL ((u8)0)
#endif
#ifndef TEXT_TILE_FRAME_TL
#define TEXT_TILE_FRAME_TL ((u8)1)
#endif
#ifndef TEXT_TILE_FRAME_TR
#define TEXT_TILE_FRAME_TR ((u8)2)
#endif
#ifndef TEXT_TILE_FRAME_BL
#define TEXT_TILE_FRAME_BL ((u8)3)
#endif
#ifndef TEXT_TILE_FRAME_BR
#define TEXT_TILE_FRAME_BR ((u8)4)
#endif
#ifndef TEXT_TILE_FRAME_H
#define TEXT_TILE_FRAME_H ((u8)5)
#endif
#ifndef TEXT_TILE_FRAME_V
#define TEXT_TILE_FRAME_V ((u8)6)
#endif
#ifndef TEXT_TILE_CURSOR
#define TEXT_TILE_CURSOR ((u8)7)
#endif
#ifndef TEXT_TILE_PAGE_WAIT
#define TEXT_TILE_PAGE_WAIT ((u8)8)
#endif
#ifndef TEXT_DIGIT_BASE
#define TEXT_DIGIT_BASE ((u8)'0')
#endif

#define TEXT_CTRL_END       ((u8)0x00)
#define TEXT_CTRL_NEWLINE   ((u8)0x0A)
#define TEXT_CTRL_WAIT      ((u8)0x01)
#define TEXT_CTRL_PAGE_WAIT ((u8)0x02)

#define PAD_KEY_RIGHT  ((u8)0x01)
#define PAD_KEY_LEFT   ((u8)0x02)
#define PAD_KEY_UP     ((u8)0x04)
#define PAD_KEY_DOWN   ((u8)0x08)
#define PAD_KEY_A      ((u8)0x10)
#define PAD_KEY_B      ((u8)0x20)
#define PAD_KEY_SELECT ((u8)0x40)
#define PAD_KEY_START  ((u8)0x80)

// Default layout: four 512-byte slots, each with a six-byte header and at most 506 payload bytes.
#define SAVE_SLOT_COUNT ((u8)4)
#define SAVE_SLOT_SIZE  ((u16)512)
#define SAVE_MAGIC0     ((u8)0x4B)
#define SAVE_MAGIC1     ((u8)0x51)
#define SAVE_VERSION    ((u8)1)

#define SAVE_OK         ((u8)1)
#define SAVE_ERR        ((u8)0)

// A bank byte plus a CPU-visible address forms this data reference; it does not switch banks by itself.
typedef __packed struct {
    u8 bank;
    const u8* ptr;
} far_ptr_t;

typedef __packed struct {
    u8 x;
    u8 y;
    u8 w;
    u8 h;
    const u8* const* items;
    u8 count;
    u8 cursor;
} menu_t;

typedef __packed struct {
    u8 id;
    u8 qty;
    const u8* name;
} item_t;

// Packed nine-byte ordinary-map descriptor. Tile IDs use bank_tiles; collision bits and event bytes
// use the descriptor bank. Width/height are tile cells, with row-major data.
typedef __packed struct {
    u8 width;
    u8 height;
    u8 bank_tiles;
    const u8* tiles;
    const u8* collision_bits;
    const void* events;
} map_t;

// One 2x2 metatile: four tile IDs plus collision, palette metadata and event ID.
// The map drawing routine uses tile IDs only; it does not apply palette attributes.
typedef __packed struct {
    u8 tile_tl;
    u8 tile_tr;
    u8 tile_bl;
    u8 tile_br;
    u8 collision;
    u8 palette;
    u8 event;
} metatile_t;

// Metatile dimensions count 2x2 cells. bank_tiles=0 means use the descriptor bank;
// nonzero bank_tiles supplies both ID-array and definition-table reads.
typedef __packed struct {
    u8 width;
    u8 height;
    u8 bank_tiles;
    const u8* metatile_ids;
    const metatile_t* metatiles;
} metatile_map_t;

typedef __packed struct {
    u8 x;
    u8 y;
    u8 w;
    u8 h;
    const u8* const* items;
    u8 count;
    u8 cursor;
    u8 prev_keys;
    u8 selected;
    u8 cancelled;
} menu_state_t;

typedef __packed struct {
    u8 x;
    u8 y;
    u8 hp;
    u8 move;
    u8 atk_min;
    u8 atk_max;
    u8 team;
    u8 acted;
} unit_t;

void __wait_vblank();
u16 __readpadex(u8 prev_keys);
u16 __getbgmapbase();
void __memset(void* dst, u8 value, u16 count);
void __memcpy(void* dst, const void* src, u16 count);
void __settile(u8 x, u8 y, u8 tile);
void __settilebg(u8 x, u8 y, u8 tile);
void __settileat(u16 base, u8 x, u8 y, u8 tile);
void __vram_memcpy(u16 dst, const void* src, u16 len);
void __vram_memset(u16 dst, u8 value, u16 len);
void __far_memcpy(void* dst, u8 bank, const void* src, u16 len);
u8 __rng8();
void __rng_seed(u16 seed);
void __scroll_bg_set(u8 scx, u8 scy);

void __settile_xy(u8 x, u8 y, u8 tile);
void __settile_rect(u8 x, u8 y, u8 w, u8 h, u8 tile);
void __settile_row(u8 x, u8 y, const u8* src, u8 len);
void __settile_col(u8 x, u8 y, const u8* src, u8 len);
void __fill_tilemap(u16 base, u8 tile, u16 count);
void __settilemap_rect(u16 base, u8 x, u8 y, u8 w, u8 h, const u8* src);

void __vram_copy(u16 dst, const void* src, u16 len);
void __vram_fill(u16 dst, u8 value, u16 len);
void __vram_copy_hblank(u16 dst, const void* src, u16 len);
void __vram_copy_dma(u16 dst, const void* src, u16 len);

u8 __farpeek8(u8 bank, const void* addr);
u16 __farpeek16(u8 bank, const void* addr);
void __farmemcpy(void* dst, u8 bank, const void* src, u16 len);
// The current GB backend evaluates/discards these arguments but emits no indirect call.
void __farcall_ptr(u8 bank, const void* func);

#define far_read8(p) __farpeek8((p).bank, (p).ptr)
#define far_read16(p) __farpeek16((p).bank, (p).ptr)
#define far_read_block(dst, p, len) __farmemcpy((dst), (p).bank, (p).ptr, (len))

void __memcpy_small(void* dst, const void* src, u8 len);
void __memset_small(void* dst, u8 value, u8 len);
void __copy16(void* dst, const void* src);
void __copy32(void* dst, const void* src);

u16 __tile_addr(u16 base, u8 x, u8 y);
u16 __map_index(u8 x, u8 y, u8 width);
u8 __xy_in_rect(u8 x, u8 y, u8 rx, u8 ry, u8 rw, u8 rh);
u8 __manhattan(u8 x1, u8 y1, u8 x2, u8 y2);

u8 __bit_test(const u8* p, u16 bit_index);
void __bit_set(u8* p, u16 bit_index);
void __bit_clear(u8* p, u16 bit_index);
void __bit_toggle(u8* p, u16 bit_index);

// Compiler intrinsic, separate from the RAM rle_decode helpers below; it is not a bounded-stream API.
u16 __rle_decode_vram(u16 dst, u8 bank, const void* src);

// Advance the compiler-provided pseudorandom generator and return one byte.
u8 rng8();
// Consume two generator bytes in high-byte/low-byte order to form a 16-bit value.
u16 rng16();
// Reduce a random byte modulo max; zero returns zero without consuming randomness.
// Modulo reduction is biased unless max divides the generator range.
u8 rand_range(u8 max);
// Select an index from cumulative byte weights using a 16-bit random draw.
// A zero total, including an empty list, returns zero; callers must distinguish
// that case from a valid index. Modulo reduction can introduce a small bias.
u8 weighted_choice(const u8* weights, u8 count);
// Replace the generator seed so subsequent calls can reproduce a sequence.
void rng_seed(u16 seed);
// Alias the byte generator; this consumes one generator step.
u8 rng_next8();
// Alias the two-step 16-bit generator.
u16 rng_next16();
// Alias rand_range and return a value in [0,max), or zero when max is zero.
u8 rng_range(u8 max);
// Return false for zero and true for values at least 100. Intermediate values
// use the modulo-based range generator, so percentages are approximate.
u8 rng_chance(u8 percent);

// Set the tile-space window, reset its cursor and redraw it immediately.
// Opening does not reset the existing character speed or load font tiles.
void text_open(u8 x, u8 y, u8 w, u8 h);
// Erase the open window with the fill tile and disable windowed character output.
void text_close();
// Decode an END-terminated stream of tile bytes and newline/wait/page controls.
// WAIT consumes a following frame-count byte. The source must remain readable
// through blocking waits; the routine does not validate stream length.
void text_print(const u8* str);
// Decode the same text controls while fetching each byte from the specified
// ROM bank. The pointer advances within that bank; it does not roll into the next bank.
void text_print_far(u8 bank, const u8* str);
// Redraw choices and block for edge-triggered navigation: UP/DOWN wrap, A
// accepts, and B returns 0xFF. Zero choices also returns 0xFF. Choice strings
// use raw tile bytes, and the caller must fit them inside the available rows.
u8 text_choice(const u8* const* choices, u8 count);
// Set VBlank waits per windowed character; zero prints without character delays.
void text_set_speed(u8 speed);
// Open and redraw a window using the same tile-space arguments as text_open.
void text_window(u8 x, u8 y, u8 w, u8 h);
// Fill the supplied tile rectangle without changing the active text window or cursor.
void text_clear_rect(u8 x, u8 y, u8 w, u8 h);
// Draw a zero-terminated tile string at absolute tile coordinates, without
// window clipping, control codes or the windowed printing delay.
void text_print_xy(u8 x, u8 y, const u8* str);
// Print an unsigned byte in decimal using only the required number of cells.
void text_print_u8(u8 x, u8 y, u8 value);
// Print an unsigned word in decimal using only the required number of cells.
void text_print_u16(u8 x, u8 y, u16 value);
// Print a minus tile for negative values, followed by the unsigned magnitude.
// Positive values use the unsigned decimal path; no plus sign is emitted.
void text_print_s16(u8 x, u8 y, s16 value);

// Replace the active script and clear wait, choice and saved-return state.
void script_run(u8 bank, const u8* script);
// Execute commands until an output/choice yields (0), a wait yields (1), or
// execution ends (2). Control/flag commands continue within the same call, so
// a script loop without a yielding command can block the game loop indefinitely.
u8 script_step();
// Set the number of subsequent script_step calls to spend waiting. Frame-based
// timing requires the application to call script_step once per frame.
void script_wait_frames(u8 n);

// Run a blocking menu loop with wraparound up/down selection, A to accept
// and B to cancel. Return 0xFF for an empty menu or cancellation. Item strings
// and menu dimensions must fit the visible tile area.
u8 menu_run(const menu_t* menu);
// Open a two-choice dialog and return the text-choice result (YES first, NO second).
u8 menu_yesno();
// Run a blocking item menu, drawing names and two-digit quantities. Return
// the selected index or 0xFF on empty input/B; this does not consume an item.
u8 menu_inventory(const item_t* items, u8 count);
// Initialize a nonblocking menu state that borrows the item pointer table.
// Selection starts unset (0xFF), and the cancellation flag starts clear.
void menu_init_state(menu_state_t* state, u8 x, u8 y, u8 w, u8 h, const u8* const* items, u8 count);
// Draw the current menu and cursor without waiting or sampling input. The
// caller schedules suitable display timing and keeps item text within bounds.
void menu_draw(menu_state_t* state);
// Sample new button presses and update cursor/selection state without drawing.
// Selected and cancelled results remain latched; a B press in the same update
// as A clears selection and leaves cancellation set.
void menu_update(menu_state_t* state);
// Read the latched selection without clearing it; null state returns 0xFF.
u8 menu_get_selected(menu_state_t* state);
// Read the latched cancellation flag; null state returns false.
u8 menu_was_cancelled(menu_state_t* state);

// Load the nine-byte ordinary-map descriptor and draw up to 20 by 18 tiles
// from its top-left corner. Drawing does not upload tile graphics or clear
// background cells beyond smaller map dimensions.
void map_load(u8 bank, const map_t* map);
// Use metatile collision when that mode is active; otherwise read one packed
// collision bit. Missing maps/out-of-range cells block movement, but a valid
// ordinary map without a collision array is entirely passable.
u8 map_is_blocked(u8 x, u8 y);
// Report whether an event exists at the cell. Ordinary maps expose a Boolean
// byte-presence test; metatile maps reduce their event ID to a Boolean here.
u8 map_trigger_at(u8 x, u8 y);
// Center an ordinary-map tile coordinate within a 20-by-18 viewport and clamp
// the scroll origin to its edges. This adjusts scroll registers only; it does
// not stream newly exposed map rows into VRAM.
void camera_center(u8 x, u8 y);
// Select metatile mode, copy its descriptor and draw the initial viewport
// with the camera at cell (0,0).
void map_load_metatile(u8 bank, const metatile_map_t* map);
// Draw a 10-by-9 metatile viewport as 20-by-18 individual background tiles.
// Out-of-range cells use definition zero; palette attributes are not written.
// Remember the camera and clear the dirty flag after the full redraw.
void map_draw_visible(u8 camera_tx, u8 camera_ty);
// Read a row-major metatile ID, returning ID zero for inactive or out-of-range
// lookups. Callers must provide a usable definition for metatile zero.
u8 map_get_metatile(u8 tx, u8 ty);
// Return the selected definition's palette byte. An out-of-range coordinate
// uses the metatile-zero fallback; this function does not write CGB attributes.
u8 map_get_attr(u8 tx, u8 ty);
// Treat out-of-range metatile cells as solid; otherwise inspect the definition
// collision flag. In ordinary-map mode, delegate to its packed collision bits.
u8 map_is_solid(u8 tx, u8 ty);
// Return a metatile event ID, or the ordinary-map Boolean trigger result.
// Missing/out-of-range metatile cells have no event.
u8 map_get_event(u8 tx, u8 ty);
// Mark the viewport for a full redraw when a valid metatile cell changes.
// The coordinate is validated but no per-cell dirty list is retained.
void map_mark_dirty(u8 tx, u8 ty);
// Redraw the remembered metatile viewport only when the shared dirty flag is set.
void map_flush_dirty();

// Validate slot and payload length, write payload bytes, then write the header
// and checksum. Return one after completing the writes; interruption can leave
// a partially replaced slot, so this is not transactional save storage.
u8 save_write(u8 slot, const void* data, u16 len);
// Require matching magic/version, exact requested length and a valid checksum
// before copying data into the destination. Validation failure leaves the
// destination unchanged. An invalid slot returns before touching RAM control;
// validation failures after enabling RAM disable it before returning zero.
u8 save_read(u8 slot, void* data, u16 len);
// Validate a slot's header, payload bounds and checksum without copying the
// payload out. A nonzero result means the stored record passes these checks.
u8 save_exists(u8 slot);
// Initialize the expected RAM access state and leave cartridge RAM disabled.
// Existing slot contents are preserved.
void save_init();
// Alias the checked save_read operation.
u8 save_load(u8 slot, void* data, u16 len);
// Alias save_exists, including its header and checksum validation.
u8 save_check(u8 slot);
// Zero the complete selected slot, including header and payload; invalid slot
// IDs are ignored. Cartridge RAM is disabled when clearing finishes.
void save_clear(u8 slot);

// Build movement costs, then convert reachable cells to one and unreachable
// 0xFF cells to zero. The caller provides one output byte per current-map cell
// and a valid unit origin; path-search workspace limits also apply.
u8 unit_move_range(unit_t* u, u8* out_mask);
// Mark cells whose Manhattan distance falls within the inclusive attack range.
// This geometric mask does not test obstacles, line of sight or other units.
u8 unit_attack_range(unit_t* u, u8* out_mask);
// A unit can act only while HP is nonzero and its acted flag is clear.
// The unit pointer must refer to a valid record.
u8 unit_can_act(const unit_t* u);

// Find a shortest cardinal path with BFS and write direction codes 0=up,
// 1=right, 2=down, 3=left. Return its byte length, or zero for failure or an
// already-reached goal. The caller supplies max_len output bytes and respects
// the shared workspace/distance limits; excessive paths are not truncated.
u8 path_find_bfs(u8 sx, u8 sy, u8 gx, u8 gy, u8* out_path, u8 max_len);
// Flood cardinal neighbors at unit cost, stopping expansion at the movement
// limit and rejecting blocked destinations. Initialize output to 0xFF only
// after validating the map and origin; invalid input leaves output unchanged.
void range_fill_move(u8 sx, u8 sy, u8 move, u8* out_costmap);

// Read a bit from the flag array. Callers must keep id below 2048.
u8 flag_get(u16 id);
// Set a flag bit without disturbing adjacent flags; id must be below 2048.
void flag_set(u16 id);
// Clear a flag bit; id must be below 2048.
void flag_clear(u16 id);
// Read a quest-state byte; quest_id must be below 64.
u8 quest_state(u8 quest_id);
// Replace a quest-state byte without validating its game-specific meaning.
// The caller must keep quest_id below 64.
void quest_set_state(u8 quest_id, u8 state);

// Expand count/value byte pairs until a zero count terminates the stream.
// The caller must provide a valid terminator and sufficient destination storage;
// there are no source or destination bounds parameters. Return the 16-bit byte count.
u16 rle_decode(void* dst, const void* src);
// Decode the same count/value format using bank-qualified reads for every source
// byte. Keep the encoded stream within the supplied bank/address mapping and
// provide enough destination space; a zero count ends the stream.
u16 rle_decode_far(void* dst, u8 bank, const void* src);

// Return the active map width in its own cell units, or zero when no map is loaded.
u8 map_current_width();
// Return the active map height in its own cell units, or zero when no map is loaded.
u8 map_current_height();

kitaqgb/lib/rpg.h

scene.h — Registro, cambio y actualización de escenas
c
#pragma once

typedef void (*SceneFunc)();

// Callbacks may be null. Keep the table and non-null targets readable for its lifetime.
// These plain function pointers do not carry a ROM bank number.
typedef __packed struct {
    SceneFunc enter;
    SceneFunc update;
    SceneFunc draw;
    SceneFunc exit;
} SceneDef;

// Attach the caller-owned scene table and clear current-scene state without invoking callbacks.
void scene_init(const SceneDef* scenes, u8 count);
// Replace the table by resetting scene state; this does not call the old scene's exit handler.
void scene_set_table(const SceneDef* scenes, u8 count);
// Ignore invalid IDs; otherwise exit the current scene and enter the requested one.
// Selecting the current ID still performs exit/enter. Callbacks run synchronously.
void scene_change(u8 scene_id);
// Clear the change flag before calling the active scene's update handler, so a
// transition made during that handler is visible afterward.
void scene_update();
// Call the active scene's draw handler if one exists; no current scene is a no-op.
void scene_draw();
// Return the stored scene ID; zero is also returned before the first transition.
u8 scene_get_current();
// Read the transition flag, which is cleared at the start of an active scene update.
u8 scene_was_changed();

kitaqgb/lib/scene.h

scroll.h — Desplazamiento del fondo, la ventana y las zonas divididas
c
#pragma once

// Flags select operations in a raster split; raw window X includes the hardware +7 offset.
#define KQ_SCROLL_SPLIT_USE_BG   0x01
#define KQ_SCROLL_SPLIT_USE_WIN  0x02
#define KQ_SCROLL_SPLIT_WIN_SHOW 0x04
#define KQ_SCROLL_SPLIT_WIN_HIDE 0x08
#define KQ_SCROLL_SPLIT_BG_COLOR0 0x10

void __scroll_bg_set(u8 scx, u8 scy);
void __scroll_bg_x_set(u8 scx);
void __scroll_bg_y_set(u8 scy);
u8 __scroll_bg_x_get();
u8 __scroll_bg_y_get();

void __scroll_win_set(u8 wx, u8 wy);
void __scroll_win_x_set(u8 wx);
void __scroll_win_y_set(u8 wy);
u8 __scroll_win_x_get();
u8 __scroll_win_y_get();

void __scroll_bg_set_buffered(u8 scx, u8 scy);
void __scroll_bg_x_set_buffered(u8 scx);
void __scroll_bg_y_set_buffered(u8 scy);
void __scroll_win_set_buffered(u8 wx, u8 wy);
void __scroll_win_x_set_buffered(u8 wx);
void __scroll_win_y_set_buffered(u8 wy);
void __scroll_flush();

void __scroll_split_reset();
void __scroll_split_push(u8 ly, u8 scx, u8 scy);
void __scroll_split_push_ex(u8 ly, u8 scx, u8 scy, u8 wx, u8 wy, u8 flags);
void __scroll_split_commit();

void __scroll_win_show();
void __scroll_win_hide();
void __scroll_bg_add(s8 dx, s8 dy);
void __scroll_win_add(s8 dx, s8 dy);

// Reset background scroll to zero and place the window at screen origin
// using hardware WX=7 and WY=0.
void Scroll_Init();
// Write both hardware background-scroll bytes immediately.
void Scroll_SetBg(u8 scx, u8 scy);
// Write horizontal background scroll while leaving vertical scroll unchanged.
void Scroll_SetBgX(u8 scx);
// Write vertical background scroll while leaving horizontal scroll unchanged.
void Scroll_SetBgY(u8 scy);
// Read the tracked current background X; this is not a direct SCX register read.
u8 Scroll_GetBgX();
// Read the tracked current background Y; pending and raster-only values are excluded.
u8 Scroll_GetBgY();

// Write raw hardware WX/WY values; callers add seven to a screen-space window X.
void Scroll_SetWindow(u8 wx, u8 wy);
// Write raw hardware WX without converting a screen-space X coordinate.
void Scroll_SetWindowX(u8 wx);
// Write the window Y coordinate through the intrinsic.
void Scroll_SetWindowY(u8 wy);
// Read tracked current WX, including its seven-pixel offset; not a live hardware read.
u8 Scroll_GetWindowX();
// Read tracked current WY; pending and raster-only values are excluded.
u8 Scroll_GetWindowY();

// Stage background-scroll values in the intrinsic buffer for a later flush.
void Scroll_SetBgBuffered(u8 scx, u8 scy);
// Stage raw window-coordinate values for a later flush.
void Scroll_SetWindowBuffered(u8 wx, u8 wy);
// Apply the buffered scroll/window state through the compiler runtime.
void Scroll_Flush();

// Apply signed deltas to the byte-sized background-scroll coordinates.
void Scroll_BgAdd(s8 dx, s8 dy);
// Apply signed deltas to the byte-sized hardware window coordinates.
void Scroll_WindowAdd(s8 dx, s8 dy);
// Request window visibility through the compiler intrinsic.
void Scroll_WindowShow();
// Request that the window be hidden through the compiler intrinsic.
void Scroll_WindowHide();

// Clear the pending split table before building a new raster configuration.
void Scroll_SplitReset();
// Append a background-scroll split directly. Use Raster_Push when caller-side
// scanline ordering and capacity validation are desired.
void Scroll_SplitPush(u8 ly, u8 scx, u8 scy);
// Append an extended split with raw background/window fields and operation flags.
void Scroll_SplitPushEx(u8 ly, u8 scx, u8 scy, u8 wx, u8 wy, u8 flags);
// Reuse the two background-scroll fields to carry the low/high RGB15 bytes
// for a split whose operation flag selects background color zero.
void Scroll_SplitPushBgColor0(u8 ly, u16 rgb15);
// Publish the pending split configuration through the compiler runtime.
void Scroll_SplitCommit();

kitaqgb/lib/scroll.h

slg.h — Tableros, listas de jugadas y deshacer
c
#pragma once

// A row-major byte board. Storage is borrowed; cell values and coordinates have game-defined meaning.
typedef __packed struct {
    u8 width;
    u8 height;
    u8* cells;
} SLGBoard;

typedef __packed struct {
    u8 x;
    u8 y;
    u8 value;
} SLGMove;

typedef __packed struct {
    SLGMove* items;
    u8 count;
    u8 capacity;
} SLGMoveList;

// Undo records are retained cell values only; popping one does not apply it to a board.
typedef __packed struct {
    SLGMove* items;
    u8 count;
    u8 capacity;
} SLGUndoStack;

// Attach width * height bytes of caller-owned cell storage without clearing it.
void slg_board_init(SLGBoard* board, u8 width, u8 height, u8* cells);
// Fill every cell with value; a null board is ignored. A valid board must own
// enough accessible cell storage for its declared dimensions.
void slg_board_clear(SLGBoard* board, u8 value);
// Return zero for a null board or out-of-range coordinate; otherwise read the
// cell. Zero therefore cannot distinguish an invalid lookup from an empty cell.
u8 slg_board_get(const SLGBoard* board, u8 x, u8 y);
// Write a cell only when the board and coordinate are valid.
void slg_board_set(SLGBoard* board, u8 x, u8 y, u8 value);
// Attach caller-owned move storage and reset the list length.
void slg_move_list_init(SLGMoveList* list, SLGMove* items, u8 capacity);
// Forget the moves without erasing their storage; a null list is ignored.
void slg_move_list_clear(SLGMoveList* list);
// Append coordinates and a value to the bounded move list. Return zero on a
// null/full list without replacing any existing move.
u8 slg_move_list_push(SLGMoveList* list, u8 x, u8 y, u8 value);
// Attach caller-owned undo records and initialize an empty stack.
void slg_undo_init(SLGUndoStack* stack, SLGMove* items, u8 capacity);
// Record a cell's previous value for later undo. Return zero if the stack is
// null or full; this function does not change the board itself.
u8 slg_undo_push(SLGUndoStack* stack, u8 x, u8 y, u8 old_value);
// Remove the newest undo record and optionally copy it out. A null output
// still discards the record; a null or empty stack returns zero.
u8 slg_undo_pop(SLGUndoStack* stack, SLGMove* out_move);

kitaqgb/lib/slg.h

sprite.h — Reserva y posición de OBJ, metasprites y animación
c
#pragma once

// Keep the default 40 for the standard DMA path. Hardware always transfers 160 bytes,
// even if this array is shortened; a custom layout must provide valid bytes for that full transfer.
#ifndef SPRITE_MAX
#define SPRITE_MAX 40
#endif

#define SPRITE_FLAG_PAL1     ((u8)0x10)
#define SPRITE_FLAG_XFLIP    ((u8)0x20)
#define SPRITE_FLAG_YFLIP    ((u8)0x40)
#define SPRITE_FLAG_PRIORITY ((u8)0x80)

// Packed hardware order is Y, X, tile, flags; screen coordinates need the GB OAM offsets.
typedef __packed struct {
    u8 y;
    u8 x;
    u8 tile;
    u8 flags;
} SpriteOamEntry;

extern __wram __aligned(256) SpriteOamEntry kq_sprite_oam[SPRITE_MAX];
extern u8 kq_sprite_active[SPRITE_MAX];
extern u8 kq_sprite_used;
extern u8 kq_sprite_height;

// Signed pixel displacements from a common origin; final byte coordinates wrap rather than clip.
typedef __packed struct {
    s8 dx;
    s8 dy;
    u8 tile;
    u8 flags;
} MetaSpritePart;

// Initialize frame/ticks within their configured ranges. This animation selects consecutive tile IDs;
// it does not change sprite size or automatically step by two tiles in 8x16 mode.
typedef __packed struct {
    u8 first_tile;
    u8 frame_count;
    u8 frame;
    u8 ticks;
    u8 ticks_per_frame;
} SpriteAnim;

void __wait_vblank();
void __oam_dma(u16 src_ptr);

// Clear allocation and shadow OAM state and reset the DMA-stub installation flag.
// The default height is eight pixels; the hardware display mode is configured elsewhere.
void sprite_init();
// Claim the first free slot, hide it, and return its ID; return 0xFF when full.
// Previously stored tile/flag bytes are retained until the caller replaces them.
u8 sprite_alloc();
// Release an allocated valid slot and hide it. Repeated frees do not decrement the count.
void sprite_free(u8 id);
// Convert screen coordinates to OAM coordinates by adding X=8 and Y=16.
// The byte additions wrap; this updates shadow storage even for an unallocated slot.
void sprite_set_pos(u8 id, u8 x, u8 y);
// Set a valid shadow slot's tile byte; allocation and hardware transfer are separate.
void sprite_set_tile(u8 id, u8 tile);
// Replace a valid shadow slot's complete hardware attribute byte.
void sprite_set_flags(u8 id, u8 flags);
// Move a valid shadow slot off screen without freeing it.
void sprite_hide(u8 id);
// Install the HRAM stub lazily and execute OAM DMA with interrupts disabled.
// This routine does not wait for VBlank and always enables interrupts afterward;
// it does not restore the caller's previous interrupt-enable state.
void sprite_flush_oam_now();
// Wait for VBlank, then transfer shadow OAM using the immediate DMA routine.
void sprite_flush_oam();
// Return the number of active slots, including slots activated by metasprite_draw.
// Hidden allocated slots remain active until sprite_free releases them.
u8 sprite_count_used();
// Report whether the software overlap estimate exceeds ten sprites on a scanline.
u8 sprite_warn_scanline_overflow();
// Estimate the largest overlap of active, non-hidden shadow sprites across
// visible scanlines using the configured sprite height. This is a software
// overlap count, not a rendered-pixel or hardware-priority simulation.
u8 sprite_max_scanline_count();
// Place consecutive parts, counting each newly activated slot once. Existing
// active slots are overwritten without increasing the allocation count. Return
// the number written; an invalid first slot or zero count writes nothing.
u8 metasprite_draw(u8 first_id, u8 x, u8 y, const MetaSpritePart* parts, u8 count);
// Advance animation ticks/frame with wrapping frame selection and return the
// resulting tile. Zero ticks-per-frame freezes animation; null state returns zero.
u8 anim_update(SpriteAnim* anim);

kitaqgb/lib/sprite.h

sprite_order.h — Selección de sprites por prioridad y rotación
c
#pragma once
// Copyright (c) 2026 DAISUKE OBA. MIT License.

// Hardware-compatible layout without requiring the sprite allocator or its
// global storage. Cast a sprite.h shadow buffer to this type when combining
// the libraries; both layouts contain exactly Y, X, tile and flags bytes.
typedef __packed struct {
    u8 y;
    u8 x;
    u8 tile;
    u8 flags;
} SpriteOrderOamEntry;

#define SPRITE_ORDER_LEVELS 4
#define SPRITE_ORDER_OAM_COUNT 40

// One submitted, visible sprite. Attributes retain their hardware meaning;
// priority 0..3 controls OAM selection order, not the BG-over-OBJ flag.
typedef __packed struct {
    SpriteOrderOamEntry oam;
    u8 priority;
} SpriteOrderItem;

// Caller-owned foreground state. Capacity is 1..255 items; count includes only
// accepted submissions. Rebuild the same logical submission list each frame so
// phase rotation distributes selection among equal-priority sprites.
typedef struct {
    SpriteOrderItem* items;
    u8 capacity;
    u8 count;
    u8 height;
    u8 phase;
} SpriteOrder;

// Bind writable item storage and select the hardware sprite height (8 or 16).
// Return 1 on success. Invalid storage, zero capacity or another height returns
// 0 and leaves a non-null state disabled. A null state returns 0 without writes.
u8 sprite_order_init(SpriteOrder* order, SpriteOrderItem* items, u8 capacity, u8 height);

// Discard this frame's submissions while preserving storage, height and phase.
// A null state is ignored. Call once before submitting the next frame's sprites.
void sprite_order_begin(SpriteOrder* order);

// Submit one sprite at signed, top-left SCREEN pixel coordinates. Preserve the
// tile and attribute bytes; use priority 0 (first) through 3 (last). Fully
// off-screen sprites, invalid priorities, disabled state and full storage return
// 0 without consuming a slot. Partly visible sprites are accepted. Return 1 on
// acceptance. Hardware 8x16 mode still ignores the tile index's low bit.
u8 sprite_order_push(SpriteOrder* order, s16 x, s16 y, u8 tile, u8 flags, u8 priority);

// Write a complete 160-byte shadow OAM: ascending priority, then cyclic order
// within each priority. Clamp limit to 40, return the number emitted and zero
// all unused entries (including Y) so they cannot consume scanline slots.
// Advance phase once for a nonempty valid queue, even when limit is zero.
// Empty queues reset phase to zero. Null/disabled/corrupt state or null output
// returns 0 without modifying output or phase.
// Output must provide 40 entries and must not overlap item/state storage.
// This only writes RAM. Build in foreground, then transfer during VBlank.
// DMG overlap priority also depends on X: this cannot override that hardware
// rule. OAM order chooses the first ten sprites per scanline on both DMG/CGB.
// It neither updates sprite_alloc's bookkeeping nor performs OAM DMA.
u8 sprite_order_build(SpriteOrder* order, SpriteOrderOamEntry* output, u8 limit);

kitaqgb/lib/sprite_order.h

system.h — Arranque, contadores de fotogramas, esperas e interrupciones
c
#pragma once

// This callback runs in the caller of system_wait_vblank, not as an installed ISR.
// Its plain pointer has no ROM bank component; keep the target callable in that mapping.
typedef void (*SystemCallback)();

extern u16 kq_system_frame;

void __wait_vblank();

// Reset the software frame counter and remove any registered callback.
void system_init();
// Wait for VBlank, count this wrapper call, then invoke the callback synchronously.
// The counter wraps at 16 bits and is not an independent hardware frame clock.
void system_wait_vblank();
// Replace the callback used by system_wait_vblank; null disables the callback.
void system_set_vblank_callback(SystemCallback callback);
// Read the software count of completed system_wait_vblank calls.
u16 system_get_frame();
// Return the low byte of the software frame counter for wrapping 8-bit timing.
u8 system_get_frame8();
// Enable CPU interrupts and return using the inline-assembly function body.
void system_enable_interrupts();
// Disable CPU interrupts and return; callers must explicitly re-enable them later.
void system_disable_interrupts();

#define gb_init system_init
#define gb_wait_vblank system_wait_vblank
#define gb_set_vblank_callback system_set_vblank_callback
#define gb_frame_count system_get_frame
#define gb_enable_interrupts system_enable_interrupts
#define gb_disable_interrupts system_disable_interrupts

kitaqgb/lib/system.h

vram.h — Actualizaciones de VRAM en cola y transferencias
c
#pragma once

// Keep this capacity in 1..255 in all units; counts and capacity/free return values are bytes.
#ifndef VRAM_QUEUE_MAX
#define VRAM_QUEUE_MAX 32
#endif

#define VRAM_CMD_BG_TILE   ((u8)1)
#define VRAM_CMD_BG_RECT   ((u8)2)
#define VRAM_CMD_BG_BLOCK  ((u8)3)
#define VRAM_CMD_MEMCPY    ((u8)4)
#define VRAM_CMD_MEMSET    ((u8)5)

// A command owns metadata only. src is a retained near pointer with no bank number or copied payload.
typedef __packed struct {
    u8 kind;
    u8 x;
    u8 y;
    u8 w;
    u8 h;
    u8 value;
    u16 dst;
    const u8* src;
    u16 len;
} VramCommand;

extern VramCommand kq_vram_queue[VRAM_QUEUE_MAX];
extern u8 kq_vram_queue_used;
extern u8 kq_vram_queue_overflowed;

void __wait_vblank();
void __settile_xy(u8 x, u8 y, u8 tile);
void __settile_rect(u8 x, u8 y, u8 w, u8 h, u8 tile);
void __settilemap_rect(u16 base, u8 x, u8 y, u8 w, u8 h, const u8* src);
void __vram_copy(u16 dst, const void* src, u16 len);
void __vram_fill(u16 dst, u8 value, u16 len);

// Start with an empty command queue and a clear overflow flag.
void vram_init();
// Discard pending commands and clear the latched overflow flag without writing VRAM.
void vram_clear_queue();
// Queue a single background tile write; return zero if no command slot is available.
u8 vram_queue_bg_tile(u8 x, u8 y, u8 tile);
// Provide the short alias for a queued background tile write.
u8 vram_queue_tile(u8 x, u8 y, u8 tile);
// Queue a rectangle filled with one tile value; coordinates and dimensions are in tiles.
u8 vram_queue_bg_rect(u8 x, u8 y, u8 w, u8 h, u8 tile);
// Queue a tile-map rectangle while retaining src rather than copying its bytes.
// Keep the source data and its ROM bank accessible until the queue is flushed.
u8 vram_queue_bg_block(u16 base, u8 x, u8 y, u8 w, u8 h, const u8* src);
// Queue a byte transfer and retain the source pointer. The source must remain
// valid and visible until flush; len is measured in bytes, not tiles.
u8 vram_queue_memcpy(u16 dst, const void* src, u16 len);
// Alias the queued byte-copy operation; this does not convert a tile count to bytes.
u8 vram_queue_tiles(u16 dst, const void* src, u16 len);
// Queue a byte fill and return zero if the command queue is full.
u8 vram_queue_memset(u16 dst, u8 value, u16 len);
// Execute pending commands in insertion order without waiting for VBlank here.
// The caller must arrange suitable VRAM access timing and a sufficient transfer budget.
// Only the used count is cleared; overflow stays latched until an explicit reset.
void vram_flush_now();
// Wait for VBlank before executing the queue. Waiting once does not itself limit
// the queued workload to the available VBlank duration.
void vram_flush();
// Return the number of queued commands, not the number of transfer bytes.
u8 vram_get_queue_used();
// Return the total number of command slots, independent of queue usage.
// This is command-buffer capacity, not free space in hardware VRAM.
u8 vram_get_queue_capacity();
// Return the remaining command-slot capacity.
u8 vram_get_queue_free();
// Read the overflow latch without clearing it.
u8 vram_get_overflowed();

kitaqgb/lib/vram.h

wire3d.h — Gráficos de alambre para DMG
c
// Compatibility names for the shared wire3d_dmg renderer.
// Select the same profile in every translation unit; compile one renderer entry.
#pragma once
#ifndef WIRE3D_DMG_HEIGHT
#define WIRE3D_DMG_HEIGHT 96
#endif
#if WIRE3D_DMG_HEIGHT != 96
#error Incompatible wire3d_dmg profile
#endif
#include "wire3d_dmg.h"

#define W3D_BG_QUEUE_LIMIT WIRE3D_DMG_BG_QUEUE_LIMIT
#define W3D_CENTER_X WIRE3D_DMG_CENTER_X
#define W3D_CENTER_Y WIRE3D_DMG_CENTER_Y
#define W3D_FAR_Z WIRE3D_DMG_FAR_Z
#define W3D_HUD_TILE_BASE WIRE3D_DMG_HUD_TILE_BASE
#define W3D_HUD_TILE_BLANK WIRE3D_DMG_HUD_TILE_BLANK
#define W3D_HUD_TILE_COUNT WIRE3D_DMG_HUD_TILE_COUNT
#define W3D_NEAR_Z WIRE3D_DMG_NEAR_Z
#define W3D_PROJECT_LIMIT WIRE3D_DMG_PROJECT_LIMIT
#define W3D_ROW_BYTES WIRE3D_DMG_ROW_BYTES
#define W3D_TILE_H WIRE3D_DMG_TILE_H
#define W3D_TILE_W WIRE3D_DMG_TILE_W
#define W3D_TRANSFORM_LIMIT WIRE3D_DMG_TRANSFORM_LIMIT
#define WIRE3D_EDGE_MASK_BINS_16 WIRE3D_DMG_EDGE_MASK_BINS_16
#define WIRE3D_FACE_NONE WIRE3D_DMG_FACE_NONE
#define WIRE3D_MODEL_EDGE_LIMIT WIRE3D_DMG_MODEL_EDGE_LIMIT
#define WIRE3D_MODEL_FACE_LIMIT WIRE3D_DMG_MODEL_FACE_LIMIT
#define WIRE3D_MODEL_HIDDEN_LINES WIRE3D_DMG_MODEL_HIDDEN_LINES
#define WIRE3D_MODEL_VERTEX_LIMIT WIRE3D_DMG_MODEL_VERTEX_LIMIT
#define WIRE3D_SCENE_OBJECT_LIMIT WIRE3D_DMG_SCENE_OBJECT_LIMIT
#define WIRE3D_SCREEN_H WIRE3D_DMG_SCREEN_H
#define WIRE3D_SCREEN_W WIRE3D_DMG_SCREEN_W
#define Wire3D_BeginFrame Wire3DDMG_BeginFrame
#define Wire3D_DrawLine2D Wire3DDMG_DrawLine2D
#define Wire3D_DrawLine3D Wire3DDMG_DrawLine3D
#define Wire3D_DrawModel Wire3DDMG_DrawModel
#define Wire3D_DrawModelScaled Wire3DDMG_DrawModelScaled
#define Wire3D_DrawScene Wire3DDMG_DrawScene
#define Wire3D_Edge Wire3DDMG_Edge
#define Wire3D_EdgeFaces Wire3DDMG_EdgeFaces
#define Wire3D_EndFrame Wire3DDMG_EndFrame
#define Wire3D_EraseModelFaces Wire3DDMG_EraseModelFaces
#define Wire3D_EraseSpan2D Wire3DDMG_EraseSpan2D
#define Wire3D_EraseTriangle2D Wire3DDMG_EraseTriangle2D
#define Wire3D_Face Wire3DDMG_Face
#define Wire3D_Init Wire3DDMG_Init
#define Wire3D_Model Wire3DDMG_Model
#define Wire3D_Object Wire3DDMG_Object
#define Wire3D_ProjectPoint Wire3DDMG_ProjectPoint
#define Wire3D_PutBgTile Wire3DDMG_PutBgTile
#define Wire3D_SelectEdgeMask Wire3DDMG_SelectEdgeMask
#define Wire3D_SetCamera Wire3DDMG_SetCamera
#define Wire3D_SetPalette Wire3DDMG_SetPalette
#define Wire3D_Vec3 Wire3DDMG_Vec3
#define w3d_abs_i16 w3ddmg_abs_i16
#define w3d_bg_map_9800 w3ddmg_bg_map_9800
#define w3d_bgq_addr_hi w3ddmg_bgq_addr_hi
#define w3d_bgq_addr_lo w3ddmg_bgq_addr_lo
#define w3d_bgq_count w3ddmg_bgq_count
#define w3d_bgq_tile w3ddmg_bgq_tile
#define w3d_bgq_value w3ddmg_bgq_value
#define w3d_bgq_x w3ddmg_bgq_x
#define w3d_bgq_y w3ddmg_bgq_y
#define w3d_bit_mask w3ddmg_bit_mask
#define w3d_build_edge_flags w3ddmg_build_edge_flags
#define w3d_build_face_visibility w3ddmg_build_face_visibility
#define w3d_cam_pitch w3ddmg_cam_pitch
#define w3d_cam_roll w3ddmg_cam_roll
#define w3d_cam_x w3ddmg_cam_x
#define w3d_cam_y w3ddmg_cam_y
#define w3d_cam_yaw w3ddmg_cam_yaw
#define w3d_cam_z w3ddmg_cam_z
#define w3d_clamp_i16 w3ddmg_clamp_i16
#define w3d_clamp_screen w3ddmg_clamp_screen
#define w3d_clear_occlusion_mask w3ddmg_clear_occlusion_mask
#define w3d_clear_occlusion_mask_asm w3ddmg_clear_occlusion_mask_asm
#define w3d_clear_stage_asm w3ddmg_clear_stage_asm
#define w3d_clear_triangle w3ddmg_clear_triangle
#define w3d_clear_vram_asm w3ddmg_clear_vram_asm
#define w3d_cos_q6 w3ddmg_cos_q6
#define w3d_edge_area w3ddmg_edge_area
#define w3d_edge_flags w3ddmg_edge_flags
#define w3d_face_visible w3ddmg_face_visible
#define w3d_fill_bg_map_asm w3ddmg_fill_bg_map_asm
#define w3d_flush_bg_queue w3ddmg_flush_bg_queue
#define w3d_hud_tiles w3ddmg_hud_tiles
#define w3d_i16 w3ddmg_i16
#define w3d_i8 w3ddmg_i8
#define w3d_inv_depth w3ddmg_inv_depth
#define w3d_is_edge_visible w3ddmg_is_edge_visible
#define w3d_line_dx w3ddmg_line_dx
#define w3d_line_dy w3ddmg_line_dy
#define w3d_line_err w3ddmg_line_err
#define w3d_line_stage_asm w3ddmg_line_stage_asm
#define w3d_line_stage_masked_c w3ddmg_line_stage_masked_c
#define w3d_line_sx w3ddmg_line_sx
#define w3d_line_sy w3ddmg_line_sy
#define w3d_line_x w3ddmg_line_x
#define w3d_line_x0 w3ddmg_line_x0
#define w3d_line_x1 w3ddmg_line_x1
#define w3d_line_y w3ddmg_line_y
#define w3d_line_y0 w3ddmg_line_y0
#define w3d_line_y1 w3ddmg_line_y1
#define w3d_load_hud_tiles w3ddmg_load_hud_tiles
#define w3d_mark_model_occluder w3ddmg_mark_model_occluder
#define w3d_mark_triangle w3ddmg_mark_triangle
#define w3d_mask_get w3ddmg_mask_get
#define w3d_mask_offset w3ddmg_mask_offset
#define w3d_mask_set w3ddmg_mask_set
#define w3d_mask_set_span w3ddmg_mask_set_span
#define w3d_neg_angle w3ddmg_neg_angle
#define w3d_occlusion_active w3ddmg_occlusion_active
#define w3d_occlusion_mask w3ddmg_occlusion_mask
#define w3d_pair_block w3ddmg_pair_block
#define w3d_pair_wait_0 w3ddmg_pair_wait_0
#define w3d_pair_wait_1 w3ddmg_pair_wait_1
#define w3d_pair_wait_10 w3ddmg_pair_wait_10
#define w3d_pair_wait_11 w3ddmg_pair_wait_11
#define w3d_pair_wait_12 w3ddmg_pair_wait_12
#define w3d_pair_wait_13 w3ddmg_pair_wait_13
#define w3d_pair_wait_14 w3ddmg_pair_wait_14
#define w3d_pair_wait_15 w3ddmg_pair_wait_15
#define w3d_pair_wait_2 w3ddmg_pair_wait_2
#define w3d_pair_wait_3 w3ddmg_pair_wait_3
#define w3d_pair_wait_4 w3ddmg_pair_wait_4
#define w3d_pair_wait_5 w3ddmg_pair_wait_5
#define w3d_pair_wait_6 w3ddmg_pair_wait_6
#define w3d_pair_wait_7 w3ddmg_pair_wait_7
#define w3d_pair_wait_8 w3ddmg_pair_wait_8
#define w3d_pair_wait_9 w3ddmg_pair_wait_9
#define w3d_plot_stage_asm w3ddmg_plot_stage_asm
#define w3d_plot_tx w3ddmg_plot_tx
#define w3d_plot_x w3ddmg_plot_x
#define w3d_plot_y w3ddmg_plot_y
#define w3d_project_camera_space w3ddmg_project_camera_space
#define w3d_project_world w3ddmg_project_world
#define w3d_put_bg_tile_safe_asm w3ddmg_put_bg_tile_safe_asm
#define w3d_reg_bgp w3ddmg_reg_bgp
#define w3d_reg_lcdc w3ddmg_reg_lcdc
#define w3d_reg_ly w3ddmg_reg_ly
#define w3d_reg_scx w3ddmg_reg_scx
#define w3d_reg_scy w3ddmg_reg_scy
#define w3d_rotate_x w3ddmg_rotate_x
#define w3d_rotate_y w3ddmg_rotate_y
#define w3d_rotate_z w3ddmg_rotate_z
#define w3d_scene_depth w3ddmg_scene_depth
#define w3d_scene_object_depth w3ddmg_scene_object_depth
#define w3d_scene_order w3ddmg_scene_order
#define w3d_screen_delta w3ddmg_screen_delta
#define w3d_screen_visible w3ddmg_screen_visible
#define w3d_screen_x w3ddmg_screen_x
#define w3d_screen_y w3ddmg_screen_y
#define w3d_sin_q6 w3ddmg_sin_q6
#define w3d_stage w3ddmg_stage
#define w3d_stage_clear_pixel w3ddmg_stage_clear_pixel
#define w3d_stage_clear_span w3ddmg_stage_clear_span
#define w3d_transfer_stage_asm w3ddmg_transfer_stage_asm
#define w3d_u16 w3ddmg_u16
#define w3d_u8 w3ddmg_u8
#define w3d_vram_tiles w3ddmg_vram_tiles
#define w3d_wait_vblank_start w3ddmg_wait_vblank_start
#define w3dbg_enter w3ddmgbg_enter
#define w3dco_enter w3ddmgco_enter
#define w3dco_loop w3ddmgco_loop
#define w3dco_page w3ddmgco_page
#define w3dcs_enter w3ddmgcs_enter
#define w3dcs_inner w3ddmgcs_inner
#define w3dcs_outer w3ddmgcs_outer
#define w3dcv_enter w3ddmgcv_enter
#define w3dcv_loop w3ddmgcv_loop
#define w3dcv_page w3ddmgcv_page
#define w3dfb_enter w3ddmgfb_enter
#define w3dfb_loop w3ddmgfb_loop
#define w3dfb_page w3ddmgfb_page
#define w3dls_branch w3ddmgls_branch
#define w3dls_done w3ddmgls_done
#define w3dls_enter w3ddmgls_enter
#define w3dls_shallow w3ddmgls_shallow
#define w3dls_shallow_loop w3ddmgls_shallow_loop
#define w3dls_shallow_skip_bridge w3ddmgls_shallow_skip_bridge
#define w3dls_steep w3ddmgls_steep
#define w3dls_steep_loop w3ddmgls_steep_loop
#define w3dls_steep_skip_bridge w3ddmgls_steep_skip_bridge
#define w3dls_x_reverse w3ddmgls_x_reverse
#define w3dls_y_reverse w3ddmgls_y_reverse
#define w3dls_y_start w3ddmgls_y_start
#define w3dps_enter w3ddmgps_enter
#define w3dps_ret w3ddmgps_ret

kitaqgb/lib/wire3d.h

wire3d_cgb.h — Gráficos de alambre en color para CGB
c
#pragma once

#ifndef KITAQGB_WIRE3D_CGB_H
#define KITAQGB_WIRE3D_CGB_H

#define WIRE3DCGB_SCREEN_W 128
#ifndef WIRE3DCGB_HEIGHT
#define WIRE3DCGB_HEIGHT 96
#endif
#if WIRE3DCGB_HEIGHT != 88 && WIRE3DCGB_HEIGHT != 96
#error WIRE3DCGB_HEIGHT must be 88 or 96
#endif
#define WIRE3DCGB_SCREEN_H WIRE3DCGB_HEIGHT
#if WIRE3DCGB_HEIGHT == 88
#define WIRE3DCGB_TILE_ROWS 11
#define WIRE3DCGB_TILE_COUNT 176
#define WIRE3DCGB_COLUMN_BYTES 176
#define WIRE3DCGB_NEG_COLUMN_BYTES 0xFF50
#define WIRE3DCGB_STAGE_RIGHT 0xDD50
#define WIRE3DCGB_STAGE_BOTTOM 0xD3AE
#define WIRE3DCGB_SECOND_DMA 0xAF
#else
#define WIRE3DCGB_TILE_ROWS 12
#define WIRE3DCGB_TILE_COUNT 192
#define WIRE3DCGB_COLUMN_BYTES 192
#define WIRE3DCGB_NEG_COLUMN_BYTES 0xFF40
#define WIRE3DCGB_STAGE_RIGHT 0xDE40
#define WIRE3DCGB_STAGE_BOTTOM 0xD3BE
#define WIRE3DCGB_SECOND_DMA 0xBF
#endif
// Reserve 3072 bytes in either profile for full-screen compatibility.
#define WIRE3DCGB_UPLOAD_BYTES (WIRE3DCGB_TILE_COUNT * 16)
#define WIRE3DCGB_FULL_SCREEN_W 160
#define WIRE3DCGB_FULL_SCREEN_H 144
#define WIRE3DCGB_FULL_TILE_LIMIT 127
#define WIRE3DCGB_STAGE_BASE 0xD300
#define WIRE3DCGB_STAGE_WRAM_BANK 2
#define WIRE3DCGB_STAGE_BYTES 3072
#define WIRE3DCGB_MODEL_VERTEX_LIMIT 24
#define WIRE3DCGB_MODEL_FACE_LIMIT 16
#define WIRE3DCGB_MODEL_EDGE_LIMIT 64
#define WIRE3DCGB_SCENE_OBJECT_LIMIT 8
#define WIRE3DCGB_FACE_NONE 255
#define WIRE3DCGB_MODEL_HIDDEN_LINES 1
#define WIRE3DCGB_COLOR_LOW 1
#define WIRE3DCGB_COLOR_MAIN 2
#define WIRE3DCGB_COLOR_HIGH 3
#define WIRE3DCGB_COLOR_DEFAULT WIRE3DCGB_COLOR_MAIN

#define WIRE3DCGB_RGB15(r5, g5, b5) ((w3dcgb_u16)((w3dcgb_u16)((r5) & 31) | ((w3dcgb_u16)((g5) & 31) << 5) | ((w3dcgb_u16)((b5) & 31) << 10)))

typedef s8 w3dcgb_i8;
typedef s16 w3dcgb_i16;
typedef u8 w3dcgb_u8;
typedef u16 w3dcgb_u16;

typedef struct {
    w3dcgb_i16 x;
    w3dcgb_i16 y;
    w3dcgb_i16 z;
} Wire3DCGB_Vec3;

typedef struct {
    w3dcgb_u8 a;
    w3dcgb_u8 b;
} Wire3DCGB_Edge;

typedef struct {
    w3dcgb_u8 a;
    w3dcgb_u8 b;
    w3dcgb_u8 c;
} Wire3DCGB_Face;

typedef struct {
    w3dcgb_u8 f0;
    w3dcgb_u8 f1;
} Wire3DCGB_EdgeFaces;

typedef struct {
    const Wire3DCGB_Vec3* vertices;
    const Wire3DCGB_Edge* edges;
    const Wire3DCGB_Face* faces;
    const Wire3DCGB_EdgeFaces* edge_faces;
    w3dcgb_u8 vertex_count;
    w3dcgb_u8 edge_count;
    w3dcgb_u8 face_count;
    w3dcgb_u8 flags;
} Wire3DCGB_Model;

typedef struct {
    const Wire3DCGB_Model* model;
    w3dcgb_i16 x;
    w3dcgb_i16 y;
    w3dcgb_i16 z;
    w3dcgb_i8 rx;
    w3dcgb_i8 ry;
    w3dcgb_i8 rz;
    w3dcgb_i16 scale_q8;
    w3dcgb_u8 visible;
    w3dcgb_u8 color;
} Wire3DCGB_Object;

typedef struct {
    w3dcgb_i16 x;
    w3dcgb_i16 y;
    w3dcgb_i16 z;
    w3dcgb_i8 rx;
    w3dcgb_i8 ry;
    w3dcgb_i8 rz;
    w3dcgb_u8 color;
} Wire3DCGB_FastCube;

void Wire3DCGB_Init();
void Wire3DCGB_InitFullScreen();
void Wire3DCGB_InitFastMapLite();
void Wire3DCGB_EnableDoubleSpeed();
void Wire3DCGB_SetScreenOffset(w3dcgb_u8 scx, w3dcgb_u8 scy);
void Wire3DCGB_SetPaletteRGB15(w3dcgb_u16 color0, w3dcgb_u16 color1, w3dcgb_u16 color2, w3dcgb_u16 color3);
void Wire3DCGB_SetLineColor(w3dcgb_u8 color);
w3dcgb_u8 Wire3DCGB_GetLineColor();
void Wire3DCGB_ClearFrameTiles();
void Wire3DCGB_BeginFrame();
void Wire3DCGB_BeginFrameFast();
void Wire3DCGB_BeginFrameSparse();
void Wire3DCGB_ClearSparseStageFast();
void Wire3DCGB_MarkDirtyRect2D(w3dcgb_u8 min_x, w3dcgb_u8 min_y, w3dcgb_u8 max_x, w3dcgb_u8 max_y);
void Wire3DCGB_SetCamera(w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 pitch, w3dcgb_i8 yaw, w3dcgb_i8 roll);
void Wire3DCGB_DrawModel(const Wire3DCGB_Model* model, w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 rx, w3dcgb_i8 ry, w3dcgb_i8 rz);
void Wire3DCGB_DrawModelScaled(const Wire3DCGB_Model* model, w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 rx, w3dcgb_i8 ry, w3dcgb_i8 rz, w3dcgb_i16 scale_q8);
void Wire3DCGB_DrawModelColor(const Wire3DCGB_Model* model, w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 rx, w3dcgb_i8 ry, w3dcgb_i8 rz, w3dcgb_u8 color);
void Wire3DCGB_DrawModelScaledColor(const Wire3DCGB_Model* model, w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 rx, w3dcgb_i8 ry, w3dcgb_i8 rz, w3dcgb_i16 scale_q8, w3dcgb_u8 color);
void Wire3DCGB_EraseModelFaces(const Wire3DCGB_Model* model, w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_i8 rx, w3dcgb_i8 ry, w3dcgb_i8 rz, w3dcgb_i16 scale_q8);
void Wire3DCGB_EraseTriangle2D(w3dcgb_u8 ax, w3dcgb_u8 ay, w3dcgb_u8 bx, w3dcgb_u8 by, w3dcgb_u8 cx, w3dcgb_u8 cy);
void Wire3DCGB_EraseSpan2D(w3dcgb_u8 y, w3dcgb_u8 x0, w3dcgb_u8 x1);
/* Signed endpoints, clipped before conversion to the rasterizer's u8 ABI. */
void Wire3DCGB_DrawLineClipped2D(w3dcgb_i16 x0, w3dcgb_i16 y0,
                               w3dcgb_i16 x1, w3dcgb_i16 y1, w3dcgb_u8 color);
void Wire3DCGB_DrawEdgeListClipped2D(const Wire3DCGB_Edge* edges, w3dcgb_u8 edge_count,
    const w3dcgb_i16* vx, const w3dcgb_i16* vy, w3dcgb_u8 vertex_count,
    w3dcgb_i16 cx, w3dcgb_i16 cy, w3dcgb_u8 color);
w3dcgb_i16 Wire3DCGB_ProjectAxis48(w3dcgb_i16 value, w3dcgb_i16 z);
void Wire3DCGB_InvalidateFrameHistory();
/* Startup-only: reserves both BG maps; queued HUD tiles are mirrored. */
void Wire3DCGB_EnableAtomicMaps();
void Wire3DCGB_EraseRect2D(w3dcgb_u8 x0, w3dcgb_u8 y0, w3dcgb_u8 x1, w3dcgb_u8 y1);
void Wire3DCGB_EraseLeftGuard24Fast();
void Wire3DCGB_DrawWhiteBorderFast();
void Wire3DCGB_ClearOcclusionMask();
void Wire3DCGB_SetOcclusionActive(w3dcgb_u8 active);
void Wire3DCGB_MarkTriangle2D(w3dcgb_u8 ax, w3dcgb_u8 ay, w3dcgb_u8 bx, w3dcgb_u8 by, w3dcgb_u8 cx, w3dcgb_u8 cy);
void Wire3DCGB_MarkPackedSilhouette2D(const w3dcgb_u8* profile, w3dcgb_u8 count,
                                     w3dcgb_i8 y0, w3dcgb_u8 x, w3dcgb_u8 y);
void Wire3DCGB_ErasePackedSilhouette2D(const w3dcgb_u8* profile, w3dcgb_u8 count,
                                      w3dcgb_i8 y0, w3dcgb_u8 x, w3dcgb_u8 y);
void Wire3DCGB_DrawScene(Wire3DCGB_Object* objects, w3dcgb_u8 count);
void Wire3DCGB_DrawFastCubes(Wire3DCGB_FastCube* cubes, w3dcgb_u8 count, w3dcgb_u8 hidden_enabled, w3dcgb_u8 selected);
void Wire3DCGB_DrawFastStatus(w3dcgb_u8 hidden_enabled, w3dcgb_u8 selected);
void Wire3DCGB_DrawFastCubeFrame(Wire3DCGB_FastCube* cubes, w3dcgb_u8 count, w3dcgb_u8 hidden_enabled, w3dcgb_u8 selected);
void Wire3DCGB_DrawFastProjectile(w3dcgb_u8 x, w3dcgb_u8 y, w3dcgb_i16 z, w3dcgb_u8 phase, w3dcgb_u8 color);
void Wire3DCGB_FastMapBegin();
void Wire3DCGB_FastMapBeginTilesOnly();
void Wire3DCGB_FastMapCell(w3dcgb_u8 tx, w3dcgb_u8 ty, w3dcgb_u8 color, w3dcgb_u8 mask);
void Wire3DCGB_FastMapRect(w3dcgb_u8 tx0, w3dcgb_u8 ty0, w3dcgb_u8 tx1, w3dcgb_u8 ty1, w3dcgb_u8 color, w3dcgb_u8 sides);
void Wire3DCGB_FastMapFlush();
void Wire3DCGB_FastMapFlushTilesOnly();
// Project camera-space coordinates without subtracting/rotating the camera.
// Depth 8..255; outputs unchanged on rejection. Shared scratch: no ISR calls.
w3dcgb_u8 Wire3DCGB_ProjectCameraPoint(w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_u8* sx, w3dcgb_u8* sy);
w3dcgb_u8 Wire3DCGB_ProjectPoint(w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_u8* sx, w3dcgb_u8* sy);
/* Fast path for games whose camera pitch, yaw, and roll stay at zero. */
w3dcgb_u8 Wire3DCGB_ProjectPointNoRotation(w3dcgb_i16 x, w3dcgb_i16 y, w3dcgb_i16 z, w3dcgb_u8* sx, w3dcgb_u8* sy);
void Wire3DCGB_DrawLine3D(w3dcgb_i16 ax, w3dcgb_i16 ay, w3dcgb_i16 az, w3dcgb_i16 bx, w3dcgb_i16 by, w3dcgb_i16 bz);
void Wire3DCGB_DrawLine3DColor(w3dcgb_i16 ax, w3dcgb_i16 ay, w3dcgb_i16 az, w3dcgb_i16 bx, w3dcgb_i16 by, w3dcgb_i16 bz, w3dcgb_u8 color);
void Wire3DCGB_DrawPoint2D(w3dcgb_u8 x, w3dcgb_u8 y);
void Wire3DCGB_DrawTinyModel2D(w3dcgb_u8 x, w3dcgb_u8 y,
                               w3dcgb_u8 turn, w3dcgb_u8 color);
void Wire3DCGB_DrawLine2D(w3dcgb_u8 ax, w3dcgb_u8 ay, w3dcgb_u8 bx, w3dcgb_u8 by);
void Wire3DCGB_DrawLine2DColor(w3dcgb_u8 ax, w3dcgb_u8 ay, w3dcgb_u8 bx, w3dcgb_u8 by, w3dcgb_u8 color);
void Wire3DCGB_DrawMaskedModel2D(const Wire3DCGB_Model* model,
                                 const w3dcgb_i8* vertex_x, const w3dcgb_i8* vertex_y,
                                 const w3dcgb_u8* edge_mask,
                                 w3dcgb_u8 x, w3dcgb_u8 y, w3dcgb_u8 color);
void Wire3DCGB_DrawEdgeList2D(const Wire3DCGB_Edge* edges, w3dcgb_u8 edge_count,
                              const w3dcgb_i8* vertex_x, const w3dcgb_i8* vertex_y,
                              w3dcgb_u8 x, w3dcgb_u8 y, w3dcgb_u8 color);
void Wire3DCGB_DrawLineList2DColor(const w3dcgb_u8* line_xy,
                                  w3dcgb_u8 line_count, w3dcgb_u8 color);
void Wire3DCGB_PutBgTile(w3dcgb_u8 x, w3dcgb_u8 y, w3dcgb_u8 tile);
void Wire3DCGB_EndFrame();
void Wire3DCGB_EndFrameFast();
void Wire3DCGB_EndFrameSparse();
void Wire3DCGB_EndFrameSparseNow();
w3dcgb_u8 Wire3DCGB_GetFullScreenTileCount();
w3dcgb_u8 Wire3DCGB_GetFullScreenOverflow();

#endif

kitaqgb/lib/wire3d_cgb.h

wire3d_dmg.h — Gráficos de alambre para DMG
c
#pragma once

// Select the viewport at build time before including this header or source.
// Default: 128x120 with consuming uploads and optional dirty/auxiliary transfer.
// Heights 88 and 96 retain the HUD and yaw-mask profile with BeginFrame clearing.
#ifndef WIRE3D_DMG_HEIGHT
#define WIRE3D_DMG_HEIGHT 120
#endif
#if WIRE3D_DMG_HEIGHT != 88 && WIRE3D_DMG_HEIGHT != 96 && WIRE3D_DMG_HEIGHT != 120
#error WIRE3D_DMG_HEIGHT must be 88, 96 or 120
#endif


#ifndef KITAQGB_WIRE3D_DMG_H
#define KITAQGB_WIRE3D_DMG_H

#if WIRE3D_DMG_HEIGHT != 120
// Monochrome 128x88/96 wireframe renderer with global, non-reentrant state.
// It takes over LCD tile data/map and reserves WRAM 0xD000..0xDFFF for staging.
// Angles wrap every 16 steps; scale 256 is unity. Scene occlusion is a coarse
// face-bounding-box/five-line-sample heuristic, not per-pixel depth testing.
#else
// Monochrome 128x120 staged renderer with global non-reentrant state.
// Reserve WRAM 0xD000..0xDFFF and the renderer's tile/map VRAM regions.
// BeginFrame does not clear pixels: uploads consume the stage. Auxiliary source
// strips alias the main stage, and dirty transfer relies on current/previous flags.
#endif
#define WIRE3D_DMG_SCREEN_W 128
#if WIRE3D_DMG_HEIGHT != 120
#define WIRE3D_DMG_SCREEN_H WIRE3D_DMG_HEIGHT
#else
#define WIRE3D_DMG_SCREEN_H 120
#endif
#define WIRE3D_DMG_MODEL_VERTEX_LIMIT 24
#if WIRE3D_DMG_HEIGHT != 120
#define WIRE3D_DMG_MODEL_EDGE_LIMIT 16
#endif
#define WIRE3D_DMG_MODEL_FACE_LIMIT 16
#define WIRE3D_DMG_SCENE_OBJECT_LIMIT 8
#define WIRE3D_DMG_FACE_NONE 255
#define WIRE3D_DMG_MODEL_HIDDEN_LINES 1
#if WIRE3D_DMG_HEIGHT != 120
#define WIRE3D_DMG_EDGE_MASK_BINS_16 16
#else
#define WIRE3D_DMG_ANGLE_STEPS 16
#endif

typedef s8 w3ddmg_i8;
typedef s16 w3ddmg_i16;
typedef u8 w3ddmg_u8;
typedef u16 w3ddmg_u16;

typedef struct {
    w3ddmg_i16 x;
    w3ddmg_i16 y;
    w3ddmg_i16 z;
} Wire3DDMG_Vec3;

typedef struct {
    w3ddmg_u8 a;
    w3ddmg_u8 b;
} Wire3DDMG_Edge;

typedef struct {
    w3ddmg_u8 a;
    w3ddmg_u8 b;
    w3ddmg_u8 c;
} Wire3DDMG_Face;

typedef struct {
    w3ddmg_u8 f0;
    w3ddmg_u8 f1;
} Wire3DDMG_EdgeFaces;

#if WIRE3D_DMG_HEIGHT != 120
// Model tables are borrowed for drawing, never copied or bank-switched.
// Counts are capped at 24 vertices, 16 edges and 16 faces; each supplied table
// must contain the referenced entries. Triangle winding with positive projected
// area is front-facing. FACE_NONE denotes a missing adjacent face.
#else
// Model tables are borrowed and must remain readable in the active bank.
// At most 24 vertices and 16 faces are processed; the model edge count is not
// limited to 16. Supply all declared edge and adjacency entries. Positive
// projected triangle area is front-facing; FACE_NONE means missing adjacency.
#endif
typedef struct {
    const Wire3DDMG_Vec3* vertices;
    const Wire3DDMG_Edge* edges;
    const Wire3DDMG_Face* faces;
    const Wire3DDMG_EdgeFaces* edge_faces;
#if WIRE3D_DMG_HEIGHT != 120
    /* Keep edge mask tables in RAM for pointer-indirect access on current KITAQGB. */
    const w3ddmg_u16* edge_masks;
#endif
    w3ddmg_u8 vertex_count;
    w3ddmg_u8 edge_count;
    w3ddmg_u8 face_count;
#if WIRE3D_DMG_HEIGHT != 120
    w3ddmg_u8 edge_mask_count;
#endif
    w3ddmg_u8 flags;
} Wire3DDMG_Model;

typedef struct {
    const Wire3DDMG_Model* model;
    w3ddmg_i16 x;
    w3ddmg_i16 y;
    w3ddmg_i16 z;
#if WIRE3D_DMG_HEIGHT != 120
    w3ddmg_i8 rx;
    w3ddmg_i8 ry;
    w3ddmg_i8 rz;
#else
    w3ddmg_u8 rx;
    w3ddmg_u8 ry;
    w3ddmg_u8 rz;
#endif
    w3ddmg_i16 scale_q8;
    w3ddmg_u8 visible;
} Wire3DDMG_Object;

#if WIRE3D_DMG_HEIGHT != 120
// Take over the LCD: wait for VBlank, switch it off, clear 6144 tile bytes and
// the BG map, install HUD tiles and the 128x96 signed-tile viewport, then enable
// BG display with scroll zero and BGP=0xB4. Reset camera, BG queue and stage.
// Reserve 0xD000..0xDFFF for staging and retain its WRAM bank mapping.
// Call BeginFrame before drawing to initialize the occlusion state as well.
#else
// Take over LCD state, clear tile VRAM and the BG map, and install a 16x15
// viewport beginning at map tile (3,1). Set scroll (8,0), BGP=0xB4 and BG display.
// Reset camera, queues, transfer modes, both dirty tables and stage. Reserve
// 0xD000..0xDFFF and retain its WRAM mapping; auxiliary storage aliases it.
// Call BeginFrame before drawing to establish occlusion state.
#endif
void Wire3DDMG_Init();
#if WIRE3D_DMG_HEIGHT != 120
// Clear staged pixels and occlusion mask and disable occlusion filtering.
// This leaves the displayed VRAM frame and pending BG tile queue unchanged.
#else
// Disable occlusion filtering only. Stage clearing normally happens during
// transfer, and Init supplies the first clean stage. This does not discard an
// unsubmitted frame, clear the mask, or reset pending BG writes/dirty flags.
#endif
void Wire3DDMG_BeginFrame();
/* Validate depth and project coordinates already in camera space. */
w3ddmg_u8 Wire3DDMG_ProjectCameraPoint(w3ddmg_i16 x,w3ddmg_i16 y,w3ddmg_i16 z,w3ddmg_u8* sx,w3ddmg_u8* sy);
// Store camera position and angles for later draws; a full turn is 16 angle
// steps. No existing drawing is reprojected and no input range validation occurs.
#if WIRE3D_DMG_HEIGHT != 120
void Wire3DDMG_SetCamera(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 pitch, w3ddmg_i8 yaw, w3ddmg_i8 roll);
#else
void Wire3DDMG_SetCamera(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 pitch, w3ddmg_u8 yaw, w3ddmg_u8 roll);
#endif
// Draw an unscaled model by delegating to DrawModelScaled with scale 256.
#if WIRE3D_DMG_HEIGHT != 120
void Wire3DDMG_DrawModel(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz);
// Scale, rotate in Y/X/Z order, translate and project at most 24 vertices;
// then draw up to 16 edges filtered by yaw masks and optional front-facing faces.
// Nonpositive scale becomes unity (256). Null model/vertex/edge pointers are
// ignored; referenced tables must remain readable. Keep scale products and
// translations in signed 16-bit range. Depth-crossing edges are dropped, not clipped.
void Wire3DDMG_DrawModelScaled(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz, w3ddmg_i16 scale_q8);
#else
void Wire3DDMG_DrawModel(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz);
// Scale up to 24 vertices, rotate Y/X/Z, translate and project, then traverse
// all edge_count entries (a byte count) with optional adjacent-face filtering.
// Face scratch is capped at 16; edge tables must contain all declared entries.
// Nonpositive scale means 256. Null model/vertex/edge pointers are ignored.
// Keep products/translations in signed 16-bit range; depth-crossing edges are dropped.
void Wire3DDMG_DrawModelScaled(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz, w3ddmg_i16 scale_q8);
#endif
// Project up to 24 vertices and erase front-facing triangle interiors from
// the stage for a model with hidden-line flags and face data. Nonpositive scale
// means 256 (unity). Up to 16 faces are considered; depth-crossing faces are
// skipped. This also replaces shared projection caches, but does not update VRAM.
#if WIRE3D_DMG_HEIGHT != 120
void Wire3DDMG_EraseModelFaces(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz, w3ddmg_i16 scale_q8);
#else
void Wire3DDMG_EraseModelFaces(const Wire3DDMG_Model* model, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz, w3ddmg_i16 scale_q8);
#endif
// Erase a triangle from staged pixels using integer scanline intersections.
// Supply viewport coordinates. Degenerate triangles are ignored; the occlusion
// mask and VRAM are unchanged.
void Wire3DDMG_EraseTriangle2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by, w3ddmg_u8 cx, w3ddmg_u8 cy);
// Order the X endpoints and erase the inclusive staged span. Both endpoints
// must be in 0..127; invalid Y is ignored. The routine does not clip X for you.
void Wire3DDMG_EraseSpan2D(w3ddmg_u8 y, w3ddmg_u8 x0, w3ddmg_u8 x1);
#if WIRE3D_DMG_HEIGHT != 120
// Process at most the first eight objects, sorted near to far by transformed
// origin depth. Draw visible valid models, then mark their front-face bounding
// rectangles to reject fully sampled later lines. This approximates inter-object
// occlusion, not a depth buffer. It clears its mask but retains existing staged
// pixels. Null arrays are ignored; objects and their data must remain readable.
#else
// Sort at most eight object origins by camera depth, near to far. Draw visible
// valid models and mark front-face bounding rectangles for later objects. The
// first sorted slot bypasses mask tests and the last needs no new occluder.
// This is coarse line rejection, not a depth buffer. Null/empty input is ignored;
// caller data and the current projection cache must remain valid during traversal.
#endif
void Wire3DDMG_DrawScene(Wire3DDMG_Object* objects, w3ddmg_u8 count);
#if WIRE3D_DMG_HEIGHT != 120
// Select a precomputed mask from the low four bits of object yaw; pitch,
// roll and camera orientation are ignored. Use 16, 8, 4 or 2 bins; other positive
// counts select entry zero (counts >=16 use the first 16). Missing data returns
// 0xFFFF. Keep the mask table readable through the current data-pointer mapping.
w3ddmg_u16 Wire3DDMG_SelectEdgeMask(const Wire3DDMG_Model* model, w3ddmg_i8 rx, w3ddmg_i8 ry, w3ddmg_i8 rz);
// Project a world point with the current camera. Return zero for rejected
// depth, leaving outputs unchanged; success writes clamped coordinates for the selected height.
// Output pointers must be valid. Screen clamping is not geometric clipping.
#else
// Project a world point with the current camera. Return zero for invalid
// depth without changing outputs; success writes clamped 128x120 coordinates.
// Both output pointers must be valid. Coordinate differences must fit s16.
#endif
w3ddmg_u8 Wire3DDMG_ProjectPoint(w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8* sx, w3ddmg_u8* sy);
#if WIRE3D_DMG_HEIGHT == 120
// Rotate in place in Y/X/Z order using 16 steps per full turn. A null
// component pointer makes the whole call a no-op; use distinct pointers.
// Each axis rotation clamps its inputs to +/-220.
void Wire3DDMG_RotatePoint(w3ddmg_i16* x, w3ddmg_i16* y, w3ddmg_i16* z, w3ddmg_u8 rx, w3ddmg_u8 ry, w3ddmg_u8 rz);
#endif
// Project both world endpoints and draw only when both pass the depth range.
// Do not intersect a crossing segment with near/far planes; projected endpoints
// are independently clamped to the screen edges.
void Wire3DDMG_DrawLine3D(w3ddmg_i16 ax, w3ddmg_i16 ay, w3ddmg_i16 az, w3ddmg_i16 bx, w3ddmg_i16 by, w3ddmg_i16 bz);
#if WIRE3D_DMG_HEIGHT != 120
// Draw a connected line into the 128x96 stage, including endpoints. During
// DrawScene, use the coarse five-sample occlusion rejection; otherwise draw directly.
// Supply viewport coordinates. VRAM is updated only by EndFrame.
#else
// Mark the bounding tile rectangle when dirty transfer is enabled, then draw
// a connected staged line. Scene drawing may reject it using five mask samples.
// Supply 128x120 viewport endpoints; low-level pixel bounds checks do not clip
// the segment geometrically.
#endif
void Wire3DDMG_DrawLine2D(w3ddmg_u8 ax, w3ddmg_u8 ay, w3ddmg_u8 bx, w3ddmg_u8 by);
#if WIRE3D_DMG_HEIGHT == 120
// Draw a wireframe rectangle directly into the staged bitplane. Endpoints are
// inclusive screen pixels in 0..127 x 0..119; both horizontal and vertical
// edges are written with byte masks and only touched tiles are uploaded.
void Wire3DDMG_DrawRect2D(w3ddmg_u8 x0, w3ddmg_u8 y0, w3ddmg_u8 x1, w3ddmg_u8 y1);
#endif
// Draw the canonical 12 edges of an 8-vertex projected box in one call.
// Vertex order is near-face corners 0..3, then far-face corners 4..7.
void Wire3DDMG_DrawBoxEdges2D(const w3ddmg_u8* sx, const w3ddmg_u8* sy);
#if WIRE3D_DMG_HEIGHT == 120
// Draw byte-pair edge indices after integer scaling and translation; scale
// zero means one, and there is no object rotation or face filtering. Project at
// most 24 vertices. Supply at most 128 edge pairs because byte offsets wrap
// after 255. Invalid vertex IDs/depth-rejected endpoints are skipped; null arrays
// are ignored. Keep coordinate products/sums representable as s16.
void Wire3DDMG_DrawIndexedEdges(const Wire3DDMG_Vec3* vertices, w3ddmg_u8 vertex_count, const w3ddmg_u8* edges, w3ddmg_u8 edge_count, w3ddmg_i16 x, w3ddmg_i16 y, w3ddmg_i16 z, w3ddmg_u8 scale);
#endif
// Queue a tile write to the 32x32 map at 0x9800 for EndFrame. Invalid map
// coordinates and submissions beyond 48 pending writes are silently ignored.
// This queue is separate from the general vram library queue.
void Wire3DDMG_PutBgTile(w3ddmg_u8 x, w3ddmg_u8 y, w3ddmg_u8 tile);
// Write the raw DMG BGP palette encoding immediately; no frame synchronization occurs.
void Wire3DDMG_SetPalette(w3ddmg_u8 bgp);
#if WIRE3D_DMG_HEIGHT != 120
// Wait for the next VBlank, flush pending BG map writes, then copy the stage
// to VRAM while polling access windows. Copying consumes the staged pixels.
// The transfer may extend beyond VBlank; this is not an atomic frame swap.
#else
// Store the EndFrame auxiliary-transfer gate; any nonzero value enables it.
// No data is copied or cleared here. Auxiliary source bytes alias the main stage.
void Wire3DDMG_SetAuxTransfer(w3ddmg_u8 flag);
// Store the dirty-transfer gate and clear both dirty histories and the main
// stage, even if the value is unchanged. VRAM is retained; enabling this over an
// old image can leave unmarked old tiles, so arrange a clean displayed baseline.
void Wire3DDMG_SetDirtyTransfer(w3ddmg_u8 flag);
// Upload and consume the full main stage immediately, polling STAT but not
// waiting for the next VBlank. Ignore transfer gates and leave dirty histories
// and BG tile queue unchanged; the caller coordinates the frame lifecycle.
void Wire3DDMG_TransferMainNow();
// Upload and consume auxiliary source strips immediately, independent of the
// auxiliary gate. No VBlank-start wait or dirty-history/BG-queue update occurs.
// The source overlaps the main stage and must be coordinated with its upload.
void Wire3DDMG_TransferAuxNow();
// Wait for the next VBlank and flush BG writes, then optionally consume the
// auxiliary strips before uploading either dirty tiles or the entire main stage.
// Auxiliary/main source overlap makes that ordering significant. STAT polling
// continues across access windows; the update need not fit one VBlank.
#endif
void Wire3DDMG_EndFrame();
// Same queue/gate/history lifecycle, without the initial fresh-VBlank wait.
// Synchronous STAT-safe upload; not an atomic swap. LCD must remain enabled.
void Wire3DDMG_EndFrameNow();

#endif
#if WIRE3D_DMG_HEIGHT == 120

#endif

kitaqgb/lib/wire3d_dmg.h

zx0.h —
c
#pragma once
// Copyright (c) 2026 DAISUKE OBA. MIT License.
// ZX0-compatible forward v2 streams; format designed by Einar Saukas.
#define ZX0_OK 0
#define ZX0_BAD_ARGUMENT 1
#define ZX0_TRUNCATED 2
#define ZX0_BAD_STREAM 3
#define ZX0_OUTPUT_FULL 4
#define ZX0_DISPLAY_ACTIVE 5
// Shared last-call status. These foreground routines are not reentrant.
extern u8 zx0_error;
// Return decoded bytes, or zero on error (possibly after partial writes).
// Source and output must not overlap or cross their current CPU bank windows.
// Capacity and packed_size are byte counts. No prefix/backward/v1 streams.
u16 zx0_decompress(void* dst, u16 capacity, const void* src, u16 packed_size);
// Decode a KQA1 raw/RLE/ZX0 asset produced with --format=auto.
// Empty raw assets return zero with zx0_error==ZX0_OK.
u16 asset_decompress(void* dst, u16 capacity, const void* src, u16 packed_size);
// Decode directly into the selected GB VRAM bank ($8000..$9FFF), with LCD off.
// Preserve LCDC, VBK and interrupt state. Output must fit before $A000.
u16 zx0_decompress_vram(u16 vram_addr, const void* src, u16 packed_size);

kitaqgb/lib/zx0.h