From 3d6abe38d72347d6b254070edb50cf56f236f5d7 Mon Sep 17 00:00:00 2001 From: "B. Watson" Date: Tue, 8 Nov 2022 03:07:04 -0500 Subject: Add/fix comments, profiling for initscreen and render. Runtime ~3:05 now. --- dla.s | 30 ++++++++++++++++++++++++++++-- drunkwalk.s | 41 ++++++++++++++++++++++++++--------------- render.s | 57 +++++++++++++++++++++++++++++++-------------------------- 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 @@ -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 @@ -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 @@ -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 -- cgit v1.2.3