; ======================================================================
; CS617 CHAPTER 07 - FIBONACCI r014 SOURCE CANDIDATE
; PB-2000C standalone language-card ROM
; Alex Barragan & ChatGPT (Solcito)
;
; r014 commitment boundary:
;   - A4 10 identity and standalone scaffold
;   - cold/BRK -> init -> timed splash -> menu
;   - one shared RAM Fibonacci table F0..F47
;   - Part I Explorer, runtime-observed working at r005
;   - Part II Zeckendorf, runtime-observed working at r006
;   - Part III complete golden-ratio candidate: editable epsilon/max_iter, runtime
;     phi=(1+sqrt(5))/2 through accepted BCD_SQRT, first-crossing stop rule
;   - Part IV Lekkerkerker experiment implemented in this revision
;
; Evidence history:
;   r001 - HD61 Error 009 on immediate IX displacement.
;   r002 - fixed operand class; then hit >16-character labels.
;   r003 - assembled; runtime exposed parser alias and UI issues.
;   r004 - fixed parser/UI; runtime exposed 2-digit -> 1-digit overwrite issue.
;   r005 - fresh whole-value Part-I edit; assembled and runtime accepted by Alex
;          with no reported regression.
;   r006 - added Part II; assembled and runtime accepted by Alex: all tests worked.
;   r007 - added Part III; assembled cleanly, default run converged to the oracle,
;          and runtime exposed bounded presentation/input usability issues.
;   r008 - bounded Part-III usability correction; assembled/runtime-observed correct,
;          including epsilon-sensitive convergence and aligned RUN presentation.
;   r009 - first stable-TM pacing attempt; assembled correctly but no visible dwell.
;   r010 - durable TM witness repaired pacing; human pacing accepted.
;   r011 - explicit Numeric SX/SY setup before Part-III configuration draw;
;          assembled correctly but did not remove the configuration-screen digit flood.
;   r012 - fixed the Part-III configuration renderer boundary; assembled and
;          runtime accepted by Alex with the digit flood removed.
;   r013 - implements Part IV Lekkerkerker experiment: exact enumeration for
;          n<=20, unbiased 256-draw sampling for n>=21, runtime 1/sqrt(5);
;          assembled and runtime-tested with computations matching the oracle.
;   r014 - final presentation-only refinement: left-column E/REF vertical comparison,
;          right-column method/count and A context, with aligned equals signs.
;          SOURCE CANDIDATE until HD61/runtime evidence.
; ======================================================================
        ORG     0
        LEVEL   0

OFFCHK:      EQU     &H04EF
WORK1:       EQU     &H0CE6
SETBK:       EQU     &H0276
CRTKY:       EQU     &H0460
SYSCLR:      EQU     &H3169
SETLCD:      EQU     &H328F
SET4LN:      EQU     &H28D8
BRSTR:       EQU     &H3280
BACKCHR:     EQU     &H2423
CURFORCEOFF: EQU     &H035E
EDCSR:       EQU     &H08CB
KEYMD:       EQU     &H09E4
SSPTP:       EQU     &H0FEF
USPTP:       EQU     &H0CE2
SSPBT:       EQU     &H0EEE
RCS:         EQU     SSPBT+16
BRKRAM:      EQU     RCS+&H40
CSREN:       EQU     &H22E0
CSRDIS:      EQU     &H22FA
REVOFF:      EQU     &H22EE
NCP:         EQU     &H0B13

KEYBS:       EQU     &H08
KEYEXE:      EQU     &H0D
KEYDEL:      EQU     &H11
KEYINS:      EQU     &H12
KEYRT:       EQU     &H1C
KEYLT:       EQU     &H1D
KEYMENU:     EQU     &H9C
KEYBRK:      EQU     &H9D
FK1:         EQU     &HFC
FK2:         EQU     &HFD
FK3:         EQU     &HFE
FK4:         EQU     &HFF

RN_EXE:      EQU     0
RN_MENU:     EQU     1
RN_BRK:      EQU     2
RN_FK1:      EQU     3
RN_FK2:      EQU     4
RN_FK3:      EQU     5
RN_FK4:      EQU     6

B_OK:        EQU     0
B_FULL:      EQU     1
B_EDGE:      EQU     2

; Bank-1 application RAM.  FIBTAB is the one private shared collection.
FIBTAB:      EQU     &H2200        ; 48 x 4 bytes = 192 bytes
WS_N:        EQU     &H22C0        ; committed Part-I index
WS_RWHY:     EQU     &H22C1        ; saved READN termination reason
WS_DPOS:     EQU     &H22C2        ; display position across formatter

; Part-II committed state.  N is u32; ZTERMS stores descending Fibonacci indices.
WS_ZN:       EQU     &H22C4        ; committed Part-II N, four bytes
WS_ZCNT:     EQU     &H22C8        ; number of Zeckendorf terms (0 for N=0)
WS_ZVIEW:    EQU     &H22C9        ; first visible term ordinal
WS_ZIT:      EQU     &H22CA        ; draw-loop term ordinal
WS_ZUSED:    EQU     &H22CB        ; chars used in current decomposition row
WS_ZLEN:     EQU     &H22CC        ; formatted token digit length

; Part-III committed configuration and runtime state.
; epsilon is stored as integer ten-thousandths: 1 == 0.0001.
WS_P3EPS:    EQU     &H22D0        ; u16, 0..10000 => 0.0000..1.0000
WS_P3MAX:    EQU     &H22D2        ; max_iter, 1..46
WS_P3N:      EQU     &H22D3        ; current ratio n, 1..46
WS_P3STOP:   EQU     &H22D4        ; 0 idle/run, 1 conv, 2 max, 3 boundary
WS_P3TM:     EQU     &H22D5        ; durable stable-TM witness for iteration pacing
P3_BIN:      EQU     &H22D6        ; temporary binary u32, four bytes

; READN r0.03 raw edit buffer/control block.  Capacity 12 permits full u32 use.
RN_BUF:      EQU     &H2300
RN_BASE:     EQU     &H2310
RN_LEN:      EQU     &H2312
RN_CAP:      EQU     &H2314
RN_POS:      EQU     &H2316
RN_DBASE:    EQU     &H2318
RN_REASON:   EQU     &H231A
RN_STAT:     EQU     &H231B
RN_SAVESS:   EQU     &H231C

FMTBUF:      EQU     &H2340        ; 11 bytes minimum; reserve 16
ZTERMS:      EQU     &H2360        ; 32 bytes; max canonical count here is 23

; Part-III native expanded-FP values (9 bytes each) and presentation buffer.
P3_PHI:      EQU     &H2380
P3_RATIO:    EQU     &H2390
P3_ERR:      EQU     &H23A0
P3_EPSFP:    EQU     &H23B0
P3_TMPFP:    EQU     &H23C0
P3_NUMFP:    EQU     &H23D0
P3_FBUF:     EQU     &H23E0        ; at least 16 bytes
P3_FLEN:     EQU     &H23F8

; Part-IV committed configuration, integer experiment state, and native FP results.
WS_P4N:      EQU     &H2500        ; experiment n, 2..46
WS_P4DONE:   EQU     &H2501        ; 0 config/no result, 1 completed result
WS_P4METH:   EQU     &H2502        ; 0 full enumeration, 1 sampled
WS_P4SEED:   EQU     &H2504        ; editable u32 seed
P4_LO:       EQU     &H2508        ; F(n), u32
P4_HI:       EQU     &H250C        ; F(n+1), u32
P4_RANGE:    EQU     &H2510        ; interval width, u32
P4_STATE:    EQU     &H2514        ; LCG state, u32
P4_THRESH:   EQU     &H2518        ; rejection threshold, u32
P4_CUR:      EQU     &H251C        ; enumeration cursor, u32
P4_OBS:      EQU     &H2520        ; accepted observation count, u16
P4_SUMZ:     EQU     &H2522        ; sum of Zeckendorf term counts, u16
P4_ASCL:     EQU     &H2524        ; floor(A*100000), u32
P4_TMP:      EQU     &H2530        ; native expanded FP scratch, 9 bytes
P4_AVG:      EQU     &H2540        ; A(n), native expanded FP
P4_EVAL:     EQU     &H2550        ; E(n), native expanded FP
P4_REF:      EQU     &H2560        ; 1/sqrt(5), native expanded FP
P4_FBUF:     EQU     &H2570        ; fixed-point presentation buffer
P4_FLEN:     EQU     &H2580        ; presentation length
; ======================================================================
; PLATFORM SCAFFOLD
; Derived from accepted CS617 Chapter 05 r012 / BOOT lineage.
; Chapter 07 changes only project identity and clean-slate BRK target here.
; ======================================================================
; Language-card header.
        DB      &H43,&H4D
        DB      &HFF,&HFF,&HFF,&HFF
        DB      &H01,&H04,&HA4,&H10
        DB      &HFF,&HFF,&HFF,&HFF
        DB      &HFF,&HFF,&HFF,&HFF
        DB      &HFF,&HFF,&HFF,&HFF
        DB      &HFF,&HFF,&HFF,&HFF
        DB      &HFF
        DB      &H03
        DB      &HC0
        DB      &HFF,&HFF,&HFF

; Pinned READN r0.03 C-ROM bank-call bridge substrate.  RN_SYSINIT copies RCS_TOP..RCS_END
; to RAM at RCS before any READN use.
        ORG     &H0C20
RCS_TOP:
        GST     UA,$6
        PHS     $6
        LDW     $6,SETBK-1
        PHSW    $7
        PST     UA,&H54
        JP      $28

_SYSCAL:
        PST     UA,&H45
        LDW     $6,&H0C10
        ST      $31,($6)
        CAL     RCS
        PST     UA,&H45
        LDW     $6,&H0C10
        LD      $28,3
        ST      $28,($6)
        PST     UA,&H54
        RTN
RCS_END:

        ORG     &H0C50
SYSCAL:
        PST     UA,&H55
        JP      RCS+(_SYSCAL-RCS_TOP)

; Accepted BOOT-ROM-derived direct scanner remains the ordinary menu/UI path.
        ORG     &H0C60
INKEY:
        CAL     OFFCHK
        LD      $17,$31
        LD      $0,&H4B

IKEYLP:
        PST     IA,$0
        GRE     KY,$1
        GRE     KY,$1
        DID     $2
        ANCW    $1,$1
        JR      Z,IKEY40

        SBC     $0,&H41
        JP      Z,CH07_COLD

IKEY10:
        LD      $3,$31

IKEY20:
        BIDW    $2
        JR      C,IKEY30
        AD      $3,$30,IKEY20

IKEY30:
        LD      $5,$0
        SB      $5,$30
        BIU     $5
        BIU     $5
        LD      $4,$5
        BIU     $4
        BIU     $4
        SB      $4,$5

        PST     UA,&H44
        PRE     IX,KEYSCAN
        LDD     $0,(IX+$4)
        LDD     $0,(IX+$3)
        PST     UA,&H54
        JR      IKEY50

IKEY40:
        SB      $0,$30
        JR      LNZ,IKEYLP
        LD      $0,$31

IKEY50:
        AN      $0,$0
        JR      Z,IKEYRET
        LD      $17,$30

IKEYRET:
        LDW     $15,WORK1
        ST      $0,($15)
        RTN


; Standalone vector table.
        ORG     &H0D80

        JP      CH07_COLD
        JP      TRAP
        JP      &H01AA
        JP      &H01BC
        JP      TRAP
        JP      TRAP
        JP      TRAP
        JP      &H00E3

DEFRT:  RTN
        DB      &HFF,&HFF
        RTN
        DB      &HFF,&HFF
        JP      DEFRT
        JP      POFF
        JP      DEFRT
        JP      &H0368
        JP      CH07_COLD
        JP      DEFRT
        JP      DEFRT
        JP      DEFRT
        JP      DEFRT
        DB      &HA4
        DB      &H10

TRAP:   RTNI

POFF:   OFF
        OFF
        OFF
        OFF
        JR      POFF

; BOOT ROM key translation table.
KEYSCAN:
KSCAN01:
        DB      0,0,0,0,0,0,0,1,0,0,0,0
KSCAN02:
        DB      "W","Q","A",0,"Z",0,0,0,0,0,"'",7
KSCAN03:
        DB      "R","E","D","S","C","X",0,0,&HFC,0,&H29,&H28
KSCAN04:
        DB      "Y","T","G","F","B","V",0,0,&HFD,0,&H5D,&H5B
KSCAN05:
        DB      "I","U","J","H","M","N",0,0,&HFE,0,&H90,&H7C
KSCAN06:
        DB      "P","O","L","K",&H20,",",0,0,&HFF,0,&H93,&H94
KSCAN07:
        DB      0,"=",":",";",0,0,0,0,&H95,0,0,&H9B
KSCAN08:
        DB      "5","4","2","1",0,"0",0,"7",0,0,0,0
