FANCO-16 v6 — WORKING PROTOTYPE =============================== V6 is a new instruction encoding and a new SIREN register layout. It is not an automatic hardware profile for older images. Applications use literal ASCII FAN1 followed by byte 06; `.version 6` selects this encoding. V5/05 and unversioned applications are rejected before resetting or changing RAM. The live root arcade remains v5; the v6 prototype has its own /v6/ path. Memory ------ 0000–000F Eight 16-bit CPU registers: a,b,x,y,p,r,sp,pc (little endian) 0010–0011 IRQ vector, little-endian word 0012–0013 Timer Hz word, 0 disables, 1–48000 supported 0014 Read-only IRQ-active flag 0015 Saturating missed-tick count; software may clear it 0020–0021 Buttons word: left/right/up/down/A/B = 1/2/4/8/16/32 0022–0023 Pointer X word (0–255) 0024–0025 Pointer Y word (0–255) 0026–0027 Pointer flags word: down=1, valid=2 0040–005F First-three-voice/basic-volume comparison aliases; see SOUND.txt 0060–006D Blitter, unchanged register meanings 0070–0078 Experimental RGBA8888 palette/blend/persistence ports; GRAPHICS.txt 0080–00A7 Ten four-byte touch slots 00D0–00E7 Two twelve-byte audio capture descriptors 0100–01FF Sixteen sixteen-byte generators 0200–02F3 Eight mixer slots, three filters, master, eight delay lines 02F4–02F7 Chip control Hz, status, fine master volume 0300–FFFF Program/data/stack RAM Other low bytes are usable scratch RAM, not unexplained reserved holes. SP initially FFFE, PC initially 1000. Stack grows downward; the program may choose another SP explicitly. Every address and byte access wraps at 16 bits, except validated DMA records, which must fit without crossing the boundary. CPU semantics ------------- Eight word registers, with `.lo`/`.hi` byte aliases. MOV and zero/sign-extending loads are flag-neutral. Arithmetic, logical operations, shifts, multiply, divide and remainder retain the existing N/Z/C/V meanings: C is carry on ADD, borrow on SUB/CMP. Compare does not store a result. Signed branches use N xor V; BMI/BPL inspect N alone, BVS/BVC inspect V alone. Regular operations: MOV, ADD, SUB, AND, OR, XOR, CMP, SHL, SHR, SAR, MUL, DIV, MOD, LEA, MOVZX, MOVSX. Byte OUT/IN write/read framebuffer pixels. Memory operands include [register], [register+signed-byte], [register++], [--register], and absolute word addresses. LEA computes an address without reading memory or changing flags. Register copies are one byte; common byte loads/stores are two bytes. Full operand forms remain available through FF. General math extensions (word register pairs, destination a..sp, source a..pc): SMULSHIFT dst,src,shift computes the exact signed 16x16 product, arithmetic shifts it right by an immediate 0..31 (rounding toward negative infinity), and stores the low word. N/Z describe that word; C=0; V=1 iff the shifted signed result is outside -32768..32767. Shift 16 is signed high product. UMULHI dst,src stores the unsigned product's high word; N/Z describe it, C=V=0. ADC adds source and incoming C; SBC subtracts source and incoming C (borrow). N/Z describe the low word, C is unsigned carry/borrow, V indicates signed overflow including incoming C. MOV can preserve carry between limbs. These operations cost 4/3/3/3 bytes/cycles respectively. PC as source means the continuation address. Invalid register descriptors or shifts trap before any architectural state, flags, instructions or cycles change. Older valid v6 byte sequences retain their meaning; v5 does not acquire these operations. DIV/MOD remain unsigned word operations; there is no new division mode. ABS dst computes signed absolute value, N/Z describe the low word, C=0, V=1 only for -32768 (result 8000 hex). SMIN/SMAX dst,src select the signed minimum/maximum; N/Z describe the result, C=V=0. All three cost 3 bytes/cycles, use the same word-register restrictions, and leave all other registers alone. Short branches use signed byte displacement from the following instruction; absolute branches use a word target. CALL pushes the continuation word. RET pops PC. IRQ entry atomically pushes PC and flags, then runs the vector. RETI restores flags and PC. Nested hardware IRQs are not queued; missed ticks count up to 255. WAIT jumps to the next armed timer edge. With no timer/pending IRQ, WAIT halts, as does HALT. SYS PRESENT latches the framebuffer; NOP is a one-byte self-copy with no flags or memory side effects. No music/pattern/score instructions or hidden instrument tables are present. FANL/FANR and code-library versioning are outside this prototype's scope. Existing SYS LOAD encoding is retained, but old code libraries must not be assumed compatible with this new ISA. Clock and atomicity ------------------- The virtual cycle clock is 120,000,000 Hz; this does not claim measured native 120 MIPS throughput. An instruction costs its encoded bytes, plus BLIT work, SLEEP duration, IRQ entry or nine-byte envelope DMA as appropriate. Writing timer low byte stages it. Writing high byte commits the projected word, including the low byte of the SAME word store. A word store is one atomic configuration change. Invalid Hz >48000 traps BEFORE any RAM/register mutation. Successful commit resets the timer epoch and pending IRQ, not the currently active handler. Rational period is 120000000/Hz, referenced to that epoch; repeated integer-cycle WAITs round up to the next edge without an accumulating rounded-period drift. A 50-Hz player runs about 0.25% slower than PAL 50.1245 Hz, which was explicitly acceptable for this prototype. All descriptor/width validation and sound-event capacity reservation occur before committing guest registers or RAM. A valid custom-envelope pointer word reserves both parameter events and all ten snapshot events first; backpressure leaves the entire instruction, including PC/cycles, unretired. It then copies nine bytes at retirement, charging nine DMA cycles. The audio renderer never reads future guest RAM to reconstruct that historical record. Audio integration is 48 kHz. CPU event retirement timestamps are accurate in this virtual cycle model, but their application is currently sample-quantized, not a cycle-accurate analog SID simulation. SIREN parameter latching is 600 Hz by default; that is a provisional design choice and is adjustable independently from CPU timer Hz. See SOUND.txt for gate and command behavior. Assembler --------- Import v6/assembler.ts, use `.version 6`, `.sound on`, and ordinary assembly syntax. Branches relax automatically. App images may contain multiple segments. The FAN1 app framing currently uses sound-on; a silent app leaves gates off. Examples: mov p, table movzx a, [p+18] ; two-byte record load mov.b [p+6], a.lo ; two-byte record store lea r, [p+18] ; address only, flag-neutral mov b, a ; one-byte word copy mov.b [p+7], 0 ; compact boolean/field initialization These forms help parsers, table walking, sprite/game state and instrument players alike. ENCODING.txt is the exact byte/descriptor chart. Observed prototype ------------------ A complete nineteen-selection native music/effect player, including touch/ keyboard selection and all program-owned data, is 4,145 bytes; the reference alias version is 4,126. The original C64 payload is 4,039 bytes. No song data or player code is in firmware. The arrangements and procedural effects are retained, but the new 50-Hz/600-Hz timing is not the old bit-identical timeline and the digital synthesis model is not a verified physical 6581 replica. Actual browser trials exercised nineteen-entry wrapping, left/right touch, audio and pause/resume. Actual iPhone hardware benchmarking remains pending.