; ---------------------------------------------------------------------------
; 6502, the program the chip runs forever.
;
; Five classic routines, chosen because they read well in the trace: a shift
; and add multiply, a bubble sort, the linear feedback shift register that gave
; the arcade machines their randomness, a 16 bit fibonacci, and a memory fill
; that checks itself.
;
; The market does not decorate this program, it interrupts it. A buy raises
; IRQ, a big buy raises NMI, and the size of the trade arrives in memory at
; $FE00 before the line goes low, exactly the way a peripheral would do it.
; ---------------------------------------------------------------------------

; zero page
mand    = $10           ; multiplicand
mier    = $11           ; multiplier
prodlo  = $12
prodhi  = $13
seed    = $14           ; lfsr state
f0lo    = $15
f0hi    = $16
f1lo    = $17
f1hi    = $18
tmplo   = $19
tmphi   = $1A
swapped = $1B
ringix  = $1C
buylo   = $1D
buyhi   = $1E
nmilo   = $1F

; visible memory
out     = $0200         ; scratch the site reads
list    = $0240         ; the eight bytes being sorted
ring    = $0220         ; last sixteen trade sizes
mailbox = $FE00         ; the size of the trade that caused the interrupt
nmibox  = $FE01

        .org $F000

; ------------------------------------------------------------------ arranque
reset   SEI
        CLD
        LDX #$FF
        TXS

        LDA #$01
        STA f0lo
        STA f1lo
        LDA #$00
        STA f0hi
        STA f1hi
        STA prodlo
        STA prodhi
        STA ringix
        STA buylo
        STA buyhi
        STA nmilo
        LDA #$A5
        STA seed
        LDA #$07
        STA mand
        LDA #$0D
        STA mier

        JSR seedlist
        CLI

; ------------------------------------------------------------------- ciclo
main    JSR mult
        JSR sort
        JSR lfsr
        JSR fib
        JSR fill
        INC out+15
        JSR seedlist
        JMP main

; ------------------------------------ multiplicacao de 8 por 8, shift e soma
mult    LDA #$00
        STA prodlo
        LDX #$08
mloop   LSR mand
        BCC mskip
        CLC
        ADC mier
mskip   ROR A
        ROR prodlo
        DEX
        BNE mloop
        STA prodhi
        LDA prodlo
        STA out
        LDA prodhi
        STA out+1
        ; repoe os operandos com valores novos vindos do lfsr
        LDA seed
        ORA #$01
        STA mand
        LDA seed
        EOR #$3F
        ORA #$01
        STA mier
        RTS

; ------------------------------------------------- ordenacao por trocas
sort    LDA #$00
        STA swapped
        LDX #$00
sloop   LDA list,X
        CMP list+1,X
        BCC snext
        BEQ snext
        LDY list+1,X
        STA list+1,X
        TYA
        STA list,X
        LDA #$01
        STA swapped
snext   INX
        CPX #$07
        BNE sloop
        LDA swapped
        BNE sort
        RTS

; ------------------------------- registo de deslocamento com realimentacao
lfsr    LDA seed
        LSR A
        BCC lnofb
        EOR #$B4
lnofb   STA seed
        STA out+2
        RTS

; -------------------------------------------------- fibonacci de 16 bits
fib     CLC
        LDA f1lo
        ADC f0lo
        STA tmplo
        LDA f1hi
        ADC f0hi
        STA tmphi
        BCS fibrst
        LDA f1lo
        STA f0lo
        LDA f1hi
        STA f0hi
        LDA tmplo
        STA f1lo
        STA out+4
        LDA tmphi
        STA f1hi
        STA out+5
        RTS
fibrst  LDA #$01
        STA f0lo
        STA f1lo
        LDA #$00
        STA f0hi
        STA f1hi
        RTS

; ------------------------------------ enche a memoria e confere byte a byte
fill    LDX #$00
floop   TXA
        EOR #$5A
        STA $0300,X
        INX
        CPX #$40
        BNE floop
        LDX #$00
cloop   TXA
        EOR #$5A
        CMP $0300,X
        BNE bad
        INX
        CPX #$40
        BNE cloop
        INC out+10
        RTS
bad     INC out+11
        RTS

; ------------------------------------ enche a lista a ordenar com o lfsr
seedlist LDX #$00
slloop  JSR lfsr
        LDA seed
        STA list,X
        INX
        CPX #$08
        BNE slloop
        RTS

; ------------------------------------------------------------ interrupcoes
; IRQ: uma compra. Conta a e guarda o tamanho no anel.
irq     PHA
        TXA
        PHA
        INC buylo
        BNE inohi
        INC buyhi
inohi   LDA buylo
        STA out+6
        LDA buyhi
        STA out+7
        LDA mailbox
        LDX ringix
        STA ring,X
        INX
        TXA
        AND #$0F
        STA ringix
        PLA
        TAX
        PLA
        RTI

; NMI: uma compra grande. Nao se pode mascarar, entra sempre.
nmi     PHA
        INC nmilo
        LDA nmilo
        STA out+8
        LDA nmibox
        STA out+9
        PLA
        RTI

; ------------------------------------------------------------------ vetores
        .org $FFFA
        .word nmi
        .word reset
        .word irq