KSCAN09:
        DB      "-","6","+","3",&H0D,".",0,"9",0,0,0,0
KSCAN10:
        DB      &H9D,&H1C,"/",&H08,0,0,0,"*",0,0,&H9C,&H11
KSCAN11:
        DB      &H1F,&H1D,&H0C,0,0,0,"8",0,0,&H1E,&H12



; ======================================================================
; APPLICATION
; ======================================================================
        ORG     &H0E80

CH07_COLD:
        PRE     SS,&H0100
        LD      $30,1
        LD      $31,0
        PSR     SZ,0
        PSR     SY,30
        PSR     SX,31
        PST     UA,&H14

        CAL     RN_SYSINIT
        CAL     SCREEN_INIT
        CAL     CH07_INIT_STATE
        CAL     CH07_SPLASH
        CAL     CH07_SPLASH_WAIT
        JP      SHOW_MENU

; Ordinary non-editor keyboard path.  INKEY catches BRK before translation
; and jumps directly to CH07_COLD, so BRK is a true clean-slate boundary.
POLLKEY:
        CAL     INKEY
        PST     UA,&H14
        RTN

WAITREL:
WR_LOOP:
        CAL     POLLKEY
        AN      $17,$17
        JR      NZ,WR_LOOP
        RTN

; ----------------------------------------------------------------------
; Initialization: one private application Fibonacci table F0..F47.
; No Part owns a separate Fibonacci generator.
; ----------------------------------------------------------------------
CH07_INIT_STATE:
        CAL     FIB_INIT
        PRE     IX,WS_N
        ST      $31,(IX+$SX)

; Part II defaults to N=0 and the canonical zero representation.
        SBW     $0,$0
        PRE     IX,WS_ZN
        STW     $0,(IX+$SX)
        LD      $4,2
        STW     $0,(IX+$4)
        PRE     IX,WS_ZCNT
        ST      $31,(IX+$SX)
        PRE     IX,WS_ZVIEW
        ST      $31,(IX+$SX)

; Part III defaults: epsilon=0.0001, max_iter=20.  Build the independent
; runtime phi reference now; BRK re-enters this path and recomputes it.
        PRE     IX,WS_P3EPS
        LDW     $0,1
        STW     $0,(IX+$SX)
        PRE     IX,WS_P3MAX
        LD      $0,20
        ST      $0,(IX+$SX)
        PRE     IX,WS_P3N
        LD      $0,1
        ST      $0,(IX+$SX)
        PRE     IX,WS_P3STOP
        ST      $31,(IX+$SX)
        CAL     P3_INIT_REF
        CAL     P3_MAKE_EPS

; Part IV defaults: first prescribed experiment n=10, seed=61707.
        PRE     IX,WS_P4N
        LD      $0,10
        ST      $0,(IX+$SX)
        PRE     IX,WS_P4DONE
        ST      $31,(IX+$SX)
        PRE     IX,WS_P4METH
        ST      $31,(IX+$SX)
        PRE     IX,WS_P4SEED
        LDW     $0,&HF10B
        STW     $0,(IX+$SX)
        SBW     $2,$2
        LD      $4,2
        STW     $2,(IX+$4)
        RTN

FIB_INIT:
; a = F0 = 0 in $15-$18; b = F1 = 1 in $5-$8.
        SBW     $15,$15
        SBW     $17,$17
        LDW     $5,1
        SBW     $7,$7

        PRE     IX,FIBTAB
        STW     $15,(IX+$SX)
        LD      $4,2
        STW     $17,(IX+$4)
        LD      $4,4
        STW     $5,(IX+$4)
        LD      $4,6
        STW     $7,(IX+$4)

; Emit F2..F47, exactly 46 additions.  Never form F48.
        LDW     $20,FIBTAB+8
        LDW     $22,4
        LD      $14,46
FI_LOOP:
        CAL     UADD32             ; a := a + b = c; b preserved
        PRE     IX,$20
        STW     $15,(IX+$SX)
        LD      $4,2
        STW     $17,(IX+$4)

; Save c, then rotate (a,b) := (b,c).
        LDW     $9,$15
        LDW     $11,$17
        LDW     $15,$5
        LDW     $17,$7
        LDW     $5,$9
        LDW     $7,$11

        ADW     $20,$22
        SB      $14,$SY
        JR      NZ,FI_LOOP
        RTN

; Input $12 = 0..47. Output F(n) in $15-$18.
FIB_LOAD:
        LD      $10,$12
        LD      $11,$31
        ADW     $10,$10
        ADW     $10,$10
        LDW     $20,FIBTAB
        ADW     $10,$20
        PRE     IX,$10
        LDW     $15,(IX+$SX)
        LD      $4,2
        LDW     $17,(IX+$4)
        RTN

; Input $12 = 0..47. Output F(n) in $5-$8 without disturbing $15-$18.
FIB_LOAD_B:
        LD      $10,$12
        LD      $11,$31
        ADW     $10,$10
        ADW     $10,$10
        LDW     $24,FIBTAB
        ADW     $10,$24
        PRE     IX,$10
        LDW     $5,(IX+$SX)
        LD      $4,2
        LDW     $7,(IX+$4)
        RTN

; ----------------------------------------------------------------------
; Cold-only splash.  Two observed TM transitions: bounded/self-advancing,
; with no EXE requirement.  MENU returns never come through this path.
; ----------------------------------------------------------------------
CH07_SPLASH:
        CAL     CLEAR_ALL
        CAL     CUR_HIDE
        LD      $6,&H00
        PRE     IZ,TXT_SPL0
        CAL     PRINTZ
        LD      $6,&H20
        PRE     IZ,TXT_SPL1
        CAL     PRINTZ
        LD      $6,&H40
        PRE     IZ,TXT_SPL2
        CAL     PRINTZ
        LD      $6,&H60
        PRE     IZ,TXT_SPL3
        CAL     PRINTZ
        RTN

CH07_SPLASH_WAIT:
        GST     TM,$8
        GST     TM,$8
        LD      $10,$8
        LD      $11,2
C7_SPLWAIT:
        CAL     OFFCHK
        GST     TM,$8
        GST     TM,$8
        LD      $12,$8
        SBC     $12,$10
        JR      Z,C7_SPLWAIT
        LD      $10,$8
        SB      $11,$30
        JR      NZ,C7_SPLWAIT
        RTN

; ======================================================================
; MAIN MENU
; ======================================================================
SHOW_MENU:
        CAL     DRAW_MENU
C7_MENULP:
        CAL     POLLKEY
        AN      $17,$17
        JR      Z,C7_MENULP
        LD      $12,$0
        SBC     $12,FK1
        JR      Z,C7_MENU1
        SBC     $12,FK2
        JR      Z,C7_MENU2
        SBC     $12,FK3
        JR      Z,C7_MENU3
        SBC     $12,FK4
        JR      Z,C7_MENU4
        CAL     WAITREL
        JR      C7_MENULP
C7_MENU1:
        CAL     WAITREL
        JP      P1_SCREEN
C7_MENU2:
        CAL     WAITREL
        JP      P2_SCREEN
C7_MENU3:
        CAL     WAITREL
        JP      P3_SCREEN
C7_MENU4:
        CAL     WAITREL
        JP      P4_SCREEN

DRAW_MENU:
        CAL     CLEAR_ALL
        CAL     CUR_HIDE
        LD      $6,&H00
        PRE     IZ,TXT_MENU0
        CAL     PRINTZ
; Rows 2 and 3 intentionally remain blank.  The period-style FK labels carry
; navigation without explanatory prose.
        LD      $6,&H60
        PRE     IZ,FK_MAIN
        CAL     PRINTZ
        RTN

; ======================================================================
; PART I - FIBONACCI EXPLORER
; ======================================================================
P1_SCREEN:
        CAL     P1_DRAW
P1_LOOP:
        CAL     POLLKEY
        AN      $17,$17
        JR      Z,P1_LOOP
        LD      $12,$0
        SBC     $12,KEYMENU
        JP      Z,P1_EXIT
        SBC     $12,FK1
        JP      Z,P1_EDIT
        SBC     $12,FK2
        JP      Z,P1_NEXT
        SBC     $12,FK3
        JP      Z,P1_PREV
        SBC     $12,FK4
        JP      Z,P1_EXIT
        CAL     WAITREL
        JR      P1_LOOP

P1_EXIT:
        CAL     WAITREL
        JP      SHOW_MENU

P1_NEXT:
        CAL     WAITREL
        PRE     IX,WS_N
        LD      $0,(IX+$SX)
        SBC     $0,47
        JR      Z,P1_REDRAW
        AD      $0,$SY
        ST      $0,(IX+$SX)
P1_REDRAW:
        JP      P1_SCREEN

P1_PREV:
        CAL     WAITREL
        PRE     IX,WS_N
        LD      $0,(IX+$SX)
        AN      $0,$0
        JR      Z,P1_REDRAW
        SB      $0,$SY
        ST      $0,(IX+$SX)
        JP      P1_SCREEN

P1_EDIT:
        CAL     WAITREL
        CAL     P1_PREP_EDIT
        CAL     P1_DRAW

; READN(buffer, current length, capacity=2, LCD base=row2 col4).
        LDW     $0,RN_BUF
        PRE     IX,RN_LEN
        LDW     $2,(IX+$SX)
        LDW     $4,2
        LD      $6,&H24
        CAL     APP_READN
        CAL     WAITREL

; WAITREL is allowed to clobber general scratch.  Reload the durable reason
; recorded by READN rather than trusting returned $8 across release polling.
        PRE     IX,RN_REASON
        LD      $8,(IX+$SX)
        PRE     IX,WS_RWHY
        ST      $8,(IX+$SX)

; MENU abandons transient text and returns to main menu; committed n survives.
        SBC     $8,RN_MENU
        JP      Z,SHOW_MENU

; Parse/validate before commit.  Invalid/empty/out-of-range leaves WS_N intact.
        CAL     P1_PARSE_EDIT
        AN      $0,$0
        JR      Z,P1_EDIT_REJECT

        PRE     IX,WS_N
        ST      $20,(IX+$SX)

; r0.03 allows function keys to terminate an edit.  After a valid commit,
; next/prev/exit are dispatched immediately; FK1 itself simply accepts.
        PRE     IX,WS_RWHY
        LD      $8,(IX+$SX)
        SBC     $8,RN_FK2
        JP      Z,P1_NEXT_EDIT
        SBC     $8,RN_FK3
        JP      Z,P1_PREV_EDIT
        SBC     $8,RN_FK4
        JP      Z,SHOW_MENU
        JP      P1_SCREEN

P1_NEXT_EDIT:
        PRE     IX,WS_N
        LD      $0,(IX+$SX)
        SBC     $0,47
        JP      Z,P1_SCREEN
        AD      $0,$SY
        ST      $0,(IX+$SX)
        JP      P1_SCREEN

P1_PREV_EDIT:
        PRE     IX,WS_N
        LD      $0,(IX+$SX)
        AN      $0,$0
        JP      Z,P1_SCREEN
        SB      $0,$SY
        ST      $0,(IX+$SX)
        JP      P1_SCREEN

P1_EDIT_REJECT:
        JP      P1_SCREEN

; Start a fresh whole-value edit.  The committed n remains in WS_N until
; validation succeeds, so empty/invalid input preserves the prior value.
P1_PREP_EDIT:
        SBW     $2,$2
        PRE     IX,RN_LEN
        STW     $2,(IX+$SX)
        RTN

; Parse RN_BUF as 1-2 ASCII digits and accept only 0..47.
; Output: $0=1 valid / 0 invalid; $20=value on success.
P1_PARSE_EDIT:
        PRE     IX,RN_LEN
        LDW     $10,(IX+$SX)
        ANCW    $10,$10
        JR      Z,P1_PARSE_BAD
        LDW     $12,2
        SBCW    $10,$12
        JR      C,P1_PARSE_LENOK
        JR      Z,P1_PARSE_LENOK
        JR      P1_PARSE_BAD
P1_PARSE_LENOK:
        SBW     $20,$20
        SBW     $12,$12
P1_PARSE_LOOP:
        LDW     $14,$12
        SBCW    $14,$10
        JR      NC,P1_PARSE_RANGE
        PRE     IX,RN_BUF
; $12/$13 is the word-sized buffer index.  Do not reuse $13 for the digit:
; doing so corrupts the index after the first character (r003: "12" -> 1).
        LD      $9,(IX+$12)
        LD      $14,$9
        SBC     $14,&H30
        JR      C,P1_PARSE_BAD
        SBC     $14,&H3A
        JR      NC,P1_PARSE_BAD
        SB      $9,&H30

; value = value*10 + digit, using only 16-bit arithmetic (safe for two digits).
        LDW     $22,$20
        ADW     $20,$20          ; 2x
        LDW     $24,$22
        ADW     $24,$24          ; 2x
        ADW     $24,$24          ; 4x
        ADW     $24,$24          ; 8x
        ADW     $20,$24          ; 10x
        SBW     $22,$22
        LD      $22,$9
        ADW     $20,$22

        ADW     $12,$SY
        JR      P1_PARSE_LOOP
