diff --git a/mandel.s b/mandel.s index 31097bf..b5c5953 100644 --- a/mandel.s +++ b/mandel.s @@ -1,17 +1,21 @@ ; Our zero-page vars -sx = $80 ; 8 bits: screen pixel x -sy = $81 ; 8 bits: screen pixel y -cx = $82 ; 16 bits fixed point -cy = $84 ; 16 bits fixed point -zx = $86 ; 16 bits fixed point -zy = $88 ; 16 bits fixed point -zx_2 = $8a ; 32 bits fixed point -zy_2 = $8e ; 32 bits fixed point -zx_zy = $92 ; 32 bits fixed point -dist = $96 ; 32 bits fixed point -iter = $9a ; 8 bits iteration count +sx = $80 ; i16: screen pixel x +sy = $82 ; i16: screen pixel y +ox = $84 ; fixed3.13: center point x +oy = $86 ; fixed3.13: center point y +cx = $84 ; fixed3.13: c_x +cy = $86 ; fixed3.13: c_y +zx = $88 ; fixed3.13: z_x +zy = $8a ; fixed3.13: z_y -temp = $a0 ; debug temp area +zx_2 = $90 ; fixed6.26: z_x^2 +zy_2 = $94 ; fixed6.26: z_y^2 +zx_zy = $98 ; fixed6.26: z_x * z_y +dist = $9c ; fixed6.26: z_x^2 + z_y^2 + +iter = $a0 ; u8: iteration count +zoom = $a1 ; u8: zoom shift level +temp = $a2 ; u16 ; FP registers in zero page FR0 = $d4 @@ -19,6 +23,77 @@ FRE = $da FR1 = $e0 FR2 = $e6 +; High data +framebuffer_top = $8000 +framebuffer_bottom = $9000 +textbuffer = $9f00 +framebuffer_end = $a000 + +height = 184 +half_height = height >> 1 +width = 160 +half_width = 160 >> 1 +width_ratio_3_13 = (5 << 11) ; 5/4 +height_ratio_3_13 = (3 << 11) ; 5/4 + +DMACTL = $D400 +DLISTL = $D402 +DLISTH = $D403 + +.data + +aspect: + ; aspect ratio! + ; pixels at 320w are 5:6 (narrow) + ; pixels at 160w are 5:3 (wide) + ; + ; cy = (sy << (8 - zoom)) * (96 / 128 = 3 / 4) + ; cx = (sx << (8 - zoom)) * ((3 / 4) * (5 / 3) = 5 / 4) + ; + ; so vertical range -92 .. 91.9 is -2.15625 .. 2.15624 + ; &horizontal range -80 .. 79.9 is -3.125 .. 3.124 + ; + ; 184h is the equiv of 220.8h at square pixels + ; 320 / 220.8 = 1.45 display aspect ratio +aspect_x: + .word 5 << (13 - 2) + +aspect_y: + .word 3 << (13 - 2) + + +bit_masks: + .byte 3 + .byte 3 << 2 + .byte 3 << 4 + .byte 3 << 6 + +display_list: + ; 48 lines overscan + .repeat 5 + .byte $70 ; 8 blank lines + .endrep + + ; 184 lines graphics + ; ANTIC mode e (160px 2bpp, 1 scan line per line) + .byte $4e + .addr framebuffer_top + .repeat half_height - 1 + .byte $0e + .endrep + .byte $4e + .addr framebuffer_bottom + .repeat half_height - 1 + .byte $0e + .endrep + + ; 1 line 40-column text + .byte $42 + .addr textbuffer + + .byte $41 ; jump and blank + .addr display_list + .code .export start @@ -181,10 +256,18 @@ positive: .macro imul16 dest, arg1, arg2 copy16 FR0, arg1 ; 12 cyc copy16 FR1, arg2 ; 12 cyc - jsr imul16_func ; 470-780 + jsr imul16_func ; 470-780 cyc copy32 dest, FR2 ; 24 cyc .endmacro +.macro imul16_round dest, arg1, arg2 + copy16 FR0, arg1 ; 12 cyc + copy16 FR1, arg2 ; 12 cyc + jsr imul16_func ; 470-780 cyc + round16 FR2 ; 5-28 cyc + copy16 dest, FR2 + 2 ; 12 cyc +.endmacro + ; min 470 cycles ; max 780 cycles .proc imul16_func @@ -269,8 +352,6 @@ next: .endmacro - - .proc mandelbrot ; input: ; cx: position scaled to 4.12 fixed point - -8..+7.9 @@ -355,29 +436,128 @@ still_in: .endproc +.macro zoom_factor dest, src, zoom, aspect + .local cont + .local enough + + ; cx = (sx << (8 - zoom)) + copy16 dest, src + ldx zoom +cont: + cpx #8 + beq enough + shl16 dest + inx + jmp cont +enough: + + ; cy = cy * (3 / 4) + ; cx = cx * (5 / 4) + imul16_round dest, dest, aspect +.endmacro + +.proc pset + ; screen coords in signed sx,sy + ; iter holds the target to use + ; @todo implement + rts +.endproc + .proc start -looplong: - ; cx = -0.5 - lda #$f7 - sta cx - lda #$ff - sta cx + 1 + ; ox = 0; oy = 0; zoom = 0 + lda #0 + sta ox + sta ox + 1 + sta oy + sta oy + 1 + sta zoom - ; cy = 1 - lda #$10 - sta cy + ; Disable display DMA lda #$00 - sta cy + 1 + sta DMACTL - jsr mandelbrot - ; should have 32-bit -15 in FR2 + ; Set up the display list + lda #.lobyte(display_list) + sta DLISTL + lda #.hibyte(display_list) + sta DLISTH - ; save the completed iter count for debugging - lda iter + ; zero the range from framebuffer_top to framebuffer_end + lda #.lobyte(framebuffer_top) sta temp + lda #.hibyte(framebuffer_top) + sta temp + 1 + +zero_page_loop: + lda #0 + ldy #0 +zero_byte_loop: + sta (temp),y + iny + bne zero_byte_loop + + inc temp + 1 + lda temp + 1 + cmp #.hibyte(framebuffer_end) + bne zero_page_loop + + ; Re-enable display DMA + lda #$22 + sta DMACTL + +main_loop: + ; sy = -92 .. 91 + lda #(256-half_height) + sta sy + lda #(256-1) + sta sy + 1 + +loop_sy: + ; sx = -80 .. 79 + lda #(256-half_width) + sta sx + lda #(256-1) + sta sx + 1 + +loop_sx: + zoom_factor cx, sx, zoom, aspect_x + zoom_factor cy, sy, zoom, aspect_y + jsr mandelbrot + jsr pset + + + lda sx + clc + adc #1 + sta sx + + cmp #half_width + beq loop_sx_done + + lda sx + 1 + adc #0 + sta sx + 1 + jmp loop_sx + +loop_sx_done: + + lda sy + clc + adc #1 + sta sy + + cmp #half_height + beq loop_sy_done + + lda sy + 1 + adc #0 + sta sy + 1 + jmp loop_sy + +loop_sy_done: loop: - ; keep looping over so we can work in the debugger - jmp looplong + ; finished + jmp loop .endproc