# Arquitectura de **Aventures en Egipte (AEE)** > Guía de orientación para un desarrollador nuevo en el proyecto. > > Cada afirmación está anclada a código real: se cita el fichero (y, cuando > ayuda, la función o el número de línea) que la respalda. Donde no he > encontrado algo, lo digo explícitamente en lugar de inventarlo. > > **Aventures en Egipte** es un juego de aventura/plataformas retro (el > protagonista "Sam" explora pirámides esquivando momias y recogiendo > tesoros), escrito en C++ + SDL3. Resolución de juego **320×200**. El rasgo > que más condiciona el código es que está **en plena migración** desde un > motor legacy propio ("Jail") hacia C++ moderno (ver > [§3](#3-el-motor-legacy-jail)). Los comentarios del código están en > valenciano/español; este documento está en castellano. > > Existe además un `docs/scenes-migration-plan.md` (histórico) sobre la > migración del sistema de escenas; aquí se documenta el **estado actual** del > código, no el plan. --- ## Índice 1. [Visión general](#1-visión-general) 2. [Punto de entrada y bucle principal](#2-punto-de-entrada-y-bucle-principal) 3. [El motor legacy "Jail"](#3-el-motor-legacy-jail) 4. [Escenas y máquina de estados](#4-escenas-y-máquina-de-estados) 5. [Renderizado: de la lógica al píxel](#5-renderizado-de-la-lógica-al-píxel) 6. [Entrada](#6-entrada) 7. [Gameplay: `ModuleGame` y entidades](#7-gameplay-modulegame-y-entidades) 8. [Sistema de escenas cinemáticas](#8-sistema-de-escenas-cinemáticas) 9. [Recursos](#9-recursos) 10. [Audio y localización](#10-audio-y-localización) 11. [Configuración y persistencia](#11-configuración-y-persistencia) 12. [Modo demo / IA](#12-modo-demo--ia) 13. [Convenciones y patrones recurrentes](#13-convenciones-y-patrones-recurrentes) 14. [Guía de navegación: "si quieres tocar X, mira Y"](#14-guía-de-navegación-si-quieres-tocar-x-mira-y) --- ## 1. Visión general El árbol `source/` separa **motor** y **juego**, pero con una particularidad: el motor tiene **dos generaciones** conviviendo (legacy "Jail" + capas nuevas). - **`source/core/jail/`** — el **motor legacy "Jail"** (APIs C planas): `Jg` (jgame), `Jd8` (jdraw8), `Ji` (jinput), `Jf` (jfile). En modernización (§3). - **`source/core/`** (resto) — capas **nuevas**: `rendering` (`Screen`, `Overlay`, `Text`, `Menu`, `sdl3gpu`), `input`, `system` (`Director`), `resources`, `audio`, `locale`. - **`source/game/`** — el juego: gameplay legacy en la raíz (`modulegame`, `prota`, `momia`, `engendro`, `bola`, `mapa`, `marcador`, `info`, `sprite`) y el sistema de **escenas** nuevo en `scenes/`. - **`source/utils/`** — `easing`, `utils`. - **`source/external/`** — vendorizado (stb, fkyaml). ~117 ficheros C++, ~40.000 líneas. **El `CLAUDE.md` define una frontera explícita "Original vs New Code"** (§79): `core/jail/` y `game/*.cpp` son *legacy en modernización* (modificar con cuidado, preservando comportamiento); `core/rendering`, `core/input`, `utils/`, `options/defines/defaults` son *código nuevo*. Interiorizar esa frontera es lo primero para no romper invariantes del juego original. **Ideas-fuerza:** 1. Un solo hilo, **tick-based**, vía callbacks de SDL3 (§2). 2. El render es **software paletizado 8-bit** (`Jd8`, 320×200) que al final se convierte a ARGB y pasa por shaders GPU (§5). 3. El flujo de pantallas es una **máquina de estados** apoyada en `Info::ctx.num_piramide`, con un `SceneRegistry` que va sustituyendo cinemáticas legacy por escenas nuevas (§4). ```mermaid graph TD SDL[SDL3 callbacks · main.cpp] --> DIR[Director] DIR -->|game_state_ + Info::ctx| DISP{createNextScene} DISP -->|==0| MG["ModuleGame (gameplay)"] DISP -->|==1| REG["SceneRegistry::tryCreate(num_piramide)"] REG --> CINE["intro / banner / slides / mort / secreta / credits…"] MG --> MAPA[Mapa] & PROTA[Prota] & MOMIA[Momia] & BOLA[Bola] & MARC[Marcador] DIR --> INP["KeyConfig / GlobalInputs / Gamepad / KeyRemap / Mouse"] MG -->|dibuja índices| JD8["Jd8 (8-bit 320×200)"] CINE --> JD8 JD8 -->|JD8_Flip → ARGB| SCREEN[Screen] OVL[Overlay] --> SCREEN SCREEN --> GPU["sdl3gpu PostFX / CrtPi / upscale"] --> WIN[Ventana] RES["Resource::Cache / List"] -.-> MG & CINE ``` --- ## 2. Punto de entrada y bucle principal ### 2.1. SDL conduce el bucle (callbacks) `source/main.cpp` define `SDL_MAIN_USE_CALLBACKS`. No hay `while` propio (clave para el port a Emscripten). `SDL_AppInit` monta todo y `SDL_AppIterate` llama a `Director::iterate()`. El arranque en `SDL_AppInit` inicializa, en orden: carpeta de config (`Jf`), sistema de recursos (`resources.pack` + fallback en Debug/WASM), `Options`, `KeyConfig`, `Locale`, presets de shaders, y luego el **motor**: `Jg::init`, `Screen::init`, `Jd8::init`, `Audio::init`, `Overlay::init`, `Menu::init`, `Resource::List`/`Cache` (con `beginLoad()`), y `Director::init` + `setup()`. ### 2.2. El `Director` `source/core/system/director.{hpp,cpp}`. Es el **orquestador singleton, único hilo del runtime** (sin fibers, mutex ni condition variables; el comentario de `director.hpp:11` lo subraya). Posee el estado de escena como miembros: `current_scene_` (`std::unique_ptr`), `game_state_`, `last_tick_ms_`, y dos buffers de frame `[320*200]` (`game_frame_`, `presentation_buffer_`). Cada `iterate()` (modelo documentado en `CLAUDE.md:161`): ``` Gamepad/KeyRemap/GlobalInputs/Mouse::update JA_Update() ← bombeo de audio if (!paused_) { if (scene && (scene->done() || JG_Quitting())) game_state_ = scene->nextState(); scene.reset(); if (!scene) scene = createNextScene(); scene->onEnter(); ← ModuleGame o SceneRegistry JI_Update() scene->tick(now - last_tick_ms_) JD8_Flip() ← índices → ARGB memcpy → game_frame } memcpy game_frame → presentation_buffer Overlay::render(presentation_buffer) Screen::present(presentation_buffer) SDL_Delay(frame_target - elapsed) ← cap de FPS ``` ### 2.3. Tiempo, pausa y salida Las escenas reciben `delta_ms` real (time-based). El gameplay (`ModuleGame`) gatea su `Update()` a 10 ms fijos vía `Jg::shouldUpdate()` (ticker del motor legacy, ya sin *yield*). La **pausa** (F11) simplemente salta el bloque de `tick()`: el overlay y el present siguen, re-presentando el último frame congelado. La **salida** se solicita con `requestQuit()` (doble ESC o `SDL_QUIT`) y `requestRestart()` hace un reinicio suave (para audio, resetea `Info::ctx`, vuelve a la intro). --- ## 3. El motor legacy "Jail" `source/core/jail/` es el sustrato heredado, **APIs C planas con prefijo por subsistema** (sin clases), que se está convirtiendo progresivamente a C++ idiomático manteniendo los nombres externos estables para no romper los *call sites* (`CLAUDE.md:92`). Es el rasgo más distintivo del proyecto. | Subsistema | Fichero | Qué hace | |---|---|---| | **`Jg`** (jgame) | `jail/jgame.*` | *Timing*: init/finalize, fixed-timestep (`Jg::shouldUpdate()` a 10 ms), flag de salida (`JG_Quitting`). | | **`Jd8`** (jdraw8) | `jail/jdraw8.*` | **Renderer software 8-bit paletizado**, buffer de pantalla 320×200 (`Jd8::Surface = Uint8*`), blits con *color key*, fades no bloqueantes (máquina de estados), `flip()` (paleta→ARGB) → `Screen::present`. | | **`Ji`** (jinput) | `jail/jinput.*` | Sondeo de teclado, *debounce*, códigos *cheat*. Filtra las teclas de GUI del juego y llama a `GlobalInputs`/`Mouse` cada update. | | **`Jf`** (jfile) | `jail/jfile.*` | I/O de ficheros: carpeta `data/` o pack; carpeta de config en `~/.config/jailgames/aee/`. | ### `Jd8` en detalle (el corazón del render) `jail/jdraw8.hpp`. API representativa: - `using Surface = Uint8*` (búfer de índices de paleta), `using Palette = Color*`. - `loadSurface`/`newSurface`/`freeSurface`, `loadPalette`/`setScreenPalette`. - Blits: `blit`, `blitCK` (con *color key*/transparencia), `blitCKCut`, `blitCKScroll`, `blitToSurface`/`blitCKToSurface` (blit entre surfaces). - `fillRect`/`fillSquare`/`putPixel`/`getPixel`. - **Fade no bloqueante** (`fadeStart*` + `fadeTickStep` que devuelve `true` al acabar): sustituye los `JD8_FadeOut` bloqueantes del código original. - `flip()` convierte el buffer indexado + paleta a ARGB y delega en `Screen::present`; `getFramebuffer()` devuelve el `Uint32*` resultante. > Mentalidad clave: **todo el dibujo del juego ocurre sobre índices de 8 bits** > en un buffer 320×200; el color real y los shaders entran solo al final. --- ## 4. Escenas y máquina de estados ### 4.1. La base `Scene` `source/game/scenes/scene.hpp` (`namespace Scenes`): ```cpp class Scene { public: virtual void onEnter() {} // una vez, antes del primer tick virtual void tick(int delta_ms) = 0; // no bloquea, NO llama a Jd8::flip virtual auto done() const -> bool = 0; virtual auto nextState() const -> int { return 1; } // 1=siguiente, 0=gameplay, -1=salir }; ``` El `Director` hace avanzar la escena hasta que `done()` es cierto, consulta `nextState()` y construye la siguiente. ### 4.2. El despachador: `game_state_` + `Info::ctx` `Director::createNextScene()` decide la siguiente escena: - `game_state_ == 0` → `new ModuleGame` (gameplay puro, §7). - `game_state_ == 1` → `SceneRegistry::tryCreate(Info::ctx.num_piramide)` (`game/scenes/scene_registry.hpp`): un mapa `int → factory` que devuelve la escena registrada para ese estado, o `nullptr` para caer al **path legacy**. Replica el viejo `ModuleSequence::Go`, incluido el *redirect* heredado `num_piramide == 6 && diners < 200 → 7` (`CLAUDE.md:104`). - `game_state_ == -1` → salir. ### 4.3. `Info::ctx`: el estado del juego `source/game/info.hpp` — `Info::GameContext ctx` (singleton inline) es la fuente de verdad del estado: ```cpp struct GameContext { int num_piramide, num_habitacio, diners, diamants, vida, momies, engendros; bool nou_personatge, pepe_activat; void reset(); }; ``` `num_piramide` es la pieza central: hace de **selector tanto de cinemáticas como de nivel jugable**. El `SceneRegistry` va migrando cada estado de cinemática a una `Scene` nueva; lo que no esté registrado cae a legacy. Por eso el registro "crece" a medida que avanza la modernización. ```mermaid graph LR SC[Scene activa] -->|done()| NS{nextState} NS -->|0| MG[ModuleGame] NS -->|1| REG["SceneRegistry(num_piramide)"] NS -->|-1| QUIT[salir] MG -->|muta Info::ctx| REG REG --> SC ``` --- ## 5. Renderizado: de la lógica al píxel El pipeline tiene dos mitades: **software paletizado** (`Jd8`) y **GPU** (`Screen` + shaders). ### 5.1. Software: dibujar índices Escenas y `ModuleGame` dibujan sobre el buffer `screen` de `Jd8` (índices 8-bit, 320×200) con blits y *color key*. `JD8_Flip()` aplica la paleta y produce un buffer ARGB (formato **ABGR8888**: `0xFF000000 + R + (G<<8) + (B<<16)`; `CLAUDE.md:220`). ### 5.2. `Overlay`: sobre el buffer ARGB `source/core/rendering/overlay.*` pinta **directamente sobre el buffer ARGB** antes de presentar: notificaciones (slide-in), info de render animada (4 segmentos), indicador de **PAUSA** y la lógica de **doble-ESC para salir**. ### 5.3. `Screen`: a la ventana (GPU o fallback) `source/core/rendering/screen.*` (singleton). Doble camino (`Screen::present`, `CLAUDE.md:204`): - **GPU con shaders** (primario, `sdl3gpu/`): sube los píxeles a una textura de escena 320×200; opcionalmente *upscale*/**supersampling** (3×/6×/9× con *downscale* Lanczos) y **estiramiento 4:3** fusionado en el *upscale*; luego el shader **PostFX** o **CRT-Pi** (con presets) a la *swapchain* con *letterboxing*. - **GPU sin shaders**: subida limpia a la *swapchain*. - **Fallback**: `SDL_UpdateTexture` + `SDL_RenderPresent` (`SDL_Renderer`). `Screen` gestiona ventana, fullscreen, zoom, 4:3, *integer scaling*, VSync, FPS. Apoyos de UI: `Text` (fuentes bitmap `.fnt`+`.gif` sobre el buffer ARGB, con *clipping* 2D) y `Menu` (menú flotante de opciones con navegación por páginas, animaciones y captura de teclas para *remapping*). --- ## 6. Entrada Toda la entrada de UI/sistema converge en **`KeyConfig`** como fuente única de verdad de las teclas (`source/core/input/key_config.*`): carga `data/input/keys.yaml` (F1–F10 GlobalInputs + F11 pausa + F12 menú) y aplica *overrides* del usuario; expone `scancode("id")`, `isGuiKey(sc)` (para que el `Director` no propague teclas de UI al juego), y persiste solo lo que difiere del default. - **`GlobalInputs`** (`global_inputs.*`) — mapea las F-keys a acciones de presentación (zoom, fullscreen, shaders, 4:3, supersampling, filtro, render info, pausa, menú). Tabla completa en `CLAUDE.md:139`. - **`Gamepad`** (`gamepad.*`) — primer mando con *hot-plug* y notificación; D-pad/stick → flechas virtuales; botones frontales → Enter sintético; SELECT → menú, START → pausa. Carga `gamecontrollerdb.txt`. - **`KeyRemap`** (`key_remap.*`) — cada frame copia `Options::keys_game.*` al estado virtual de scancodes estándar (UP/DOWN/LEFT/RIGHT). Permite remapear el movimiento **sin tocar el código legacy** de `prota.cpp`/`mapa.cpp`. - **`Mouse`** (`mouse.*`) — auto-oculta el cursor tras 3 s de inactividad. > Reparto deliberado: las teclas de **UI/sistema** viven en `KeyConfig` > (`keys.yaml`); las de **movimiento del jugador** en `Options::keys_game` > (`config.yaml`, sección `controls:`). --- ## 7. Gameplay: `ModuleGame` y entidades `source/game/modulegame.{hpp,cpp}` es la **escena de gameplay puro** (`game_state_ == 0`). Hereda de `Scenes::Scene` y sustituye el viejo `Go()` bloqueante por un `tick()`. Tres fases internas (`Phase`): `FADING_IN → PLAYING → FADING_OUT → DONE` (`modulegame.hpp:46`), con un `PaletteFade` para los fundidos no bloqueantes. Coordina las entidades del nivel, todas con una `Jd8::Surface gfx_` compartida: - **`Mapa`** (`game/mapa.*`) — la sala/pirámide: tiles con contenido (`CONTE_RES`/`CONTE_TRESOR`/`CONTE_FARAO`…), colisión y dibujo del escenario. - **`Prota`** (`game/prota.*`) — el protagonista "Sam" (hereda de `Sprite`), movimiento y colisión. - **`Momia`** (`game/momia.*`) — enemigo que persigue al `Prota` (recibe `Prota*`); variante `dimoni` (demonio). - **`Bola`** (`game/bola.*`) — bola/roca que interactúa con el `Prota`. - **`Engendro`** (`game/engendro.*`) — entidad generada (su `update()` devuelve `bool`); `Info::ctx.engendros` lleva la cuenta. - **`Marcador`** (`game/marcador.*`) — el marcador (vidas, dinero, diamantes), lee del `Prota`/`Info::ctx`. `ModuleGame::tick()` hace `draw()` (a `screen`, sin `flip` — lo hace el `Director`) y `update()` (gateado por `Jg::shouldUpdate`). Cuando la partida acaba (`final_ != 0`: muerte o cambio de sala), `applyFinalTransitions()` muta `Info::ctx` y `nextState()` devuelve el estado siguiente. Todas las entidades de gameplay derivan de **`Sprite`** (`game/sprite.*`), clase base con `draw()`/`update()` sobre `Jd8`. --- ## 8. Sistema de escenas cinemáticas Las pantallas no jugables (`game_state_ == 1`) son `Scene`s registradas en el `SceneRegistry`. Las concretas viven en `source/game/scenes/`: `boot_loader` (carga incremental, §9), `banner`, `intro`, `intro_new_logo`, `intro_sprites`, `slides`, `menu` (`menu_scene`), `mort` (secuencia de muerte), `secreta` (pantalla secreta) y `credits`. Sobre ellas hay un **conjunto de utilidades de animación** reutilizables —el andamiaje "cinematográfico" del juego—: - **`Timeline`** (`scenes/timeline.*`) — secuenciación temporal de eventos. - **`FrameAnimator`** (`scenes/frame_animator.*`) — animación por fotogramas. - **`SpriteMover`** (`scenes/sprite_mover.*`) — movimiento interpolado de sprites (con `easing`). - **`PaletteFade`** (`scenes/palette_fade.*`) — fundidos por paleta no bloqueantes (también usado por `ModuleGame`). - **`SurfaceHandle`** (`scenes/surface_handle.*`) — propiedad RAII de una `Jd8::Surface` (las escenas poseen sus assets y los liberan en el destructor). - **`scene_utils`** — helpers compartidos. --- ## 9. Recursos - **`Resource::List`** (`core/resources/resource_list.*`) — registro de rutas de asset desde **`data/config/assets.yaml`**, con consulta O(1). - **`Resource::Cache`** (`core/resources/resource_cache.*`) — caché de assets con **carga incremental**: `beginLoad()` (en `SDL_AppInit`) + la escena `BootLoaderScene` que el `Director` arranca automáticamente mientras `Resource::Cache::isLoadDone()` sea falso (una barra de progreso con la ventana viva). - **Pack y fallback**: `resource_pack.*` + `resource_helper.*` sirven desde **`resources.pack`** (formato propio "AEE1", `CLAUDE.md:237`); en release nativo es estricto (solo pack), en Debug/WASM hay *fallback* a `data/`. - **Formatos**: GIF/paletas para gráficos (vía `Jd8`), fuentes `.fnt`+`.gif`, OGG/WAV para audio, GLSL para shaders. --- ## 10. Audio y localización - **Audio**: `core/audio/audio.*` (singleton, aplica `Options::audio`) sobre **`jail_audio`** (`Ja`, `jail/jail_audio.hpp` / `core/audio/jail_audio.hpp`), mezcla propia con streams SDL3 (OGG vía `stb_vorbis`, WAV). `JA_Update()` se bombea cada frame desde el `Director`; pausa/resume con F11. - **Localización**: `core/locale/locale.*` — mapa plano clave→cadena cargado de YAML (`data/locale/ca.yaml`, valenciano por defecto). Claves con notación de puntos (`menu.items.zoom`); si falta una clave, devuelve la propia clave (fallback visible para depurar). --- ## 11. Configuración y persistencia - **`Options`** (`source/game/options.*`) — namespace con globals `inline` y carga/guardado YAML. Structs: `KeysGame` (movimiento), `Video`, `RenderInfo`, `Audio`, `Window`, `Game`, `PostFXPreset`, `CrtPiPreset`. - **`defines.hpp`** — constantes del juego: `Texts::WINDOW_TITLE`/`VERSION`, `GameScreen::WIDTH=320`/`HEIGHT=200`/`BUFFER_SIZE=64000`. - **`defaults.hpp`** — valores por defecto (`Defaults::KeysGame`, `Video`, `Audio`, `Window`, `Game`). - **`KeyConfig`** — teclas de UI (§6). Ficheros persistentes en `~/.config/jailgames/aee/` (`CLAUDE.md:224`): `config.yaml` (vídeo/audio/ventana/render_info/controles), `keys.yaml` (overrides de UI), `postfx.yaml` (6 presets), `crtpi.yaml` (4 presets), y en Debug `debug.yaml` (estado inicial de gameplay para pruebas). **Builds condicionales**: `NDEBUG` (release: pack estricto, sin `debug.yaml`), `__EMSCRIPTEN__` (WASM: fuerza ventana/zoom/4:3, mantiene fallback de assets, sin persistencia MEMFS). --- ## 12. Modo demo / IA **No he encontrado un modo demo, *attract mode* ni IA de demostración en este proyecto.** Lo he buscado explícitamente: la única aparición de "replay" es un comentario en `jail_audio.hpp` sobre re-reproducción de pistas de audio, sin relación con un modo demo. A diferencia de los proyectos hermanos `coffee_crisis` (playback de input grabado) o `jaildoctors_dilemma` (tour de habitaciones), aquí el flujo de atracción —si lo hubiera— se construiría sobre el `SceneRegistry` y las escenas cinemáticas (§8), pero **hoy no existe** tal cosa implementada. --- ## 13. Convenciones y patrones recurrentes - **Frontera legacy/nuevo** (`CLAUDE.md:79`): lo más importante. `core/jail/` y `game/*.cpp` son legacy en modernización (preservar comportamiento); el resto es código nuevo. Los assets de `data/gfx`/`data/music` son **intocables**. - **Namespaces legacy abreviados** `Jg`/`Jd8`/`Ji`/`Jf`/`Ja` (APIs C planas), con nombres externos estables durante la transición. - **Single-thread, tick-based**: sin fibers/mutex; las escenas no bloquean ni llaman a `Jd8::flip` (lo hace el `Director`). - **Render paletizado 8-bit** sobre buffer 320×200; color y shaders solo al final (`JD8_Flip` → `Screen`). - **Singletons con `init()`/`destroy()`/`get()`** (`Screen`, `Audio`, `Director`, `Menu`, `Overlay`, `Resource::*`, `Jd8`/`Jg` como módulos), creados/destruidos en orden explícito en `SDL_AppInit`/`SDL_AppQuit`. - **Máquina de estados por `Info::ctx.num_piramide`** + `SceneRegistry` que migra cinemáticas legacy a `Scene`s nuevas de forma incremental. - **Fades y timing no bloqueantes**: lo que antes eran bucles bloqueantes (`JD8_FadeOut`) ahora son máquinas de estados que avanzan un paso por tick. - **Comentarios** en valenciano/español; muchos `#include` con comentario de justificación (estilo IWYU). --- ## 14. Guía de navegación: "si quieres tocar X, mira Y" | Quiero… | Empieza por… | |---|---| | Entender el arranque | `source/main.cpp` (`SDL_AppInit`) + `core/system/director.cpp` | | El bucle / orden del frame | `Director::iterate()` (`director.cpp`) | | Tocar el motor de dibujo | `core/jail/jdraw8.*` (`Jd8`) | | Timing / fixed-timestep | `core/jail/jgame.*` (`Jg::shouldUpdate`) | | Añadir/editar una pantalla | `game/scenes/` (hereda de `Scenes::Scene`) + `SceneRegistry::registerScene` | | Cómo se decide la siguiente pantalla | `Director::createNextScene` + `Info::ctx.num_piramide` + `scene_registry.*` | | El estado del juego | `game/info.hpp` (`Info::ctx`) | | **Gameplay** | `game/modulegame.*` (fases) + entidades `prota/momia/bola/engendro/mapa/marcador` | | Animaciones de cinemáticas | `game/scenes/{timeline,frame_animator,sprite_mover,palette_fade,surface_handle}.*` | | Composición final / shaders | `core/rendering/screen.*` + `sdl3gpu/` + presets `postfx.yaml`/`crtpi.yaml` | | Overlays (notificaciones/PAUSA/info) | `core/rendering/overlay.*` | | Texto / menú | `core/rendering/text.*`, `core/rendering/menu.*` | | Teclas de UI / F1–F12 | `core/input/key_config.*` + `global_inputs.*` + `data/input/keys.yaml` | | Remapear movimiento | `core/input/key_remap.*` + `Options::keys_game` | | Mando | `core/input/gamepad.*` | | Cargar recursos / barra de carga | `core/resources/resource_cache.*` + `resource_list.*` + `scenes/boot_loader_scene.*` | | Audio | `core/audio/audio.*` + `jail_audio.hpp` (`Ja`) | | Idiomas | `core/locale/locale.*` + `data/locale/` | | Opciones / constantes | `game/options.*`, `game/defines.hpp`, `game/defaults.hpp` | | Carpetas y pack | `core/jail/jfile.*` (`Jf`) + `core/resources/resource_pack.*` | --- *Documento generado a partir de la lectura directa del código en el commit actual de la rama `main`. Si algo aquí no cuadra con el código, el código manda: actualiza este documento.*