P1_PARSE_RANGE:
        LDW     $22,48
        SBCW    $20,$22
        JR      NC,P1_PARSE_BAD
        LD      $0,1
        RTN
P1_PARSE_BAD:
        LD      $0,0
        RTN

P1_DRAW:
        CAL     CLEAR_ALL
        CAL     CUR_HIDE
        LD      $6,&H00
        PRE     IZ,TXT_P1_TITLE
        CAL     PRINTZ

        LD      $6,&H20
        PRE     IZ,TXT_P1_N
        CAL     PRINTZ
        PRE     IX,WS_N
        LD      $15,(IX+$SX)
        LD      $16,$31
        SBW     $17,$17
        CAL     PUT_U32

        LD      $6,&H40
        PRE     IZ,TXT_P1_F
        CAL     PRINTZ
        PRE     IX,WS_N
        LD      $12,(IX+$SX)
        CAL     FIB_LOAD
        CAL     PUT_U32

        LD      $6,&H60
        PRE     IZ,FK_P1
        CAL     PRINTZ
        RTN

; ======================================================================
; PART II - ZECKENDORF DECOMPOSITION
; ======================================================================
; Contract surface:
;   - N is any u32, 0..4294967295
;   - positive N uses canonical distinct nonconsecutive F2..F47 terms
;   - N=0 displays representation 0
;   - rows 2/3 browse from the same first term ordinal
;   - LEFT/RIGHT (and FK2/FK3) move by one term boundary, never raw chars
; ======================================================================
P2_SCREEN:
        CAL     P2_DRAW
P2_LOOP:
        CAL     POLLKEY
        AN      $17,$17
        JR      Z,P2_LOOP
        LD      $12,$0
        SBC     $12,KEYMENU
        JP      Z,P2_EXIT
        SBC     $12,FK1
        JP      Z,P2_EDIT
        SBC     $12,FK2
        JP      Z,P2_LEFT
        SBC     $12,KEYLT
        JP      Z,P2_LEFT
        SBC     $12,FK3
        JP      Z,P2_RIGHT
        SBC     $12,KEYRT
        JP      Z,P2_RIGHT
        SBC     $12,FK4
        JP      Z,P2_EXIT
        CAL     WAITREL
        JR      P2_LOOP

P2_EXIT:
        CAL     WAITREL
        JP      SHOW_MENU

P2_LEFT:
        CAL     WAITREL
        JP      P2_LNOW
P2_LNOW:
        PRE     IX,WS_ZVIEW
        LD      $0,(IX+$SX)
        AN      $0,$0
        JP      Z,P2_SCREEN
        SB      $0,$SY
        ST      $0,(IX+$SX)
        JP      P2_SCREEN

P2_RIGHT:
        CAL     WAITREL
        JP      P2_RNOW
P2_RNOW:
        PRE     IX,WS_ZCNT
        LD      $1,(IX+$SX)
        AN      $1,$1
        JP      Z,P2_SCREEN
        PRE     IX,WS_ZVIEW
        LD      $0,(IX+$SX)
        LD      $2,$0
        AD      $2,$SY
        SBC     $2,$1
        JP      NC,P2_SCREEN
        AD      $0,$SY
        ST      $0,(IX+$SX)
        JP      P2_SCREEN

; Start a fresh whole-value u32 edit.  The previous committed N/decomposition
; survives until the new raw text parses completely and without overflow.
P2_EDIT:
        CAL     WAITREL
        CAL     P2_PREP_EDIT
        CAL     P2_DRAW

; READN(buffer, len=0, capacity=10, LCD base=row1 col4).
        LDW     $0,RN_BUF
        PRE     IX,RN_LEN
        LDW     $2,(IX+$SX)
        LDW     $4,10
        LD      $6,&H04
        CAL     APP_READN
        CAL     WAITREL

        PRE     IX,RN_REASON
        LD      $8,(IX+$SX)
        PRE     IX,WS_RWHY
        ST      $8,(IX+$SX)

; MENU is cancellation/navigation: preserve committed Part-II state.
        SBC     $8,RN_MENU
        JP      Z,SHOW_MENU

        CAL     P2_PARSE
        AN      $0,$0
        JP      Z,P2_SCREEN

; Commit the parsed u32 only after complete validation.
        PRE     IX,WS_ZN
        STW     $15,(IX+$SX)
        LD      $4,2
        STW     $17,(IX+$4)
        CAL     P2_BUILD

; FK termination means accept then perform the requested action.
        PRE     IX,WS_RWHY
        LD      $8,(IX+$SX)
        SBC     $8,RN_FK2
        JP      Z,P2_LNOW
        SBC     $8,RN_FK3
        JP      Z,P2_RNOW
        SBC     $8,RN_FK4
        JP      Z,SHOW_MENU
        JP      P2_SCREEN

P2_PREP_EDIT:
        SBW     $2,$2
        PRE     IX,RN_LEN
        STW     $2,(IX+$SX)
        RTN

; Parse 1..10 ASCII decimal digits to u32 using the accepted Numeric UDECAPP.
; Output: $0=1 valid / 0 invalid; $15-$18=value on success.
P2_PARSE:
        PRE     IX,RN_LEN
        LDW     $20,(IX+$SX)
        ANCW    $20,$20
        JP      Z,P2_PBAD
        LDW     $22,10
        SBCW    $20,$22
        JP      C,P2_PSTART
        JP      Z,P2_PSTART
        JP      P2_PBAD
P2_PSTART:
        SBW     $15,$15
        SBW     $17,$17
        SBW     $22,$22
P2_PLOOP:
        LDW     $24,$22
        SBCW    $24,$20
        JP      NC,P2_POK
        PRE     IX,RN_BUF
        LD      $5,(IX+$22)
        LD      $12,$5
        SBC     $12,&H30
        JP      C,P2_PBAD
        SBC     $12,&H3A
        JP      NC,P2_PBAD
        SB      $5,&H30
        CAL     UDECAPP
        AN      $4,$4
        JP      NZ,P2_PBAD
        ADW     $22,$SY
        JP      P2_PLOOP
P2_POK:
        LD      $0,1
        RTN
P2_PBAD:
        LD      $0,0
        RTN

; Canonical greedy decomposition.  Since UINT32_MAX < F48, F47 is sufficient
; as the largest basis element.  After selecting Fi, skip Fi-1 explicitly.
P2_BUILD:
        PRE     IX,WS_ZN
        LDW     $15,(IX+$SX)
        LD      $4,2
        LDW     $17,(IX+$4)
        PRE     IX,WS_ZCNT
        ST      $31,(IX+$SX)
        PRE     IX,WS_ZVIEW
        ST      $31,(IX+$SX)
        LD      $20,47
P2_GLOOP:
        LD      $10,$20
        SBC     $10,2
        JP      C,P2_GDONE
        LD      $12,$20
        CAL     FIB_LOAD_B

; Unsigned remainder >= Fi ?  Compare high word, then low word.
        LDW     $10,$17
        SBCW    $10,$7
        JP      C,P2_GSKIP
        JP      NZ,P2_GTAKE
        LDW     $10,$15
        SBCW    $10,$5
        JP      C,P2_GSKIP
P2_GTAKE:
        CAL     USUB32
        PRE     IX,WS_ZCNT
        LD      $10,(IX+$SX)
        PRE     IX,ZTERMS
        ST      $20,(IX+$10)
        AD      $10,$SY
        PRE     IX,WS_ZCNT
        ST      $10,(IX+$SX)
        SB      $20,$SY
        SB      $20,$SY
        JP      P2_GLOOP
P2_GSKIP:
        SB      $20,$SY
        JP      P2_GLOOP
P2_GDONE:
        RTN

P2_DRAW:
        CAL     CLEAR_ALL
        CAL     CUR_HIDE

; Row 1: committed N is continuously visible while browsing.
        LD      $6,&H00
        PRE     IZ,TXT_P2_N
        CAL     PRINTZ
        PRE     IX,WS_ZN
        LDW     $15,(IX+$SX)
        LD      $4,2
        LDW     $17,(IX+$4)
        CAL     PUT_U32

; Rows 2/3 start at the same term ordinal, but pack independently.
        CAL     P2_DSYM
        CAL     P2_DDEC

        LD      $6,&H60
        PRE     IZ,FK_P2
        CAL     PRINTZ
        RTN

; Row 2 symbolic form: F47+F45+...  Never split a token at the right edge.
P2_DSYM:
        LD      $6,&H20
        PRE     IX,WS_ZCNT
        LD      $20,(IX+$SX)
        AN      $20,$20
        JP      Z,P2_SYM0
        PRE     IX,WS_ZVIEW
        LD      $20,(IX+$SX)
        PRE     IX,WS_ZIT
        ST      $20,(IX+$SX)
        PRE     IX,WS_ZUSED
        ST      $31,(IX+$SX)
P2_SYMLP:
        PRE     IX,WS_ZIT
        LD      $20,(IX+$SX)
        PRE     IX,WS_ZCNT
        LD      $21,(IX+$SX)
        SBC     $20,$21
        JP      NC,P2_SYMDONE
        PRE     IX,ZTERMS
        LD      $12,(IX+$20)

; Format the Fibonacci index itself (2..47) with the accepted decimal formatter.
        LD      $15,$12
        LD      $16,$31
        SBW     $17,$17
        PRE     IX,WS_DPOS
        ST      $6,(IX+$SX)
        PRE     IX,FMTBUF
        CAL     UFMT32DEC
        PRE     IX,WS_DPOS
        LD      $6,(IX+$SX)
        PRE     IX,WS_ZLEN
        ST      $14,(IX+$SX)

; needed = optional '+' + 'F' + decimal index.  Require total <= 32.
        PRE     IX,WS_ZUSED
        LD      $22,(IX+$SX)
        PRE     IX,WS_ZLEN
        LD      $23,(IX+$SX)
        AD      $23,$SY
        AN      $22,$22
        JR      Z,P2_SYMNSEP
        AD      $23,$SY
P2_SYMNSEP:
        LD      $24,$22
        AD      $24,$23
        SBC     $24,33
        JP      NC,P2_SYMDONE

        AN      $22,$22
        JR      Z,P2_SYMNP
        LD      $16,&H2B
        CAL     PUTC
P2_SYMNP:
        LD      $16,&H46
        CAL     PUTC
        PRE     IX,WS_ZLEN
        LD      $13,(IX+$SX)
        PRE     IX,FMTBUF
        CAL     PRINT_RAM

; Advance one whole term boundary.
        PRE     IX,WS_ZUSED
        LD      $22,(IX+$SX)
        PRE     IX,WS_ZLEN
        LD      $23,(IX+$SX)
        AD      $23,$SY
        AN      $22,$22
        JR      Z,P2_SYMUSED
        AD      $23,$SY
P2_SYMUSED:
        AD      $22,$23
        PRE     IX,WS_ZUSED
        ST      $22,(IX+$SX)
        PRE     IX,WS_ZIT
        LD      $20,(IX+$SX)
        AD      $20,$SY
        ST      $20,(IX+$SX)
        JP      P2_SYMLP
P2_SYM0:
        PRE     IZ,TXT_ZERO
        CAL     PRINTZ
P2_SYMDONE:
        RTN

; Row 3 decimal Fibonacci values, same first term ordinal as row 2.
P2_DDEC:
        LD      $6,&H40
        PRE     IX,WS_ZCNT
        LD      $20,(IX+$SX)
        AN      $20,$20
        JP      Z,P2_DEC0
        PRE     IX,WS_ZVIEW
        LD      $20,(IX+$SX)
        PRE     IX,WS_ZIT
        ST      $20,(IX+$SX)
        PRE     IX,WS_ZUSED
        ST      $31,(IX+$SX)
P2_DECLP:
        PRE     IX,WS_ZIT
        LD      $20,(IX+$SX)
        PRE     IX,WS_ZCNT
        LD      $21,(IX+$SX)
        SBC     $20,$21
        JP      NC,P2_DECDONE
        PRE     IX,ZTERMS
        LD      $12,(IX+$20)
        CAL     FIB_LOAD

        PRE     IX,WS_DPOS
        ST      $6,(IX+$SX)
        PRE     IX,FMTBUF
        CAL     UFMT32DEC
        PRE     IX,WS_DPOS
        LD      $6,(IX+$SX)
        PRE     IX,WS_ZLEN
        ST      $14,(IX+$SX)

; needed = optional '+' + formatted Fibonacci value.
        PRE     IX,WS_ZUSED
        LD      $22,(IX+$SX)
        PRE     IX,WS_ZLEN
        LD      $23,(IX+$SX)
        AN      $22,$22
        JR      Z,P2_DECNSEP
        AD      $23,$SY
