;;; -*- Mode: asm; indent-tabs-mode: t; tab-width: 8 -*- ;;drawing line from 2 cordinates ;;# (X_pos, Y_pos) # ;;# * # ;;# * # ;;# * # ;;# (X_end, Y_end) # ;;NOTE THAT X_pos <= X_end, Y_pos <= Y_end. Max 45deg! .proc line_down .include "line.inc"; Defines memory positions, ex X_pos ;;We need to clear this memory LDA #$00 STA <V STA <dy_2 STA $FD ; for pixel_draw ;; V = 2*(dx -dy) SEC LDA dx SBC dy STA >V Mult_16 >V, <V ;dy_2 = dy*2 Mult_16 >dy_2, <dy_2 ;>dy_2 = dy (same address) ;; This is an Bresenham's line algorithm, se wikipedia bellow. ;;https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm ;; We need to compute the Value D = 2*dy - dx, ;; but it may be or get negative. ;; IN the loop we may set D = D -V ;; Because math D needs to be at least >=V. ;; V_max = %00000001 11111111 ;; We therefor need to add this offset to V 00000001 11111111 ;; and to its branch logic later in the loop. ;;D = 2*dy - dx + 2*255 Mov_16 >D, <D, >dy_2, <dy_2 Add_16 >D, <D, #$ff, #$01, ! Sub_16 >D, <D, dx, #$00 selfmod: ;; Self modifying code. Makes LDA and SBC instructions each take 1 cycle less. ;; You can remove this if you run the loop without # at dy_2 and V. ;;Note: The offsets like +2 etc is because there are instructions betwean the label and the ;address that needs to be modified ;; dy_2 ;; Modifies LDA >dy_2 LDA >dy_2 STA case_2 +1 ;; Modifies LDA <dy_2 LDA <dy_2 STA case_2 +7 ;; V ;;Modidies SBC >V LDA >V STA case_1 +1 ;; Modifies SBC <V LDA <V STA case_1 +7 end_selfmod: JSR pixel_draw ;;only used first pixel. after this relative position is abused ;; X = X_end - X_pos LDA X_end SEC SBC X_pos TAX ;LDX X_pos LDY #$00 for_x: ;; Paints A to address in |btp_mem_pos* + Y| ;; Y is pixel position in the chunk. Therefor it may be that Y = 0, 1, 2, 3, 4, ,5 ,6 ,7. LDA byte_to_paint ;A byte containing a single 1. Coresponds to X position in the chunk. ORA (>btp_mem_pos), Y STA (>btp_mem_pos), Y increment_pixel_x: LSR byte_to_paint ; Rotates the pixel one bit to the left ON THE SCREEN. BCC increment_pixel_x_end; We need to move to the next chunk move_8px_left: ;; Next chunk is 8 addresses away. Look in pixel_draw for more detail. ;; -8. ;; C = 1 therefore you se 07 Add_16 >btp_mem_pos, <btp_mem_pos, #$07, #$00, ! ;; Restores byte to paint LDA #%10000000 STA byte_to_paint increment_pixel_x_end: DEX BEQ end ;We keep track on when to stop line draw with the X registry. ;;If D < %00000010 00000000: case_2 ;;else case 1. Lag_16 >D, <D, #$00, #$02, case_2 case_1: ;; D = D - V ;; Because Lag_16: ;; C =1 so we can use ! ;; A = >D Sub_16_A >D, <D, #>V, #<V, ! increment_y_pos: INY ; Increment Y pos inside the buffer CPY #$08 BNE for_x move_8px_down: ; Z=1 --> C=1 LDY #$00 ;; Switch to chunk bellow ; C = 1 ; So we subtract #$3F, #$01 +C Add_16 >btp_mem_pos, <btp_mem_pos, #$3F, #$01, !; +320 JMP for_x increment_y_pos_end: case_2: Add_16 >D, <D, #>dy_2, #<dy_2, ! ;D = D + 2*dy JMP for_x end: RTS .endproc