; ; Simple Implementation of ; The Mandelbrot Set ; ; By Samuel Pearce ; ; ; Constants ; SCALE = 16 ; Screen scale (1px = ~0.09) MAX_ITERS = 12 ; Maximum number of iterations to do OFFS_X = $E7 ; -25, X-Offset of the render view OFFS_Y = $F1 ; -15, Y-Offset of the render view THRESH = 2 ; If a point goes beyond this value (2.0 fixpt) it's not in the set ; ; Variables ; ARG_1 = $00 ; 16-bit maths argument ARG_2 = $02 ; 16-bit maths argument ARG_3 = $04 ; 16-bit maths argument WORKNR = $06 ; 32-bit product PT_IDX = $20 ; 16-bit pointer into point array CN_C_R = $22 ; Complex Number 'C' Real Part CN_C_I = $24 ; Complex Number 'C' Imaginary Part CN_Z_R = $26 ; Complex Number 'Z' Real Part CN_Z_I = $28 ; Complex Number 'Z' Imaginary Part GRID_X = $2A ; Current X coordinate in framebuffer GRID_Y = $2B ; Current Y coordinate in framebuffer ITERS = $2C ; Number of iterations performed FB_IDX = $2D ; Index into framebuffer of currently edited byte FBMASK = $2E ; Mask of the framebuffer bit to alter LOAD_N = $2F ; Current loading char number POINTS = $7000 ; Storage of 32x32 4-Byte Complex Numbers .WORD $8000 .ORG $8000 ;---------------------------; ; Program Start & Setup ; ;---------------------------; reset: CLD ; Clear decimal mode CLI ; Clear interrupts LDA #POINTS STA PT_IDX+1 init_pts: LDA #POINTS STA PT_IDX+1 LDA #%10000000 ; Init framebuffer bitmask STA FBMASK ; Write to mask LDA #= 3.0; Clear pixel LDA CN_Z_R+0 ; Get low byte BNE clear_px ; Z(r) > 2.0; Clear pixel JMP @cp_i @cp_rn: CMP #$FE ; Check if it's above -2.0 BCC clear_px ; Z(r) < -2.0; Clear pixel @cp_i: LDA CN_Z_I+1 ; Get high byte of imaginary component BMI @cp_in ; Jump to negative check if byte is negative @cp_ip: CMP #$02 ; Check if it's above 2 BCC @cpend ; Z(r) < 2.0; Continue to imaginary check BNE clear_px ; Z(r) >= 3.0; Clear pixel LDA CN_Z_I+0 ; Get low byte BNE clear_px ; Z(r) > 2.0; Clear pixel JMP @cpend @cp_in: CMP #$FE ; Check if it's above -2.0 BCC clear_px ; Z(r) < -2.0; Clear pixel @cpend: JMP loop_end ; Point is still in the set clear_px: LDA FBMASK ; Get the framebuffer mask EOR #$FF ; Invert mask LDY FB_IDX ; Load framebuf index AND GL_FRAME_BUF,Y ; Load byte from framebuf and mask out current bit STA GL_FRAME_BUF,Y ; Store updated byte to framebuf loop_end: ; Write new Z value to point array ; and increment point array index 4 times (at start of next value) LDX #0 ; Clear X LDY #0 ; Clear Y put_z: LDA CN_Z_R,X ; Get Xth byte of Z on zero page STA (PT_IDX),Y ; Write to the point array INC PT_IDX+0 ; Increment point index low byte BNE @e ; skip increment if we didn't wrap INC PT_IDX+1 ; Increment high byte @e: INX ; Increment counter CPX #4 ; Check if we've copied all bytes yet BCC put_z ; Loop through all point bytes LSR FBMASK ; Shift the bitmask BCC @nobe ; Bit is still in the mask; Skip Increment ROR FBMASK ; Roll carry back into bitmask INC FB_IDX ; Increment framebuffer index @nobe: INC GRID_X ; Increment X coordinate LDA GRID_X ; Check X value CMP #$20 ; Loop until 32 BCC @again LDA #0 ; Clear A STA GRID_X ; Reset X to 0 for next row JSR ldch_inc ; Update loading animation INC GRID_Y ; Increment Y coordinate LDA GRID_Y ; Check Y value CMP #$20 ; Loop until 32 BCS @fdone ; if carry is set, we're done with this frame @again: JMP calc_point ; Jump back up to calculate next point @fdone: JSR GL_DRAW_BUF ; Draw framebuf to screen INC ITERS ; Increment number of iterations LDA ITERS ; Fetch iteration count CMP #MAX_ITERS ; Check if we've reached the limit BCS fin ; Yes: Skip to end JMP iterate ; No: Loop again fin: LDA #str_setup ; Get high byte of string page STA $F1 ; Store high byte LDY #0 ; Clear Y @char: LDA ($F0),Y ; Get char from string BEQ @done ; Check if we've reached the end STA $FF00 ; Write it to the console INY ; Increment index JMP @char ; Loop until null terminator @done: RTS str_setup: .ASCIIZ "Setting up... " str_calc: .ASCIIZ "Calculating... " str_done: .ASCIIZ "Done!" ; ; Include my simple 16-bit Maths library ; that provides rational values and multiplication ; .INCLUDE "maths.asm" ; ; Include my basic Graphics Library ; that provides a 32x32 1bpp screen ; .INCLUDE "jraphics.asm"