P2_DECNSEP:
        LD      $24,$22
        AD      $24,$23
        SBC     $24,33
        JP      NC,P2_DECDONE

        AN      $22,$22
        JR      Z,P2_DECNP
        LD      $16,&H2B
        CAL     PUTC
P2_DECNP:
        PRE     IX,WS_ZLEN
        LD      $13,(IX+$SX)
        PRE     IX,FMTBUF
        CAL     PRINT_RAM

        PRE     IX,WS_ZUSED
        LD      $22,(IX+$SX)
        PRE     IX,WS_ZLEN
        LD      $23,(IX+$SX)
        AN      $22,$22
        JR      Z,P2_DECUSED
        AD      $23,$SY
P2_DECUSED:
        AD      $22,$23
        PRE     IX,WS_ZUSED
        ST      $22,(IX+$SX)
        PRE     IX,WS_ZIT
        LD      $20,(IX+$SX)
        AD      $20,$SY
        ST      $20,(IX+$SX)
        JP      P2_DECLP
P2_DEC0:
        PRE     IZ,TXT_ZERO
        CAL     PRINTZ
P2_DECDONE:
        RTN

; ======================================================================
; PART III - CHASING THE GOLDEN RATIO
; ======================================================================
; Contract surface:
;   - R(n)=F(n+1)/F(n), n=1..46
;   - epsilon editable, default 0.0001; human-friendly input with up to 4 decimals
;   - max_iter editable 1..46, default 20
;   - runtime phi=(1+sqrt(5))/2; BCD_SQRT is actually called on numeric 5
;   - stop at first abs(R-phi)<=epsilon, else max_iter/boundary
;   - current n, R, phi and error are drawn every iteration; final reason remains
; ======================================================================
P3_SCREEN:
        PRE     IX,WS_P3STOP
        LD      $0,(IX+$SX)
        AN      $0,$0
        JP      Z,P3_CFG
        CAL     P3_DRAW_RES
        JP      P3_WAIT
P3_CFG:
        CAL     P3_DRAW_CFG
P3_WAIT:
        CAL     POLLKEY
        AN      $17,$17
        JP      Z,P3_WAIT
        LD      $12,$0
        SBC     $12,KEYMENU
        JP      Z,P3_EXIT
        SBC     $12,FK1
        JP      Z,P3_EDIT_E
        SBC     $12,FK2
        JP      Z,P3_EDIT_M
        SBC     $12,FK3
        JP      Z,P3_RUN
        SBC     $12,FK4
        JP      Z,P3_EXIT
        CAL     WAITREL
        JP      P3_WAIT

P3_EXIT:
        CAL     WAITREL
        JP      SHOW_MENU

; ----------------------------------------------------------------------
; Epsilon edit.  Human-friendly forms are accepted and canonicalized to
; ten-thousandths: 0/1, .d..dddd, 0.d..dddd, 1.0..1.0000.
; Internally epsilon is a u16 count of 1/10000 units.
; ----------------------------------------------------------------------
P3_EDIT_E:
        CAL     WAITREL
        CAL     P3_PREP_EDIT
        CAL     P3_DRAW_EEDIT
        LDW     $0,RN_BUF
        PRE     IX,RN_LEN
        LDW     $2,(IX+$SX)
        LDW     $4,6
        LD      $6,&H24
        CAL     APP_READN
        CAL     WAITREL
        PRE     IX,RN_REASON
        LD      $8,(IX+$SX)
        PRE     IX,WS_RWHY
        ST      $8,(IX+$SX)
        SBC     $8,RN_MENU
        JP      Z,SHOW_MENU
        CAL     P3_PARSE_E
        AN      $0,$0
        JP      Z,P3_SCREEN
        PRE     IX,WS_P3EPS
        STW     $20,(IX+$SX)
        CAL     P3_MAKE_EPS
        PRE     IX,WS_P3STOP
        ST      $31,(IX+$SX)
        PRE     IX,WS_RWHY
        LD      $8,(IX+$SX)
        SBC     $8,RN_FK2
        JP      Z,P3_EDIT_M
        SBC     $8,RN_FK3
        JP      Z,P3_RUN
        SBC     $8,RN_FK4
        JP      Z,SHOW_MENU
        JP      P3_SCREEN

; ----------------------------------------------------------------------
; max_iter edit.  Reuse the already-exercised 1-2 digit Part-I parser,
; then tighten the accepted range to 1..46.
; ----------------------------------------------------------------------
P3_EDIT_M:
        CAL     WAITREL
        CAL     P3_PREP_EDIT
        CAL     P3_DRAW_MEDIT
        LDW     $0,RN_BUF
        PRE     IX,RN_LEN
        LDW     $2,(IX+$SX)
        LDW     $4,2
        LD      $6,&H24
        CAL     APP_READN
        CAL     WAITREL
        PRE     IX,RN_REASON
        LD      $8,(IX+$SX)
        PRE     IX,WS_RWHY
        ST      $8,(IX+$SX)
        SBC     $8,RN_MENU
        JP      Z,SHOW_MENU
        CAL     P1_PARSE_EDIT
        AN      $0,$0
        JP      Z,P3_SCREEN
        LD      $0,$20
        AN      $0,$0
        JP      Z,P3_SCREEN
        LD      $0,$20
        SBC     $0,47
        JP      NC,P3_SCREEN
        PRE     IX,WS_P3MAX
        ST      $20,(IX+$SX)
        PRE     IX,WS_P3STOP
        ST      $31,(IX+$SX)
        PRE     IX,WS_RWHY
        LD      $8,(IX+$SX)
        SBC     $8,RN_FK1
        JP      Z,P3_EDIT_E
        SBC     $8,RN_FK3
        JP      Z,P3_RUN
        SBC     $8,RN_FK4
        JP      Z,SHOW_MENU
        JP      P3_SCREEN

P3_PREP_EDIT:
        SBW     $2,$2
        PRE     IX,RN_LEN
        STW     $2,(IX+$SX)
        RTN

; Parse human-friendly epsilon text -> $20 word ten-thousandths.
; Accepted:
;   0 / 1
;   .d .. .dddd
;   0.d .. 0.dddd
;   1.0 .. 1.0000
; Fractional input is right-padded to four places: 0.01 -> 0.0100 -> 100 units.
; $0=1 valid, $0=0 invalid.  No committed state is changed here.
P3_PARSE_E:
        PRE     IX,RN_LEN
        LDW     $10,(IX+$SX)
        ANCW    $10,$10
        JP      Z,P3_PE_BAD
        LDW     $12,6
        SBCW    $10,$12
        JP      C,P3_PE_LENOK
        JP      Z,P3_PE_LENOK
        JP      P3_PE_BAD

P3_PE_LENOK:
        PRE     IX,RN_BUF
        LD      $9,(IX+$SX)
        LD      $0,$9
        SBC     $0,&H2E
        JP      Z,P3_PE_DOT
        LD      $0,$9
        SBC     $0,&H30
        JP      Z,P3_PE_ZERO
        LD      $0,$9
        SBC     $0,&H31
        JP      Z,P3_PE_ONE
        JP      P3_PE_BAD

; Leading-dot form: .d through .dddd (length 2..5).
P3_PE_DOT:
        PRE     IX,RN_LEN
        LDW     $10,(IX+$SX)
        LDW     $12,2
        SBCW    $10,$12
        JP      C,P3_PE_BAD
        PRE     IX,RN_LEN
        LDW     $10,(IX+$SX)
        LDW     $12,5
        SBCW    $10,$12
        JP      C,P3_PE_DOTOK
        JP      Z,P3_PE_DOTOK
        JP      P3_PE_BAD
P3_PE_DOTOK:
        LD      $9,0
        LDW     $22,1
        PRE     IX,RN_LEN
        LD      $14,(IX+$SX)
        SB      $14,$SY
        LD      $8,$14
        JP      P3_PE_DIGS

P3_PE_ZERO:
        LD      $9,0
        JP      P3_PE_LEAD
P3_PE_ONE:
        LD      $9,1

; Leading 0/1.  A bare 0 or 1 is valid.  Otherwise require '.' plus 1..4 digits.
P3_PE_LEAD:
        PRE     IX,RN_LEN
        LDW     $10,(IX+$SX)
        LDW     $12,1
        SBCW    $10,$12
        JP      Z,P3_PE_INT
        PRE     IX,RN_LEN
        LDW     $10,(IX+$SX)
        LDW     $12,3
        SBCW    $10,$12
        JP      C,P3_PE_BAD
        LD      $4,1
        PRE     IX,RN_BUF
        LD      $0,(IX+$4)
        SBC     $0,&H2E
        JP      NZ,P3_PE_BAD
        LDW     $22,2
        PRE     IX,RN_LEN
        LD      $14,(IX+$SX)
        SB      $14,$SY
        SB      $14,$SY
        LD      $8,$14
        JP      P3_PE_DIGS

P3_PE_INT:
        AN      $9,$9
        JP      Z,P3_PE_ZINT
        LDW     $20,10000
        JP      P3_PE_OK
P3_PE_ZINT:
        SBW     $20,$20
        JP      P3_PE_OK

P3_PE_DIGS:
        SBW     $20,$20
P3_PE_LOOP:
        PRE     IX,RN_BUF
        LD      $5,(IX+$22)
        LD      $0,$5
        SBC     $0,&H30
        JP      C,P3_PE_BAD
        LD      $0,$5
        SBC     $0,&H3A
        JP      NC,P3_PE_BAD
        SB      $5,&H30

; $20 = $20*10 + digit.
        LDW     $24,$20
        ADW     $20,$20
        LDW     $26,$24
        ADW     $26,$26
        ADW     $26,$26
        ADW     $26,$26
        ADW     $20,$26
        SBW     $26,$26
        LD      $26,$5
        ADW     $20,$26
        ADW     $22,$SY
        SB      $14,$SY
        JP      NZ,P3_PE_LOOP

; Integer part 1 is valid only when the fractional value is zero.
        AN      $9,$9
        JP      NZ,P3_PE_INT1

; Right-pad the fractional digits to four places.
        LD      $14,4
        SB      $14,$8
P3_PE_PADLP:
        AN      $14,$14
        JP      Z,P3_PE_OK
        LDW     $24,$20
        ADW     $20,$20
        LDW     $26,$24
        ADW     $26,$26
        ADW     $26,$26
        ADW     $26,$26
        ADW     $20,$26
        SB      $14,$SY
        JP      P3_PE_PADLP

P3_PE_INT1:
        ANCW    $20,$20
        JP      NZ,P3_PE_BAD
        LDW     $20,10000
P3_PE_OK:
        LD      $0,1
        RTN
P3_PE_BAD:
        LD      $0,0
        RTN

; ----------------------------------------------------------------------
; Runtime numerical reference and epsilon construction.
; These are native expanded-FP values from the accepted Chapter 03 layer.
; ----------------------------------------------------------------------
P3_INIT_REF:
; A = 5, then actually call accepted sqrt capability.
        LDW     $15,5
        CAL     BCD_FROM_U16
        SBW     $0,$0
        SBW     $2,$2
        SBW     $4,$4
        SBW     $6,$6
        SB      $8,$8
        CAL     BCD_SQRT
        CAL     P3_ST_TMP

; A = sqrt(5) + 1.
        LDW     $15,1
        CAL     BCD_FROM_U16
        LDM     $0,$10,8
        LD      $8,$18
        CAL     P3_LD_TMP
        CAL     BCD_ADD
        CAL     P3_ST_TMP

; A = (sqrt(5)+1)/2 = phi.
        LDW     $15,2
        CAL     BCD_FROM_U16
        LDM     $0,$10,8
        LD      $8,$18
        CAL     P3_LD_TMP
        CAL     BCD_DIV
        JP      P3_ST_PHI

P3_MAKE_EPS:
; A = epsilon_units / 10000.
        PRE     IX,WS_P3EPS
        LDW     $15,(IX+$SX)
        CAL     BCD_FROM_U16
        CAL     P3_ST_TMP
        LDW     $15,10000
        CAL     BCD_FROM_U16
        LDM     $0,$10,8
        LD      $8,$18
        CAL     P3_LD_TMP
        CAL     BCD_DIV
        JP      P3_ST_EPS

; Convert binary u32 $15-$18 to native FP using accepted u16 conversion,
; 65536=(32768+32768), multiply, and add.  No private floating core.
P3_FROM_U32:
        PRE     IX,P3_BIN
        STW     $15,(IX+$SX)
        LD      $4,2
        STW     $17,(IX+$4)

; A = high word.
        PRE     IX,P3_BIN
        LD      $4,2
        LDW     $15,(IX+$4)
        CAL     BCD_FROM_U16
        CAL     P3_ST_TMP

; B = 65536 exactly.
        LDW     $15,&H8000
        CAL     BCD_FROM_U16
        LDM     $0,$10,8
        LD      $8,$18
        CAL     BCD_ADD
        LDM     $0,$10,8
        LD      $8,$18

