aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--dla.s269
-rw-r--r--drunkwalk.s125
-rw-r--r--mkdlatbl.pl9
-rw-r--r--render.s94
5 files changed, 262 insertions, 237 deletions
diff --git a/Makefile b/Makefile
index 3109cd9..2c28fc8 100644
--- a/Makefile
+++ b/Makefile
@@ -4,7 +4,7 @@ PERL = perl
all: dla.xex
-dla.xex: dla.s io.s dlatbl.s xex.inc printint.s
+dla.xex: dla.s io.s dlatbl.s xex.inc printint.s render.s drunkwalk.s
$(CL65) $(CL65FLAGS) -l dla.list -Ln dla.labels -t none -o dla.xex dla.s
dlatbl.s: mkdlatbl.pl
diff --git a/dla.s b/dla.s
index 3e549f5..9ebf2c1 100644
--- a/dla.s
+++ b/dla.s
@@ -13,8 +13,9 @@
loadaddr = $2000
screen = $4000 ; must be on a x000 (4K) boundary
screen2 = screen + $1000 ; rest of screen RAM after 4K boundary
+ pixarray = screen + $20
linelen = $20 ; aka 32 bytes, antic F (GR.8) in narrow mode.
- maxlines = $C0 ; 192 lines of display
+ maxlines = $aa ; 170 lines of display
screenbytes = maxlines * linelen
dl_len = 202 ; remember to update this if you modify the display list!
dlist = screen - dl_len
@@ -34,6 +35,7 @@ pixmask: .res 1 ; ditto.
cursor_x: .res 1 ; cursor x/y are args to plot/unplot/locate
cursor_y: .res 1
pixptr2: .res 2 ; used by drunkwalk
+screenptr = pixptr2
circlesize: .res 1 ; 0 to 3
@@ -156,6 +158,7 @@ dfltseed:
generate: ;;; start of generate()
jsr initscreen
+
; wait for shadow regs to get updated...
lda RTCLOK+2
wl:
@@ -240,6 +243,7 @@ checkmaxparts:
bne next_particle
main_done:
+ jsr render
lda #0
sta CRITIC
sta COLOR2
@@ -404,7 +408,7 @@ isloop0:
bne isloop0
; next, clear screen memory
- ldx #>screenbytes ; clear this many pages
+ ldx #$72 ; clear this many pages
tay ; 0 again
isloop:
sta (pixptr),y
@@ -432,224 +436,20 @@ isloop:
sta COLCRS+1
rts
-;;; Subroutine: plotsetup
-;;; - 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:
+ .include "render.s"
+
+plot:
ldx cursor_y
lda lineaddrs_l,x
sta pixptr
lda lineaddrs_h,x
sta pixptr+1
-
- ldx cursor_x
- ldy xoffsets,x
- lda xmasks,x
- sta pixmask
-
- rts
-
-;;; Subroutine: plot
-;;; plots a pixel at (cursor_x, cursor_y)
-plot:
- jsr plotsetup
- lda (pixptr),y
- ora pixmask
+ ldy cursor_x
+ lda #1
sta (pixptr),y
rts
-oob:
- rts
-;;; Subroutine: drunkwalk
-;;; 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 is the innermost loop, so it should be as optimized as
-;;; possible (we're not there yet).
-drunkwalk:
- ; X holds the X coord the whole time, only needs to be loaded on entry.
- ; preload pixptr, too.
- ldx part_x ; 3
- ldy part_y ; 3
- lda lineaddrs_l,y ; 5
- sta pixptr ; 3
- lda lineaddrs_h,y ; 5
- sta pixptr+1 ; 3
- ; 4 code paths: TODO: count
- ; note that part_x and part_y are *never* zero; all the bne's here
- ; are "branch always".
- ; all the "cmp #0" here get their operands modified by set_limits.
-dwloop:
- ldy part_y ; 3
- bit RANDOM ; 4 ; use top 2 bits (probably more random, definitely faster)
- bmi lr ; 2/3
- bvc down ; 2/3
- dey ; 2 ; N=1 V=1 up
-selfmod_ymin = * + 1
- cpy #0 ; 2
- beq oob ; 2
- jmp check_lru
-down:
- iny ; 2 ; N=1 V=0 down
-selfmod_ymax = * + 1
- cpy #0 ; 2
- beq oob ; 2
- jmp check_lrd
-lr:
- bvc right ; 2/3
- dex ; 3 ; N=0 V=1 left
-selfmod_xmin = * + 1
- cpx #0 ; 2
- beq oob ; 2
- ldy xoffsets-1,x ; 4 ; moved left, check left X neighbor only.
- lda xmasks-1,x ; 4 ; right X neighbor definitely empty, because
- and (pixptr),y ; 5 ; we just moved out of that cell.
- bne stick ; 2/3
- beq check_ud ; 3 ; still have to check Y (up/down) neighbors.
-right:
- inx ; 3 ; N=0 V=0 right
-selfmod_xmax = * + 1
- cpx #0 ; 2
- beq oob ; 2
- ldy xoffsets+1,x ; 4 ; as above, moved right, check right X neighbor only.
- lda xmasks+1,x ; 4
- and (pixptr),y ; 5
- bne stick ; 2/3
- ; fall through to check_ud
-
-check_ud:
- ; this happens when the pixel moved left or right.
- ; (0,-1)
- ; subtract 32 (one line) from the pointer. one cycle faster
- ; than reloading from lineaddrs_l/h table.
- lda pixptr ; 3
- sec ; 2
- sbc #$20 ; 2
- sta pixptr2 ; 3
- lda pixptr+1 ; 3
- sbc #0 ; 2
- sta pixptr2+1 ; 3
- ;ldx part_x ; X already has this from before
- ldy xoffsets,x ; 4
- lda xmasks,x ; 4
- sta pixmask ; 3
- and (pixptr2),y ; 5
- bne stick ; 2/3
- ; (0,1)
- tya ; 2
- ora #$40 ; 2 ; add 64, AKA 2 screen lines
- tay ; 2
- lda (pixptr2),y ; 5
- and pixmask ; 3
- bne stick ; 2/3
- jmp dwloop ; 3 ; too far for a branch
-
-stick: ; we always get here with Z flag clear
- stx part_x ; only update part_x at exit.
- rts
-
- ; this happens when the pixel moved up.
-check_lru:
- sty part_y ; 3
- lda lineaddrs_l,y ; 5
- sta pixptr ; 3
- lda lineaddrs_h,y ; 5
- sta pixptr+1 ; 3
-
- ; 3/4 of the time, we can use a faster code path, check
- ; (-1,0) and (1,0) at the same time. this happens only when
- ; both pixels lie within the same byte.
- ;ldx part_x ; X already has this from before
- lda fastmasks,x ; 4
- beq slow_x_lru ; 2/3
- ldy xoffsets,x ; 4
- and (pixptr),y ; 5
- bne stick ; 2/3
- beq check_u ; 2/3
-slow_x_lru:
- ; (-1,0)
- ldy xoffsets-1,x ; 4
- lda xmasks-1,x ; 4
- and (pixptr),y ; 5
- bne stick ; 2/3
- ; (1,0)
- ldy xoffsets+1,x ; 4
- lda xmasks+1,x ; 4
- and (pixptr),y ; 5
- bne stick ; 2/3
-
-check_u:
- ; (0,-1)
- ; subtract 32 (one line) from the pointer. one cycle faster
- ; than reloading from lineaddrs_l/h table.
- lda pixptr ; 3
- sec ; 2
- sbc #$20 ; 2
- sta pixptr2 ; 3
- lda pixptr+1 ; 3
- sbc #0 ; 2
- sta pixptr2+1 ; 3
- ;ldx part_x ; X already has this from before
- ldy xoffsets,x ; 4
- lda xmasks,x ; 4
- ;sta pixmask ; 3
- and (pixptr2),y ; 5
- bne stick ; 2/3
- jmp dwloop ; 3 ; too far for a branch
-
-
- ; this happens when the pixel moved down.
-check_lrd:
- sty part_y ; 3
- lda lineaddrs_l,y ; 5
- sta pixptr ; 3
- lda lineaddrs_h,y ; 5
- sta pixptr+1 ; 3
-
- ; 3/4 of the time, we can use a faster code path, check
- ; (-1,0) and (1,0) at the same time. this happens only when
- ; both pixels lie within the same byte.
- ;ldx part_x ; X already has this from before
- lda fastmasks,x ; 4
- beq slow_x_lrd ; 2/3
- ldy xoffsets,x ; 4
- and (pixptr),y ; 5
- bne stick ; 2/3
- beq check_d ; 2/3
-slow_x_lrd:
- ; (-1,0)
- ldy xoffsets-1,x ; 4
- lda xmasks-1,x ; 4
- and (pixptr),y ; 5
- bne stick ; 2/3
- ; (1,0)
- ldy xoffsets+1,x ; 4
- lda xmasks+1,x ; 4
- and (pixptr),y ; 5
- bne stick ; 2/3
-
-check_d:
- ; (0,-1)
- lda pixptr ; 3
- clc ; 2
- adc #$20 ; 2
- sta pixptr2 ; 3
- lda pixptr+1 ; 3
- adc #0 ; 2
- sta pixptr2+1 ; 3
- ;ldx part_x ; X already has this from before
- ldy xoffsets,x ; 4
- lda xmasks,x ; 4
- ;sta pixmask ; 3
- and (pixptr2),y ; 5
- bne stick2 ; 2/3
- jmp dwloop ; 3 ; too far for a branch
-stick2:
- stx part_x ; only update part_x at exit.
- rts
+ .include "drunkwalk.s"
;;; Subroutine: drawseed
;;; dispatch to appropriate seed subroutine
@@ -664,9 +464,9 @@ drawseed:
;;; Subroutine: seed_point
;;; draw initial point in center
seed_point:
- lda #$7f
+ lda #center_x
sta cursor_x
- lda #$5f
+ lda #center_y
sta cursor_y
jmp plot
@@ -675,56 +475,56 @@ seed_point:
seed_long:
lda #$1
sta cursor_x
- lda #$5f
+ lda #center_y
sta cursor_y
slnoop:
jsr plot
inc cursor_x
lda cursor_x
- cmp #$ff
+ cmp #$aa
bne slnoop
rts
;;; Subroutine: seed_plus
;;; plus share, made of two 20px lines intersecting in the center
seed_plus:
- lda #$7f
+ lda #center_x
sta cursor_x
- lda #$55
+ lda #center_y-10
sta cursor_y
sploop:
jsr plot
inc cursor_y
lda cursor_y
- cmp #$69
+ cmp #center_y+10
bne sploop
- lda #$75
+ lda #center_x-10
sta cursor_x
- lda #$5f
+ lda #center_y
sta cursor_y
slloop:
jsr plot
inc cursor_x
lda cursor_x
- cmp #$89
+ cmp #center_x+10
bne slloop
rts
;;; Subroutine: seed_4pt
;;; four points, the corners of a 20px square
seed_4pt:
- lda #$75
+ lda #center_x-10
sta cursor_x
- lda #$55
+ lda #center_y-10
sta cursor_y
jsr plot
- lda #$68
+ lda #center_y+10
sta cursor_y
jsr plot
- lda #$88
+ lda #center_x+10
sta cursor_x
jsr plot
- lda #$55
+ lda #center_y-10
sta cursor_y
jmp plot
@@ -805,7 +605,7 @@ ci_done:
; banner and saveprompt must start with a clear-screen code.
banner:
.byte $7d, "Diffusion Limited Aggregate",$9b
- .byte "Urchlay's ASM version 0.1.3",$9b,$9b
+ .byte "Urchlay's ASM version 0.1.99",$9b,$9b
.byte "Particle count range: 1 to 65535",$9b
.byte "How many particles [",$0
@@ -852,17 +652,17 @@ seeds_h: .byte >(seed_point-1),>(seed_plus-1),>(seed_4pt-1),>(seed_long-1)
; code by 384 bytes, but compared to calculating the address, is
; twice as fast!
lineaddrs_l:
- laddr .set screen
- .repeat 192
+ laddr .set pixarray
+ .repeat 170
.byte <laddr
- laddr .set laddr + $20
+ laddr .set laddr + 170
.endrep
lineaddrs_h:
- laddr .set screen
- .repeat 192
+ laddr .set pixarray
+ .repeat 170
.byte >laddr
- laddr .set laddr + $20
+ laddr .set laddr + 170
.endrep
; tables to replace X coord => mask-and-offset calculations.
@@ -895,6 +695,7 @@ fastmasks:
xex_org dlist
.byte blank8, blank8, blank8
+ .byte blank8
.byte gr8 | lms
.word screen
.repeat 127
diff --git a/drunkwalk.s b/drunkwalk.s
new file mode 100644
index 0000000..ca80475
--- /dev/null
+++ b/drunkwalk.s
@@ -0,0 +1,125 @@
+;;; Subroutine: drunkwalk
+;;; 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 is the innermost loop, so it should be as optimized as
+;;; possible.
+; Y and X are backwards: Y holds the X coordinate, and X holds the Y coordinate.
+; Has to be, because there's no (zpind),x addressing mode.
+oob:
+ rts
+
+drunkwalk:
+ ldy part_x ; 3
+ ldx part_y ; 3
+
+ ; do we need this now?
+ lda lineaddrs_l,x ; 5
+ sta pixptr ; 3
+ lda lineaddrs_h,x ; 5
+ sta pixptr+1 ; 3
+
+ bit RANDOM ; 4 ; use top 2 bits (probably more random, definitely faster)
+ bmi lr ; 2/3
+ bvc down ; 2/3
+up:
+ dex ; 2 ; N=1 V=1 up
+selfmod_ymin = * + 1
+ cpx #0 ; 2
+ beq oob ; 2
+ stx part_y
+ jmp check_lru
+down:
+ inx ; 2 ; N=1 V=0 down
+selfmod_ymax = * + 1
+ cpx #0 ; 2
+ beq oob ; 2
+ stx part_y
+ jmp check_lrd
+lr:
+ bvc right ; 2/3
+left:
+ dey ; 3 ; N=0 V=1 left
+selfmod_xmin = * + 1
+ cpy #0 ; 2
+ beq oob ; 2
+ sty part_x
+ ; check left neighbor (we just vacated the right one)
+ dey
+ lda (pixptr),y
+ bne stick
+ iny
+ jmp check_ud ; 3 ; still have to check Y (up/down) neighbors.
+right:
+ iny ; 3 ; N=0 V=0 right
+selfmod_xmax = * + 1
+ cpy #0 ; 2
+ beq oob ; 2
+ sty part_x
+ ; check right neighbor (we just vacated the left one)
+ iny
+ lda (pixptr),y
+ bne stick
+ dey
+ ; fall through to check_ud
+
+check_ud:
+ ; check up neighbor
+ lda lineaddrs_l-1,x
+ sta pixptr2
+ lda lineaddrs_h-1,x
+ sta pixptr2+1
+ lda (pixptr2),y
+ bne stick
+
+ ; check down neighbor
+ lda lineaddrs_l+1,x
+ sta pixptr2
+ lda lineaddrs_h+1,x
+ sta pixptr2+1
+ lda (pixptr2),y
+ bne stick
+ jmp drunkwalk
+
+check_lru:
+ ; check left neighbor
+ dey
+ lda (pixptr),y
+ bne stick
+ iny
+ ; check right neighbor
+ iny
+ lda (pixptr),y
+ bne stick
+ dey
+ ; check up neighbor
+ lda lineaddrs_l-1,x
+ sta pixptr2
+ lda lineaddrs_h-1,x
+ sta pixptr2+1
+ lda (pixptr2),y
+ bne stick
+ jmp drunkwalk
+
+check_lrd:
+ ; check left neighbor
+ dey
+ lda (pixptr),y
+ bne stick
+ iny
+ ; check right neighbor
+ iny
+ lda (pixptr),y
+ bne stick
+ dey
+ ; check down neighbor
+ lda lineaddrs_l+1,x
+ sta pixptr2
+ lda lineaddrs_h+1,x
+ sta pixptr2+1
+ lda (pixptr2),y
+ bne stick
+ jmp drunkwalk
+
+stick:
+ rts
diff --git a/mkdlatbl.pl b/mkdlatbl.pl
index a941d38..37fb31b 100644
--- a/mkdlatbl.pl
+++ b/mkdlatbl.pl
@@ -12,8 +12,8 @@ sub bdcos {
return cos($_[0] / 128 * $PI);
}
-$centerx = 127;
-$centery = 95;
+$centerx = 85;
+$centery = 85;
for $r (15, 30, 45, 75) {
push @xmin, $centerx - ($r + 10);
@@ -28,6 +28,9 @@ for $r (15, 30, 45, 75) {
}
}
+print "center_x = $centerx\n";
+print "center_y = $centery\n";
+
print "xmin:\n";
for(@xmin) {
print " .byte $_\n";
@@ -35,6 +38,7 @@ for(@xmin) {
print "xmax:\n";
for(@xmax) {
+ $_ = 169 if $_ >= 170;
print " .byte $_\n";
}
@@ -45,6 +49,7 @@ for(@ymin) {
print "ymax:\n";
for(@ymax) {
+ $_ = 169 if $_ >= 170;
print " .byte $_\n";
}
diff --git a/render.s b/render.s
new file mode 100644
index 0000000..867003e
--- /dev/null
+++ b/render.s
@@ -0,0 +1,94 @@
+;;; Subroutine: render
+;;; Convert 1px per byte array at pixarray to packed 8px/byte at screen.
+; pixarray is 170x170. screen is 256x170 (TODO: fix display list).
+; each screen line is: 43 blank px, 170 graphics px, 43 blank.
+ screenbyte = FR0
+ colcount = FR0+1
+
+render:
+ lda #<screen
+ sta screenptr
+ lda #>screen
+ sta screenptr+1
+ lda #<pixarray
+ sta pixptr
+ lda #>pixarray
+ sta pixptr+1
+
+ ldx #0
+rline:
+ lda #0
+ sta colcount
+ sta screenbyte
+
+; ; clear 40px on left
+; ldy #4
+;lclr:
+; sta (screenptr),y
+; dey
+; bpl lclr
+;
+; ; clear 40px on right
+; ldy #$1b
+;rclr:
+; sta (screenptr),y
+; iny
+; cpy #$20
+; bne rclr
+
+; clear whole line. this is why pixarray is offset from screen by
+; one screen line.
+ ldy #$1f
+rclr:
+ sta (screenptr),y
+ dey
+ bpl rclr
+
+ ; first pixels start at column 40, plus...
+ lda #5
+ sta screenbyte
+ lda #$10 ; ...mask starts out 0001000, 3 more blank px on left
+ sta pixmask
+
+rpix:
+ ldy colcount ; ranges 0 to 169
+ lda (pixptr),y
+ beq notset ; 0 = not set, non-zero = set
+ ; if we found a set pixel, set it in the bitmap
+ ldy screenbyte
+ lda (screenptr),y
+ ora pixmask
+ sta (screenptr),y
+notset:
+ ; pixmask >>= 1; if(pixmask == 0) { pixmask = 0x80; screenbyte++; }
+ lsr pixmask
+ bne pmok
+ ;ror pixmask
+ lda #$80
+ sta pixmask
+ inc screenbyte
+pmok:
+ inc colcount
+ lda colcount
+ cmp #$aa
+ bne rpix
+ ; pixptr += 0xaa;
+ clc
+ adc pixptr
+ sta pixptr
+ lda pixptr+1
+ adc #0
+ sta pixptr+1
+ ; screenptr += 0x20;
+ clc
+ lda screenptr
+ adc #$20
+ sta screenptr
+ lda screenptr+1
+ adc #0
+ sta screenptr+1
+ inx
+ cpx #$aa ; hit last line yet?
+ bne rline ; if not, go render next line.
+
+ rts