From d10d5aa7dbd55abae2ea4a855dbdbd698ff3b6fc Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Mon, 27 Apr 2026 06:40:04 +0100 Subject: [PATCH 1/8] Internal Viewport 270p (480x270) --- discussion/index.ndjson | 3 +- .../AGD-0030-internal-viewport-270p.md | 133 ++++++++++++++++++ .../DEC-0022-internal-viewport-270p.md | 115 +++++++++++++++ .../PLN-0043-runtime-270p-core-migration.md | 123 ++++++++++++++++ ...LN-0044-host-and-tests-270p-propagation.md | 120 ++++++++++++++++ ...LN-0045-specs-and-docs-270p-publication.md | 105 ++++++++++++++ 6 files changed, 598 insertions(+), 1 deletion(-) create mode 100644 discussion/workflow/agendas/AGD-0030-internal-viewport-270p.md create mode 100644 discussion/workflow/decisions/DEC-0022-internal-viewport-270p.md create mode 100644 discussion/workflow/plans/PLN-0043-runtime-270p-core-migration.md create mode 100644 discussion/workflow/plans/PLN-0044-host-and-tests-270p-propagation.md create mode 100644 discussion/workflow/plans/PLN-0045-specs-and-docs-270p-publication.md diff --git a/discussion/index.ndjson b/discussion/index.ndjson index 5a1fa6fa..49df7439 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -1,4 +1,4 @@ -{"type":"meta","next_id":{"DSC":30,"AGD":30,"DEC":22,"PLN":43,"LSN":39,"CLSN":1}} +{"type":"meta","next_id":{"DSC":31,"AGD":31,"DEC":23,"PLN":46,"LSN":39,"CLSN":1}} {"type":"discussion","id":"DSC-0023","status":"done","ticket":"perf-full-migration-to-atomic-telemetry","title":"Agenda - [PERF] Full Migration to Atomic Telemetry","created_at":"2026-04-10","updated_at":"2026-04-10","tags":["perf","runtime","telemetry"],"agendas":[{"id":"AGD-0021","file":"workflow/agendas/AGD-0021-full-migration-to-atomic-telemetry.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}],"decisions":[{"id":"DEC-0008","file":"workflow/decisions/DEC-0008-full-migration-to-atomic-telemetry.md","status":"accepted","created_at":"2026-04-10","updated_at":"2026-04-10"}],"plans":[{"id":"PLN-0007","file":"workflow/plans/PLN-0007-full-migration-to-atomic-telemetry.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}],"lessons":[{"id":"LSN-0028","file":"lessons/DSC-0023-perf-full-migration-to-atomic-telemetry/LSN-0028-converging-to-single-atomic-telemetry-source.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}]} {"type":"discussion","id":"DSC-0020","status":"done","ticket":"jenkins-gitea-integration","title":"Jenkins Gitea Integration and Relocation","created_at":"2026-04-07","updated_at":"2026-04-07","tags":["ci","jenkins","gitea"],"agendas":[{"id":"AGD-0018","file":"workflow/agendas/AGD-0018-jenkins-gitea-integration-and-relocation.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}],"decisions":[{"id":"DEC-0003","file":"workflow/decisions/DEC-0003-jenkins-gitea-strategy.md","status":"accepted","created_at":"2026-04-07","updated_at":"2026-04-07"}],"plans":[{"id":"PLN-0003","file":"workflow/plans/PLN-0003-jenkins-gitea-execution.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}],"lessons":[{"id":"LSN-0021","file":"lessons/DSC-0020-jenkins-gitea-integration/LSN-0021-jenkins-gitea-integration.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}]} {"type":"discussion","id":"DSC-0021","status":"done","ticket":"asset-entry-codec-enum-with-metadata","title":"Asset Entry Codec Enum Contract","created_at":"2026-04-09","updated_at":"2026-04-09","tags":["asset","runtime","codec","metadata"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0024","file":"lessons/DSC-0021-asset-entry-codec-enum-contract/LSN-0024-string-on-the-wire-enum-in-runtime.md","status":"done","created_at":"2026-04-09","updated_at":"2026-04-09"}]} @@ -28,3 +28,4 @@ {"type":"discussion","id":"DSC-0017","status":"done","ticket":"asset-entry-metadata-normalization-contract","title":"Asset Entry Metadata Normalization Contract","created_at":"2026-03-27","updated_at":"2026-04-09","tags":[],"agendas":[{"id":"AGD-0016","file":"workflow/agendas/AGD-0016-asset-entry-metadata-normalization-contract.md","status":"done","created_at":"2026-03-27","updated_at":"2026-04-09"}],"decisions":[{"id":"DEC-0004","file":"workflow/decisions/DEC-0004-asset-entry-metadata-normalization-contract.md","status":"accepted","created_at":"2026-04-09","updated_at":"2026-04-09"}],"plans":[],"lessons":[{"id":"LSN-0023","file":"lessons/DSC-0017-asset-metadata-normalization/LSN-0023-typed-asset-metadata-helpers.md","status":"done","created_at":"2026-04-09","updated_at":"2026-04-09"}]} {"type":"discussion","id":"DSC-0018","status":"done","ticket":"asset-load-asset-id-int-contract","title":"Asset Load Asset ID Int Contract","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["asset","runtime","abi"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0019","file":"lessons/DSC-0018-asset-load-asset-id-int-contract/LSN-0019-asset-load-id-abi-convergence.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"}]} {"type":"discussion","id":"DSC-0019","status":"done","ticket":"jenkinsfile-correction","title":"Jenkinsfile Correction and Relocation","created_at":"2026-04-07","updated_at":"2026-04-07","tags":["ci","jenkins"],"agendas":[{"id":"AGD-0017","file":"workflow/agendas/AGD-0017-jenkinsfile-correction.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}],"decisions":[{"id":"DEC-0002","file":"workflow/decisions/DEC-0002-jenkinsfile-strategy.md","status":"accepted","created_at":"2026-04-07","updated_at":"2026-04-07"}],"plans":[{"id":"PLN-0002","file":"workflow/plans/PLN-0002-jenkinsfile-execution.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}],"lessons":[{"id":"LSN-0020","file":"lessons/DSC-0019-jenkins-ci-standardization/LSN-0020-jenkins-standard-relocation.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}]} +{"type":"discussion","id":"DSC-0030","status":"open","ticket":"internal-viewport-270p","title":"Agenda - Internal Viewport 270p (480x270)","created_at":"2026-04-27","updated_at":"2026-04-27","tags":["gfx","runtime","viewport","resolution","frame-composer","host"],"agendas":[{"id":"AGD-0030","file":"workflow/agendas/AGD-0030-internal-viewport-270p.md","status":"done","created_at":"2026-04-27","updated_at":"2026-04-27"}],"decisions":[{"id":"DEC-0022","file":"workflow/decisions/DEC-0022-internal-viewport-270p.md","status":"accepted","created_at":"2026-04-27","updated_at":"2026-04-27","ref_agenda":"AGD-0030"}],"plans":[{"id":"PLN-0043","file":"workflow/plans/PLN-0043-runtime-270p-core-migration.md","status":"review","created_at":"2026-04-27","updated_at":"2026-04-27","ref_decisions":["DEC-0022"]},{"id":"PLN-0044","file":"workflow/plans/PLN-0044-host-and-tests-270p-propagation.md","status":"review","created_at":"2026-04-27","updated_at":"2026-04-27","ref_decisions":["DEC-0022"]},{"id":"PLN-0045","file":"workflow/plans/PLN-0045-specs-and-docs-270p-publication.md","status":"review","created_at":"2026-04-27","updated_at":"2026-04-27","ref_decisions":["DEC-0022"]}],"lessons":[]} diff --git a/discussion/workflow/agendas/AGD-0030-internal-viewport-270p.md b/discussion/workflow/agendas/AGD-0030-internal-viewport-270p.md new file mode 100644 index 00000000..d0317036 --- /dev/null +++ b/discussion/workflow/agendas/AGD-0030-internal-viewport-270p.md @@ -0,0 +1,133 @@ +--- +id: AGD-0030 +ticket: internal-viewport-270p +title: Agenda - Internal Viewport 270p (480x270) +status: done +created: 2026-04-27 +resolved: 2026-04-27 +decision: DEC-0022 +tags: [gfx, runtime, viewport, resolution, frame-composer, host] +--- + +# Agenda - Internal Viewport 270p (480x270) + +## Contexto + +O runtime hoje trata `320x180` como viewport interna canonica em pontos importantes do pipeline, inclusive documentacao de hardware, `FrameComposer`, `SceneViewportResolver` e testes do host/debug overlay. + +A proposta e subir a resolucao interna para `480x270`, preservando a mesma proporcao `16:9`, mas alterando custo de composicao, tamanho de caches, area visivel da camera e possivelmente algumas expectativas implicitas de contrato entre runtime, host, assets e tooling. + +Existe contexto arquitetural recente relevante: + +- `DSC-0025` separou cena canonica, viewport cache e politica de resolver; +- `DSC-0026` consolidou `FrameComposer` como dono da composicao do frame; +- a mudanca agora nao e apenas trocar um par de constantes, porque a viewport interna participa de sizing, copy policy, camera framing e budget de memoria. + +## Problema + +Precisamos decidir se a viewport interna do Prometeu deve deixar de ser `320x180` e passar a ser `480x270` como novo baseline do runtime. + +A decisao precisa fechar: + +- se `480x270` vira contrato fixo do sistema ou apenas default configuravel; - vira contrato fixo do sistema +- se a camera e o frame visible devem realmente expor mais mundo ou apenas densidade maior; - esse deve ser o frame visible default (zoom de camera sera discutido em outra agenda) +- como ficam caches, copy regions, sprite/world composition e apresentacao no host; - devem seguir o mesmo padrao que temos hj, mas com uma area maior. +- qual o impacto aceito em CPU, RAM e largura de banda para o target handheld. - o impacto foi aceito na integra. esssa mudanca eh definitiva e deve perfurar em specs e docs. + +## Pontos Criticos + +- Compatibilidade de contrato: + qualquer lugar que hoje assume `320x180` pode deixar de ser detalhe interno e passar a ser break de comportamento observavel. - devemos corrigir onde for necessario. +- Custo de frame: + `480x270` aumenta pixels por frame em 2.25x versus `320x180`, o que pode afetar render software, fades, copy/convert no host e overlays. - o impacto foi aceito na integra. +- Viewport cache e resolver: + o `SceneViewportResolver` e o sizing do `FrameComposer` dependem diretamente da viewport para anchor, drift, hysteresis e regioes de refresh. -- mudancas necessarias para esse novo tamanho. +- Semantica de camera: + aumentar a viewport pode mudar gameplay, enquadramento, spawn visibility e design de HUD se o jogo passa a ver mais mundo. -- sem compat. nao ha jogos ainda usando essas features. +- Host e debug tooling: + overlay, apresentacao desktop e eventuais capturas/testes visuais hoje ainda carregam suposicoes de `320x180`. - precisamos atuar em mudancas ali tb +- Escopo de migracao: + precisamos decidir se a troca cobre apenas runtime/host ou tambem specs, exemplos, assets de referencia e testes de regressao. - devemos migrar tudo para o novo tamanho. os assets nao sao necessarios, podemos mante-los no mesmo tamanho, com excessao dos glyphos de texto. + +## Hotspots Atuais + +- [hardware.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-drivers/src/hardware.rs#L24) +- [frame_composer.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-drivers/src/frame_composer.rs#L197) +- [scene_viewport_resolver.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-hal/src/scene_viewport_resolver.rs#L56) +- [overlay.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/host/prometeu-host-desktop-winit/src/overlay.rs#L478) + +## Alvo da Discussao + +Definir o contrato correto para a viewport interna 270p no runtime e quais propagacoes sao obrigatorias antes de qualquer mudanca em spec ou codigo. + +## Opcoes + +### Opcao A - Manter `320x180` como contrato canonico + +- **Abordagem:** + rejeitar a troca de baseline e, se necessario, melhorar apenas o upscale/apresentacao no host. +- **Pro:** + evita reabrir camera, caches, testes e budget de composicao. +- **Con:** + nao entrega mais area/pixel density interna e pode limitar qualidade visual ou framing pretendido. +- **Manutenibilidade:** + custo baixo agora, mas posterga a pergunta arquitetural se `320x180` ja nao representa mais o alvo real do produto. + +### Opcao B - Promover `480x270` a nova viewport canonica fixa + +- **Abordagem:** + trocar o baseline interno do sistema inteiro para `480x270` e propagar a mudanca onde o contrato hoje assume `320x180`. +- **Pro:** + simplifica o modelo final: uma resolucao interna oficial, sem modo duplo. +- **Con:** + aumenta custo por frame, pode expor mais mundo do que jogos atuais esperam e exige migracao coordenada em runtime/host/tests/specs. +- **Manutenibilidade:** + boa se o produto realmente quer 270p como target oficial; ruim se depois precisarmos voltar a variabilidade. + +### Opcao C - Introduzir viewport interna configuravel com `320x180` e `480x270` + +- **Abordagem:** + transformar a viewport interna em configuracao de sistema/composer, permitindo coexistencia de 180p e 270p. +- **Pro:** + reduz risco de migracao abrupta e facilita benchmark comparativo. +- **Con:** + amplia superficie de contrato, multiplica combinacoes de teste e pode contaminar caminhos que hoje assumem um unico baseline. +- **Manutenibilidade:** + pior no curto e medio prazo; so vale se variabilidade de resolucao for requisito real de produto, nao apenas etapa de transicao. + +## Sugestao / Recomendacao + +Seguir inicialmente com a **Opcao B** como hipotese de trabalho: `480x270` deve ser tratado como novo baseline canonico, nao como configuracao geral. + +A recomendacao, porem, fica condicionada a duas verificacoes antes do fechamento da agenda: + +- confirmar que o efeito desejado e realmente aumentar a viewport observavel do jogo, e nao apenas melhorar a cadeia de apresentacao; +- confirmar que o custo extra de composicao e caches cabe no budget aceito para o handheld alvo. + +Se qualquer uma dessas premissas falhar, a Opcao A ou uma variante mais restrita da Opcao C volta a ser competitiva. + +## Perguntas em Aberto + +- A mudanca pretende mostrar mais mundo por frame ou manter o mesmo framing com outra granularidade visual? - mostrar mais mundo +- `480x270` deve ser contrato global do runtime ou apenas default do host desktop? - contrato global do runtime, o prometeu passa a ser um console 270p +- Quais syscalls, specs ou expectativas de cartridge assumem implicitamente a area visivel atual? - todas se e quando necessario +- O budget de `SceneViewportCache` e das copias incrementais continua aceitavel com 2.25x mais pixels? - sim, aqui se tornarao ainda mais importantes +- Fade, overlay e conversao `RGB565 -> RGBA8` no host permanecem viaveis sem nova rodada de otimizacao? - por enquanto iremos com o que temos, otimizaremos depois +- Ha assets, HUDs ou testes snapshot que dependem do framing de `320x180`? - nao, nada que nao possa ser migrado para o novo tamanho, mas sem necessidade de vc atuar nisso. + +## Criterio para Encerrar + +Esta agenda pode ser encerrada quando houver alinhamento suficiente para escrever uma decisao que feche explicitamente: + +- se `480x270` substitui `320x180` como contrato canonico; - sim +- se a viewport maior muda framing/gameplay observavel ou apenas rasterizacao interna; - maior framing +- quais modulos precisam de propagacao obrigatoria em runtime, host, specs e testes; - todos +- qual evidence minima de custo/memoria e necessaria para executar a migracao com seguranca. - o preco jah foi aceito, iremos migrar. + +## Resolucao + +A agenda foi encerrada com decisao favoravel a promover `480x270` como resolucao interna canonica do Prometeu. + +O novo tamanho passa a definir o frame visible default do console, com maior area observavel de mundo, sem compromisso de compatibilidade com o framing anterior de `320x180`. + +A migracao deve perfurar runtime, host, touch, specs, docs e testes. Otimizacoes de custo adicionais nao bloqueiam a mudanca: o aumento de CPU, RAM e bandwidth foi aceito como custo estrutural do novo baseline. diff --git a/discussion/workflow/decisions/DEC-0022-internal-viewport-270p.md b/discussion/workflow/decisions/DEC-0022-internal-viewport-270p.md new file mode 100644 index 00000000..d3d97cf4 --- /dev/null +++ b/discussion/workflow/decisions/DEC-0022-internal-viewport-270p.md @@ -0,0 +1,115 @@ +--- +id: DEC-0022 +ticket: internal-viewport-270p +title: Internal Viewport 270p (480x270) as Canonical Runtime Contract +status: accepted +created: 2026-04-27 +accepted: 2026-04-27 +agenda: AGD-0030 +plans: [PLN-0043, PLN-0044, PLN-0045] +tags: [gfx, runtime, viewport, resolution, frame-composer, host, touch] +--- + +## Status + +Accepted on `2026-04-27`. + +This decision is normatively locked until explicitly revised by a later decision. + +## Contexto + +O runtime do Prometeu ainda trata `320x180` como resolucao interna canonica em pontos centrais do sistema, incluindo `Hardware`, `FrameComposer`, host desktop, touch mapping, documentacao de hardware e testes. + +O trabalho recente de `DSC-0025` e `DSC-0026` consolidou o modelo correto para esse tipo de mudanca: viewport cache, resolver e frame composition ja possuem ownership claro e aceitam propagacao consistente a partir de um baseline unico de viewport. + +O objetivo desta decisao nao e melhorar upscale do host. O objetivo e redefinir o contrato do console para `480x270` como resolucao interna oficial, com maior area visivel de mundo por frame. + +## Decisao + +O Prometeu SHALL adotar `480x270` como resolucao interna canonica do runtime. + +`320x180` MUST cease to be treated as o baseline operacional do console em runtime, host, specs, docs e testes. + +`480x270` MUST representar o frame visible default do sistema. A mudanca e observavel: o console passa a mostrar mais mundo por frame. + +O runtime MUST NOT introduzir, nesta migracao, um modo dual `180p/270p` nem uma configuracao geral de viewport interna. + +Qualquer discussao futura sobre zoom de camera, framing alternativo ou modos adicionais MUST acontecer em discussao separada e MUST NOT enfraquecer este contrato base por inferencia. + +## Rationale + +Um baseline unico e fixo reduz ambiguidade de contrato e evita contaminar `FrameComposer`, host e specs com variabilidade que nao foi pedida como requisito real de produto. + +Aumentar apenas a cadeia de apresentacao do host nao resolve o objetivo do trabalho, porque o requisito aceito e ampliar o frame visible do console, nao apenas ampliar a imagem final. + +O custo estrutural de `480x270` foi explicitamente aceito. Portanto, CPU, RAM e bandwidth adicionais nao sao criterio de veto nesta decisao; passam a ser apenas materia de otimizacao posterior. + +Como ainda nao existem jogos dependentes do framing anterior, nao ha motivo para carregar compatibilidade legada como restricao principal desta migracao. + +## Invariantes / Contrato + +- `Hardware::W` e `Hardware::H` MUST convergir para `480` e `270`. +- O framebuffer canonico do runtime MUST operar em `480x270` RGB565. +- O host desktop MUST criar sua superficie base a partir da nova resolucao canonica e MUST mapear touch/pointer para o novo dominio absoluto. +- `FrameComposer` MUST usar `480x270` como viewport base para scene binding, camera framing, cache sizing e resolver ownership. +- `SceneViewportResolver` e `SceneViewportCache` MUST preservar o modelo atual de ownership e refresh policy; a mudanca e de baseline dimensional, nao de arquitetura. +- O efeito observavel da camera MUST ser maior framing por frame. Esta decisao MUST NOT ser reinterpretada como mero aumento de densidade com framing igual. +- A conversao `RGB565 -> RGBA8`, fades, overlay e copy paths MAY permanecer com a implementacao atual nesta etapa. Otimizacao posterior e permitida, mas nao e precondicao para adotar `480x270`. +- Assets existentes MUST continuar validos quando seu contrato nao depende da resolucao base. A migracao de assets em massa MUST NOT ser inventada como parte obrigatoria desta decisao. +- Glyphs e superficies textuais MAY exigir ajuste posterior quando o novo framing expuser necessidade de nova ocupacao visual, mas isso nao bloqueia o baseline 270p. + +## Impactos + +### Runtime + +- `Hardware`, `Gfx`, `FrameComposer`, `SceneViewportResolver` e caminhos relacionados passam a operar sobre `480x270`. +- Buffers de frame e custos por pixel aumentam estruturalmente. +- O budget de viewport cache e copy path continua valido conceitualmente, mas com volume maior de trabalho e memoria. + +### Host + +- O host desktop deve recriar sua superficie `Pixels` no novo tamanho base. +- O mapeamento de input absoluto deve seguir `480x270`. +- Overlay e qualquer teste de RGBA host-owned devem abandonar hardcodes de `320x180`. + +### Firmware / Guest / ABI + +- O espaco visivel observado pelo software convidado muda porque a camera default passa a enquadrar uma area maior. +- Esta decisao nao cria nova syscall, nao muda formato de argumento e nao introduz seletor de resolucao. + +### Specs / Docs + +- As specs canonicas do runtime MUST publicar `480x270` como resolucao oficial. +- Textos sobre touch e framebuffer MUST ser atualizados para refletir o novo dominio coordenado. + +### Tooling / Tests + +- Testes com hardcodes de `320x180` MUST migrar. +- Snapshots, asserts de tamanho e fixtures de host/debug MUST convergir para `480x270`. + +## Referencias + +- `AGD-0030` - Internal Viewport 270p (480x270) +- `DSC-0025` - Scene Bank and Viewport Cache Refactor +- `DSC-0026` - Integrate render_all with Scene Cache and Camera +- [hardware.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-drivers/src/hardware.rs:116) +- [runner.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/host/prometeu-host-desktop-winit/src/runner.rs:229) +- [input.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/host/prometeu-host-desktop-winit/src/input.rs:73) +- [04-gfx-peripheral.md](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/docs/specs/runtime/04-gfx-peripheral.md:22) +- [07-touch-peripheral.md](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/docs/specs/runtime/07-touch-peripheral.md:20) + +## Propagacao Necessaria + +- Atualizar constantes canonicas de resolucao em runtime. +- Atualizar criacao de framebuffer e apresentacao no host desktop. +- Atualizar mapping absoluto de touch/pointer. +- Atualizar testes de `FrameComposer`, `SceneViewportResolver`, host overlay e demais asserts fixos de tamanho. +- Atualizar specs e docs que ainda publicam `320x180`. +- Escrever um plano de execucao que separe: + runtime/host/tests; + specs/docs; + qualquer ajuste textual ou visual adicional nao bloqueante. + +## Revision Log + +- `2026-04-27`: Initial accepted decision from `AGD-0030`. diff --git a/discussion/workflow/plans/PLN-0043-runtime-270p-core-migration.md b/discussion/workflow/plans/PLN-0043-runtime-270p-core-migration.md new file mode 100644 index 00000000..006ac08f --- /dev/null +++ b/discussion/workflow/plans/PLN-0043-runtime-270p-core-migration.md @@ -0,0 +1,123 @@ +--- +id: PLN-0043 +ticket: internal-viewport-270p +title: Runtime 270p Core Migration +status: review +created: 2026-04-27 +completed: +tags: [gfx, runtime, viewport, resolution, frame-composer] +--- + +## Briefing + +This plan executes the first mandatory slice of `DEC-0022`: migrate the canonical runtime resolution from `320x180` to `480x270` inside the core runtime path before any host-facing or documentation-only propagation. + +This plan intentionally prioritizes runtime ownership, framebuffer sizing, `FrameComposer` baseline, resolver/cache sizing behavior, and runtime-local tests. It does not include host window/input propagation or specs/docs publication. + +## Decisions de Origem + +- `DEC-0022` - Internal Viewport 270p (480x270) as Canonical Runtime Contract + +## Alvo + +Make the runtime itself operate canonically at `480x270` RGB565 and preserve the existing scene/cache/resolver architecture under the new baseline. + +## Escopo + +- Update canonical runtime width/height constants. +- Propagate the new resolution through `Hardware`, `Gfx`, and `FrameComposer`. +- Preserve `SceneViewportResolver` and `SceneViewportCache` architecture while updating runtime assumptions and tests derived from the old baseline. +- Recompute runtime expectations that explicitly depended on `320x180`. + +## Fora de Escopo + +- Host desktop surface creation and pointer mapping. +- Host overlay RGBA fixtures. +- Specs and docs publication. +- Asset migrations or text/glyph content redesign. + +## Plano de Execucao + +### Step 1 - Promote runtime-wide canonical dimensions + +**What:** +Change the runtime’s canonical internal framebuffer dimensions from `320x180` to `480x270`. + +**How:** +Update the canonical constants and any runtime-local documentation/comments that still publish the old baseline, ensuring all `Gfx` and `FrameComposer` construction paths inherit the new dimensions from the same source of truth. + +**File(s):** +- `crates/console/prometeu-drivers/src/hardware.rs` +- `crates/console/prometeu-drivers/src/gfx.rs` + +### Step 2 - Rebaseline frame composition and scene runtime sizing + +**What:** +Make `FrameComposer` use `480x270` as the canonical viewport baseline for scene binding and scene-runtime construction. + +**How:** +Keep the existing ownership split (`FrameComposer` -> `SceneViewportCache` + `SceneViewportResolver`) intact, but update construction-time expectations and tests that hardcode `320x180`. Preserve the current cache sizing algorithm and hysteresis derivation; do not introduce configurable dual-mode resolution. + +**File(s):** +- `crates/console/prometeu-drivers/src/frame_composer.rs` + +### Step 3 - Rebaseline resolver expectations under 270p + +**What:** +Update resolver tests and derived numeric expectations to the `480x270` viewport. + +**How:** +Adjust test fixtures that currently instantiate `SceneViewportResolver::new(320, 180, 25, 16, 12, 20)` and recompute anchor, clamp, and refresh-region assertions from the 270p baseline. Preserve behavioral intent: +- anchor initialization; +- parallax propagation; +- hysteresis stability; +- edge clamping; +- incremental refresh behavior. + +**File(s):** +- `crates/console/prometeu-hal/src/scene_viewport_resolver.rs` + +### Step 4 - Rebaseline runtime integration tests + +**What:** +Update runtime-level tests that validate compositor/runtime invariants using the old resolution. + +**How:** +Migrate runtime integration assertions so they derive expected sizes from the new baseline or from the runtime constants. Keep scene-cache and sprite-order semantics unchanged; only the canonical viewport contract changes. + +**File(s):** +- `crates/console/prometeu-drivers/src/hardware.rs` +- `crates/console/prometeu-drivers/src/frame_composer.rs` +- `crates/console/prometeu-drivers/src/gfx.rs` + +## Criterios de Aceite + +- `Hardware::W == 480` and `Hardware::H == 270`. +- Runtime-owned frame composition uses `480x270` as the canonical viewport. +- Runtime tests no longer hardcode `320x180` as the canonical internal resolution. +- Resolver/cache behavior remains architecturally unchanged apart from the dimensional baseline. +- No configurable `180p/270p` runtime mode is introduced. + +## Tests / Validacao + +### Unit Tests + +- `cargo test` for: + `prometeu-drivers` + `prometeu-hal` + +### Integration Tests + +- Verify `FrameComposer` scene-binding/runtime tests under the new viewport. +- Verify resolver numeric assertions after updating the viewport baseline. + +### Manual Verification + +- Inspect runtime constants and constructor callsites to confirm a single canonical source of truth. +- Confirm no new runtime API for resolution selection was added. + +## Riscos + +- Resolver tests may fail with multiple derived-value changes at once, requiring careful recomputation rather than blind constant replacement. +- Some runtime assertions may accidentally embed old visible-framing assumptions instead of true contract checks. +- Runtime-only completion does not yet yield correct host presentation; that gap is intentional and deferred to the next plan. diff --git a/discussion/workflow/plans/PLN-0044-host-and-tests-270p-propagation.md b/discussion/workflow/plans/PLN-0044-host-and-tests-270p-propagation.md new file mode 100644 index 00000000..8e57e8e9 --- /dev/null +++ b/discussion/workflow/plans/PLN-0044-host-and-tests-270p-propagation.md @@ -0,0 +1,120 @@ +--- +id: PLN-0044 +ticket: internal-viewport-270p +title: Host and Test Propagation for 270p +status: review +created: 2026-04-27 +completed: +tags: [host, tests, viewport, resolution, touch, overlay] +--- + +## Briefing + +This plan executes the second mandatory slice of `DEC-0022`: propagate the accepted `480x270` runtime contract into host presentation, absolute pointer mapping, host-side overlay/test fixtures, and any remaining test surfaces that still assume `320x180`. + +This plan depends on `PLN-0043` completing first. It must not redefine the runtime contract; it only propagates the already-accepted 270p baseline into host-owned behavior and validation surfaces. + +## Decisions de Origem + +- `DEC-0022` - Internal Viewport 270p (480x270) as Canonical Runtime Contract + +## Alvo + +Make the desktop host and test surface faithfully consume the new canonical runtime resolution and touch domain. + +## Escopo + +- Update host framebuffer/surface creation to `480x270`. +- Update absolute pointer/touch mapping to the new canonical domain. +- Update host overlay fixtures and tests that still allocate or draw against `320x180`. +- Sweep remaining test hardcodes outside the core runtime step. + +## Fora de Escopo + +- Core runtime ownership changes already covered by `PLN-0043`. +- Specs and docs publication. +- Post-migration visual redesign or typography/layout tuning beyond strict propagation. + +## Plano de Execucao + +### Step 1 - Rebaseline host presentation surface + +**What:** +Make the desktop host create and present its base `Pixels` surface using the new canonical runtime dimensions. + +**How:** +Update host initialization and redraw flow so `PixelsBuilder`, frame copy, and overlay composition all consume `Hardware::W/H` after the runtime constants move to `480x270`. + +**File(s):** +- `crates/host/prometeu-host-desktop-winit/src/runner.rs` +- `crates/host/prometeu-host-desktop-winit/src/utilities.rs` + +### Step 2 - Rebaseline absolute input mapping + +**What:** +Align pointer/touch translation with the new canonical framebuffer domain. + +**How:** +Update `window_to_fb()` and any clamping logic to map window coordinates into `[0, 479] x [0, 269]` through the canonical `Hardware::W/H` path. + +**File(s):** +- `crates/host/prometeu-host-desktop-winit/src/input.rs` + +### Step 3 - Update host overlay fixtures and tests + +**What:** +Remove host overlay hardcodes that still allocate or draw a `320x180` RGBA buffer. + +**How:** +Update overlay tests and any host-owned fixtures so they use `480x270` or derive from the canonical hardware constants where appropriate. Preserve overlay semantics; do not redesign the overlay in this plan. + +**File(s):** +- `crates/host/prometeu-host-desktop-winit/src/overlay.rs` + +### Step 4 - Sweep remaining non-doc resolution assertions + +**What:** +Capture and update any remaining code or tests outside specs/docs that still depend on the old baseline. + +**How:** +Search for `320x180`, `320, 180`, and equivalent fixed-size assumptions under host/runtime test surfaces and migrate them to the accepted 270p contract or to canonical constants. + +**File(s):** +- `crates/host/prometeu-host-desktop-winit/src/*` +- any remaining test modules under `crates/console/*` + +## Criterios de Aceite + +- The desktop host creates its base surface from the `480x270` canonical runtime dimensions. +- Absolute pointer/touch mapping uses the new framebuffer domain. +- Host overlay tests no longer hardcode `320x180`. +- No host-owned code path reintroduces the old baseline as an implicit contract. + +## Tests / Validacao + +### Unit Tests + +- `cargo test` for: + `prometeu-host-desktop-winit` + any directly impacted console crates + +### Integration Tests + +- Verify runtime frame copy still lands correctly in the host RGBA surface. +- Verify pointer mapping clamps to the new canonical framebuffer bounds. + +### Manual Verification + +- Launch the desktop host and confirm the window presents a `480x270` logical framebuffer. +- Confirm overlay still renders and aligns within the new frame domain. +- Confirm pointer/touch interaction reaches the expected screen edges. + +## Riscos + +- Host visual regressions may appear only at runtime even when tests pass. +- Overlay layout may become visually awkward at 270p even if functionally correct; cosmetic tuning is intentionally deferred. +- Partial migration risks mismatch between runtime dimensions and host test fixtures if `PLN-0043` is not completed first. + +## Dependencies + +- `PLN-0043` MUST complete first. diff --git a/discussion/workflow/plans/PLN-0045-specs-and-docs-270p-publication.md b/discussion/workflow/plans/PLN-0045-specs-and-docs-270p-publication.md new file mode 100644 index 00000000..e43227f3 --- /dev/null +++ b/discussion/workflow/plans/PLN-0045-specs-and-docs-270p-publication.md @@ -0,0 +1,105 @@ +--- +id: PLN-0045 +ticket: internal-viewport-270p +title: Specs and Docs Publication for 270p +status: review +created: 2026-04-27 +completed: +tags: [specs, docs, runtime, viewport, resolution] +--- + +## Briefing + +This plan executes the final mandatory slice of `DEC-0022`: publish the accepted `480x270` console contract in canonical specs and supporting documentation after runtime and host propagation are already in place. + +This plan must run last. It exists to prevent public documentation from getting ahead of executable reality. + +## Decisions de Origem + +- `DEC-0022` - Internal Viewport 270p (480x270) as Canonical Runtime Contract + +## Alvo + +Update canonical published documentation so the repository describes Prometeu as a `480x270` console with matching framebuffer and touch coordinate semantics. + +## Escopo + +- Update runtime specs that explicitly publish `320x180`. +- Update any nearby prose that describes visual behavior in a way that now depends on the new baseline. +- Update related README/index material if it repeats the old resolution as canonical fact. + +## Fora de Escopo + +- Runtime or host code changes. +- Asset migration. +- Any broader narrative cleanup unrelated to the 270p contract. + +## Plano de Execucao + +### Step 1 - Update framebuffer and graphics specs + +**What:** +Publish `480x270` as the canonical graphics/framebuffer resolution in the runtime graphics spec. + +**How:** +Update the base-resolution and related descriptive sections so they state the new canonical resolution without ambiguity. Any prose that references `320x180` as a defining visual baseline must be revised to stay accurate. + +**File(s):** +- `docs/specs/runtime/04-gfx-peripheral.md` + +### Step 2 - Update touch coordinate contract + +**What:** +Publish the new absolute touch domain that matches the 270p framebuffer. + +**How:** +Update the touch spec so resolution, coordinate ranges, and any coordinate-space examples reflect `[0, 479] x [0, 269]`. + +**File(s):** +- `docs/specs/runtime/07-touch-peripheral.md` + +### Step 3 - Sweep remaining resolution references in runtime docs + +**What:** +Remove remaining canonical `320x180` references from runtime docs and supporting material where they now contradict `DEC-0022`. + +**How:** +Search runtime specs and adjacent docs for explicit resolution references and update only the ones that are part of the public console contract. Do not rewrite unrelated prose that merely mentions resolution in a different context unless it becomes incorrect after the migration. + +**File(s):** +- `docs/specs/runtime/*.md` +- `docs/specs/runtime/README.md` +- any other directly affected docs under `docs/` + +## Criterios de Aceite + +- Canonical runtime docs publish `480x270` as the official internal resolution. +- Touch docs publish coordinate ranges consistent with `480x270`. +- No remaining public spec text describes `320x180` as the canonical console baseline. +- Documentation order reflects executable truth: runtime/host migration is already completed before docs close. + +## Tests / Validacao + +### Unit Tests + +- No code unit tests are required for documentation-only changes. + +### Integration Tests + +- Re-run any repository validation or doc-linked checks that are already part of the normal workflow if available. + +### Manual Verification + +- Read the updated specs end-to-end for `gfx` and `touch` to confirm they agree with `DEC-0022`. +- Confirm no public-facing contradiction remains between docs and the implemented runtime baseline. + +## Riscos + +- Publishing docs before code would create a contract/execution mismatch; this is why this plan must remain last. +- Resolution references can hide in explanatory prose and examples, not only in obvious headings. +- Over-editing adjacent docs can accidentally turn a narrowly scoped publication task into a broad editorial rewrite. + +## Dependencies + +- `PLN-0043` MUST complete first. +- `PLN-0044` SHOULD complete first, and MUST complete first if any host-facing docs mention live desktop behavior. -- 2.47.2 From 4ca53046bfc0417a9b2e32c69150a258298e8c3c Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Mon, 27 Apr 2026 06:42:44 +0100 Subject: [PATCH 2/8] implement PLN-0043 runtime 270p core migration --- .../prometeu-drivers/src/frame_composer.rs | 49 +++++++++++++------ .../console/prometeu-drivers/src/hardware.rs | 6 +-- .../src/scene_viewport_resolver.rs | 36 +++++++------- discussion/index.ndjson | 2 +- .../PLN-0043-runtime-270p-core-migration.md | 4 +- 5 files changed, 58 insertions(+), 39 deletions(-) diff --git a/crates/console/prometeu-drivers/src/frame_composer.rs b/crates/console/prometeu-drivers/src/frame_composer.rs index 0520c16a..7f6c476b 100644 --- a/crates/console/prometeu-drivers/src/frame_composer.rs +++ b/crates/console/prometeu-drivers/src/frame_composer.rs @@ -340,6 +340,7 @@ impl FrameComposer { mod tests { use super::*; use crate::gfx::Gfx; + use crate::hardware::Hardware; use crate::memory_banks::{ GlyphBankPoolAccess, GlyphBankPoolInstaller, MemoryBanks, SceneBankPoolInstaller, }; @@ -405,10 +406,14 @@ mod tests { #[test] fn frame_composer_starts_unbound_with_empty_owned_state() { - let frame_composer = - FrameComposer::new(320, 180, Arc::new(MemoryBanks::new()), make_glyph_slot_index(&[])); + let frame_composer = FrameComposer::new( + Hardware::W, + Hardware::H, + Arc::new(MemoryBanks::new()), + make_glyph_slot_index(&[]), + ); - assert_eq!(frame_composer.viewport_size(), (320, 180)); + assert_eq!(frame_composer.viewport_size(), (Hardware::W, Hardware::H)); assert_eq!(frame_composer.active_scene_id(), None); assert!(frame_composer.active_scene().is_none()); assert_eq!(frame_composer.scene_status(), SceneStatus::Unbound); @@ -425,7 +430,8 @@ mod tests { let banks = Arc::new(MemoryBanks::new()); banks.install_scene_bank(3, Arc::new(make_scene())); - let frame_composer = FrameComposer::new(320, 180, banks, make_glyph_slot_index(&[(1, 0)])); + let frame_composer = + FrameComposer::new(Hardware::W, Hardware::H, banks, make_glyph_slot_index(&[(1, 0)])); let scene = frame_composer.scene_bank_slot(3).expect("scene bank slot 3 should be resident"); @@ -442,7 +448,7 @@ mod tests { let expected_scene = banks.scene_bank_slot(3).expect("scene bank slot 3 should be resident"); let mut frame_composer = - FrameComposer::new(320, 180, banks, make_glyph_slot_index(&[(1, 0)])); + FrameComposer::new(Hardware::W, Hardware::H, banks, make_glyph_slot_index(&[(1, 0)])); assert!(frame_composer.bind_scene(3)); @@ -462,7 +468,7 @@ mod tests { banks.install_scene_bank(1, Arc::new(make_scene())); let mut frame_composer = - FrameComposer::new(320, 180, banks, make_glyph_slot_index(&[(1, 0)])); + FrameComposer::new(Hardware::W, Hardware::H, banks, make_glyph_slot_index(&[(1, 0)])); assert!(frame_composer.bind_scene(1)); frame_composer.unbind_scene(); @@ -476,8 +482,12 @@ mod tests { #[test] fn set_camera_stores_top_left_pixel_coordinates() { - let mut frame_composer = - FrameComposer::new(320, 180, Arc::new(MemoryBanks::new()), make_glyph_slot_index(&[])); + let mut frame_composer = FrameComposer::new( + Hardware::W, + Hardware::H, + Arc::new(MemoryBanks::new()), + make_glyph_slot_index(&[]), + ); frame_composer.set_camera(-12, 48); @@ -490,17 +500,21 @@ mod tests { banks.install_scene_bank(0, Arc::new(make_scene())); let mut frame_composer = - FrameComposer::new(320, 180, banks, make_glyph_slot_index(&[(1, 0)])); + FrameComposer::new(Hardware::W, Hardware::H, banks, make_glyph_slot_index(&[(1, 0)])); assert!(frame_composer.bind_scene(0)); let cache = frame_composer.cache().expect("cache should exist for bound scene"); - assert_eq!((cache.width(), cache.height()), (45, 27)); + assert_eq!((cache.width(), cache.height()), (65, 38)); } #[test] fn missing_scene_binding_falls_back_to_no_scene_state() { - let mut frame_composer = - FrameComposer::new(320, 180, Arc::new(MemoryBanks::new()), make_glyph_slot_index(&[])); + let mut frame_composer = FrameComposer::new( + Hardware::W, + Hardware::H, + Arc::new(MemoryBanks::new()), + make_glyph_slot_index(&[]), + ); assert!(!frame_composer.bind_scene(7)); @@ -514,7 +528,8 @@ mod tests { let banks = Arc::new(MemoryBanks::new()); banks.install_scene_bank(0, Arc::new(make_scene())); - let mut frame_composer = FrameComposer::new(320, 180, banks, make_glyph_slot_index(&[])); + let mut frame_composer = + FrameComposer::new(Hardware::W, Hardware::H, banks, make_glyph_slot_index(&[])); let panic = catch_unwind(AssertUnwindSafe(|| frame_composer.bind_scene(0))) .expect_err("bind_scene should panic when dependency is missing"); @@ -649,8 +664,12 @@ mod tests { #[test] fn frame_composer_emits_ordered_sprites_for_rendering() { - let mut frame_composer = - FrameComposer::new(320, 180, Arc::new(MemoryBanks::new()), make_glyph_slot_index(&[])); + let mut frame_composer = FrameComposer::new( + Hardware::W, + Hardware::H, + Arc::new(MemoryBanks::new()), + make_glyph_slot_index(&[]), + ); frame_composer.begin_frame(); assert!(frame_composer.emit_sprite(Sprite { diff --git a/crates/console/prometeu-drivers/src/hardware.rs b/crates/console/prometeu-drivers/src/hardware.rs index 4a6138f4..6cf23447 100644 --- a/crates/console/prometeu-drivers/src/hardware.rs +++ b/crates/console/prometeu-drivers/src/hardware.rs @@ -21,7 +21,7 @@ use std::sync::Arc; /// for easier testing and different host implementations (Desktop, Web, etc.). /// /// ### Console Specifications: -/// - **Resolution**: 320x180 (16:9 Aspect Ratio). +/// - **Resolution**: 480x270 (16:9 Aspect Ratio). /// - **Color Depth**: RGB565 (16-bit). /// - **Audio**: Stereo, Command-based mixing. /// - **Input**: 12-button Digital Gamepad + Absolute Touch/Mouse. @@ -115,9 +115,9 @@ impl HardwareBridge for Hardware { impl Hardware { /// Internal hardware width in pixels. - pub const W: usize = 320; + pub const W: usize = 480; /// Internal hardware height in pixels. - pub const H: usize = 180; + pub const H: usize = 270; /// Creates a fresh hardware instance with default settings. pub fn new() -> Self { diff --git a/crates/console/prometeu-hal/src/scene_viewport_resolver.rs b/crates/console/prometeu-hal/src/scene_viewport_resolver.rs index b2a65a50..04d33b74 100644 --- a/crates/console/prometeu-hal/src/scene_viewport_resolver.rs +++ b/crates/console/prometeu-hal/src/scene_viewport_resolver.rs @@ -433,20 +433,20 @@ mod tests { #[test] fn first_update_initializes_master_and_layer_anchors() { let scene = make_scene(); - let mut resolver = SceneViewportResolver::new(320, 180, 25, 16, 12, 20); + let mut resolver = SceneViewportResolver::new(480, 270, 35, 21, 12, 20); let update = resolver.update(&scene, 0, 0); - assert_eq!(update.master_anchor, TileAnchor { x: 12, y: 8 }); - assert_eq!(update.layer_anchors[0], TileAnchor { x: 12, y: 8 }); - assert_eq!(update.layer_anchors[1], TileAnchor { x: 12, y: 8 }); + assert_eq!(update.master_anchor, TileAnchor { x: 17, y: 10 }); + assert_eq!(update.layer_anchors[0], TileAnchor { x: 17, y: 10 }); + assert_eq!(update.layer_anchors[1], TileAnchor { x: 17, y: 10 }); assert_eq!(update.refresh_requests.len(), 4); } #[test] fn per_layer_copy_requests_follow_parallax_factor() { let scene = make_scene(); - let mut resolver = SceneViewportResolver::new(320, 180, 25, 16, 12, 20); + let mut resolver = SceneViewportResolver::new(480, 270, 35, 21, 12, 20); let update = resolver.update(&scene, 32, 48); @@ -461,24 +461,24 @@ mod tests { #[test] fn hysteresis_prevents_small_back_and_forth_refresh_churn() { let scene = make_scene(); - let mut resolver = SceneViewportResolver::new(320, 180, 25, 16, 12, 20); + let mut resolver = SceneViewportResolver::new(480, 270, 35, 21, 12, 20); let _ = resolver.update(&scene, 0, 0); let update = resolver.update(&scene, 8, 0); assert!(update.refresh_requests.is_empty()); - assert_eq!(update.master_anchor, TileAnchor { x: 12, y: 8 }); + assert_eq!(update.master_anchor, TileAnchor { x: 17, y: 10 }); } #[test] fn repeated_high_speed_movement_advances_in_tile_steps() { let scene = make_scene(); - let mut resolver = SceneViewportResolver::new(320, 180, 25, 16, 12, 20); + let mut resolver = SceneViewportResolver::new(480, 270, 35, 21, 12, 20); let _ = resolver.update(&scene, 0, 0); let update = resolver.update(&scene, 64, 0); - assert!(update.master_anchor.x > 12); + assert!(update.master_anchor.x > 17); assert!(update.refresh_requests.iter().any(|request| matches!( request, CacheRefreshRequest::RefreshColumn { layer_index: 0, .. } @@ -489,18 +489,18 @@ mod tests { #[test] fn anchors_clamp_near_scene_edges() { let scene = make_scene(); - let mut resolver = SceneViewportResolver::new(320, 180, 25, 16, 12, 20); + let mut resolver = SceneViewportResolver::new(480, 270, 35, 21, 12, 20); let update = resolver.update(&scene, 10_000, 10_000); - assert_eq!(update.master_anchor, TileAnchor { x: 51, y: 56 }); - assert_eq!(update.layer_anchors[0], TileAnchor { x: 51, y: 56 }); + assert_eq!(update.master_anchor, TileAnchor { x: 46, y: 53 }); + assert_eq!(update.layer_anchors[0], TileAnchor { x: 46, y: 53 }); } #[test] fn corner_trigger_converts_to_non_overlapping_region_requests() { let scene = make_scene(); - let mut resolver = SceneViewportResolver::new(320, 180, 25, 16, 12, 20); + let mut resolver = SceneViewportResolver::new(480, 270, 35, 21, 12, 20); let _ = resolver.update(&scene, 0, 0); let update = resolver.update(&scene, 64, 80); @@ -515,15 +515,15 @@ mod tests { .collect(); assert_eq!(regions.len(), 2); - assert_eq!(regions[0].x + regions[0].width, 25); - assert_eq!(regions[0].height, 16); - assert_eq!(regions[1].width, 24); - assert_eq!(regions[1].height, 1); + assert_eq!(regions[0].x + regions[0].width, 35); + assert_eq!(regions[0].height, 21); + assert_eq!(regions[1].width, 34); + assert_eq!(regions[1].height, 2); } #[test] fn reset_scene_requests_full_invalidation_for_all_layers() { - let mut resolver = SceneViewportResolver::new(320, 180, 25, 16, 12, 20); + let mut resolver = SceneViewportResolver::new(480, 270, 35, 21, 12, 20); let requests = resolver.reset_scene(); diff --git a/discussion/index.ndjson b/discussion/index.ndjson index 49df7439..412c0fbe 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -28,4 +28,4 @@ {"type":"discussion","id":"DSC-0017","status":"done","ticket":"asset-entry-metadata-normalization-contract","title":"Asset Entry Metadata Normalization Contract","created_at":"2026-03-27","updated_at":"2026-04-09","tags":[],"agendas":[{"id":"AGD-0016","file":"workflow/agendas/AGD-0016-asset-entry-metadata-normalization-contract.md","status":"done","created_at":"2026-03-27","updated_at":"2026-04-09"}],"decisions":[{"id":"DEC-0004","file":"workflow/decisions/DEC-0004-asset-entry-metadata-normalization-contract.md","status":"accepted","created_at":"2026-04-09","updated_at":"2026-04-09"}],"plans":[],"lessons":[{"id":"LSN-0023","file":"lessons/DSC-0017-asset-metadata-normalization/LSN-0023-typed-asset-metadata-helpers.md","status":"done","created_at":"2026-04-09","updated_at":"2026-04-09"}]} {"type":"discussion","id":"DSC-0018","status":"done","ticket":"asset-load-asset-id-int-contract","title":"Asset Load Asset ID Int Contract","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["asset","runtime","abi"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0019","file":"lessons/DSC-0018-asset-load-asset-id-int-contract/LSN-0019-asset-load-id-abi-convergence.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"}]} {"type":"discussion","id":"DSC-0019","status":"done","ticket":"jenkinsfile-correction","title":"Jenkinsfile Correction and Relocation","created_at":"2026-04-07","updated_at":"2026-04-07","tags":["ci","jenkins"],"agendas":[{"id":"AGD-0017","file":"workflow/agendas/AGD-0017-jenkinsfile-correction.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}],"decisions":[{"id":"DEC-0002","file":"workflow/decisions/DEC-0002-jenkinsfile-strategy.md","status":"accepted","created_at":"2026-04-07","updated_at":"2026-04-07"}],"plans":[{"id":"PLN-0002","file":"workflow/plans/PLN-0002-jenkinsfile-execution.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}],"lessons":[{"id":"LSN-0020","file":"lessons/DSC-0019-jenkins-ci-standardization/LSN-0020-jenkins-standard-relocation.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}]} -{"type":"discussion","id":"DSC-0030","status":"open","ticket":"internal-viewport-270p","title":"Agenda - Internal Viewport 270p (480x270)","created_at":"2026-04-27","updated_at":"2026-04-27","tags":["gfx","runtime","viewport","resolution","frame-composer","host"],"agendas":[{"id":"AGD-0030","file":"workflow/agendas/AGD-0030-internal-viewport-270p.md","status":"done","created_at":"2026-04-27","updated_at":"2026-04-27"}],"decisions":[{"id":"DEC-0022","file":"workflow/decisions/DEC-0022-internal-viewport-270p.md","status":"accepted","created_at":"2026-04-27","updated_at":"2026-04-27","ref_agenda":"AGD-0030"}],"plans":[{"id":"PLN-0043","file":"workflow/plans/PLN-0043-runtime-270p-core-migration.md","status":"review","created_at":"2026-04-27","updated_at":"2026-04-27","ref_decisions":["DEC-0022"]},{"id":"PLN-0044","file":"workflow/plans/PLN-0044-host-and-tests-270p-propagation.md","status":"review","created_at":"2026-04-27","updated_at":"2026-04-27","ref_decisions":["DEC-0022"]},{"id":"PLN-0045","file":"workflow/plans/PLN-0045-specs-and-docs-270p-publication.md","status":"review","created_at":"2026-04-27","updated_at":"2026-04-27","ref_decisions":["DEC-0022"]}],"lessons":[]} +{"type":"discussion","id":"DSC-0030","status":"open","ticket":"internal-viewport-270p","title":"Agenda - Internal Viewport 270p (480x270)","created_at":"2026-04-27","updated_at":"2026-04-27","tags":["gfx","runtime","viewport","resolution","frame-composer","host"],"agendas":[{"id":"AGD-0030","file":"workflow/agendas/AGD-0030-internal-viewport-270p.md","status":"done","created_at":"2026-04-27","updated_at":"2026-04-27"}],"decisions":[{"id":"DEC-0022","file":"workflow/decisions/DEC-0022-internal-viewport-270p.md","status":"accepted","created_at":"2026-04-27","updated_at":"2026-04-27","ref_agenda":"AGD-0030"}],"plans":[{"id":"PLN-0043","file":"workflow/plans/PLN-0043-runtime-270p-core-migration.md","status":"done","created_at":"2026-04-27","updated_at":"2026-04-27","ref_decisions":["DEC-0022"]},{"id":"PLN-0044","file":"workflow/plans/PLN-0044-host-and-tests-270p-propagation.md","status":"review","created_at":"2026-04-27","updated_at":"2026-04-27","ref_decisions":["DEC-0022"]},{"id":"PLN-0045","file":"workflow/plans/PLN-0045-specs-and-docs-270p-publication.md","status":"review","created_at":"2026-04-27","updated_at":"2026-04-27","ref_decisions":["DEC-0022"]}],"lessons":[]} diff --git a/discussion/workflow/plans/PLN-0043-runtime-270p-core-migration.md b/discussion/workflow/plans/PLN-0043-runtime-270p-core-migration.md index 006ac08f..e8b97e57 100644 --- a/discussion/workflow/plans/PLN-0043-runtime-270p-core-migration.md +++ b/discussion/workflow/plans/PLN-0043-runtime-270p-core-migration.md @@ -2,9 +2,9 @@ id: PLN-0043 ticket: internal-viewport-270p title: Runtime 270p Core Migration -status: review +status: done created: 2026-04-27 -completed: +completed: 2026-04-27 tags: [gfx, runtime, viewport, resolution, frame-composer] --- -- 2.47.2 From 6a681ba4bcc466c5aac9f0e81dbeb5418f8c2136 Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Mon, 27 Apr 2026 06:44:18 +0100 Subject: [PATCH 3/8] implement PLN-0044 host 270p propagation --- crates/host/prometeu-host-desktop-winit/src/overlay.rs | 5 +++-- discussion/index.ndjson | 2 +- .../plans/PLN-0044-host-and-tests-270p-propagation.md | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/crates/host/prometeu-host-desktop-winit/src/overlay.rs b/crates/host/prometeu-host-desktop-winit/src/overlay.rs index b55967d7..5028eb86 100644 --- a/crates/host/prometeu-host-desktop-winit/src/overlay.rs +++ b/crates/host/prometeu-host-desktop-winit/src/overlay.rs @@ -437,6 +437,7 @@ fn glyph_bits(ch: char) -> [u8; 7] { #[cfg(test)] mod tests { use super::*; + use prometeu_drivers::hardware::Hardware; fn sample_snapshot() -> OverlaySnapshot { OverlaySnapshot { @@ -474,8 +475,8 @@ mod tests { #[test] fn draw_overlay_writes_to_host_rgba_frame() { - let mut frame = vec![0u8; 320 * 180 * 4]; - draw_overlay(&mut frame, 320, 180, &sample_snapshot()); + let mut frame = vec![0u8; Hardware::W * Hardware::H * 4]; + draw_overlay(&mut frame, Hardware::W, Hardware::H, &sample_snapshot()); assert!(frame.iter().any(|&byte| byte != 0)); } diff --git a/discussion/index.ndjson b/discussion/index.ndjson index 412c0fbe..f69a7e3b 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -28,4 +28,4 @@ {"type":"discussion","id":"DSC-0017","status":"done","ticket":"asset-entry-metadata-normalization-contract","title":"Asset Entry Metadata Normalization Contract","created_at":"2026-03-27","updated_at":"2026-04-09","tags":[],"agendas":[{"id":"AGD-0016","file":"workflow/agendas/AGD-0016-asset-entry-metadata-normalization-contract.md","status":"done","created_at":"2026-03-27","updated_at":"2026-04-09"}],"decisions":[{"id":"DEC-0004","file":"workflow/decisions/DEC-0004-asset-entry-metadata-normalization-contract.md","status":"accepted","created_at":"2026-04-09","updated_at":"2026-04-09"}],"plans":[],"lessons":[{"id":"LSN-0023","file":"lessons/DSC-0017-asset-metadata-normalization/LSN-0023-typed-asset-metadata-helpers.md","status":"done","created_at":"2026-04-09","updated_at":"2026-04-09"}]} {"type":"discussion","id":"DSC-0018","status":"done","ticket":"asset-load-asset-id-int-contract","title":"Asset Load Asset ID Int Contract","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["asset","runtime","abi"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0019","file":"lessons/DSC-0018-asset-load-asset-id-int-contract/LSN-0019-asset-load-id-abi-convergence.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"}]} {"type":"discussion","id":"DSC-0019","status":"done","ticket":"jenkinsfile-correction","title":"Jenkinsfile Correction and Relocation","created_at":"2026-04-07","updated_at":"2026-04-07","tags":["ci","jenkins"],"agendas":[{"id":"AGD-0017","file":"workflow/agendas/AGD-0017-jenkinsfile-correction.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}],"decisions":[{"id":"DEC-0002","file":"workflow/decisions/DEC-0002-jenkinsfile-strategy.md","status":"accepted","created_at":"2026-04-07","updated_at":"2026-04-07"}],"plans":[{"id":"PLN-0002","file":"workflow/plans/PLN-0002-jenkinsfile-execution.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}],"lessons":[{"id":"LSN-0020","file":"lessons/DSC-0019-jenkins-ci-standardization/LSN-0020-jenkins-standard-relocation.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}]} -{"type":"discussion","id":"DSC-0030","status":"open","ticket":"internal-viewport-270p","title":"Agenda - Internal Viewport 270p (480x270)","created_at":"2026-04-27","updated_at":"2026-04-27","tags":["gfx","runtime","viewport","resolution","frame-composer","host"],"agendas":[{"id":"AGD-0030","file":"workflow/agendas/AGD-0030-internal-viewport-270p.md","status":"done","created_at":"2026-04-27","updated_at":"2026-04-27"}],"decisions":[{"id":"DEC-0022","file":"workflow/decisions/DEC-0022-internal-viewport-270p.md","status":"accepted","created_at":"2026-04-27","updated_at":"2026-04-27","ref_agenda":"AGD-0030"}],"plans":[{"id":"PLN-0043","file":"workflow/plans/PLN-0043-runtime-270p-core-migration.md","status":"done","created_at":"2026-04-27","updated_at":"2026-04-27","ref_decisions":["DEC-0022"]},{"id":"PLN-0044","file":"workflow/plans/PLN-0044-host-and-tests-270p-propagation.md","status":"review","created_at":"2026-04-27","updated_at":"2026-04-27","ref_decisions":["DEC-0022"]},{"id":"PLN-0045","file":"workflow/plans/PLN-0045-specs-and-docs-270p-publication.md","status":"review","created_at":"2026-04-27","updated_at":"2026-04-27","ref_decisions":["DEC-0022"]}],"lessons":[]} +{"type":"discussion","id":"DSC-0030","status":"open","ticket":"internal-viewport-270p","title":"Agenda - Internal Viewport 270p (480x270)","created_at":"2026-04-27","updated_at":"2026-04-27","tags":["gfx","runtime","viewport","resolution","frame-composer","host"],"agendas":[{"id":"AGD-0030","file":"workflow/agendas/AGD-0030-internal-viewport-270p.md","status":"done","created_at":"2026-04-27","updated_at":"2026-04-27"}],"decisions":[{"id":"DEC-0022","file":"workflow/decisions/DEC-0022-internal-viewport-270p.md","status":"accepted","created_at":"2026-04-27","updated_at":"2026-04-27","ref_agenda":"AGD-0030"}],"plans":[{"id":"PLN-0043","file":"workflow/plans/PLN-0043-runtime-270p-core-migration.md","status":"done","created_at":"2026-04-27","updated_at":"2026-04-27","ref_decisions":["DEC-0022"]},{"id":"PLN-0044","file":"workflow/plans/PLN-0044-host-and-tests-270p-propagation.md","status":"done","created_at":"2026-04-27","updated_at":"2026-04-27","ref_decisions":["DEC-0022"]},{"id":"PLN-0045","file":"workflow/plans/PLN-0045-specs-and-docs-270p-publication.md","status":"review","created_at":"2026-04-27","updated_at":"2026-04-27","ref_decisions":["DEC-0022"]}],"lessons":[]} diff --git a/discussion/workflow/plans/PLN-0044-host-and-tests-270p-propagation.md b/discussion/workflow/plans/PLN-0044-host-and-tests-270p-propagation.md index 8e57e8e9..fcbd7878 100644 --- a/discussion/workflow/plans/PLN-0044-host-and-tests-270p-propagation.md +++ b/discussion/workflow/plans/PLN-0044-host-and-tests-270p-propagation.md @@ -2,9 +2,9 @@ id: PLN-0044 ticket: internal-viewport-270p title: Host and Test Propagation for 270p -status: review +status: done created: 2026-04-27 -completed: +completed: 2026-04-27 tags: [host, tests, viewport, resolution, touch, overlay] --- -- 2.47.2 From 1ab2898f5e59f5e847fb570ff352f6512ad0466e Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Tue, 28 Apr 2026 18:17:12 +0100 Subject: [PATCH 4/8] Internal Viewport 270p (480x270) --- crates/tools/pbxgen-stress/src/lib.rs | 87 +++++++++++++-------- test-cartridges/stress-console/assets.pa | Bin 35452 -> 100989 bytes test-cartridges/stress-console/program.pbx | Bin 1205 -> 1205 bytes 3 files changed, 53 insertions(+), 34 deletions(-) diff --git a/crates/tools/pbxgen-stress/src/lib.rs b/crates/tools/pbxgen-stress/src/lib.rs index 284f7b87..e89b2479 100644 --- a/crates/tools/pbxgen-stress/src/lib.rs +++ b/crates/tools/pbxgen-stress/src/lib.rs @@ -26,6 +26,13 @@ use std::path::PathBuf; const STRESS_GLYPH_ASSET_ID: AssetId = 100; const STRESS_SCENE_ASSET_ID: AssetId = 1; +const STRESS_VIEWPORT_W: i32 = 480; +const STRESS_VIEWPORT_H: i32 = 270; +const STRESS_SPRITE_COLS: i32 = 48; +const STRESS_SPRITE_ROWS: i32 = 24; +const STRESS_SPRITE_SPACING_PX: i32 = 10; +const STRESS_SCENE_TILE_W: usize = 96; +const STRESS_SCENE_TILE_H: usize = 64; fn asm(s: &str) -> Vec { assemble(s).expect("assemble") @@ -141,34 +148,38 @@ fn heavy_load(rom: &mut Vec) { rom.extend(asm("PUSH_I32 0\nHOSTCALL 0")); - rom.extend(asm( - "GET_GLOBAL 0\nPUSH_I32 2\nMUL\nPUSH_I32 192\nMOD\nGET_GLOBAL 0\nPUSH_I32 76\nMOD\nHOSTCALL 4", - )); + let scene_width_px = (STRESS_SCENE_TILE_W * 8) as i32; + let scene_height_px = (STRESS_SCENE_TILE_H * 8) as i32; + let camera_x_span = scene_width_px - STRESS_VIEWPORT_W; + let camera_y_span = scene_height_px - STRESS_VIEWPORT_H; + rom.extend(asm(&format!( + "GET_GLOBAL 0\nPUSH_I32 2\nMUL\nPUSH_I32 {camera_x_span}\nMOD\nGET_GLOBAL 0\nPUSH_I32 {camera_y_span}\nMOD\nHOSTCALL 4" + ))); rom.extend(asm("PUSH_I32 0\nSET_LOCAL 0")); let row_loop_start = rom.len() as u32; - rom.extend(asm("GET_LOCAL 0\nPUSH_I32 16\nLT")); + rom.extend(asm(&format!("GET_LOCAL 0\nPUSH_I32 {STRESS_SPRITE_ROWS}\nLT"))); let jif_row_end_offset = rom.len() + 2; rom.extend(asm("JMP_IF_FALSE 0")); rom.extend(asm("PUSH_I32 0\nSET_LOCAL 1")); let col_loop_start = rom.len() as u32; - rom.extend(asm("GET_LOCAL 1\nPUSH_I32 32\nLT")); + rom.extend(asm(&format!("GET_LOCAL 1\nPUSH_I32 {STRESS_SPRITE_COLS}\nLT"))); let jif_col_end_offset = rom.len() + 2; rom.extend(asm("JMP_IF_FALSE 0")); - rom.extend(asm( + rom.extend(asm(&format!( "PUSH_I32 0\n\ - GET_LOCAL 0\nPUSH_I32 32\nMUL\nGET_LOCAL 1\nADD\nGET_GLOBAL 0\nADD\nPUSH_I32 15\nMOD\nPUSH_I32 1\nADD\n\ - GET_LOCAL 1\nPUSH_I32 10\nMUL\nGET_GLOBAL 0\nPUSH_I32 10\nMOD\nADD\nPUSH_I32 320\nMOD\n\ - GET_LOCAL 0\nPUSH_I32 10\nMUL\nGET_GLOBAL 0\nPUSH_I32 2\nMUL\nPUSH_I32 10\nMOD\nADD\nPUSH_I32 180\nMOD\n\ + GET_LOCAL 0\nPUSH_I32 {STRESS_SPRITE_COLS}\nMUL\nGET_LOCAL 1\nADD\nGET_GLOBAL 0\nADD\nPUSH_I32 15\nMOD\nPUSH_I32 1\nADD\n\ + GET_LOCAL 1\nPUSH_I32 {STRESS_SPRITE_SPACING_PX}\nMUL\nGET_GLOBAL 0\nPUSH_I32 10\nMOD\nADD\nPUSH_I32 {STRESS_VIEWPORT_W}\nMOD\n\ + GET_LOCAL 0\nPUSH_I32 {STRESS_SPRITE_SPACING_PX}\nMUL\nGET_GLOBAL 0\nPUSH_I32 2\nMUL\nPUSH_I32 10\nMOD\nADD\nPUSH_I32 {STRESS_VIEWPORT_H}\nMOD\n\ GET_LOCAL 0\nGET_LOCAL 1\nADD\nGET_GLOBAL 0\nADD\nPUSH_I32 4\nMOD\n\ PUSH_I32 0\n\ GET_LOCAL 1\nGET_GLOBAL 0\nADD\nPUSH_I32 1\nBIT_AND\nPUSH_I32 0\nNEQ\n\ GET_LOCAL 0\nGET_GLOBAL 0\nADD\nPUSH_I32 1\nBIT_AND\nPUSH_I32 0\nNEQ\n\ GET_LOCAL 0\nGET_LOCAL 1\nADD\nPUSH_I32 4\nMOD\n\ - HOSTCALL 5\nPOP_N 1", - )); + HOSTCALL 5\nPOP_N 1" + ))); rom.extend(asm("GET_LOCAL 1\nPUSH_I32 1\nADD\nSET_LOCAL 1")); let jmp_col_loop_offset = rom.len() + 2; @@ -180,23 +191,23 @@ fn heavy_load(rom: &mut Vec) { rom.extend(asm("JMP 0")); let row_loop_end = rom.len() as u32; - rom.extend(asm("GET_GLOBAL 0\nPUSH_I32 3\nMUL\nPUSH_I32 220\nMOD\n\ + rom.extend(asm("GET_GLOBAL 0\nPUSH_I32 3\nMUL\nPUSH_I32 380\nMOD\n\ PUSH_I32 8\n\ PUSH_CONST 0\n\ GET_GLOBAL 0\nPUSH_I32 2047\nMUL\nPUSH_I32 65535\nBIT_AND\n\ HOSTCALL 1")); - rom.extend(asm("PUSH_I32 12\n\ - GET_GLOBAL 0\nPUSH_I32 2\nMUL\nPUSH_I32 120\nMOD\nPUSH_I32 24\nADD\n\ + rom.extend(asm("PUSH_I32 16\n\ + GET_GLOBAL 0\nPUSH_I32 2\nMUL\nPUSH_I32 186\nMOD\nPUSH_I32 32\nADD\n\ PUSH_CONST 1\n\ GET_GLOBAL 0\nPUSH_I32 4093\nMUL\nPUSH_I32 65535\nBIT_AND\n\ HOSTCALL 1")); - rom.extend(asm("PUSH_I32 220\n\ - GET_GLOBAL 0\nPUSH_I32 5\nMUL\nPUSH_I32 140\nMOD\n\ + rom.extend(asm("PUSH_I32 336\n\ + GET_GLOBAL 0\nPUSH_I32 5\nMUL\nPUSH_I32 194\nMOD\n\ PUSH_CONST 2\n\ GET_GLOBAL 0\nPUSH_I32 1237\nMUL\nPUSH_I32 65535\nBIT_AND\n\ HOSTCALL 1")); - rom.extend(asm("GET_GLOBAL 0\nPUSH_I32 4\nMUL\nPUSH_I32 180\nMOD\nPUSH_I32 80\nADD\n\ - GET_GLOBAL 0\nPUSH_I32 3\nMUL\nPUSH_I32 90\nMOD\nPUSH_I32 70\nADD\n\ + rom.extend(asm("GET_GLOBAL 0\nPUSH_I32 4\nMUL\nPUSH_I32 240\nMOD\nPUSH_I32 112\nADD\n\ + GET_GLOBAL 0\nPUSH_I32 3\nMUL\nPUSH_I32 120\nMOD\nPUSH_I32 88\nADD\n\ PUSH_CONST 3\n\ GET_GLOBAL 0\nPUSH_I32 3001\nMUL\nPUSH_I32 65535\nBIT_AND\n\ HOSTCALL 1")); @@ -326,19 +337,23 @@ fn build_scene_bank() -> SceneBank { flip_x: false, flip_y: false, }; - 64 * 32 + STRESS_SCENE_TILE_W * STRESS_SCENE_TILE_H ]; - for step in 0..8 { - let x = 4 + step * 7 + layer_index * 2; - let y = 2 + step * 3 + layer_index * 2; - let index = y * 64 + x; - tiles[index] = Tile { - active: true, - glyph: Glyph { glyph_id: 0, palette_id: layer_index as u8 + 1 }, - flip_x: false, - flip_y: false, - }; + for y in 0..STRESS_SCENE_TILE_H { + for x in 0..STRESS_SCENE_TILE_W { + let diagonal = (x + layer_index * 2) % 11 == (y * 2) % 11; + let stripe = (x / 6 + y / 5 + layer_index) % 5 == 0; + if diagonal || stripe { + let index = y * STRESS_SCENE_TILE_W + x; + tiles[index] = Tile { + active: true, + glyph: Glyph { glyph_id: 0, palette_id: layer_index as u8 + 1 }, + flip_x: false, + flip_y: false, + }; + } + } } SceneLayer { @@ -351,15 +366,19 @@ fn build_scene_bank() -> SceneBank { 2 => ParallaxFactor { x: 0.5, y: 0.5 }, _ => ParallaxFactor { x: 0.25, y: 0.25 }, }, - tilemap: TileMap { width: 64, height: 32, tiles }, + tilemap: TileMap { + width: STRESS_SCENE_TILE_W, + height: STRESS_SCENE_TILE_H, + tiles, + }, } }); // Keep the farthest layer a bit sparser so the diagonal remains visually readable. - for step in 0..4 { - let x = 10 + step * 12; - let y = 4 + step * 5; - let index = y * 64 + x; + for step in 0..12 { + let x = 10 + step * 7; + let y = 4 + step * 3; + let index = y * STRESS_SCENE_TILE_W + x; layers[3].tilemap.tiles[index].active = false; } diff --git a/test-cartridges/stress-console/assets.pa b/test-cartridges/stress-console/assets.pa index ca43164c50f6549648ce3bc8bdc03c745d70fe71..aad01aef04d41d430cdb613f37a26d8d556fe01e 100644 GIT binary patch literal 100989 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 SgA8yTP&2@8sB`(BdHDn5j3`84<_$t)Mesh zocxaQ6jKf3k delta 170 zcmdnWxs`K+03-ha1_lNd1_vO?z#z`xGg+Qdo>5@3J&;tG9M32TBr6$R8676?XVhid z!Z7(A<0+;)43l>;>B;f{bvS^u0rfEfNhKg%0i;!cw8UgqW=+vMK%N5-gH*5rNsx-3 g$RW(3kh%aMtpHcU3{?{am37;^kXeKg0MY9iGXMYp -- 2.47.2 From 38fc71f739f6221fd7d5531e564b04ff6a7a7c8b Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Tue, 28 Apr 2026 18:19:17 +0100 Subject: [PATCH 5/8] Internal Viewport 270p (480x270) --- discussion/index.ndjson | 4 +- .../AGD-0030-internal-viewport-270p.md | 133 ------------------ .../DEC-0022-internal-viewport-270p.md | 115 --------------- .../PLN-0043-runtime-270p-core-migration.md | 123 ---------------- ...LN-0044-host-and-tests-270p-propagation.md | 120 ---------------- ...LN-0045-specs-and-docs-270p-publication.md | 105 -------------- docs/specs/runtime/04-gfx-peripheral.md | 10 +- docs/specs/runtime/07-touch-peripheral.md | 6 +- 8 files changed, 10 insertions(+), 606 deletions(-) delete mode 100644 discussion/workflow/agendas/AGD-0030-internal-viewport-270p.md delete mode 100644 discussion/workflow/decisions/DEC-0022-internal-viewport-270p.md delete mode 100644 discussion/workflow/plans/PLN-0043-runtime-270p-core-migration.md delete mode 100644 discussion/workflow/plans/PLN-0044-host-and-tests-270p-propagation.md delete mode 100644 discussion/workflow/plans/PLN-0045-specs-and-docs-270p-publication.md diff --git a/discussion/index.ndjson b/discussion/index.ndjson index f69a7e3b..5a65b427 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -1,4 +1,4 @@ -{"type":"meta","next_id":{"DSC":31,"AGD":31,"DEC":23,"PLN":46,"LSN":39,"CLSN":1}} +{"type":"meta","next_id":{"DSC":31,"AGD":31,"DEC":23,"PLN":46,"LSN":40,"CLSN":1}} {"type":"discussion","id":"DSC-0023","status":"done","ticket":"perf-full-migration-to-atomic-telemetry","title":"Agenda - [PERF] Full Migration to Atomic Telemetry","created_at":"2026-04-10","updated_at":"2026-04-10","tags":["perf","runtime","telemetry"],"agendas":[{"id":"AGD-0021","file":"workflow/agendas/AGD-0021-full-migration-to-atomic-telemetry.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}],"decisions":[{"id":"DEC-0008","file":"workflow/decisions/DEC-0008-full-migration-to-atomic-telemetry.md","status":"accepted","created_at":"2026-04-10","updated_at":"2026-04-10"}],"plans":[{"id":"PLN-0007","file":"workflow/plans/PLN-0007-full-migration-to-atomic-telemetry.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}],"lessons":[{"id":"LSN-0028","file":"lessons/DSC-0023-perf-full-migration-to-atomic-telemetry/LSN-0028-converging-to-single-atomic-telemetry-source.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}]} {"type":"discussion","id":"DSC-0020","status":"done","ticket":"jenkins-gitea-integration","title":"Jenkins Gitea Integration and Relocation","created_at":"2026-04-07","updated_at":"2026-04-07","tags":["ci","jenkins","gitea"],"agendas":[{"id":"AGD-0018","file":"workflow/agendas/AGD-0018-jenkins-gitea-integration-and-relocation.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}],"decisions":[{"id":"DEC-0003","file":"workflow/decisions/DEC-0003-jenkins-gitea-strategy.md","status":"accepted","created_at":"2026-04-07","updated_at":"2026-04-07"}],"plans":[{"id":"PLN-0003","file":"workflow/plans/PLN-0003-jenkins-gitea-execution.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}],"lessons":[{"id":"LSN-0021","file":"lessons/DSC-0020-jenkins-gitea-integration/LSN-0021-jenkins-gitea-integration.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}]} {"type":"discussion","id":"DSC-0021","status":"done","ticket":"asset-entry-codec-enum-with-metadata","title":"Asset Entry Codec Enum Contract","created_at":"2026-04-09","updated_at":"2026-04-09","tags":["asset","runtime","codec","metadata"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0024","file":"lessons/DSC-0021-asset-entry-codec-enum-contract/LSN-0024-string-on-the-wire-enum-in-runtime.md","status":"done","created_at":"2026-04-09","updated_at":"2026-04-09"}]} @@ -28,4 +28,4 @@ {"type":"discussion","id":"DSC-0017","status":"done","ticket":"asset-entry-metadata-normalization-contract","title":"Asset Entry Metadata Normalization Contract","created_at":"2026-03-27","updated_at":"2026-04-09","tags":[],"agendas":[{"id":"AGD-0016","file":"workflow/agendas/AGD-0016-asset-entry-metadata-normalization-contract.md","status":"done","created_at":"2026-03-27","updated_at":"2026-04-09"}],"decisions":[{"id":"DEC-0004","file":"workflow/decisions/DEC-0004-asset-entry-metadata-normalization-contract.md","status":"accepted","created_at":"2026-04-09","updated_at":"2026-04-09"}],"plans":[],"lessons":[{"id":"LSN-0023","file":"lessons/DSC-0017-asset-metadata-normalization/LSN-0023-typed-asset-metadata-helpers.md","status":"done","created_at":"2026-04-09","updated_at":"2026-04-09"}]} {"type":"discussion","id":"DSC-0018","status":"done","ticket":"asset-load-asset-id-int-contract","title":"Asset Load Asset ID Int Contract","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["asset","runtime","abi"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0019","file":"lessons/DSC-0018-asset-load-asset-id-int-contract/LSN-0019-asset-load-id-abi-convergence.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"}]} {"type":"discussion","id":"DSC-0019","status":"done","ticket":"jenkinsfile-correction","title":"Jenkinsfile Correction and Relocation","created_at":"2026-04-07","updated_at":"2026-04-07","tags":["ci","jenkins"],"agendas":[{"id":"AGD-0017","file":"workflow/agendas/AGD-0017-jenkinsfile-correction.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}],"decisions":[{"id":"DEC-0002","file":"workflow/decisions/DEC-0002-jenkinsfile-strategy.md","status":"accepted","created_at":"2026-04-07","updated_at":"2026-04-07"}],"plans":[{"id":"PLN-0002","file":"workflow/plans/PLN-0002-jenkinsfile-execution.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}],"lessons":[{"id":"LSN-0020","file":"lessons/DSC-0019-jenkins-ci-standardization/LSN-0020-jenkins-standard-relocation.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}]} -{"type":"discussion","id":"DSC-0030","status":"open","ticket":"internal-viewport-270p","title":"Agenda - Internal Viewport 270p (480x270)","created_at":"2026-04-27","updated_at":"2026-04-27","tags":["gfx","runtime","viewport","resolution","frame-composer","host"],"agendas":[{"id":"AGD-0030","file":"workflow/agendas/AGD-0030-internal-viewport-270p.md","status":"done","created_at":"2026-04-27","updated_at":"2026-04-27"}],"decisions":[{"id":"DEC-0022","file":"workflow/decisions/DEC-0022-internal-viewport-270p.md","status":"accepted","created_at":"2026-04-27","updated_at":"2026-04-27","ref_agenda":"AGD-0030"}],"plans":[{"id":"PLN-0043","file":"workflow/plans/PLN-0043-runtime-270p-core-migration.md","status":"done","created_at":"2026-04-27","updated_at":"2026-04-27","ref_decisions":["DEC-0022"]},{"id":"PLN-0044","file":"workflow/plans/PLN-0044-host-and-tests-270p-propagation.md","status":"done","created_at":"2026-04-27","updated_at":"2026-04-27","ref_decisions":["DEC-0022"]},{"id":"PLN-0045","file":"workflow/plans/PLN-0045-specs-and-docs-270p-publication.md","status":"review","created_at":"2026-04-27","updated_at":"2026-04-27","ref_decisions":["DEC-0022"]}],"lessons":[]} +{"type":"discussion","id":"DSC-0030","status":"done","ticket":"internal-viewport-270p","title":"Agenda - Internal Viewport 270p (480x270)","created_at":"2026-04-27","updated_at":"2026-04-28","tags":["gfx","runtime","viewport","resolution","frame-composer","host"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0039","file":"lessons/DSC-0030-internal-viewport-270p/LSN-0039-resolution-baseline-changes-are-runtime-wide-contracts.md","status":"done","created_at":"2026-04-28","updated_at":"2026-04-28"}]} diff --git a/discussion/workflow/agendas/AGD-0030-internal-viewport-270p.md b/discussion/workflow/agendas/AGD-0030-internal-viewport-270p.md deleted file mode 100644 index d0317036..00000000 --- a/discussion/workflow/agendas/AGD-0030-internal-viewport-270p.md +++ /dev/null @@ -1,133 +0,0 @@ ---- -id: AGD-0030 -ticket: internal-viewport-270p -title: Agenda - Internal Viewport 270p (480x270) -status: done -created: 2026-04-27 -resolved: 2026-04-27 -decision: DEC-0022 -tags: [gfx, runtime, viewport, resolution, frame-composer, host] ---- - -# Agenda - Internal Viewport 270p (480x270) - -## Contexto - -O runtime hoje trata `320x180` como viewport interna canonica em pontos importantes do pipeline, inclusive documentacao de hardware, `FrameComposer`, `SceneViewportResolver` e testes do host/debug overlay. - -A proposta e subir a resolucao interna para `480x270`, preservando a mesma proporcao `16:9`, mas alterando custo de composicao, tamanho de caches, area visivel da camera e possivelmente algumas expectativas implicitas de contrato entre runtime, host, assets e tooling. - -Existe contexto arquitetural recente relevante: - -- `DSC-0025` separou cena canonica, viewport cache e politica de resolver; -- `DSC-0026` consolidou `FrameComposer` como dono da composicao do frame; -- a mudanca agora nao e apenas trocar um par de constantes, porque a viewport interna participa de sizing, copy policy, camera framing e budget de memoria. - -## Problema - -Precisamos decidir se a viewport interna do Prometeu deve deixar de ser `320x180` e passar a ser `480x270` como novo baseline do runtime. - -A decisao precisa fechar: - -- se `480x270` vira contrato fixo do sistema ou apenas default configuravel; - vira contrato fixo do sistema -- se a camera e o frame visible devem realmente expor mais mundo ou apenas densidade maior; - esse deve ser o frame visible default (zoom de camera sera discutido em outra agenda) -- como ficam caches, copy regions, sprite/world composition e apresentacao no host; - devem seguir o mesmo padrao que temos hj, mas com uma area maior. -- qual o impacto aceito em CPU, RAM e largura de banda para o target handheld. - o impacto foi aceito na integra. esssa mudanca eh definitiva e deve perfurar em specs e docs. - -## Pontos Criticos - -- Compatibilidade de contrato: - qualquer lugar que hoje assume `320x180` pode deixar de ser detalhe interno e passar a ser break de comportamento observavel. - devemos corrigir onde for necessario. -- Custo de frame: - `480x270` aumenta pixels por frame em 2.25x versus `320x180`, o que pode afetar render software, fades, copy/convert no host e overlays. - o impacto foi aceito na integra. -- Viewport cache e resolver: - o `SceneViewportResolver` e o sizing do `FrameComposer` dependem diretamente da viewport para anchor, drift, hysteresis e regioes de refresh. -- mudancas necessarias para esse novo tamanho. -- Semantica de camera: - aumentar a viewport pode mudar gameplay, enquadramento, spawn visibility e design de HUD se o jogo passa a ver mais mundo. -- sem compat. nao ha jogos ainda usando essas features. -- Host e debug tooling: - overlay, apresentacao desktop e eventuais capturas/testes visuais hoje ainda carregam suposicoes de `320x180`. - precisamos atuar em mudancas ali tb -- Escopo de migracao: - precisamos decidir se a troca cobre apenas runtime/host ou tambem specs, exemplos, assets de referencia e testes de regressao. - devemos migrar tudo para o novo tamanho. os assets nao sao necessarios, podemos mante-los no mesmo tamanho, com excessao dos glyphos de texto. - -## Hotspots Atuais - -- [hardware.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-drivers/src/hardware.rs#L24) -- [frame_composer.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-drivers/src/frame_composer.rs#L197) -- [scene_viewport_resolver.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-hal/src/scene_viewport_resolver.rs#L56) -- [overlay.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/host/prometeu-host-desktop-winit/src/overlay.rs#L478) - -## Alvo da Discussao - -Definir o contrato correto para a viewport interna 270p no runtime e quais propagacoes sao obrigatorias antes de qualquer mudanca em spec ou codigo. - -## Opcoes - -### Opcao A - Manter `320x180` como contrato canonico - -- **Abordagem:** - rejeitar a troca de baseline e, se necessario, melhorar apenas o upscale/apresentacao no host. -- **Pro:** - evita reabrir camera, caches, testes e budget de composicao. -- **Con:** - nao entrega mais area/pixel density interna e pode limitar qualidade visual ou framing pretendido. -- **Manutenibilidade:** - custo baixo agora, mas posterga a pergunta arquitetural se `320x180` ja nao representa mais o alvo real do produto. - -### Opcao B - Promover `480x270` a nova viewport canonica fixa - -- **Abordagem:** - trocar o baseline interno do sistema inteiro para `480x270` e propagar a mudanca onde o contrato hoje assume `320x180`. -- **Pro:** - simplifica o modelo final: uma resolucao interna oficial, sem modo duplo. -- **Con:** - aumenta custo por frame, pode expor mais mundo do que jogos atuais esperam e exige migracao coordenada em runtime/host/tests/specs. -- **Manutenibilidade:** - boa se o produto realmente quer 270p como target oficial; ruim se depois precisarmos voltar a variabilidade. - -### Opcao C - Introduzir viewport interna configuravel com `320x180` e `480x270` - -- **Abordagem:** - transformar a viewport interna em configuracao de sistema/composer, permitindo coexistencia de 180p e 270p. -- **Pro:** - reduz risco de migracao abrupta e facilita benchmark comparativo. -- **Con:** - amplia superficie de contrato, multiplica combinacoes de teste e pode contaminar caminhos que hoje assumem um unico baseline. -- **Manutenibilidade:** - pior no curto e medio prazo; so vale se variabilidade de resolucao for requisito real de produto, nao apenas etapa de transicao. - -## Sugestao / Recomendacao - -Seguir inicialmente com a **Opcao B** como hipotese de trabalho: `480x270` deve ser tratado como novo baseline canonico, nao como configuracao geral. - -A recomendacao, porem, fica condicionada a duas verificacoes antes do fechamento da agenda: - -- confirmar que o efeito desejado e realmente aumentar a viewport observavel do jogo, e nao apenas melhorar a cadeia de apresentacao; -- confirmar que o custo extra de composicao e caches cabe no budget aceito para o handheld alvo. - -Se qualquer uma dessas premissas falhar, a Opcao A ou uma variante mais restrita da Opcao C volta a ser competitiva. - -## Perguntas em Aberto - -- A mudanca pretende mostrar mais mundo por frame ou manter o mesmo framing com outra granularidade visual? - mostrar mais mundo -- `480x270` deve ser contrato global do runtime ou apenas default do host desktop? - contrato global do runtime, o prometeu passa a ser um console 270p -- Quais syscalls, specs ou expectativas de cartridge assumem implicitamente a area visivel atual? - todas se e quando necessario -- O budget de `SceneViewportCache` e das copias incrementais continua aceitavel com 2.25x mais pixels? - sim, aqui se tornarao ainda mais importantes -- Fade, overlay e conversao `RGB565 -> RGBA8` no host permanecem viaveis sem nova rodada de otimizacao? - por enquanto iremos com o que temos, otimizaremos depois -- Ha assets, HUDs ou testes snapshot que dependem do framing de `320x180`? - nao, nada que nao possa ser migrado para o novo tamanho, mas sem necessidade de vc atuar nisso. - -## Criterio para Encerrar - -Esta agenda pode ser encerrada quando houver alinhamento suficiente para escrever uma decisao que feche explicitamente: - -- se `480x270` substitui `320x180` como contrato canonico; - sim -- se a viewport maior muda framing/gameplay observavel ou apenas rasterizacao interna; - maior framing -- quais modulos precisam de propagacao obrigatoria em runtime, host, specs e testes; - todos -- qual evidence minima de custo/memoria e necessaria para executar a migracao com seguranca. - o preco jah foi aceito, iremos migrar. - -## Resolucao - -A agenda foi encerrada com decisao favoravel a promover `480x270` como resolucao interna canonica do Prometeu. - -O novo tamanho passa a definir o frame visible default do console, com maior area observavel de mundo, sem compromisso de compatibilidade com o framing anterior de `320x180`. - -A migracao deve perfurar runtime, host, touch, specs, docs e testes. Otimizacoes de custo adicionais nao bloqueiam a mudanca: o aumento de CPU, RAM e bandwidth foi aceito como custo estrutural do novo baseline. diff --git a/discussion/workflow/decisions/DEC-0022-internal-viewport-270p.md b/discussion/workflow/decisions/DEC-0022-internal-viewport-270p.md deleted file mode 100644 index d3d97cf4..00000000 --- a/discussion/workflow/decisions/DEC-0022-internal-viewport-270p.md +++ /dev/null @@ -1,115 +0,0 @@ ---- -id: DEC-0022 -ticket: internal-viewport-270p -title: Internal Viewport 270p (480x270) as Canonical Runtime Contract -status: accepted -created: 2026-04-27 -accepted: 2026-04-27 -agenda: AGD-0030 -plans: [PLN-0043, PLN-0044, PLN-0045] -tags: [gfx, runtime, viewport, resolution, frame-composer, host, touch] ---- - -## Status - -Accepted on `2026-04-27`. - -This decision is normatively locked until explicitly revised by a later decision. - -## Contexto - -O runtime do Prometeu ainda trata `320x180` como resolucao interna canonica em pontos centrais do sistema, incluindo `Hardware`, `FrameComposer`, host desktop, touch mapping, documentacao de hardware e testes. - -O trabalho recente de `DSC-0025` e `DSC-0026` consolidou o modelo correto para esse tipo de mudanca: viewport cache, resolver e frame composition ja possuem ownership claro e aceitam propagacao consistente a partir de um baseline unico de viewport. - -O objetivo desta decisao nao e melhorar upscale do host. O objetivo e redefinir o contrato do console para `480x270` como resolucao interna oficial, com maior area visivel de mundo por frame. - -## Decisao - -O Prometeu SHALL adotar `480x270` como resolucao interna canonica do runtime. - -`320x180` MUST cease to be treated as o baseline operacional do console em runtime, host, specs, docs e testes. - -`480x270` MUST representar o frame visible default do sistema. A mudanca e observavel: o console passa a mostrar mais mundo por frame. - -O runtime MUST NOT introduzir, nesta migracao, um modo dual `180p/270p` nem uma configuracao geral de viewport interna. - -Qualquer discussao futura sobre zoom de camera, framing alternativo ou modos adicionais MUST acontecer em discussao separada e MUST NOT enfraquecer este contrato base por inferencia. - -## Rationale - -Um baseline unico e fixo reduz ambiguidade de contrato e evita contaminar `FrameComposer`, host e specs com variabilidade que nao foi pedida como requisito real de produto. - -Aumentar apenas a cadeia de apresentacao do host nao resolve o objetivo do trabalho, porque o requisito aceito e ampliar o frame visible do console, nao apenas ampliar a imagem final. - -O custo estrutural de `480x270` foi explicitamente aceito. Portanto, CPU, RAM e bandwidth adicionais nao sao criterio de veto nesta decisao; passam a ser apenas materia de otimizacao posterior. - -Como ainda nao existem jogos dependentes do framing anterior, nao ha motivo para carregar compatibilidade legada como restricao principal desta migracao. - -## Invariantes / Contrato - -- `Hardware::W` e `Hardware::H` MUST convergir para `480` e `270`. -- O framebuffer canonico do runtime MUST operar em `480x270` RGB565. -- O host desktop MUST criar sua superficie base a partir da nova resolucao canonica e MUST mapear touch/pointer para o novo dominio absoluto. -- `FrameComposer` MUST usar `480x270` como viewport base para scene binding, camera framing, cache sizing e resolver ownership. -- `SceneViewportResolver` e `SceneViewportCache` MUST preservar o modelo atual de ownership e refresh policy; a mudanca e de baseline dimensional, nao de arquitetura. -- O efeito observavel da camera MUST ser maior framing por frame. Esta decisao MUST NOT ser reinterpretada como mero aumento de densidade com framing igual. -- A conversao `RGB565 -> RGBA8`, fades, overlay e copy paths MAY permanecer com a implementacao atual nesta etapa. Otimizacao posterior e permitida, mas nao e precondicao para adotar `480x270`. -- Assets existentes MUST continuar validos quando seu contrato nao depende da resolucao base. A migracao de assets em massa MUST NOT ser inventada como parte obrigatoria desta decisao. -- Glyphs e superficies textuais MAY exigir ajuste posterior quando o novo framing expuser necessidade de nova ocupacao visual, mas isso nao bloqueia o baseline 270p. - -## Impactos - -### Runtime - -- `Hardware`, `Gfx`, `FrameComposer`, `SceneViewportResolver` e caminhos relacionados passam a operar sobre `480x270`. -- Buffers de frame e custos por pixel aumentam estruturalmente. -- O budget de viewport cache e copy path continua valido conceitualmente, mas com volume maior de trabalho e memoria. - -### Host - -- O host desktop deve recriar sua superficie `Pixels` no novo tamanho base. -- O mapeamento de input absoluto deve seguir `480x270`. -- Overlay e qualquer teste de RGBA host-owned devem abandonar hardcodes de `320x180`. - -### Firmware / Guest / ABI - -- O espaco visivel observado pelo software convidado muda porque a camera default passa a enquadrar uma area maior. -- Esta decisao nao cria nova syscall, nao muda formato de argumento e nao introduz seletor de resolucao. - -### Specs / Docs - -- As specs canonicas do runtime MUST publicar `480x270` como resolucao oficial. -- Textos sobre touch e framebuffer MUST ser atualizados para refletir o novo dominio coordenado. - -### Tooling / Tests - -- Testes com hardcodes de `320x180` MUST migrar. -- Snapshots, asserts de tamanho e fixtures de host/debug MUST convergir para `480x270`. - -## Referencias - -- `AGD-0030` - Internal Viewport 270p (480x270) -- `DSC-0025` - Scene Bank and Viewport Cache Refactor -- `DSC-0026` - Integrate render_all with Scene Cache and Camera -- [hardware.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-drivers/src/hardware.rs:116) -- [runner.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/host/prometeu-host-desktop-winit/src/runner.rs:229) -- [input.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/host/prometeu-host-desktop-winit/src/input.rs:73) -- [04-gfx-peripheral.md](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/docs/specs/runtime/04-gfx-peripheral.md:22) -- [07-touch-peripheral.md](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/docs/specs/runtime/07-touch-peripheral.md:20) - -## Propagacao Necessaria - -- Atualizar constantes canonicas de resolucao em runtime. -- Atualizar criacao de framebuffer e apresentacao no host desktop. -- Atualizar mapping absoluto de touch/pointer. -- Atualizar testes de `FrameComposer`, `SceneViewportResolver`, host overlay e demais asserts fixos de tamanho. -- Atualizar specs e docs que ainda publicam `320x180`. -- Escrever um plano de execucao que separe: - runtime/host/tests; - specs/docs; - qualquer ajuste textual ou visual adicional nao bloqueante. - -## Revision Log - -- `2026-04-27`: Initial accepted decision from `AGD-0030`. diff --git a/discussion/workflow/plans/PLN-0043-runtime-270p-core-migration.md b/discussion/workflow/plans/PLN-0043-runtime-270p-core-migration.md deleted file mode 100644 index e8b97e57..00000000 --- a/discussion/workflow/plans/PLN-0043-runtime-270p-core-migration.md +++ /dev/null @@ -1,123 +0,0 @@ ---- -id: PLN-0043 -ticket: internal-viewport-270p -title: Runtime 270p Core Migration -status: done -created: 2026-04-27 -completed: 2026-04-27 -tags: [gfx, runtime, viewport, resolution, frame-composer] ---- - -## Briefing - -This plan executes the first mandatory slice of `DEC-0022`: migrate the canonical runtime resolution from `320x180` to `480x270` inside the core runtime path before any host-facing or documentation-only propagation. - -This plan intentionally prioritizes runtime ownership, framebuffer sizing, `FrameComposer` baseline, resolver/cache sizing behavior, and runtime-local tests. It does not include host window/input propagation or specs/docs publication. - -## Decisions de Origem - -- `DEC-0022` - Internal Viewport 270p (480x270) as Canonical Runtime Contract - -## Alvo - -Make the runtime itself operate canonically at `480x270` RGB565 and preserve the existing scene/cache/resolver architecture under the new baseline. - -## Escopo - -- Update canonical runtime width/height constants. -- Propagate the new resolution through `Hardware`, `Gfx`, and `FrameComposer`. -- Preserve `SceneViewportResolver` and `SceneViewportCache` architecture while updating runtime assumptions and tests derived from the old baseline. -- Recompute runtime expectations that explicitly depended on `320x180`. - -## Fora de Escopo - -- Host desktop surface creation and pointer mapping. -- Host overlay RGBA fixtures. -- Specs and docs publication. -- Asset migrations or text/glyph content redesign. - -## Plano de Execucao - -### Step 1 - Promote runtime-wide canonical dimensions - -**What:** -Change the runtime’s canonical internal framebuffer dimensions from `320x180` to `480x270`. - -**How:** -Update the canonical constants and any runtime-local documentation/comments that still publish the old baseline, ensuring all `Gfx` and `FrameComposer` construction paths inherit the new dimensions from the same source of truth. - -**File(s):** -- `crates/console/prometeu-drivers/src/hardware.rs` -- `crates/console/prometeu-drivers/src/gfx.rs` - -### Step 2 - Rebaseline frame composition and scene runtime sizing - -**What:** -Make `FrameComposer` use `480x270` as the canonical viewport baseline for scene binding and scene-runtime construction. - -**How:** -Keep the existing ownership split (`FrameComposer` -> `SceneViewportCache` + `SceneViewportResolver`) intact, but update construction-time expectations and tests that hardcode `320x180`. Preserve the current cache sizing algorithm and hysteresis derivation; do not introduce configurable dual-mode resolution. - -**File(s):** -- `crates/console/prometeu-drivers/src/frame_composer.rs` - -### Step 3 - Rebaseline resolver expectations under 270p - -**What:** -Update resolver tests and derived numeric expectations to the `480x270` viewport. - -**How:** -Adjust test fixtures that currently instantiate `SceneViewportResolver::new(320, 180, 25, 16, 12, 20)` and recompute anchor, clamp, and refresh-region assertions from the 270p baseline. Preserve behavioral intent: -- anchor initialization; -- parallax propagation; -- hysteresis stability; -- edge clamping; -- incremental refresh behavior. - -**File(s):** -- `crates/console/prometeu-hal/src/scene_viewport_resolver.rs` - -### Step 4 - Rebaseline runtime integration tests - -**What:** -Update runtime-level tests that validate compositor/runtime invariants using the old resolution. - -**How:** -Migrate runtime integration assertions so they derive expected sizes from the new baseline or from the runtime constants. Keep scene-cache and sprite-order semantics unchanged; only the canonical viewport contract changes. - -**File(s):** -- `crates/console/prometeu-drivers/src/hardware.rs` -- `crates/console/prometeu-drivers/src/frame_composer.rs` -- `crates/console/prometeu-drivers/src/gfx.rs` - -## Criterios de Aceite - -- `Hardware::W == 480` and `Hardware::H == 270`. -- Runtime-owned frame composition uses `480x270` as the canonical viewport. -- Runtime tests no longer hardcode `320x180` as the canonical internal resolution. -- Resolver/cache behavior remains architecturally unchanged apart from the dimensional baseline. -- No configurable `180p/270p` runtime mode is introduced. - -## Tests / Validacao - -### Unit Tests - -- `cargo test` for: - `prometeu-drivers` - `prometeu-hal` - -### Integration Tests - -- Verify `FrameComposer` scene-binding/runtime tests under the new viewport. -- Verify resolver numeric assertions after updating the viewport baseline. - -### Manual Verification - -- Inspect runtime constants and constructor callsites to confirm a single canonical source of truth. -- Confirm no new runtime API for resolution selection was added. - -## Riscos - -- Resolver tests may fail with multiple derived-value changes at once, requiring careful recomputation rather than blind constant replacement. -- Some runtime assertions may accidentally embed old visible-framing assumptions instead of true contract checks. -- Runtime-only completion does not yet yield correct host presentation; that gap is intentional and deferred to the next plan. diff --git a/discussion/workflow/plans/PLN-0044-host-and-tests-270p-propagation.md b/discussion/workflow/plans/PLN-0044-host-and-tests-270p-propagation.md deleted file mode 100644 index fcbd7878..00000000 --- a/discussion/workflow/plans/PLN-0044-host-and-tests-270p-propagation.md +++ /dev/null @@ -1,120 +0,0 @@ ---- -id: PLN-0044 -ticket: internal-viewport-270p -title: Host and Test Propagation for 270p -status: done -created: 2026-04-27 -completed: 2026-04-27 -tags: [host, tests, viewport, resolution, touch, overlay] ---- - -## Briefing - -This plan executes the second mandatory slice of `DEC-0022`: propagate the accepted `480x270` runtime contract into host presentation, absolute pointer mapping, host-side overlay/test fixtures, and any remaining test surfaces that still assume `320x180`. - -This plan depends on `PLN-0043` completing first. It must not redefine the runtime contract; it only propagates the already-accepted 270p baseline into host-owned behavior and validation surfaces. - -## Decisions de Origem - -- `DEC-0022` - Internal Viewport 270p (480x270) as Canonical Runtime Contract - -## Alvo - -Make the desktop host and test surface faithfully consume the new canonical runtime resolution and touch domain. - -## Escopo - -- Update host framebuffer/surface creation to `480x270`. -- Update absolute pointer/touch mapping to the new canonical domain. -- Update host overlay fixtures and tests that still allocate or draw against `320x180`. -- Sweep remaining test hardcodes outside the core runtime step. - -## Fora de Escopo - -- Core runtime ownership changes already covered by `PLN-0043`. -- Specs and docs publication. -- Post-migration visual redesign or typography/layout tuning beyond strict propagation. - -## Plano de Execucao - -### Step 1 - Rebaseline host presentation surface - -**What:** -Make the desktop host create and present its base `Pixels` surface using the new canonical runtime dimensions. - -**How:** -Update host initialization and redraw flow so `PixelsBuilder`, frame copy, and overlay composition all consume `Hardware::W/H` after the runtime constants move to `480x270`. - -**File(s):** -- `crates/host/prometeu-host-desktop-winit/src/runner.rs` -- `crates/host/prometeu-host-desktop-winit/src/utilities.rs` - -### Step 2 - Rebaseline absolute input mapping - -**What:** -Align pointer/touch translation with the new canonical framebuffer domain. - -**How:** -Update `window_to_fb()` and any clamping logic to map window coordinates into `[0, 479] x [0, 269]` through the canonical `Hardware::W/H` path. - -**File(s):** -- `crates/host/prometeu-host-desktop-winit/src/input.rs` - -### Step 3 - Update host overlay fixtures and tests - -**What:** -Remove host overlay hardcodes that still allocate or draw a `320x180` RGBA buffer. - -**How:** -Update overlay tests and any host-owned fixtures so they use `480x270` or derive from the canonical hardware constants where appropriate. Preserve overlay semantics; do not redesign the overlay in this plan. - -**File(s):** -- `crates/host/prometeu-host-desktop-winit/src/overlay.rs` - -### Step 4 - Sweep remaining non-doc resolution assertions - -**What:** -Capture and update any remaining code or tests outside specs/docs that still depend on the old baseline. - -**How:** -Search for `320x180`, `320, 180`, and equivalent fixed-size assumptions under host/runtime test surfaces and migrate them to the accepted 270p contract or to canonical constants. - -**File(s):** -- `crates/host/prometeu-host-desktop-winit/src/*` -- any remaining test modules under `crates/console/*` - -## Criterios de Aceite - -- The desktop host creates its base surface from the `480x270` canonical runtime dimensions. -- Absolute pointer/touch mapping uses the new framebuffer domain. -- Host overlay tests no longer hardcode `320x180`. -- No host-owned code path reintroduces the old baseline as an implicit contract. - -## Tests / Validacao - -### Unit Tests - -- `cargo test` for: - `prometeu-host-desktop-winit` - any directly impacted console crates - -### Integration Tests - -- Verify runtime frame copy still lands correctly in the host RGBA surface. -- Verify pointer mapping clamps to the new canonical framebuffer bounds. - -### Manual Verification - -- Launch the desktop host and confirm the window presents a `480x270` logical framebuffer. -- Confirm overlay still renders and aligns within the new frame domain. -- Confirm pointer/touch interaction reaches the expected screen edges. - -## Riscos - -- Host visual regressions may appear only at runtime even when tests pass. -- Overlay layout may become visually awkward at 270p even if functionally correct; cosmetic tuning is intentionally deferred. -- Partial migration risks mismatch between runtime dimensions and host test fixtures if `PLN-0043` is not completed first. - -## Dependencies - -- `PLN-0043` MUST complete first. diff --git a/discussion/workflow/plans/PLN-0045-specs-and-docs-270p-publication.md b/discussion/workflow/plans/PLN-0045-specs-and-docs-270p-publication.md deleted file mode 100644 index e43227f3..00000000 --- a/discussion/workflow/plans/PLN-0045-specs-and-docs-270p-publication.md +++ /dev/null @@ -1,105 +0,0 @@ ---- -id: PLN-0045 -ticket: internal-viewport-270p -title: Specs and Docs Publication for 270p -status: review -created: 2026-04-27 -completed: -tags: [specs, docs, runtime, viewport, resolution] ---- - -## Briefing - -This plan executes the final mandatory slice of `DEC-0022`: publish the accepted `480x270` console contract in canonical specs and supporting documentation after runtime and host propagation are already in place. - -This plan must run last. It exists to prevent public documentation from getting ahead of executable reality. - -## Decisions de Origem - -- `DEC-0022` - Internal Viewport 270p (480x270) as Canonical Runtime Contract - -## Alvo - -Update canonical published documentation so the repository describes Prometeu as a `480x270` console with matching framebuffer and touch coordinate semantics. - -## Escopo - -- Update runtime specs that explicitly publish `320x180`. -- Update any nearby prose that describes visual behavior in a way that now depends on the new baseline. -- Update related README/index material if it repeats the old resolution as canonical fact. - -## Fora de Escopo - -- Runtime or host code changes. -- Asset migration. -- Any broader narrative cleanup unrelated to the 270p contract. - -## Plano de Execucao - -### Step 1 - Update framebuffer and graphics specs - -**What:** -Publish `480x270` as the canonical graphics/framebuffer resolution in the runtime graphics spec. - -**How:** -Update the base-resolution and related descriptive sections so they state the new canonical resolution without ambiguity. Any prose that references `320x180` as a defining visual baseline must be revised to stay accurate. - -**File(s):** -- `docs/specs/runtime/04-gfx-peripheral.md` - -### Step 2 - Update touch coordinate contract - -**What:** -Publish the new absolute touch domain that matches the 270p framebuffer. - -**How:** -Update the touch spec so resolution, coordinate ranges, and any coordinate-space examples reflect `[0, 479] x [0, 269]`. - -**File(s):** -- `docs/specs/runtime/07-touch-peripheral.md` - -### Step 3 - Sweep remaining resolution references in runtime docs - -**What:** -Remove remaining canonical `320x180` references from runtime docs and supporting material where they now contradict `DEC-0022`. - -**How:** -Search runtime specs and adjacent docs for explicit resolution references and update only the ones that are part of the public console contract. Do not rewrite unrelated prose that merely mentions resolution in a different context unless it becomes incorrect after the migration. - -**File(s):** -- `docs/specs/runtime/*.md` -- `docs/specs/runtime/README.md` -- any other directly affected docs under `docs/` - -## Criterios de Aceite - -- Canonical runtime docs publish `480x270` as the official internal resolution. -- Touch docs publish coordinate ranges consistent with `480x270`. -- No remaining public spec text describes `320x180` as the canonical console baseline. -- Documentation order reflects executable truth: runtime/host migration is already completed before docs close. - -## Tests / Validacao - -### Unit Tests - -- No code unit tests are required for documentation-only changes. - -### Integration Tests - -- Re-run any repository validation or doc-linked checks that are already part of the normal workflow if available. - -### Manual Verification - -- Read the updated specs end-to-end for `gfx` and `touch` to confirm they agree with `DEC-0022`. -- Confirm no public-facing contradiction remains between docs and the implemented runtime baseline. - -## Riscos - -- Publishing docs before code would create a contract/execution mismatch; this is why this plan must remain last. -- Resolution references can hide in explanatory prose and examples, not only in obvious headings. -- Over-editing adjacent docs can accidentally turn a narrowly scoped publication task into a broad editorial rewrite. - -## Dependencies - -- `PLN-0043` MUST complete first. -- `PLN-0044` SHOULD complete first, and MUST complete first if any host-facing docs mention live desktop behavior. diff --git a/docs/specs/runtime/04-gfx-peripheral.md b/docs/specs/runtime/04-gfx-peripheral.md index 9948ec54..9e757c1e 100644 --- a/docs/specs/runtime/04-gfx-peripheral.md +++ b/docs/specs/runtime/04-gfx-peripheral.md @@ -23,7 +23,7 @@ It is an explicit 2D graphics device based on: ### Base resolution -- **320 × 180 pixels** +- **480 × 270 pixels** - aspect ratio close to 16:9 - scalable by the host (nearest-neighbor) @@ -142,9 +142,9 @@ The cache is a window of tiles around the camera. Example: -- Screen: 320×180 -- 16×16 tiles → 20×12 visible -- Cache: 22×14 (1-tile margin) +- Screen: 480×270 +- 16×16 tiles → approximately 30×17 visible +- Current runtime cache sizing with 16×16 layers: 35×21 tiles It stores tiles already resolved from the tilemap. @@ -316,7 +316,7 @@ In v1, deferred `gfx.*` overlay/debug primitives are drained after both fades an The fade is implemented without continuous per-pixel alpha and without floats. It uses a **discrete integer level** (0..31), which in practice produces an -"almost continuous" visual result in 320×180 pixel art. +"almost continuous" visual result in Prometeu's `480x270` pixel-art framebuffer. --- diff --git a/docs/specs/runtime/07-touch-peripheral.md b/docs/specs/runtime/07-touch-peripheral.md index c96dfc30..19999641 100644 --- a/docs/specs/runtime/07-touch-peripheral.md +++ b/docs/specs/runtime/07-touch-peripheral.md @@ -20,11 +20,11 @@ Core contract: ## 2 Coordinate Space - TOUCH coordinates use **the same space as the framebuffer** -- Resolution: **320×180** +- Resolution: **480×270** - Origin: top-left corner `(0,0)` - Ranges: - - `x ∈ [0, 319]` - - `y ∈ [0, 179]` + - `x ∈ [0, 479]` + - `y ∈ [0, 269]` TOUCH is **absolute**: -- 2.47.2 From b82363d06578c65150550d743acbf25e4ee644b8 Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Tue, 28 Apr 2026 18:19:28 +0100 Subject: [PATCH 6/8] Internal Viewport 270p (480x270) --- ...line-changes-are-runtime-wide-contracts.md | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 discussion/lessons/DSC-0030-internal-viewport-270p/LSN-0039-resolution-baseline-changes-are-runtime-wide-contracts.md diff --git a/discussion/lessons/DSC-0030-internal-viewport-270p/LSN-0039-resolution-baseline-changes-are-runtime-wide-contracts.md b/discussion/lessons/DSC-0030-internal-viewport-270p/LSN-0039-resolution-baseline-changes-are-runtime-wide-contracts.md new file mode 100644 index 00000000..de5024c5 --- /dev/null +++ b/discussion/lessons/DSC-0030-internal-viewport-270p/LSN-0039-resolution-baseline-changes-are-runtime-wide-contracts.md @@ -0,0 +1,72 @@ +--- +id: LSN-0039 +ticket: internal-viewport-270p +title: Resolution Baseline Changes Are Runtime-Wide Contracts, Not Host-Only Resizes +created: 2026-04-28 +tags: [gfx, runtime, viewport, resolution, frame-composer, host, docs] +--- + +## Context + +`DSC-0030` changed Prometeu's canonical internal viewport from `320x180` to `480x270`. The important outcome was not just a larger host window or sharper scaling. The accepted contract changed what the console shows per frame, which forced coordinated propagation through runtime constants, frame composition, host presentation, pointer mapping, tests, stress fixtures, and published specs. + +The work only became truly complete after specs and touch semantics were updated to match executable reality. Until that final publication step, the discussion was still operationally open even though most code paths had already migrated. + +## Key Decisions + +### Resolution Baseline Is a Console Contract + +**What:** +`480x270` became the single canonical runtime framebuffer and viewport baseline for Prometeu. + +**Why:** +Treating resolution as a host presentation detail would preserve the old framing and miss the product-level intent. The migration was explicitly about showing more world per frame, so the contract had to move at the runtime level. + +**Trade-offs:** +This increases framebuffer, cache, and copy-path cost. It also makes partial migrations dangerous because old assumptions can survive in tests, tools, and docs even after the main runtime constants change. + +### Propagation Must Follow Ownership Boundaries + +**What:** +The migration propagated through the systems that actually own the contract: +- runtime constants and `FrameComposer` viewport behavior; +- host framebuffer creation and absolute touch mapping; +- tests and stress cartridges that encode visible-domain assumptions; +- public specs for graphics and touch semantics. + +**Why:** +Viewport changes cross subsystem boundaries, but each subsystem should update only the part it owns. That keeps the migration coherent without re-opening unrelated architecture. + +**Trade-offs:** +The work naturally splits into several execution slices. That adds coordination overhead, but it prevents one oversized patch from mixing runtime behavior, host presentation, and documentation cleanup without a clear boundary. + +### Housekeeping Should Wait for the Last Contract Publication Step + +**What:** +The discussion was only ready for cleanup after the docs slice closed and no public spec still described `320x180` as canonical. + +**Why:** +A finished implementation with stale published contract text is still incomplete from the repository's point of view. Housekeeping should reflect published truth, not just mostly-finished code. + +**Trade-offs:** +This keeps discussions open slightly longer, but it avoids archiving a thread before the normative contract is actually consistent everywhere it is published. + +## Patterns and Algorithms + +- Treat viewport or resolution changes as contract migrations, not cosmetic host tweaks. +- Split propagation by ownership: runtime, host/tests, then specs/docs. +- Rebase stress fixtures and generated cartridges when they encode screen-domain assumptions. +- Use one canonical source of resolution truth in code and make docs follow only after executable migration is complete. + +## Pitfalls + +- Updating only the host surface can look successful while silently preserving the wrong gameplay framing. +- Test fixtures and generated artifacts often keep old screen bounds longer than production code. +- Documentation can lag behind implementation and keep the discussion operationally open even when code seems done. + +## Takeaways + +- Internal resolution is part of the console contract and must be migrated runtime-wide. +- A framing change is not equivalent to a presentation-scale change. +- Specs and generated stress assets are part of closing the contract, not optional cleanup. +- Housekeeping should happen only after code, tests, tooling, and published docs agree on the same baseline. -- 2.47.2 From eda9c6e61332d9e852d3680c50ba78af150c5103 Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Tue, 28 Apr 2026 18:27:11 +0100 Subject: [PATCH 7/8] Internal Viewport 270p (480x270) --- Cargo.toml | 5 +---- VERSION.txt | 2 +- scripts/gen-version.sh | 2 +- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 7e6459fc..cc8e5d61 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,15 +1,12 @@ [workspace] members = [ - "crates/console/prometeu-bytecode", - + "crates/console/prometeu-bytecode", "crates/console/prometeu-drivers", "crates/console/prometeu-firmware", "crates/console/prometeu-hal", "crates/console/prometeu-system", "crates/console/prometeu-vm", - "crates/host/prometeu-host-desktop-winit", - "crates/tools/prometeu-cli", "crates/tools/pbxgen-stress", "crates/dev/prometeu-test-support", diff --git a/VERSION.txt b/VERSION.txt index 8b137891..6e8bf73a 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ - +0.1.0 diff --git a/scripts/gen-version.sh b/scripts/gen-version.sh index c0fa86ee..4f32215b 100755 --- a/scripts/gen-version.sh +++ b/scripts/gen-version.sh @@ -1,5 +1,5 @@ #!/bin/bash # Get version from git tag or fallback to Cargo.toml version -VERSION=$(git describe --tags --abbrev=0 2>/dev/null || grep -m 1 '^version =' crates/prometeu/Cargo.toml | cut -d '"' -f 2 || echo "0.1.0") +VERSION=$(git describe --tags --abbrev=0 2>/dev/null || grep -m 1 '^version =' crates/tools/prometeu-cli/Cargo.toml | cut -d '"' -f 2 || echo "0.1.0") echo "$VERSION" > VERSION.txt echo "Generated VERSION.txt with version $VERSION" \ No newline at end of file -- 2.47.2 From 1bd64e6bc50820978bc39d279a791d93cbf24513 Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Tue, 28 Apr 2026 18:27:29 +0100 Subject: [PATCH 8/8] Internal Viewport 270p (480x270) --- crates/tools/pbxgen-stress/src/lib.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/crates/tools/pbxgen-stress/src/lib.rs b/crates/tools/pbxgen-stress/src/lib.rs index e89b2479..6af0bde7 100644 --- a/crates/tools/pbxgen-stress/src/lib.rs +++ b/crates/tools/pbxgen-stress/src/lib.rs @@ -366,11 +366,7 @@ fn build_scene_bank() -> SceneBank { 2 => ParallaxFactor { x: 0.5, y: 0.5 }, _ => ParallaxFactor { x: 0.25, y: 0.25 }, }, - tilemap: TileMap { - width: STRESS_SCENE_TILE_W, - height: STRESS_SCENE_TILE_H, - tiles, - }, + tilemap: TileMap { width: STRESS_SCENE_TILE_W, height: STRESS_SCENE_TILE_H, tiles }, } }); -- 2.47.2