; A = high*65536.
        CAL     P3_LD_TMP
        CAL     BCD_MUL
        CAL     P3_ST_TMP

; B = low word; A = high part; result = full u32.
        PRE     IX,P3_BIN
        LDW     $15,(IX+$SX)
        CAL     BCD_FROM_U16
        LDM     $0,$10,8
        LD      $8,$18
        CAL     P3_LD_TMP
        CAL     BCD_ADD
        RTN

P3_MK_RATIO:
; Numerator F(n+1).
        PRE     IX,WS_P3N
        LD      $12,(IX+$SX)
        AD      $12,$SY
        CAL     FIB_LOAD
        CAL     P3_FROM_U32
        CAL     P3_ST_NUM

; Denominator F(n), then divide numerator by denominator.
        PRE     IX,WS_P3N
        LD      $12,(IX+$SX)
        CAL     FIB_LOAD
        CAL     P3_FROM_U32
        LDM     $0,$10,8
        LD      $8,$18
        CAL     P3_LD_NUM
        CAL     BCD_DIV
        JP      P3_ST_RATIO

P3_MK_ERR:
; Compare ratio with phi, then subtract smaller from larger.
        CAL     P3_LD_RATIO
        CAL     P3_LD_PHI_B
        CAL     NCP
        JP      C,P3_ERR_LOW
        CAL     P3_LD_RATIO
        CAL     P3_LD_PHI_B
        CAL     BCD_SUB
        JP      P3_ST_ERR
P3_ERR_LOW:
        CAL     P3_LD_PHI
        CAL     P3_LD_RATIO_B
        CAL     BCD_SUB
        JP      P3_ST_ERR

P3_IS_CONV:
; Return $0=1 iff error <= epsilon.
        CAL     P3_LD_ERR
        CAL     P3_LD_EPS_B
        CAL     NCP
        JP      C,P3_IC_Y
        JP      Z,P3_IC_Y
        LD      $0,0
        RTN
P3_IC_Y:
        LD      $0,1
        RTN

; ----------------------------------------------------------------------
; Automatic run.  One iteration == one displayed R(n), beginning at n=1.
; ----------------------------------------------------------------------
P3_RUN:
        CAL     WAITREL
        PRE     IX,WS_P3STOP
        ST      $31,(IX+$SX)
        PRE     IX,WS_P3N
        LD      $0,1
        ST      $0,(IX+$SX)
P3_RUNLP:
        CAL     P3_MK_RATIO
        CAL     P3_MK_ERR
        CAL     P3_DRAW_CUR

; Cooperative escape is checked at the iteration boundary.  BRK is already
; intercepted by POLLKEY and returns through the clean-slate cold path.
        CAL     POLLKEY
        AN      $17,$17
        JP      Z,P3_RCHECK
        LD      $12,$0
        SBC     $12,KEYMENU
        JP      Z,P3_RUNEXIT
        SBC     $12,FK4
        JP      Z,P3_RUNEXIT
        CAL     WAITREL
P3_RCHECK:
        CAL     P3_IS_CONV
        AN      $0,$0
        JP      NZ,P3_STOP_CONV

        PRE     IX,WS_P3N
        LD      $0,(IX+$SX)
        PRE     IX,WS_P3MAX
        LD      $1,(IX+$SX)
        LD      $2,$0
        SBC     $2,$1
        JP      Z,P3_STOP_MAX
        LD      $2,$0
        SBC     $2,46
        JP      Z,P3_STOP_BOUND

; The displayed intermediate state is evidence, not decoration.  r008 redrew
; iterations too quickly for a human to observe them, producing a numeric stream.
; Hold each nonterminal iteration until the next stable one-second TM transition.
; Final CONV/MAX/BOUND states do not wait here because they remain on screen.
        CAL     P3_ITER_WAIT

        PRE     IX,WS_P3N
        LD      $0,(IX+$SX)
        AD      $0,$SY
        ST      $0,(IX+$SX)
        JP      P3_RUNLP

; Human-observable iteration pacing.  TM has one-second resolution in the accepted
; Life/PerfMon lineage.  Use a stable complete-TM read so pacing is independent of
; CPU/emulator speed.  MENU/FK4 remain cooperative escape paths during the dwell;
; BRK is still caught by INKEY/POLLKEY and enters CH07_COLD.
P3_ITER_WAIT:
        GST     TM,$8
P3_IW_STABLE:
        LD      $9,$8
        GST     TM,$8
        SBC     $8,$9
        JP      NZ,P3_IW_STABLE

; r009 kept this witness in $10 across POLLKEY.  That is not a safe lifetime:
; ordinary firmware/application calls may alter scratch registers.  Persist the
; stable starting TM byte in RAM and reload it only at the comparison point.
        PRE     IX,WS_P3TM
        ST      $8,(IX+$SX)

P3_IW_LOOP:
        CAL     POLLKEY
        AN      $17,$17
        JP      Z,P3_IW_TICK
        LD      $12,$0
        SBC     $12,KEYMENU
        JP      Z,P3_RUNEXIT
        LD      $12,$0
        SBC     $12,FK4
        JP      Z,P3_RUNEXIT
        CAL     WAITREL
P3_IW_TICK:
        GST     TM,$8
P3_IW_ST2:
        LD      $9,$8
        GST     TM,$8
        SBC     $8,$9
        JP      NZ,P3_IW_ST2
        PRE     IX,WS_P3TM
        LD      $10,(IX+$SX)
        LD      $12,$8
        SBC     $12,$10
        JP      Z,P3_IW_LOOP
        RTN

P3_RUNEXIT:
        CAL     WAITREL
        JP      SHOW_MENU
P3_STOP_CONV:
        PRE     IX,WS_P3STOP
        LD      $0,1
        ST      $0,(IX+$SX)
        JP      P3_SCREEN
P3_STOP_MAX:
        PRE     IX,WS_P3STOP
        LD      $0,2
        ST      $0,(IX+$SX)
        JP      P3_SCREEN
P3_STOP_BOUND:
        PRE     IX,WS_P3STOP
        LD      $0,3
        ST      $0,(IX+$SX)
        JP      P3_SCREEN

; ----------------------------------------------------------------------
; Part-III screens.
; ----------------------------------------------------------------------
; UFMT32DEC has an explicit integration precondition: SX=0 and SY=1.
; The first Part-III configuration draw after cold boot must not inherit an
; ambient special-register state.  READN later re-establishes this environment,
; which explains why the r010 numeric spill was a one-time post-boot symptom.
P3_FMT_ENV:
        LD      $30,1
        LD      $31,0
        PSR     SZ,0
        PSR     SY,30
        PSR     SX,31
        PST     UA,&H14
        RTN

P3_DRAW_CFG:
        CAL     P3_FMT_ENV
        CAL     CLEAR_ALL
        CAL     CUR_HIDE
        LD      $6,&H00
        PRE     IZ,TXT_P3_TITLE
        CAL     PRINTZ
        LD      $6,&H20
        PRE     IZ,TXT_P3_EPS
        CAL     PRINTZ
        CAL     P3_PRINT_EPS
        LD      $6,&H40
        PRE     IZ,TXT_P3_MAX
        CAL     PRINTZ
        PRE     IX,WS_P3MAX
        LD      $15,(IX+$SX)
        LD      $16,$31
        SBW     $17,$17
        CAL     PUT_U32
        LD      $6,&H60
        PRE     IZ,FK_P3
        CAL     PRINTZ
        RTN

P3_DRAW_EEDIT:
        CAL     CLEAR_ALL
        CAL     CUR_HIDE
        LD      $6,&H00
        PRE     IZ,TXT_P3_SET_E
        CAL     PRINTZ
        LD      $6,&H20
        PRE     IZ,TXT_P3_EPS
        CAL     PRINTZ
        LD      $6,&H40
        PRE     IZ,TXT_P3_EFMT
        CAL     PRINTZ
        LD      $6,&H60
        PRE     IZ,FK_P3
        CAL     PRINTZ
        RTN

P3_DRAW_MEDIT:
        CAL     CLEAR_ALL
        CAL     CUR_HIDE
        LD      $6,&H00
        PRE     IZ,TXT_P3_SET_M
        CAL     PRINTZ
        LD      $6,&H20
        PRE     IZ,TXT_P3_MAXS
        CAL     PRINTZ
        LD      $6,&H40
        PRE     IZ,TXT_P3_MFMT
        CAL     PRINTZ
        LD      $6,&H60
        PRE     IZ,FK_P3
        CAL     PRINTZ
        RTN

P3_DRAW_CUR:
        CAL     P3_DRAW_DATA
        RTN

P3_DRAW_RES:
        CAL     P3_DRAW_DATA
        PRE     IX,WS_P3STOP
        LD      $0,(IX+$SX)
        LD      $6,&H54
        SBC     $0,1
        JP      Z,P3_DR_CONV
        PRE     IX,WS_P3STOP
        LD      $0,(IX+$SX)
        SBC     $0,2
        JP      Z,P3_DR_MAX
        PRE     IZ,TXT_P3_BOUND
        CAL     PRINTZ
        RTN
P3_DR_CONV:
        PRE     IZ,TXT_P3_CONV
        CAL     PRINTZ
        RTN
P3_DR_MAX:
        PRE     IZ,TXT_P3_MAXR
        CAL     PRINTZ
        RTN

P3_DRAW_DATA:
        CAL     CLEAR_ALL
        CAL     CUR_HIDE
; Rows 1-3 align the '=' signs in column 4.
; Row 1 keeps n at the far right so the three measured quantities form a column.
        LD      $6,&H00
        PRE     IZ,TXT_P3_R
        CAL     PRINTZ
        CAL     P3_LD_RATIO
        CAL     P3_PRINT_ONE
        LD      $6,&H1C
        PRE     IZ,TXT_P3_N
        CAL     PRINTZ
        PRE     IX,WS_P3N
        LD      $15,(IX+$SX)
        LD      $16,$31
        SBW     $17,$17
        CAL     PUT_U32
; row 2: phi
        LD      $6,&H20
        PRE     IZ,TXT_P3_PHI
        CAL     PRINTZ
        CAL     P3_LD_PHI
        CAL     P3_PRINT_ONE
; row 3: absolute error
        LD      $6,&H40
        PRE     IZ,TXT_P3_ERR
        CAL     PRINTZ
        CAL     P3_LD_ERR
        CAL     P3_PRINT_UNIT
; row 4: active controls
        LD      $6,&H60
        PRE     IZ,FK_P3
        CAL     PRINTZ
        RTN

; Print committed epsilon as exactly 0.dddd or 1.0000.
P3_PRINT_EPS:
; Build the complete canonical epsilon text before crossing the firmware text
; boundary.  r011 still loaded the numeric input, emitted "0." through PUTC
; (ROM &H0197), then trusted $15-$18 to remain live for UFMT32DEC.  That
; preservation was never part of the proven display primitive contract.
        PRE     IX,WS_DPOS
        ST      $6,(IX+$SX)

        PRE     IX,WS_P3EPS
        LDW     $15,(IX+$SX)
        LDW     $20,$15
        LDW     $22,10000
        SBCW    $20,$22
        JP      Z,P3_PEPS_ONE

; Format the fractional integer first, while no firmware display call can
; disturb its live registers.  Valid committed epsilon below 1.0000 is 0..9999,
; therefore UFMT32DEC must return 1..4 digits.
        SBW     $17,$17
        PRE     IX,FMTBUF
        CAL     UFMT32DEC
        LD      $13,$14             ; source digit count
        LD      $12,4
        SB      $12,$14             ; leading-zero count
        LD      $10,2               ; destination index after "0."

        PRE     IX,P3_FBUF
        LD      $16,"0"
        ST      $16,(IX+$SX)
        LD      $4,1
        LD      $16,"."
        ST      $16,(IX+$4)

P3_PEPS_PAD:
        AN      $12,$12
        JP      Z,P3_PEPS_DIG
        PRE     IX,P3_FBUF
        LD      $16,"0"
        ST      $16,(IX+$10)
        AD      $10,$SY
        SB      $12,$SY
        JP      P3_PEPS_PAD

P3_PEPS_DIG:
        LD      $11,0
P3_PEPS_CPY:
        SBC     $11,$13
        JP      NC,P3_PEPS_OUT
        PRE     IX,FMTBUF
        LD      $16,(IX+$11)
        PRE     IX,P3_FBUF
        ST      $16,(IX+$10)
        AD      $11,$SY
        AD      $10,$SY
        JP      P3_PEPS_CPY

P3_PEPS_OUT:
        PRE     IX,WS_DPOS
        LD      $6,(IX+$SX)
        LD      $13,6
        PRE     IX,P3_FBUF
        JP      PRINT_RAM

