aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorB. Watson <urchlay@slackware.uk>2022-11-08 03:07:04 -0500
committerB. Watson <urchlay@slackware.uk>2022-11-08 03:07:19 -0500
commit3d6abe38d72347d6b254070edb50cf56f236f5d7 (patch)
treeed204fb4b2e90caea36c102e00d0f50099fcdd45
parent8303d83efab1ee1135cf2396a792479966ed2303 (diff)
downloaddla-asm-3d6abe38d72347d6b254070edb50cf56f236f5d7.tar.gz
Add/fix comments, profiling for initscreen and render. Runtime ~3:05 now.
-rw-r--r--dla.s30
-rw-r--r--drunkwalk.s41
-rw-r--r--render.s57
3 files changed, 85 insertions, 43 deletions
diff --git a/dla.s b/dla.s
index bae1b39..4bc8559 100644
--- a/dla.s
+++ b/dla.s
@@ -355,7 +355,10 @@ jsaveimage:
jmp saveimage
;;; Subroutine: set_limits
-;;; Sets the X/Y min/max limits based on circlesize
+;;; Sets the X/Y min/max limits based on circlesize.
+;;; Preserves Y register, trashes everything else.
+; The selfmod_* addresses are operands to compare instructions,
+; found in drunkwalk.s.
set_limits:
ldx circlesize
lda xmin,x
@@ -369,9 +372,20 @@ set_limits:
rts
;;; Subroutine: initscreen
-;;; clear screen memory and point ANTIC to our display list.
+;;; Clear screen and pixarray memory, point ANTIC to our display list.
;;; no arguments. trashes all registers.
+; Take 18 jiffies (0.3 sec). Probably not worth optimizing.
+; Uncomment next line to see how long it takes (check locations
+; $0600-$0603 in atari800 debugger).
+; INITSCR_PROFILE = 1
initscreen:
+.ifdef INITSCR_PROFILE
+ lda RTCLOK+1
+ sta $0600
+ lda RTCLOK+2
+ sta $0601
+.endif
+
lda #<screen
sta pixptr
lda #>screen
@@ -405,6 +419,9 @@ isloop:
lda #>dlist
sta SDLSTH
+ ; sneaky: tell the E: driver that screen RAM starts in our buffer,
+ ; so we can use printchr and printchrx to print to the bottom text
+ ; line in graphics mode.
lda #<textbuf
sta SAVMSC
lda #>textbuf
@@ -413,10 +430,19 @@ isloop:
sta ROWCRS
sta COLCRS
sta COLCRS+1
+.ifdef INITSCR_PROFILE
+ lda RTCLOK+1
+ sta $0602
+ lda RTCLOK+2
+ sta $0603
+.endif
rts
.include "render.s"
+;;; Subroutine: plot
+;;; Turns on the pixel at (cursor_x, cursor_y), in pixarray.
+;;; Trashes all registers (and pixptr).
plot:
ldx cursor_y
lda lineaddrs_l,x
diff --git a/drunkwalk.s b/drunkwalk.s
index 02ab67d..8cea4cf 100644
--- a/drunkwalk.s
+++ b/drunkwalk.s
@@ -1,11 +1,20 @@
;;; 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.
+;;; Spawn a particle, walk it randomly until it's adjacent to a set
+;;; pixel, then draw it. If it goes out of bounds, start over (spawn
+;;; another).
;;; 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.
+
+; Here be self-modifying code. All the 'cpx #0' and 'cpy #0' get
+; their operands modified by set_limits.
+
+; BEWARE!
+; 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.
+
+; TODO: Fix the cycle counts. I did them from my years-old memory, and
+; I got at least one wrong, after looking it up again.
drunkwalk:
oob:
@@ -24,29 +33,29 @@ oob:
move_pixel:
bit RANDOM ; 4 ; use top 2 bits (probably more random, definitely faster)
- bmi lr ; 2/3
- bvc down ; 2/3
+ bmi lr ; 3/4
+ bvc down ; 3/4
up:
dex ; 2 ; N=1 V=1 up
selfmod_ymin = * + 1
cpx #0 ; 2
- beq oob ; 2
+ beq oob ; 3
stx cursor_y
jmp check_lru
down:
inx ; 2 ; N=1 V=0 down
selfmod_ymax = * + 1
cpx #0 ; 2
- beq oob ; 2
+ beq oob ; 3
stx cursor_y
jmp check_lrd
lr:
- bvc right ; 2/3
+ bvc right ; 3/4
left:
dey ; 3 ; N=0 V=1 left
selfmod_xmin = * + 1
cpy #0 ; 2
- beq oob ; 2
+ beq oob ; 3
sty cursor_x
; check left neighbor (we just vacated the right one)
dey
@@ -58,7 +67,7 @@ right:
iny ; 3 ; N=0 V=0 right
selfmod_xmax = * + 1
cpy #0 ; 2
- beq oob ; 2
+ beq oob ; 3
sty cursor_x
; check right neighbor (we just vacated the left one)
iny
@@ -83,9 +92,10 @@ check_ud:
sta pixptr2+1
lda (pixptr2),y
bne stick
- jmp move_pixel
+ jmp move_pixel ; pixel didn't stick, move it again.
check_lru:
+ ; pixel's Y coord changed, must update pointer.
lda lineaddrs_l,x ; 5
sta pixptr ; 3
lda lineaddrs_h,x ; 5
@@ -108,9 +118,10 @@ check_lru:
sta pixptr2+1
lda (pixptr2),y
bne stick
- jmp move_pixel
+ jmp move_pixel ; pixel didn't stick, move it again.
check_lrd:
+ ; pixel's Y coord changed, must update pointer.
lda lineaddrs_l,x ; 5
sta pixptr ; 3
lda lineaddrs_h,x ; 5
@@ -133,7 +144,7 @@ check_lrd:
sta pixptr2+1
lda (pixptr2),y
bne stick
- jmp move_pixel
+ jmp move_pixel ; pixel didn't stick, move it again.
stick:
; pixel stuck next to an existing pixel, draw it and return.
diff --git a/render.s b/render.s
index 867003e..2faf755 100644
--- a/render.s
+++ b/render.s
@@ -1,11 +1,24 @@
;;; 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).
+; pixarray is 170x170. screen is 256x170.
; each screen line is: 43 blank px, 170 graphics px, 43 blank.
+
+; This is slow. It takes around 40 jiffies (0.6 sec). However, it only
+; happens once per generate. So not worth optimizing, really.
+
screenbyte = FR0
colcount = FR0+1
+; RENDER_PROFILE = 1
+
render:
+.ifdef RENDER_PROFILE
+ lda RTCLOK+1
+ sta $0600
+ lda RTCLOK+2
+ sta $0601
+.endif
+
lda #<screen
sta screenptr
lda #>screen
@@ -16,26 +29,11 @@ render:
sta pixptr+1
ldx #0
-rline:
+rline_loop:
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
@@ -44,13 +42,13 @@ rclr:
dey
bpl rclr
- ; first pixels start at column 40, plus...
+ ; first pixels start at column 40 (5 bytes in)...
lda #5
sta screenbyte
- lda #$10 ; ...mask starts out 0001000, 3 more blank px on left
+ lda #$10 ; ...plus, mask starts out 0001000, 3 more columns to the right.
sta pixmask
-rpix:
+rpix_loop:
ldy colcount ; ranges 0 to 169
lda (pixptr),y
beq notset ; 0 = not set, non-zero = set
@@ -60,18 +58,19 @@ rpix:
ora pixmask
sta (screenptr),y
notset:
+
; pixmask >>= 1; if(pixmask == 0) { pixmask = 0x80; screenbyte++; }
lsr pixmask
- bne pmok
- ;ror pixmask
- lda #$80
- sta pixmask
+ bcc pmok
+ ror pixmask
inc screenbyte
pmok:
+
inc colcount
lda colcount
cmp #$aa
- bne rpix
+ bne rpix_loop
+
; pixptr += 0xaa;
clc
adc pixptr
@@ -89,6 +88,12 @@ pmok:
sta screenptr+1
inx
cpx #$aa ; hit last line yet?
- bne rline ; if not, go render next line.
+ bne rline_loop ; if not, go render next line.
+.ifdef RENDER_PROFILE
+ lda RTCLOK+1
+ sta $0602
+ lda RTCLOK+2
+ sta $0603
+.endif
rts