dos33fsprogs/two-liners/entropy.s

216 lines
5.2 KiB
ArmAsm
Raw Normal View History

2018-05-27 05:03:45 +00:00
; Entropy
; by Dave McKellar of Toronto
; Two-line BASIC program
; Found on Beagle Brother's Apple Mechanic Disk
; Converted to 6502 Assembly by Deater (Vince Weaver) vince@deater.net
2018-05-27 05:03:45 +00:00
; 24001 ROT=0:FOR I=1 TO 15: READ A,B: POKE A,B: NEXT: DATA
; 232,252,233,29,7676,1,7678,4,7679,0,7680,18,7681,63,
; 7682,36,7683,36,7684,45,7685,45,7686,54,7687,54,7688,63,
; 7689,0
; 24002 FOR I=1 TO 99: HGR2: FOR E=.08 TO .15 STEP .01:
; FOR Y=4 to 189 STEP 6: FOR X=4 to 278 STEP 6:
; SCALE=(RND(1)<E)*RND(1)*E*20+1: XDRAW 1 AT X,Y:
2018-05-29 04:01:23 +00:00
; NEXT: NEXT: NEXT: NEXT
2018-05-27 05:03:45 +00:00
2018-05-28 04:02:37 +00:00
; Optimization
; 144 bytes: first working version (including DOS33 4-byte size/addr)
2018-05-28 04:30:40 +00:00
; 141 bytes: nextx: cache XPOS in X register
; 140 bytes: nexty: we know state of carry flag
2018-05-28 04:59:28 +00:00
; 139 bytes: change jmp to bcs
; 138 bytes: jmp at end now fits into a bcs
; 136 bytes: store YPOS on stack
; 135 bytes: store X to HGR_SCALE rather than TXA+STA
; 131 bytes: some fancy branch elimination by noticing X=1
2018-05-29 04:01:23 +00:00
; 126 bytes: nextx: simplify by using knowledge of possible x/y vals
; 124 bytes: qkumba noticed we can bump yloop up to include the
; pha, letting us remove two now unneeded stack ops
; 123 bytes: qkumba noticed XDRAW0 always exits with X==0 so
; we can move some things to use X instead and
; can get a "1" value simply by using INX
; 122 bytes: Nick Westgate noticed that we could save a byte
; in eloop by pushing the stx ELOOP to the beginning
; rather than the end.
2018-05-28 04:02:37 +00:00
2018-05-27 22:45:07 +00:00
;BLT=BCC, BGE=BCS
2018-05-27 05:03:45 +00:00
; zero page locations
HGR_SHAPE = $1A
2018-05-27 22:45:07 +00:00
FAC_EXP = $9D
FAC_HO = $9E
FAC_MOH = $9F
FAC_MO = $A0
FAC_LO = $A1
FAC_SGN = $A2
RND_EXP = $C9
RND_HO = $CA
RND_MOH = $CB
RND_MO = $CC
RND_LO = $CD
RND_SGN = $CE
2018-05-27 05:03:45 +00:00
HGR_SCALE = $E7
HGR_ROTATION = $F9
2018-05-27 22:45:07 +00:00
EPOS = $FC
2018-05-27 05:03:45 +00:00
XPOS = $FD
XPOSH = $FE
YPOS = $FF
; ROM calls
2018-05-27 22:45:07 +00:00
CONINT = $E6FB
FMULT = $E97F
2018-05-28 04:02:37 +00:00
MUL10 = $EA39
DIV10 = $EA55
MOVAF = $EB63
FLOAT = $EB93
2018-05-27 22:45:07 +00:00
RND = $EFAE
2018-05-27 05:03:45 +00:00
HGR2 = $F3D8
HPOSN = $F411
XDRAW0 = $F65D
2018-05-28 05:30:12 +00:00
2018-05-27 05:03:45 +00:00
entropy:
2018-05-29 04:01:23 +00:00
jsr HGR2 ; Hi-res graphics, no text at bottom
; Y=0, A=$60 after this call
2018-05-27 05:03:45 +00:00
ldx #8 ; Unlike the BASIC, our loop is *100
; 8 to 15 rather than .08 to .15
2018-05-28 04:22:47 +00:00
eloop:
stx EPOS ; EPOS was temporarily in X
2018-05-29 04:01:23 +00:00
lda #4 ; FOR Y=4 to 189 STEP 6
2018-05-28 04:22:47 +00:00
yloop:
pha ; YPOS stored on stack
2018-05-29 04:01:23 +00:00
lda #4 ; FOR X=4 to 278 STEP 6
2018-05-27 05:03:45 +00:00
sta XPOS
ldx #0 ; can't fit 278 in one byte, need overflow byte
stx XPOSH
2018-05-28 04:22:47 +00:00
xloop:
2018-05-27 05:03:45 +00:00
; SCALE=(RND(1)<E)*RND(1)*E*20+1
2018-05-27 22:45:07 +00:00
;
; Equivalent to IF RND(1)<E THEN SCALE=RND(1)*E*20+1
; ELSE SCALE=1
; Note the Apple II generates a seed based on keypresses
; but by default RND is never seeded from there.
; Someone actually wrote an entire academic paper complaining about
; this
;
; J.W. Aldridge. "Cautions regarding random number generation
; on the Apple II", Behavior Research Methods, Instruments,
; & Computers, 1987, 19 (4), 397-399.
2018-05-29 04:01:23 +00:00
; Many of these values are in Applesoft 5-byte floating point
2018-05-28 05:30:12 +00:00
; get random value in FAC
2018-05-29 04:01:23 +00:00
; (floating point accumlator)
inx ; X is always 0 coming in, increment to 1
; RND(1), Force 1
2018-05-29 04:01:23 +00:00
; returns "random" value between 0 and 1
2018-05-28 05:30:12 +00:00
jsr RND+6 ; we skip passing the argument
; as a floating point value
2018-05-29 04:01:23 +00:00
; as that would be a pain
2018-05-27 22:45:07 +00:00
; Compare to E
2018-05-28 05:30:12 +00:00
jsr MUL10 ; EPOS is E*100
jsr MUL10 ; so multiply rand*100 before compare
2018-05-29 04:01:23 +00:00
jsr CONINT ; now convert to int, result in X
; X is now RND(1)*100
2018-05-27 22:45:07 +00:00
2018-05-28 05:30:12 +00:00
cpx EPOS ; compare E*100 to RND*100
ldx #1 ; load 1 into X (this is clever)
bcs done ; if EPOS>=RND then SCALE=1, skip ahead
2018-05-28 04:02:37 +00:00
; SCALE=RND(1)*E*20+1
; EPOS is E*100, so RND(1)*(EPOS/10)*2+1
2018-05-28 05:30:12 +00:00
2018-05-28 05:38:48 +00:00
; What this does:
; if EPOS is 8,9 then value is either 1 or 2
; if EPOS is 10,11,12,13,14 then value is either 1, 2, or 3
2018-05-28 05:32:17 +00:00
; put random value in FAC
; ldx #1 ; RND(1), Force 1, this set from earlier
jsr RND+6 ; skip arg parsing in RND
2018-05-28 04:02:37 +00:00
lda EPOS
2018-05-28 05:32:17 +00:00
jsr FLOAT ; convert value in A to float in FAC
jsr DIV10 ; FAC=FAC/10
2018-05-28 04:02:37 +00:00
2018-05-28 05:32:17 +00:00
ldy #>RND_EXP ; point (Y,A) to RND value
2018-05-28 04:02:37 +00:00
lda #<RND_EXP
2018-05-29 04:01:23 +00:00
jsr FMULT ; multiply FAC by RND in (Y,A)
2018-05-27 15:22:38 +00:00
2018-05-28 05:32:17 +00:00
inc FAC_EXP ; multiply by 2
2018-05-28 04:02:37 +00:00
2018-05-28 05:32:17 +00:00
jsr CONINT ; convert to int (in X)
2018-05-28 04:02:37 +00:00
2018-05-28 04:59:28 +00:00
inx ; add 1
2018-05-28 04:02:37 +00:00
done:
stx HGR_SCALE ; set scale value
2018-05-27 05:03:45 +00:00
2018-05-28 04:45:59 +00:00
ldy XPOSH ; setup X and Y co-ords
2018-05-27 05:03:45 +00:00
ldx XPOS
2018-05-28 05:38:48 +00:00
pla ; YPOS is on stack
2018-05-28 04:59:28 +00:00
pha
2018-05-28 04:45:59 +00:00
jsr HPOSN ; X= (y,x) Y=(a)
2018-05-27 05:03:45 +00:00
2018-05-28 04:45:59 +00:00
ldx #<shape_table ; point to our shape
2018-05-27 05:03:45 +00:00
ldy #>shape_table
2018-05-28 04:45:59 +00:00
lda #0 ; ROT=0
2018-05-27 05:03:45 +00:00
2018-05-28 04:45:59 +00:00
jsr XDRAW0 ; XDRAW 1 AT X,Y
; Both A and X are 0 at exit
2018-05-27 05:03:45 +00:00
2018-05-28 04:22:47 +00:00
nextx: ; NEXT X
lda XPOS ; 2
clc ; 1
adc #6 ; x+=6 ; 2
sta XPOS ; 2
2018-05-29 04:01:23 +00:00
; we know that the X=4 to 278 STEP 6 loop passes through exactly 256
; so we can check for that by looking for overflow to zero
bne skip ; 2
inc XPOSH ; 2
skip:
; the X=4 to 278 STEP 6 loop actually ends when X is at 280, which
; is 256+24. The lower part of the loop does not hit 24, so we
; can check for the end by looking for the low byte at 24.
2018-05-28 04:22:47 +00:00
2018-05-29 04:01:23 +00:00
cmp #24 ; see if less than 278 ; 2
bne xloop ; if so, loop ; 2
2018-05-28 04:22:47 +00:00
;============
2018-05-29 04:01:23 +00:00
; 15
2018-05-28 04:22:47 +00:00
nexty: ; NEXT Y
2018-05-28 05:32:17 +00:00
pla ; YPOS on stack
adc #5 ; y+=6
; carry always set coming in, so only add 5
2018-05-28 04:30:40 +00:00
cmp #189 ; see if less than 189
bcc yloop ; if so, loop
2018-05-28 04:45:59 +00:00
2018-05-28 04:22:47 +00:00
nexte: ; NEXT E
ldx EPOS
inx ; EPOS saved at beginning og eloop
cpx #15
2018-05-28 04:45:59 +00:00
bcc eloop ; branch if <15
2018-05-27 05:03:45 +00:00
2018-05-28 04:59:28 +00:00
bcs entropy
2018-05-27 05:03:45 +00:00
shape_table:
; .byte 1,0 ; 1 shape
; .byte 4,0 ; offset at 4 bytes
.byte 18,63,36,36,45,45,54,54,63,0 ; data