P3_PEPS_ONE:
        PRE     IX,WS_DPOS
        LD      $6,(IX+$SX)
        PRE     IZ,TXT_P3_ONE
        JP      PRINTZ

; ----------------------------------------------------------------------
; Native-FP presentation.  Ratio/phi are in [1,2), so the compact six-digit
; mantissa renders as d.ddddd.  Error uses the accepted Chapter-03 unit-domain
; formatter shape and keeps six significant digits.
; ----------------------------------------------------------------------
P3_PRINT_ONE:
        PRE     IX,WS_DPOS
        ST      $6,(IX+$SX)
        CAL     P3_FMT_ONE
        PRE     IX,WS_DPOS
        LD      $6,(IX+$SX)
        JP      P3_PRINT_F

P3_PRINT_UNIT:
        PRE     IX,WS_DPOS
        ST      $6,(IX+$SX)
        CAL     P3_FMT_UNIT
        PRE     IX,WS_DPOS
        LD      $6,(IX+$SX)
        JP      P3_PRINT_F

P3_PRINT_F:
        PRE     IX,P3_FLEN
        LD      $13,(IX+$SX)
        PRE     IX,P3_FBUF
        JP      PRINT_RAM

P3_FMT_ONE:
        CAL     BCD_TO_F32
        LD      $20,$15
        LD      $21,$16
        LD      $22,$17
        PRE     IX,P3_FBUF
        LD      $13,0
        LD      $16,$22
        DID     $16
        AN      $16,&H0F
        AD      $16,&H30
        CAL     P3_FPUT
        LD      $16,"."
        CAL     P3_FPUT
        LD      $16,$22
        AN      $16,&H0F
        AD      $16,&H30
        CAL     P3_FPUT
        LD      $12,$21
        CAL     P3_FPAIR
        LD      $12,$20
        CAL     P3_FPAIR
        PRE     IX,P3_FLEN
        ST      $13,(IX+$SX)
        RTN

P3_FMT_UNIT:
        CAL     BCD_TO_F32
        LD      $20,$15
        LD      $21,$16
        LD      $22,$17
        LD      $23,$18
        PRE     IX,P3_FBUF
        LD      $13,0
        LD      $16,"0"
        CAL     P3_FPUT
        LD      $16,"."
        CAL     P3_FPUT
        AN      $23,$23
        JP      NZ,P3_U_NONZERO
        LD      $14,6
P3_U_ZLOOP:
        LD      $16,"0"
        CAL     P3_FPUT
        SB      $14,$SY
        JP      NZ,P3_U_ZLOOP
        JP      P3_U_DONE
P3_U_NONZERO:
        LD      $14,$23
        AN      $14,&H3F
        SB      $14,$SY
P3_U_LEAD:
        AN      $14,$14
        JP      Z,P3_U_DIGITS
        LD      $16,"0"
        CAL     P3_FPUT
        SB      $14,$SY
        JP      P3_U_LEAD
P3_U_DIGITS:
        LD      $12,$22
        CAL     P3_FPAIR
        LD      $12,$21
        CAL     P3_FPAIR
        LD      $12,$20
        CAL     P3_FPAIR
P3_U_DONE:
        PRE     IX,P3_FLEN
        ST      $13,(IX+$SX)
        RTN

P3_FPUT:
        STI     $16,(IX+$SX)
        AD      $13,$SY
        RTN
P3_FPAIR:
        LD      $16,$12
        DID     $16
        AN      $16,&H0F
        AD      $16,&H30
        CAL     P3_FPUT
        LD      $16,$12
        AN      $16,&H0F
        AD      $16,&H30
        CAL     P3_FPUT
        RTN

; ----------------------------------------------------------------------
; Native-FP workspace helpers.
; ----------------------------------------------------------------------
P3_ST_PHI:
        PRE     IX,P3_PHI
        STIM    $10,(IX+$SX),8
        STI     $18,(IX+$SX)
        RTN
P3_LD_PHI:
        PRE     IX,P3_PHI
        LDIM    $10,(IX+$SX),8
        LDD     $18,(IX+$SX)
        RTN
P3_LD_PHI_B:
        PRE     IX,P3_PHI
        LDIM    $0,(IX+$SX),8
        LDD     $8,(IX+$SX)
        RTN
P3_ST_RATIO:
        PRE     IX,P3_RATIO
        STIM    $10,(IX+$SX),8
        STI     $18,(IX+$SX)
        RTN
P3_LD_RATIO:
        PRE     IX,P3_RATIO
        LDIM    $10,(IX+$SX),8
        LDD     $18,(IX+$SX)
        RTN
P3_LD_RATIO_B:
        PRE     IX,P3_RATIO
        LDIM    $0,(IX+$SX),8
        LDD     $8,(IX+$SX)
        RTN
P3_ST_ERR:
        PRE     IX,P3_ERR
        STIM    $10,(IX+$SX),8
        STI     $18,(IX+$SX)
        RTN
P3_LD_ERR:
        PRE     IX,P3_ERR
        LDIM    $10,(IX+$SX),8
        LDD     $18,(IX+$SX)
        RTN
P3_ST_EPS:
        PRE     IX,P3_EPSFP
        STIM    $10,(IX+$SX),8
        STI     $18,(IX+$SX)
        RTN
P3_LD_EPS_B:
        PRE     IX,P3_EPSFP
        LDIM    $0,(IX+$SX),8
        LDD     $8,(IX+$SX)
        RTN
P3_ST_TMP:
        PRE     IX,P3_TMPFP
        STIM    $10,(IX+$SX),8
        STI     $18,(IX+$SX)
        RTN
P3_LD_TMP:
        PRE     IX,P3_TMPFP
        LDIM    $10,(IX+$SX),8
        LDD     $18,(IX+$SX)
        RTN
P3_ST_NUM:
        PRE     IX,P3_NUMFP
        STIM    $10,(IX+$SX),8
        STI     $18,(IX+$SX)
        RTN
P3_LD_NUM:
        PRE     IX,P3_NUMFP
        LDIM    $10,(IX+$SX),8
        LDD     $18,(IX+$SX)
        RTN

; ======================================================================
; PART IV - LEKKERKERKER EXPERIMENT
; ======================================================================
; Required laboratory policy:
;   n=10,20       -> complete enumeration of [F(n),F(n+1))
;   n=30,40,46    -> 256 accepted samples, reset seed per run
; Exploratory policy used here: n<=20 enumerates; n>=21 samples.
; Sample mapping is unbiased: threshold = 2^32 mod range; reject x<threshold,
; then use x mod range.  Sampling is with replacement.
; ======================================================================
P4_SCREEN:
        PRE     IX,WS_P4DONE
        LD      $0,(IX+$SX)
        AN      $0,$0
        JP      Z,P4_CFG
        CAL     P4_DRAW_RES
        JP      P4_WAIT
P4_CFG:
        CAL     P4_SET_METH
        CAL     P4_DRAW_CFG
P4_WAIT:
        CAL     POLLKEY
        AN      $17,$17
        JP      Z,P4_WAIT
        LD      $12,$0
        SBC     $12,KEYMENU
        JP      Z,P4_EXIT
        SBC     $12,FK1
        JP      Z,P4_EDIT_N
        SBC     $12,FK2
        JP      Z,P4_EDIT_S
        SBC     $12,FK3
        JP      Z,P4_RUN
        SBC     $12,FK4
        JP      Z,P4_EXIT
        CAL     WAITREL
        JP      P4_SCREEN

P4_EXIT:
        CAL     WAITREL
        JP      SHOW_MENU

P4_PREP_EDIT:
        SBW     $2,$2
        PRE     IX,RN_LEN
        STW     $2,(IX+$SX)
        RTN

P4_EDIT_N:
        CAL     WAITREL
        CAL     P4_PREP_EDIT
        CAL     P4_DRAW_NED
        LDW     $0,RN_BUF
        PRE     IX,RN_LEN
        LDW     $2,(IX+$SX)
        LDW     $4,2
        LD      $6,&H24
        CAL     APP_READN
        CAL     WAITREL
        PRE     IX,RN_REASON
        LD      $8,(IX+$SX)
        PRE     IX,WS_RWHY
        ST      $8,(IX+$SX)
        SBC     $8,RN_MENU
        JP      Z,SHOW_MENU
        CAL     P1_PARSE_EDIT
        AN      $0,$0
        JP      Z,P4_SCREEN
        LD      $0,$20
        SBC     $0,2
        JP      C,P4_SCREEN
        LD      $0,$20
        SBC     $0,47
        JP      NC,P4_SCREEN
        PRE     IX,WS_P4N
        ST      $20,(IX+$SX)
        PRE     IX,WS_P4DONE
        ST      $31,(IX+$SX)
        PRE     IX,WS_RWHY
        LD      $8,(IX+$SX)
        SBC     $8,RN_FK2
        JP      Z,P4_EDIT_S
        SBC     $8,RN_FK3
        JP      Z,P4_RUN
        SBC     $8,RN_FK4
        JP      Z,SHOW_MENU
        JP      P4_SCREEN

P4_EDIT_S:
        CAL     WAITREL
        CAL     P4_PREP_EDIT
        CAL     P4_DRAW_SED
        LDW     $0,RN_BUF
        PRE     IX,RN_LEN
        LDW     $2,(IX+$SX)
        LDW     $4,10
        LD      $6,&H27
        CAL     APP_READN
        CAL     WAITREL
        PRE     IX,RN_REASON
        LD      $8,(IX+$SX)
        PRE     IX,WS_RWHY
        ST      $8,(IX+$SX)
        SBC     $8,RN_MENU
        JP      Z,SHOW_MENU
        CAL     P2_PARSE
        AN      $0,$0
        JP      Z,P4_SCREEN
        PRE     IX,WS_P4SEED
        STW     $15,(IX+$SX)
        LD      $4,2
        STW     $17,(IX+$4)
        PRE     IX,WS_P4DONE
        ST      $31,(IX+$SX)
        PRE     IX,WS_RWHY
        LD      $8,(IX+$SX)
        SBC     $8,RN_FK1
        JP      Z,P4_EDIT_N
        SBC     $8,RN_FK3
        JP      Z,P4_RUN
        SBC     $8,RN_FK4
        JP      Z,SHOW_MENU
        JP      P4_SCREEN

P4_SET_METH:
        PRE     IX,WS_P4N
        LD      $0,(IX+$SX)
        SBC     $0,21
        JP      C,P4_M_ENUM
        PRE     IX,WS_P4METH
        LD      $0,1
        ST      $0,(IX+$SX)
        RTN
P4_M_ENUM:
        PRE     IX,WS_P4METH
        ST      $31,(IX+$SX)
        RTN

P4_RUN:
        CAL     WAITREL
        PRE     IX,WS_P4DONE
        ST      $31,(IX+$SX)
        CAL     P4_SET_METH
        CAL     P4_PREP_IV
        CAL     P4_INIT_REF
        CAL     P4_DRAW_RUN
        PRE     IX,WS_P4METH
        LD      $0,(IX+$SX)
        AN      $0,$0
        JP      NZ,P4_RUN_SAMP
        CAL     P4_RUN_ENUM
        JP      P4_RUN_FIN
P4_RUN_SAMP:
        CAL     P4_RUN_SMP
P4_RUN_FIN:
        CAL     P4_FIN_MATH
        PRE     IX,WS_P4DONE
        LD      $0,1
        ST      $0,(IX+$SX)
        JP      P4_SCREEN

P4_RUNEXIT:
        CAL     WAITREL
        JP      SHOW_MENU

; Build interval endpoints and clear run accumulators.
P4_PREP_IV:
        PRE     IX,WS_P4N
        LD      $12,(IX+$SX)
        CAL     FIB_LOAD
        PRE     IX,P4_LO
        STW     $15,(IX+$SX)
        LD      $4,2
        STW     $17,(IX+$4)

        PRE     IX,WS_P4N
        LD      $12,(IX+$SX)
        AD      $12,$SY
        CAL     FIB_LOAD
        PRE     IX,P4_HI
        STW     $15,(IX+$SX)
        LD      $4,2
        STW     $17,(IX+$4)

; range = hi - lo.
        PRE     IX,P4_LO
        LDW     $5,(IX+$SX)
        LD      $4,2
        LDW     $7,(IX+$4)
        PRE     IX,P4_HI
        LDW     $15,(IX+$SX)
        LD      $4,2
        LDW     $17,(IX+$4)
        CAL     USUB32
        PRE     IX,P4_RANGE
        STW     $15,(IX+$SX)
        LD      $4,2
        STW     $17,(IX+$4)

        PRE     IX,P4_OBS
        SBW     $0,$0
        STW     $0,(IX+$SX)
        PRE     IX,P4_SUMZ
        STW     $0,(IX+$SX)
        RTN

