aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dla.s252
1 files changed, 183 insertions, 69 deletions
diff --git a/dla.s b/dla.s
index 3c2f84f..a031fe4 100644
--- a/dla.s
+++ b/dla.s
@@ -8,6 +8,7 @@
; to use 1 byte for the X coordinate.
.include "atari.inc"
+ .macpack atari ; for scrcode macro
.include "xex.inc"
loadaddr = $2000
@@ -40,6 +41,11 @@
dlist = screen - dl_len
+ linebuf = $0580
+ textbuf = $0590
+ fptmp = $05a0
+ cloksav = $a0
+
; start of init segment. gets overwritten by the main program...
; and since the rest of the xex isn't loaded yet, can't call
; subroutines from it!
@@ -47,7 +53,7 @@
.include "io.s" ; printchrx and getchrx
msg:
.byte "Diffusion Limited Aggregate",$9b
- .byte "Urchlay's ASM version 0.0.4",$9b,$9b
+ .byte "Urchlay's ASM version 0.0.5",$9b,$9b
.byte "How many particles [",.sprintf("%d", DEFAULTPART),"]? ",$0
init:
; set default particles (if user just hits return)
@@ -76,13 +82,13 @@ readloop:
bcc readloop ; if not, ignore it.
cmp #$3a
bcs readloop
- sta LBUFF,x
+ sta textbuf,x
jsr printchrx
inx
cpx #5
bne readloop
lda #0
- sta LBUFF,x ; zero-terminate
+ sta textbuf,x ; zero-terminate
readdone:
cpx #0
beq usedefault
@@ -93,7 +99,7 @@ readdone:
sta maxparticles+1
ldx #0
digloop:
- lda LBUFF,x
+ lda textbuf,x
beq digitsdone ; hit zero terminator
ldy #$0a
lda #0
@@ -109,7 +115,7 @@ mul10loop:
sta addtmp+1
dey
bne mul10loop
- lda LBUFF,x
+ lda textbuf,x
and #$0f
clc
adc addtmp
@@ -129,6 +135,10 @@ usedefault:
xex_org loadaddr
main: ;;; start of main()
+ lda #$90
+ sta COLOR2
+ lda #$0e
+ sta COLOR1
jsr initscreen
; wait for shadow regs to get updated...
lda RTCLOK+2
@@ -162,12 +172,8 @@ wl:
sta cursor_y
jsr plot
- ; spawn a new particle
next_particle:
- jsr spawn
- ;lda #0
- ;sta CONSOL ; click when spawning a particle
-
+ jsr spawn ; spawn a new particle
jsr drunkwalk ; walk it around
beq next_particle ; if it went out of bounds, try again
@@ -225,15 +231,143 @@ main_done:
lda #DMA_ON
sta SDMCTL
lda RTCLOK
- sta FR0
+ sta cloksav
lda RTCLOK+1
- sta FR0+1
+ sta cloksav+1
lda RTCLOK+2
- sta FR0+2
+ sta cloksav+2
+
+; print menu
+ ldx #menulen
+blloop:
+ lda menumsg,x
+ sta textbuf,x
+ dex
+ bpl blloop
+
+; calculate and print elapsed time in minutes. our only use of
+; the floating point ROM routines.
+ ldx #0
+ stx FR0
+ inx
+ stx FR0+1
+ jsr IFP ; FR0 now FP 256.0
+ jsr FMOVE ; FR1 = FR0 (both are 256.0)
+ jsr FMUL ; FR0 = FR0 * FR1 (65536.0)
+ jsr FMOVE ; FR1 = FR0
+ ldx #0
+ stx FR0+1
+ lda cloksav
+ sta FR0
+ jsr IFP ; FR0 now cloksav in FP, FR1 = 65536.0
+ jsr FMUL ; FR0 = FR0 * FR1
+ jsr FMOVE ; FR1 = FR0, aka the high byte of cloksav in jiffies
+ lda cloksav+1 ; convert low 2 bytes of cloksav to FP...
+ sta FR0+1
+ lda cloksav+2
+ sta FR0
+ jsr IFP ; ...ok, now:
+ jsr FADD ; add the high bytes in jiffies, result in FR0 again
+ ; we now have the 3-byte jiffy count in FR0.
+ ; 3600 NTSC jiffies = 1 minute, so divide.
+ ldx #<fp3600
+ ldy #>fp3600
+ jsr FLD1R ; FR1 = 3600.0
+ lda PAL ; are we on a PAL Atari?
+ and #$0e
+ bne ntsc ; no, use constant as-is
+ lda #$30 ; yes, adjust (3000 PAL jiffies/sec)
+ sta FR0+1
+ntsc:
+ jsr FDIV ; FR0 = FR0 / FR1
+ jsr FASC ; render as ASCII
+
+ ; FASC puts its results at LBUFF ($0580, aka linebuf).
+ ; Unfortunately it can have a leading zero, and the last
+ ; digit has the high bit set (as a terminator). We want only
+ ; 6 characters including the decimal point, which could be e.g.
+ ; 1.2345 12.345 123.45 1234.5
+ ldx #$ff
+ lda linebuf
+ cmp #'0' ; skip the leading zero if present
+ bne ascloop
+ inx
+ascloop:
+ inx
+ lda linebuf,x
+ and #$df ; convert to screencode
+ bmi ascdone ; hit the terminator digit
+ sta textbuf,x
+ cpx #6
+ bne ascloop
+ beq xdone
+
+ascdone:
+ and #$7f
+ sta textbuf,x
+ inx
+
+xdone:
+ lda #$6d ; screen code for "m"
+ sta textbuf,x
+
+ ; user might have hit some random key during plotting; ignore it.
+keyloop:
+ ldx #$ff
+ stx CH
+
+waitkey:
+ lda CH
+ cmp #$ff
+ beq waitkey
+
+ ; see what key was hit
+ and #$3f ; ignore shift and inverse
+ cmp #$28 ; Redo
+ bne notredo
+ jmp main
+notredo:
+ cmp #$2e ; WriteCSV
+ beq writecsv
+ cmp #$3e ; Save
+ beq saveimage
+ cmp #$2a ; Exit
+ bne keyloop ; ignore any other keystroke
+ ;rts ; exit to DOS
+ jmp COLDSV ; reboot
+
+writecsv:
+saveimage:
+notyet:
+ lda #$40
+ sta COLOR2
+
hang: jmp hang
; TODO: code to save image goes here.
;;; End of main()
+ ; floating point constant 3600.0
+fp3600: .byte $41,$36,$00,$00,$00,$00
+
+; screen codes for menu
+menumsg:
+ .byte $00,$00,$00 ; 3 digits of minutes
+ .byte $00 ; 1 decimal point
+ .byte $00,$00 ; 2 digits fractional minutes
+ .byte $00 ; 1 the letter "m"
+ .byte $00 ; 1 space
+ .byte 'S'-$20+$80 ; 1
+ scrcode "ave " ; 3
+ .byte 'W'-$20+$80 ; 1
+ scrcode "rtCSV " ; 6
+ .byte 'R'-$20+$80 ; 1
+ scrcode "edo " ; 4
+ .byte 'E'-$20+$80 ; 1
+ scrcode "xit? " ; 5
+ .byte $80 ; 1 (cursor)
+ .byte $00 ; 1 space (filler) to make 32 bytes
+menulen = * - menumsg
+
;;; Subroutine: set_limits
;;; Sets the X/Y min/max limits based on circlesize
set_limits:
@@ -254,9 +388,18 @@ set_limits:
initscreen:
jsr set_screenptr
- ldx #>screenbytes ; clear this many pages
+ ; first, clear linebuf and textbuf
lda #0
tay
+isloop0:
+ sta linebuf,y
+ iny
+ cpy #$40
+ bne isloop0
+
+ ; next, clear screen memory
+ ldx #>screenbytes ; clear this many pages
+ tay ; 0 again
isloop:
sta (screenptr),y
iny
@@ -288,47 +431,15 @@ set_screenptr:
;;; - set pixptr to point to screen memory at cursor_y.
;;; - set pixmask to the mask for cursor_x.
;;; - set Y reg to the byte offset for cursor_x.
+;;; - returns with cursor_x in X reg, pixmask in A reg too.
;;; Called by plot, unplot, and locate.
plotsetup:
- ; used to:
- ;lda cursor_y
- ;sta pixptr
- ;lda #0
- ;sta pixptr+1
- ;ldx #5 ; multiply 16-bit pixptr by 32, by left-shifting 5 times.
-;pshiftloop:
- ;asl pixptr
- ;rol pixptr+1
- ;dex
- ;bne pshiftloop
- ;clc ; add screenptr to calculated value
- ;lda pixptr
- ;adc screenptr
- ;sta pixptr
- ;lda pixptr+1
- ;adc screenptr+1
- ;sta pixptr+1
-
- ; now, use a table, which makes this run ~2x as fast!
ldx cursor_y
lda lineaddrs_l,x
sta pixptr
lda lineaddrs_h,x
sta pixptr+1
- ; used to:
- ;lda cursor_x
- ;and #$07 ; keep low 3 bits...
- ;tax
- ;lda masks,x ; get the mask
- ;sta pixmask ; ...and save it
- ;lda cursor_x ; top 5 bits are byte offset, shift 'em down
- ;lsr
- ;lsr
- ;lsr
- ;tay ; put byte offset in Y
-
- ; now, use tables, which shaves another ~8% off runtime:
ldx cursor_x
ldy xoffsets,x
lda xmasks,x
@@ -363,8 +474,7 @@ unplot:
;;; otherwise, return with Z=1
locate:
jsr plotsetup
- lda (pixptr),y
- and pixmask
+ and (pixptr),y
rts
masks: .byte $80,$40,$20,$10,$08,$04,$02,$01
@@ -383,8 +493,8 @@ spawn:
;;; Walk the point around randomly until it either is
;;; adjacent to a set pixel or goes out of bounds.
;;; Return with Z=0 if out of bounds, Z=1 if it hit a pixel.
-;;; This and check_neighbors are the innermost loop, so they
-;;; should be as optimized as possible (we're not there yet).
+;;; This is the innermost loop, so it should be as optimized as
+;;; possible (we're not there yet).
drunkwalk:
lda RANDOM ; pick a random direction, up/down/left/right
and #$C0 ; use top 2 bits (hopefully more random than bottom 2).
@@ -394,7 +504,7 @@ drunkwalk:
beq down
cmp #$40
beq left
- ; right
+ ; $00: right
inc part_x
bne checkbounds
up:
@@ -432,31 +542,24 @@ checkbounds:
dontplot:
;stx SDMCTL ; nope, shadow updates are off...
stx DMACTL
- jsr check_neighbors
- bne stick
- beq drunkwalk
-stick:
-oob:
- rts
-
-;;; Subroutine: check_neighbors
-;;; return with Z=1 if any of the 4 neighbor pixels (l/r/u/d)
-;;; are set. otherwise, return Z=0.
-check_neighbors:
+ ; check neighbors. used to be a subroutine, inlined it.
; (-1,0)
dec cursor_x
- jsr locate
+ jsr plotsetup
+ and (pixptr),y
bne stick
; (1,0)
inc cursor_x
inc cursor_x
- jsr locate
+ jsr plotsetup
+ and (pixptr),y
bne stick
; (0,-1)
dec cursor_x
dec cursor_y
- jsr locate
+ jsr plotsetup
+ and (pixptr),y
bne stick
; (0,1)
; used to:
@@ -469,6 +572,13 @@ check_neighbors:
tay
lda (pixptr),y
and pixmask
+ bne stick
+ beq drunkwalk
+
+stick:
+oob:
+ rts
+
rts
;;;;; end of executable code
@@ -477,8 +587,8 @@ check_neighbors:
.include "dlatbl.s"
; table of addresses, for each line on the screen. bloats the
- ; code by 320 bytes, but compared to calculating the address, is
- ; 3.5x as fast!
+ ; code by 384 bytes, but compared to calculating the address, is
+ ; twice as fast!
lineaddrs_l:
laddr .set screen
.repeat 192
@@ -512,6 +622,7 @@ xmasks:
; ANTIC opcodes
blank8 = $70
gr8 = $0f
+ gr0 = $02
lms = $40
jvb = $41
@@ -524,10 +635,13 @@ xmasks:
.endrep
.byte gr8 | lms
.word screen2
- .repeat maxlines - 129
+ .repeat maxlines - 132
.byte gr8
.endrep
+ .byte gr0 | lms
+ .word textbuf
.byte jvb
.word dlist
+ ;.out .sprintf("%d",* - dlist)
xex_run loadaddr