# windemo — jedno okienko: tekst + ikonki góra/dół

Samodzielny `.xex` na Atari 8-bit z VBXE. Bez żadnych assetów z dysku, bez kodu
gry — jeden plik, ~1,6 kB.

```
mads windemo.asm -o:windemo.xex
```

Sterowanie: joystick 0 góra/dół zmienia liczbę (klik, potem auto-repeat
z przyspieszeniem, jak w oryginale). Wyjścia nie ma — po prostu wyłącz Atari.

---

## Tryb graficzny: ani tekstowy, ani mieszany

Cała gra — geoscape, menu, okienka — to **jedna bitmapa**. ANTIC jest wyłączony
już na starcie (`SDMCTL = 0`, `DMACTL = 0`); nie ma display listy, nie ma trybu
znakowego, nie ma playfielda. Obraz generuje VBXE: overlay 320×200, jeden bajt na
piksel, 256 kolorów z palety VBXE #1, framebuffer w VRAM pod `$000000`, stride 320.

Bez VBXE gra się nie uruchomi. Przy tej ilości grafiki nie ma na to rady.

## Teksty: rysowane programowo, glif po glifie

Nie ma tu żadnego `CHBASE`. W VRAM leży „arkusz" fontu, a każdy znak jest wbijany
do framebuffera **blitterem VBXE — jeden blit na znak**.

W grze arkusz siedzi pod `$038000`: 96 glifów (ASCII 32..127), każdy dopchany do
8×16 = 128 bajtów, żeby adres wychodził jako `idx<<7` bez mnożenia (realnie
używane jest 8×9). `draw_text` idzie po stringu zakończonym zerem, odejmuje 32,
odpala blit w trybie 1 (indeks 0 = przezroczysty) i przesuwa `text_x`
o proporcjonalną szerokość z tabeli. Font wypada z oryginalnego `SMALLSET.DAT`
skryptem w Pythonie.

Arkusze są dwa. Jeden ma wypalone oryginalne kolory (dwutonowy). Drugi to **maska**
— każdy piksel to 255. Blitter z `AND = kolor` zamienia go w dowolny indeks
palety, więc jeden font daje tekst w dowolnym kolorze.

To demo nie dołącza żadnego fontu: buduje maskę w locie z zestawu znaków
z ROM-u OS pod `$E000` (patrz `font_expand`). Każdy zapalony bit → 255, zgaszony
→ 0. Dokładnie ta sama technika, tylko bez pliku z danymi.

## Okienko

Ramka to wypełniony prostokąt, lico to drugi, wsunięty o 2 piksele. W grze
w środek wchodzi jeszcze blit wycinka oryginalnej tekstury `.SCR` z innego banku
VRAM, w tych samych współrzędnych ekranowych — dlatego tło okna wygląda jak
w oryginale. Pod oknem nic się nie zapisuje: geoscape ma swoją kopię w VRAM
i wraca jednym pełnoekranowym blitem.

## Ikonki góra/dół

To nie są trójkąciki. `aw_draw` w tym pliku to przepisany 1:1
`ArrowButton::draw()` z OpenXcoma (`src/Interface/ArrowButton.cpp:94-303`).

Przycisk strzałki w X-COM-ie to **fazowane pudełko** — góra i lewa `_color+2`,
dół i prawa `_color+5`, lico `_color+4`, trzy narożne piksele ustawiane osobno —
a w nim trójkąt szeroki na 9 px z nóżką 3×3, cały w `_color+1`. Rozmiar 13×14.

Wciśnięcie to `ImageButton::mousePress` → `invert(_color+3)`, czyli piksel `p`
przechodzi w `2*(_color+3) - p`. Dla `_color+N` wychodzi z tego po prostu
`_color+(6-N)` — więc te same pięć kolorów czytane od tyłu daje wygląd wciśnięty
za darmo. W demie robi to `aw_col`; w grze ta sama tabela offsetów jest wypiekana
do VRAM w obu wariantach naraz.

Lista `box_ops` / `up_ops` / `dn_ops` to dosłownie kolejne wywołania `drawRect`
i `setPixel` z tamtego pliku, zapisane jako `(dx, dy, w, h, offset koloru)`.

---

## Gdzie to jest w prawdziwym kodzie

| co | plik |
|---|---|
| okno (ramka + tło + przyciski) | `src-common/window.asm` |
| tekst (arkusz fontu + blit glifu) | `src-geo/core/font.asm` |
| blitter VBXE + adresowanie VRAM | `src-geo/core/blit.asm` |
| widget strzałki | `src-geo/screens/arrows.inc` + `arrows_data.inc` |
| wypiekanie strzałek z C++ | `tools/geo_arrows.py` |