; Complete enumeration.  The exploratory policy limits this to n<=20,
; so the largest population is F19=4181 observations.
P4_RUN_ENUM:
        PRE     IX,P4_LO
        LDW     $15,(IX+$SX)
        LD      $4,2
        LDW     $17,(IX+$4)
        PRE     IX,P4_CUR
        STW     $15,(IX+$SX)
        LD      $4,2
        STW     $17,(IX+$4)
P4_EN_LOOP:
        CAL     P4_ABORT
        AN      $0,$0
        JP      NZ,P4_RUNEXIT

; Stop exactly at the excluded upper endpoint.
        PRE     IX,P4_HI
        LDW     $5,(IX+$SX)
        LD      $4,2
        LDW     $7,(IX+$4)
        PRE     IX,P4_CUR
        LDW     $15,(IX+$SX)
        LD      $4,2
        LDW     $17,(IX+$4)
        LDW     $20,$17
        SBCW    $20,$7
        JP      NZ,P4_EN_OBS
        LDW     $20,$15
        SBCW    $20,$5
        JP      Z,P4_EN_DONE
P4_EN_OBS:
        CAL     P4_ZCOUNT
        CAL     P4_ACC_Z

; cur++ modulo 2^32; this interval cannot overflow u32 for n<=20.
        PRE     IX,P4_CUR
        LDW     $15,(IX+$SX)
        LD      $4,2
        LDW     $17,(IX+$4)
        ADW     $15,$SY
        JP      NC,P4_EN_ST
        ADW     $17,$SY
P4_EN_ST:
        PRE     IX,P4_CUR
        STW     $15,(IX+$SX)
        LD      $4,2
        STW     $17,(IX+$4)
        JP      P4_EN_LOOP
P4_EN_DONE:
        RTN

; Sample exactly 256 accepted draws, with replacement.  Generator state is reset
; from the committed seed for every run, so experiment order cannot affect results.
P4_RUN_SMP:
        PRE     IX,WS_P4SEED
        LDW     $15,(IX+$SX)
        LD      $4,2
        LDW     $17,(IX+$4)
        PRE     IX,P4_STATE
        STW     $15,(IX+$SX)
        LD      $4,2
        STW     $17,(IX+$4)
        CAL     P4_MK_THRESH
P4_SA_LOOP:
        PRE     IX,P4_OBS
        LDW     $20,(IX+$SX)
        LDW     $22,256
        SBCW    $20,$22
        JP      Z,P4_SA_DONE
        CAL     P4_ABORT
        AN      $0,$0
        JP      NZ,P4_RUNEXIT
        CAL     P4_LCG_NEXT

; Accept x only when x >= threshold.
        PRE     IX,P4_THRESH
        LDW     $5,(IX+$SX)
        LD      $4,2
        LDW     $7,(IX+$4)
        PRE     IX,P4_STATE
        LDW     $15,(IX+$SX)
        LD      $4,2
        LDW     $17,(IX+$4)
        CAL     P4_AGE_B
        AN      $0,$0
        JP      Z,P4_SA_LOOP

; offset = x mod range, then N = lo + offset.
        PRE     IX,P4_RANGE
        LDW     $5,(IX+$SX)
        LD      $4,2
        LDW     $7,(IX+$4)
        PRE     IX,P4_STATE
        LDW     $15,(IX+$SX)
        LD      $4,2
        LDW     $17,(IX+$4)
        CAL     UDIV32NZ
        LDW     $15,$10
        LDW     $17,$12
        PRE     IX,P4_LO
        LDW     $5,(IX+$SX)
        LD      $4,2
        LDW     $7,(IX+$4)
        CAL     UADD32
        CAL     P4_ZCOUNT
        CAL     P4_ACC_Z
        JP      P4_SA_LOOP
P4_SA_DONE:
        RTN

; LCG: s = 25173*s + 13849 (mod 2^32).
P4_LCG_NEXT:
        PRE     IX,P4_STATE
        LDW     $15,(IX+$SX)
        LD      $4,2
        LDW     $17,(IX+$4)
        LDW     $5,25173
        SBW     $7,$7
        CAL     UMUL32
        LDW     $5,13849
        SBW     $7,$7
        CAL     UADD32
        PRE     IX,P4_STATE
        STW     $15,(IX+$SX)
        LD      $4,2
        STW     $17,(IX+$4)
        RTN

; threshold = 2^32 mod range = (-range mod 2^32) mod range.
P4_MK_THRESH:
        PRE     IX,P4_RANGE
        LDW     $5,(IX+$SX)
        LD      $4,2
        LDW     $7,(IX+$4)
        SBW     $15,$15
        SBW     $17,$17
        CAL     USUB32
        PRE     IX,P4_RANGE
        LDW     $5,(IX+$SX)
        LD      $4,2
        LDW     $7,(IX+$4)
        CAL     UDIV32NZ
        PRE     IX,P4_THRESH
        STW     $10,(IX+$SX)
        LD      $4,2
        STW     $12,(IX+$4)
        RTN

; Return $0=1 iff unsigned A ($15-$18) >= B ($5-$8).
P4_AGE_B:
        LDW     $20,$17
        SBCW    $20,$7
        JP      C,P4_AGE_NO
        JP      NZ,P4_AGE_YES
        LDW     $20,$15
        SBCW    $20,$5
        JP      C,P4_AGE_NO
P4_AGE_YES:
        LD      $0,1
        RTN
P4_AGE_NO:
        LD      $0,0
        RTN

; Canonical Zeckendorf term count for N in $15-$18.  Because Part IV samples
; [F(n),F(n+1)), no term above F(n) can occur.  F1 is never used.
P4_ZCOUNT:
        PRE     IX,WS_P4N
        LD      $20,(IX+$SX)
        LD      $0,0
P4_Z_LOOP:
        LD      $10,$20
        SBC     $10,2
        JP      C,P4_Z_DONE
        LD      $12,$20
        CAL     FIB_LOAD_B
        LDW     $22,$17
        SBCW    $22,$7
        JP      C,P4_Z_SKIP
        JP      NZ,P4_Z_TAKE
        LDW     $22,$15
        SBCW    $22,$5
        JP      C,P4_Z_SKIP
P4_Z_TAKE:
        CAL     USUB32
        AD      $0,$SY
        SB      $20,$SY
        SB      $20,$SY
        JP      P4_Z_LOOP
P4_Z_SKIP:
        SB      $20,$SY
        JP      P4_Z_LOOP
P4_Z_DONE:
        RTN

P4_ACC_Z:
        PRE     IX,P4_SUMZ
        LDW     $20,(IX+$SX)
        SBW     $22,$22
        LD      $22,$0
        ADW     $20,$22
        STW     $20,(IX+$SX)
        PRE     IX,P4_OBS
        LDW     $20,(IX+$SX)
        ADW     $20,$SY
        STW     $20,(IX+$SX)
        RTN

; Poll cooperative escape only at an observation boundary.  All long-lived run
; state is in RAM, so no scratch register is trusted across POLLKEY.
P4_ABORT:
        CAL     POLLKEY
        AN      $17,$17
        JP      Z,P4_AB_NO
        LD      $12,$0
        SBC     $12,KEYMENU
        JP      Z,P4_AB_YES
        LD      $12,$0
        SBC     $12,FK4
        JP      Z,P4_AB_YES
        CAL     WAITREL
P4_AB_NO:
        LD      $0,0
        RTN
P4_AB_YES:
        LD      $0,1
        RTN

; Runtime reference = 1/sqrt(5), using the same accepted sqrt capability but an
; independent formula from Part III's phi construction.
P4_INIT_REF:
        LDW     $15,5
        CAL     BCD_FROM_U16
        CAL     BCD_SQRT
        CAL     P4_ST_TMP
        LDW     $15,1
        CAL     BCD_FROM_U16
        CAL     P4_LD_TMP_B
        CAL     BCD_DIV
        JP      P4_ST_REF

P4_FIN_MATH:
        CAL     P4_MK_AVG
        CAL     P4_MK_E
        RTN

; A(n) exact native-FP mean, plus floor(A*100000) for compact display.
P4_MK_AVG:
        PRE     IX,P4_SUMZ
        LDW     $15,(IX+$SX)
        SBW     $17,$17
        LDW     $5,&H86A0
        LDW     $7,1
        CAL     UMUL32
        PRE     IX,P4_OBS
        LDW     $5,(IX+$SX)
        CAL     UDIV3216NZ
        PRE     IX,P4_ASCL
        STW     $15,(IX+$SX)
        LD      $4,2
        STW     $17,(IX+$4)

; Native FP A = sumZ / observations.
        PRE     IX,P4_SUMZ
        LDW     $15,(IX+$SX)
        CAL     BCD_FROM_U16
        CAL     P4_ST_TMP
        PRE     IX,P4_OBS
        LDW     $15,(IX+$SX)
        CAL     BCD_FROM_U16
        LDM     $0,$10,8
        LD      $8,$18
        CAL     P4_LD_TMP
        CAL     BCD_DIV
        JP      P4_ST_AVG

; E = 1 - 2*A/n.
P4_MK_E:
        LDW     $15,2
        CAL     BCD_FROM_U16
        LDM     $0,$10,8
        LD      $8,$18
        CAL     P4_LD_AVG
        CAL     BCD_MUL
        CAL     P4_ST_TMP

        PRE     IX,WS_P4N
        LD      $15,(IX+$SX)
        LD      $16,$31
        CAL     BCD_FROM_U16
        LDM     $0,$10,8
        LD      $8,$18
        CAL     P4_LD_TMP
        CAL     BCD_DIV
        CAL     P4_ST_TMP

        LDW     $15,1
        CAL     BCD_FROM_U16
        CAL     P4_LD_TMP_B
        CAL     BCD_SUB
        JP      P4_ST_E

; Part-IV screens.
P4_DRAW_CFG:
        CAL     CLEAR_ALL
        CAL     CUR_HIDE
        LD      $6,&H00
        PRE     IZ,TXT_P4_TITLE
        CAL     PRINTZ
        LD      $6,&H20
        PRE     IZ,TXT_P4_N
        CAL     PRINTZ
        PRE     IX,WS_P4N
        LD      $15,(IX+$SX)
        LD      $16,$31
        SBW     $17,$17
        CAL     PUT_U32
        PRE     IZ,TXT_P4_MSEP
        CAL     PRINTZ
        CAL     P4_PRINT_METH
        LD      $6,&H40
        PRE     IZ,TXT_P4_SEED
        CAL     PRINTZ
        PRE     IX,WS_P4SEED
        LDW     $15,(IX+$SX)
        LD      $4,2
        LDW     $17,(IX+$4)
        CAL     PUT_U32
        LD      $6,&H60
        PRE     IZ,FK_P4
        CAL     PRINTZ
        RTN

P4_DRAW_NED:
        CAL     CLEAR_ALL
        CAL     CUR_HIDE
        LD      $6,&H00
        PRE     IZ,TXT_P4_SETN
        CAL     PRINTZ
        LD      $6,&H20
        PRE     IZ,TXT_P4_NPR
        CAL     PRINTZ
        LD      $6,&H40
        PRE     IZ,TXT_P4_NRNG
        CAL     PRINTZ
        LD      $6,&H60
        PRE     IZ,FK_P4
        CAL     PRINTZ
        RTN

P4_DRAW_SED:
        CAL     CLEAR_ALL
        CAL     CUR_HIDE
        LD      $6,&H00
        PRE     IZ,TXT_P4_SETS
        CAL     PRINTZ
        LD      $6,&H20
        PRE     IZ,TXT_P4_SPR
        CAL     PRINTZ
        LD      $6,&H40
        PRE     IZ,TXT_P4_SRNG
        CAL     PRINTZ
        LD      $6,&H60
        PRE     IZ,FK_P4
        CAL     PRINTZ
        RTN

P4_DRAW_RUN:
        CAL     CLEAR_ALL
        CAL     CUR_HIDE
        LD      $6,&H00
        PRE     IZ,TXT_P4_RUN
        CAL     PRINTZ
        LD      $6,&H20
        PRE     IZ,TXT_P4_N
        CAL     PRINTZ
        PRE     IX,WS_P4N
        LD      $15,(IX+$SX)
        LD      $16,$31
        SBW     $17,$17
        CAL     PUT_U32
        PRE     IZ,TXT_P4_MSEP
        CAL     PRINTZ
        CAL     P4_PRINT_METH
        LD      $6,&H40
        PRE     IZ,TXT_P4_WORK
        CAL     PRINTZ
        LD      $6,&H60
        PRE     IZ,FK_EXIT
        CAL     PRINTZ
        RTN

P4_DRAW_RES:
        CAL     CLEAR_ALL
        CAL     CUR_HIDE
