Fix: gif.cpp no desfeia l'interlace, trinxava qualsevol GIF entrellaçat
(tota la sortida de Pillow). Afegeix Defaults::UI::Font per centralitzar
noms/rutes i mou data/font → data/fonts.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Abans el binari només arrencava si la CWD era la que contenia data/
(típicament build/). Executat des de qualsevol altra carpeta no trobava
keys.yaml, paletes, etc. i es moria al carregar el primer recurs.
Patró seguit de ../aee: Resource::Helper guarda un data root absolut
i resolve(rel) el prefixa davant de rutes no absolutes. Director fa
setDataRoot(SDL_GetBasePath()) com a primera acció del ctor, així tots
els loaders posteriors hi passen sense canvis al call site.
Migrats a Resource::Helper::resolve els loaders que obrien std::ifstream
directament amb el path rebut: Locale, KeyConfig, Player, Map, Tilemap
i EntityLoader. Els que ja usaven Resource::Helper::loadFile
(Resource::Cache, PaletteLoader) hereten el fix automàticament.
Els fitxers de system_folder_ (config.yaml, debug.yaml, postfx.yaml,
crtpi.yaml) es passen com a rutes absolutes i resolve() les deixa
intactes, així no es veuen afectats.
Test targets (test_entities_smoke, test_scene_flow) enllacen ara
resource_helper.cpp perquè el seu codi passa per Helper::resolve. Els
tests corren amb CWD = repo root, on les rutes "data/..." funcionen
amb data root buit sense canviar cap assert.
Verificat executant el binari des de build/, /tmp i / — tots tres
troben els recursos i arrenquen correctament, tant en debug com en
release (release sempre arranca a LOGO).
Director encadena LOGO → TITLE → INTRO → GAME amb factories injectades
al ctor de cada placeholder (sense que cap escena conegui el tipus de
la següent). L'escena d'arrencada surt de `debug.yaml` en debug build i
és sempre LOGO en release.
Comportament:
- Release: `debug.yaml` s'ignora; arranca sempre a LOGO.
- Debug: es llig `debug.yaml`. Si no existeix, es crea automàticament
amb `start_scene: GAME` per no arrossegar 15 s de placeholders al dia
a dia de gameplay. Valor invàlid o YAML corrupte → warning + GAME,
però el fitxer no es reescriu (respectem l'edició manual).
`debug.yaml` viu a `$XDG_CONFIG_HOME/jailgames/aee_2026/`, al costat
de `config.yaml`, i queda fora del repo (ajust per màquina de dev).
L'estat mutable d'Options (window, video, audio, locale, presets, paths)
es mou a un anonymous namespace dins options.cpp. L'API pública del
namespace passa a ser:
- Getters const-ref: window(), video(), audio(), locale(),
configVersion(), postfxPresets(), crtpiPresets().
- Setters específics que muten i persisteixen via saveToFile():
setWindowZoom, setWindowFullscreen, setVideoVSync,
setVideoScalingMode, setVideoRenderInfoPosition,
setVideoRenderInfoShowTime, setShaderEnabled, setActiveShaderName,
setPostFXPreset, setCrtPiPreset.
Els setters NO notifiquen els subsistemes: el caller (global_inputs.cpp)
crida explícitament Screen::setWindowZoom, reapplyShader, etc. La part
"observers" del audit es deixa WONTFIX justificat — notificar des
d'Options invertiria la direcció Director→Screen/Audio i Options
aprenria del layout dels subsistemes.
CONV-02 tanca al pas: la part Options dels "globals sense observers"
queda resolta amb la nova encapsulació. Map::* (l'altra meitat de
CONV-02) ja s'havia tancat amb PATCH-07.
Smoke tests 13/13 OK; log Game start → Bye! sota xvfb-run +
SDL_VIDEODRIVER=dummy + SIGINT idèntic al baseline de main.
clang-tidy i cppcheck nets sobre els fitxers modificats.
Refs: docs/audit-game.md (COUP-03, CONV-02, INCONS-01).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Notifier::init i RenderInfo::init cridaven Resource::Cache::get() i
construïen cadascun la seua pròpia instància de Text a partir de
"8bithud.gif" + "data/font/8bithud.fnt" (strings hardcoded). Notifier
també llegia la paleta "ui" a cada render().
Ara:
- Director construeix una sola std::shared_ptr<Text> compartida.
- RenderInfo::init(Frame, shared_ptr<Text>) i Notifier::init
(shared_ptr<Text>, const Palette&) reben els recursos injectats.
- Notifier desa la Palette una volta i la consulta localment a
render(), sense tocar el cache global.
Resultat: els overlays perden la dependència dels noms dels assets
i del cache; el cicle de vida queda controlat pel Director. El camp
intern text_ passa a shared_ptr<Text>.
El document d'auditoria es tanca:
- PATCH-02, COUP-05 → DEFERRED (feature beyond cleanup scope).
- INC-04 → WONTFIX (coexistència justificada de writeDX/write*).
- Estat global: neteja completada.
Build + smoke 5s xvfb OK (exit 124).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
core/rendering/render_info ja no inclou game/options.hpp ni
game/ui/ui_palette.hpp. S'introdueix RenderInfo::Frame amb tot l'estat
extern (posició, show_time, shader_enabled, shader_name, shader_preset,
colors) que el caller injecta a cada init()/update(). La lògica de
persistència (cyclePosition/toggleShowTime) surt de RenderInfo i passa
a global_inputs.cpp, que muta Options i crida saveToFile() directament.
Options::buildRenderInfoFrame(text_color, shadow_color) centralitza la
construcció del Frame seguint el mateix patró que buildScreenConfig /
buildPostFXParams. Director i GameScene criden aquest builder quan
necessiten un Frame (amb UiColor::RENDER_INFO_{TEXT,SHADOW} com a
colors actius).
Amb aquest canvi queda tancada COUP-01: core/rendering/ no té cap
include de game/*.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>