diff options
-rw-r--r-- | dla.s | 252 |
1 files changed, 183 insertions, 69 deletions
@@ -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 |