; Row 1: n and exact half-open population interval.
        LD      $6,&H00
        PRE     IZ,TXT_P4_N
        CAL     PRINTZ
        PRE     IX,WS_P4N
        LD      $15,(IX+$SX)
        LD      $16,$31
        SBW     $17,$17
        CAL     PUT_U32
        PRE     IZ,TXT_P4_LBR
        CAL     PRINTZ
        PRE     IX,P4_LO
        LDW     $15,(IX+$SX)
        LD      $4,2
        LDW     $17,(IX+$4)
        CAL     PUT_U32
        PRE     IZ,TXT_P4_COMMA
        CAL     PRINTZ
        PRE     IX,P4_HI
        LDW     $15,(IX+$SX)
        LD      $4,2
        LDW     $17,(IX+$4)
        CAL     PUT_U32
        PRE     IZ,TXT_P4_RPAR
        CAL     PRINTZ

; Rows 2-3 are arranged for human visual comparison.
; Left column is the scientific comparison: measured E over independent REF,
; with the '=' signs aligned vertically.  Right column is supporting context:
; method/count over A, again with aligned '=' signs.
        LD      $6,&H20
        PRE     IZ,TXT_P4_ERES
        CAL     PRINTZ
        CAL     P4_LD_E
        CAL     P3_PRINT_UNIT

        LD      $6,&H30
        CAL     P4_PRINT_RM
        PRE     IX,P4_OBS
        LDW     $15,(IX+$SX)
        SBW     $17,$17
        CAL     PUT_U32

        LD      $6,&H40
        PRE     IZ,TXT_P4_RREF
        CAL     PRINTZ
        CAL     P4_LD_REF
        CAL     P3_PRINT_UNIT

        LD      $6,&H50
        PRE     IZ,TXT_P4_ARES
        CAL     PRINTZ
        CAL     P4_PRINT_A

        LD      $6,&H60
        PRE     IZ,FK_P4
        CAL     PRINTZ
        RTN

P4_PRINT_METH:
        PRE     IX,WS_P4METH
        LD      $0,(IX+$SX)
        AN      $0,$0
        JP      Z,P4_PM_ENUM
        PRE     IZ,TXT_P4_SAMP
        JP      PRINTZ
P4_PM_ENUM:
        PRE     IZ,TXT_P4_ENUM
        JP      PRINTZ

; Result-screen method/count label.  Both forms are seven characters so
; the '=' aligns with TXT_P4_ARES in the row below.
P4_PRINT_RM:
        PRE     IX,WS_P4METH
        LD      $0,(IX+$SX)
        AN      $0,$0
        JP      Z,P4_RM_ENUM
        PRE     IZ,TXT_P4_RSAMP
        JP      PRINTZ
P4_RM_ENUM:
        PRE     IZ,TXT_P4_RENUM
        JP      PRINTZ

; Display floor(A*100000) with an explicit five-digit fractional field.
; Build the complete string before calling firmware output.
P4_PRINT_A:
        PRE     IX,WS_DPOS
        ST      $6,(IX+$SX)
        PRE     IX,P4_ASCL
        LDW     $15,(IX+$SX)
        LD      $4,2
        LDW     $17,(IX+$4)
        PRE     IX,FMTBUF
        CAL     UFMT32DEC
        LD      $13,$14             ; source length
        LD      $11,0               ; source index
        LD      $10,0               ; destination index
        LD      $12,$14
        SBC     $12,6
        JP      C,P4_A_SMALL

; len>=6: integer digits = len-5.
        LD      $12,$14
        SB      $12,5
P4_A_COPYI:
        LD      $0,$11
        SBC     $0,$12
        JP      NC,P4_A_DOT
        PRE     IX,FMTBUF
        LD      $16,(IX+$11)
        PRE     IX,P4_FBUF
        ST      $16,(IX+$10)
        AD      $11,$SY
        AD      $10,$SY
        JP      P4_A_COPYI
P4_A_DOT:
        PRE     IX,P4_FBUF
        LD      $16,"."
        ST      $16,(IX+$10)
        AD      $10,$SY
        JP      P4_A_FRAC

P4_A_SMALL:
        PRE     IX,P4_FBUF
        LD      $16,"0"
        ST      $16,(IX+$SX)
        LD      $10,1
        LD      $16,"."
        ST      $16,(IX+$10)
        AD      $10,$SY
        LD      $12,5
        SB      $12,$14
P4_A_PAD:
        AN      $12,$12
        JP      Z,P4_A_FRAC
        PRE     IX,P4_FBUF
        LD      $16,"0"
        ST      $16,(IX+$10)
        AD      $10,$SY
        SB      $12,$SY
        JP      P4_A_PAD

P4_A_FRAC:
        LD      $0,$11
        SBC     $0,$13
        JP      NC,P4_A_OUT
        PRE     IX,FMTBUF
        LD      $16,(IX+$11)
        PRE     IX,P4_FBUF
        ST      $16,(IX+$10)
        AD      $11,$SY
        AD      $10,$SY
        JP      P4_A_FRAC
P4_A_OUT:
        PRE     IX,P4_FLEN
        ST      $10,(IX+$SX)
        PRE     IX,WS_DPOS
        LD      $6,(IX+$SX)
        PRE     IX,P4_FLEN
        LD      $13,(IX+$SX)
        PRE     IX,P4_FBUF
        JP      PRINT_RAM

; Part-IV native-FP workspace helpers.
P4_ST_TMP:
        PRE     IX,P4_TMP
        STIM    $10,(IX+$SX),8
        STI     $18,(IX+$SX)
        RTN
P4_LD_TMP:
        PRE     IX,P4_TMP
        LDIM    $10,(IX+$SX),8
        LDD     $18,(IX+$SX)
        RTN
P4_LD_TMP_B:
        PRE     IX,P4_TMP
        LDIM    $0,(IX+$SX),8
        LDD     $8,(IX+$SX)
        RTN
P4_ST_AVG:
        PRE     IX,P4_AVG
        STIM    $10,(IX+$SX),8
        STI     $18,(IX+$SX)
        RTN
P4_LD_AVG:
        PRE     IX,P4_AVG
        LDIM    $10,(IX+$SX),8
        LDD     $18,(IX+$SX)
        RTN
P4_ST_E:
        PRE     IX,P4_EVAL
        STIM    $10,(IX+$SX),8
        STI     $18,(IX+$SX)
        RTN
P4_LD_E:
        PRE     IX,P4_EVAL
        LDIM    $10,(IX+$SX),8
        LDD     $18,(IX+$SX)
        RTN
P4_ST_REF:
        PRE     IX,P4_REF
        STIM    $10,(IX+$SX),8
        STI     $18,(IX+$SX)
        RTN
P4_LD_REF:
        PRE     IX,P4_REF
        LDIM    $10,(IX+$SX),8
        LDD     $18,(IX+$SX)
        RTN

; ======================================================================
; DISPLAY / FORMAT HELPERS
; ======================================================================
SCREEN_INIT:
        PST     UA,&H14
        CAL     OFFCHK
        PPO     &HC0
        LDW     $0,&H12B5
SI_DELAY:
        SBW     $0,$SY
        JR      NZ,SI_DELAY
        CAL     &H02D4
        PPO     &HC3
        LD      $0,&H0C
        LDW     $1,&H3000
        STLM    $0,3
        CAL     CLEAR_ALL
        CAL     &H0304
        CAL     &H0306
        PST     UA,&H54
        PRE     IX,KEYMD
        ST      $31,(IX+$SX)
        PST     UA,&H14
        RTN

CLEAR_ALL:
        LD      $6,$SX
        LD      $8,128
        CAL     &H018D
        RTN

PUTC:
        LD      $7,$16
        LD      $0,$7
        DIU     $7
        DID     $0
        OR      $7,$SZ
        CAL     &H0197
        RTN

PRINTZ:
        LDI     $7,(IZ+$SX)
        LD      $0,$7
        DIU     $7
        DID     $0
        OR      $7,$SZ
        RTN     Z
        CAL     &H0197
        JR      PRINTZ

; IX=RAM buffer, $13=length, $6=display position.
PRINT_RAM:
        AN      $13,$13
        RTN     Z
        LD      $12,0
PRAM_LOOP:
        SBC     $12,$13
        RTN     NC
        LD      $16,(IX+$12)
        CAL     PUTC
        AD      $12,$SY
        JR      PRAM_LOOP

; Input $15-$18 unsigned u32; print decimal at current $6.
PUT_U32:
        PRE     IX,WS_DPOS
        ST      $6,(IX+$SX)
        PRE     IX,FMTBUF
        CAL     UFMT32DEC
        PRE     IX,WS_DPOS
        LD      $6,(IX+$SX)
        LD      $13,$14
        PRE     IX,FMTBUF
        JP      PRINT_RAM

; ======================================================================
; ROM STRINGS
; ======================================================================
TXT_SPL0:      DB      "                                ",0
TXT_SPL1:      DB      "         Xandrian Labs          ",0
TXT_SPL2:      DB      "       CS617 / Fibonacci        ",0
TXT_SPL3:      DB      "                                ",0

TXT_MENU0:     DB      "CS617 Fibonacci                 ",0
FK_MAIN:       DB      "[explr ][zeck  ][ratio ][lekkr ]",0

FK_EXIT:       DB      "                        [exit  ]",0

TXT_P1_TITLE:  DB      "Fibonacci Explorer              ",0
TXT_P1_N:      DB      "n = ",0
TXT_P1_F:      DB      "F(n) = ",0
FK_P1:         DB      "[n     ][next  ][prev  ][exit  ]",0

TXT_P2_N:      DB      "N = ",0
FK_P2:         DB      "[n     ][left  ][right ][exit  ]",0
TXT_ZERO:      DB      "0",0

TXT_P3_TITLE:  DB      "Golden Ratio                    ",0
TXT_P3_EPS:    DB      "eps=",0
TXT_P3_MAX:    DB      "max_iter=",0
TXT_P3_MAXS:   DB      "max=",0
TXT_P3_SET_E:  DB      "Set epsilon                     ",0
TXT_P3_SET_M:  DB      "Set max_iter                    ",0
TXT_P3_EFMT:   DB      "0..1, up to 4 decimals          ",0
TXT_P3_MFMT:   DB      "range 1..46                     ",0
TXT_P3_N:      DB      "n=",0
TXT_P3_R:      DB      "R   =",0
TXT_P3_PHI:    DB      "phi =",0
TXT_P3_ERR:    DB      "err =",0
TXT_P3_CONV:   DB      "CONV",0
TXT_P3_MAXR:   DB      "MAX",0
TXT_P3_BOUND:  DB      "BOUND",0
TXT_P3_ONE:    DB      "1.0000",0
FK_P3:         DB      "[eps   ][iter  ][run   ][exit  ]",0

TXT_P4_TITLE:  DB      "Lekkerkerker Experiment         ",0
TXT_P4_RUN:    DB      "Lekkerkerker RUN                ",0
TXT_P4_N:      DB      "n=",0
TXT_P4_MSEP:   DB      " method=",0
TXT_P4_SEED:   DB      "seed=",0
TXT_P4_SETN:   DB      "Set n                           ",0
TXT_P4_NPR:    DB      "n = ",0
TXT_P4_NRNG:   DB      "range 2..46                     ",0
TXT_P4_SETS:   DB      "Set seed                        ",0
TXT_P4_SPR:    DB      "seed = ",0
TXT_P4_SRNG:   DB      "u32 0..4294967295               ",0
TXT_P4_WORK:   DB      "working...                      ",0
TXT_P4_LBR:    DB      " [",0
TXT_P4_COMMA:  DB      ",",0
TXT_P4_RPAR:   DB      ")",0
TXT_P4_CNT:    DB      " #=",0
TXT_P4_AVG:    DB      " A=",0
TXT_P4_E:      DB      "E=",0
TXT_P4_REF:    DB      " ref=",0
TXT_P4_ENUM:   DB      "enum",0
TXT_P4_SAMP:   DB      "sample",0
TXT_P4_ERES:   DB      "E   =",0
TXT_P4_RREF:   DB      "REF =",0
TXT_P4_ARES:   DB      "A     =",0
TXT_P4_RENUM:  DB      "enum  =",0
TXT_P4_RSAMP:  DB      "sample=",0
FK_P4:         DB      "[n     ][seed  ][run   ][exit  ]",0

; ======================================================================
; Reusable input and numeric dependencies.
; ======================================================================
#INCLUDE (readn.inc)
#INCLUDE (uadd32.inc)
#INCLUDE (usub32.inc)
#INCLUDE (umul32.inc)
#INCLUDE (udecapp.inc)
#INCLUDE (udiv32.inc)
#INCLUDE (udiv16.inc)
#INCLUDE (fmt32.inc)

; Accepted Chapter-03 native BCD numerical/presentation surfaces for Parts III-IV.
#INCLUDE (bcd_add.inc)
#INCLUDE (bcd_sub.inc)
#INCLUDE (bcd_mul.inc)
#INCLUDE (bcd_div.inc)
#INCLUDE (bcd_from_u16.inc)
#INCLUDE (bcd_sqrt.inc)
#INCLUDE (bcd_to_f32.inc)

        ORG     &HFFFF
        DB      0
