FANCO v6 experimental RGBA palette and RGB effects ================================================ Only v6 implements these ports. 0070–0078 were scratch bytes in earlier prototypes and are now intentionally assigned to graphics. There is no frame-sized RGB RAM allocation in the guest's 64 KiB address space. Ports (hex addresses, byte accesses unless stated) ------------------------------------------------ 0070 Palette write index (0–255) 0071 Staged red (0–255) 0072 Staged green (0–255) 0073 Blue: writing commits staged R,G, this B and staged alpha (0078) to the selected RGBA8888 palette entry, then increments 0070 modulo 256. Reads return the last written B. 0074 Drawing mode: 0 indexed replace, 1 RGB alpha-over, 2 RGB additive. Other values currently behave as indexed replace. 0075 Drawing alpha, 0–255; reset value 255. 0076 Persistence multiplier, 0–255; reset value 255. 0077 Command, write-only action; reads return zero after an action: 1 clear the indexed framebuffer to index 0 and discard RGB overrides; 2 materialize the currently visible image into the RGB surface; 3 materialize and multiply RGB channels by persistence/255. Other command values do nothing. Each command 1–3 costs 65536 virtual work cycles, in addition to instruction bytes. There is no hidden per-presentation decay; the guest issues command 3 once per desired frame. 0078 Staged palette alpha, 0–255; reset value 255. Latched when writing B at 0073, NOT when selecting an index. Existing RGB-only uploads therefore remain opaque without any new initialization. Default palette is the old RGB332 conversion, including rounding: red and green are round(level*255/7), blue is level*85. Palette 0 is initially black. Every palette entry's alpha resets to 255. Indexed replacement ignores palette alpha and remains opaque; alpha is applied only in drawing modes 1 and 2. The palette is RGB888 in the display's ordinary sRGB encoding, NOT linear light or OKLCH. Alpha is an effect amount, not a transparent canvas output; the browser receives opaque RGBA. Wide-gamut/OKLCH support is not implemented. Palette upload example (one entry, then auto-advance): mov.b [0x70],32 mov.b [0x71],20 mov.b [0x72],100 mov.b [0x78],128 ; optional per-entry alpha, otherwise stays 255 mov.b [0x73],240 Temporal and readback semantics ------------------------------- The indexed framebuffer is retained exactly: OUT always stores its source index; IN always reads that index, including after blended drawing. No RGB-to-index quantization or index arithmetic is used for blending. Every pixel is either indexed or an RGB override. Mode 0 writes an index and removes that pixel's RGB override. All indexed pixels resolve through the CURRENT palette, so changing a palette entry recolors previously drawn indexed pixels without redrawing them. Changing the palette does not retroactively recolor RGB overrides: these are accumulated historical RGB. Modes 1 and 2 read the currently visible destination RGB, resolve the source index through the palette at instruction retirement, then store an RGB override. Effective alpha A = floor((global_alpha*palette_alpha + 127)/255). Thus different indices provide different per-pixel alpha in a single BLIT or OUT stream without changing the global alpha per pixel. With source channel S and destination channel D, per channel: alpha-over: floor((S*A + D*(255-A) + 127)/255) additive: min(255, D + floor((S*A + 127)/255)) Alpha zero still writes the IN-visible index and materializes the unchanged visible destination. Command 3 uses floor((channel*persistence+127)/255). Repeated fading can settle on a small nonzero value because of rounding; command 1 guarantees a complete clear. Palette edits after command 2/3 do not recolor the materialized image until new indexed replacement writes. The draw mode and alpha apply equally to OUT and every BLIT destination pixel. Existing BLIT fill, RAM copy, keyed RAM copy and indexed framebuffer copy modes retain their clipping, index keying and source-snapshot rules. Framebuffer BLIT mode 3 copies INDICES, not RGB overrides, and blends those indices using the current palette and draw controls. This is deliberate IN-compatible behavior, not a hidden RGB copy operation. BLIT's alpha-black fill is useful for fading only a rectangle while keeping another rectangle palette-indexed. Palette index 0 must be black for that. All effects happen at guest instruction retirement, not in host animation callbacks. Word stores commit low byte then high byte inside one atomic instruction; e.g. a word store to 0072 stages G then commits its B high byte. Palette programming has no extra work charge; it changes one palette entry. SYS PRESENT captures the visible palette/RGB result before the guest runs again. Rendering or taking extra host snapshots never changes VM state. The host performs only palette expansion and presentation. All geometry, particle motion, palette selection and effect commands belong to guest code. Loading a new application resets palette RGB/alpha, staged alpha, draw mode, global alpha and persistence; ordinary application RAM segments may then initialize the control bytes. Palette commits themselves require guest writes to 0073.