mod7_table = $1c00 div7_table = $1d00 hposn_low = $1e00 hposn_high = $1f00 ;========================== ; draw box scene ;========================== ; data in INL/INH SET_COLOR = $C0 ; special case, color 0..15 in bottom nybble END = $80 ; 0 : CLEAR = $81 ; 0 : clear screen to black (0) BOX = $82 ; 4 : x1,y1 to x2,y2 HLIN = $83 ; 3 : x1,x2 at y1 VLIN = $84 ; 3 : at x1 from y1 to y2 PLOT = $85 ; 2 : x1,y1 HLIN_ADD= $86 ; 2 : x1,x2 at prev_y1+1 HLIN_ADD_LSAME= $87 ; 1 : prev_x1,x2 at prev_y1+1 HLIN_ADD_RSAME= $88 ; 1 : x1,prev_x2 at prev_y1+1 BOX_ADD= $89 ; 3 : x1,prev_y1+1, x2, y2 BOX_ADD_LSAME= $8A ; 2 : prev_x1,prev_y1+1, x2, y2 BOX_ADD_RSAME= $8B ; 2 : x1,prev_y1+1, prev_x2, y2 VLIN_ADD= $8C ; 2 : at prev_x1+1 from y1 to y2 BLACK = $00 RED = $01 DARK_BLUE = $02 MAGENTA = $03 GREEN = $04 GREY1 = $05 MEDIUM_BLUE = $06 LIGHT_BLUE = $07 BROWN = $08 ORANGE = $09 GREY2 = $0A PINK = $0B LIGHT_GREEN = $0C YELLOW = $0D AQUA = $0E WHITE = $0f ; top bit not set, command ; top bit set, repeat last command ; ??xx xxxx ; 00 = co-ord ; 10 = new command ; 11 = new-color draw_scene: lda #0 ; always clear to black ; sta COLOR sta clear_all_color+1 jsr clear_all draw_scene_loop: wait_delay_smc: lda #200 jsr wait ldy #0 lda (INL),Y ; load next byte bpl repeat_last ; if top bit 0, repeat last ; command asl ; clear top bit bmi set_color ; if negative, color lsr ; shift back down sta LAST_TYPE ; store last type jsr inc_inl ; 16 bit increment repeat_last: lda LAST_TYPE beq done_scene ; if 0, END ; use jump table for rest and #$3f tax dex ; types start at 1 lda draw_table_h,X sta table_jsr_smc+2 ; pha lda draw_table_l,X ; pha sta table_jsr_smc+1 table_jsr_smc: jsr $FFFF ;======================================== ; adds A to input pointer and continues update_pointer: ldx LAST_TYPE lda bytes_used,X update_pointer_already_in_a: clc adc INL sta INL lda #0 adc INH sta INH bcc draw_scene_loop ; bra (would only be set if wrap $FFFF) ;============================ ; done scene ;============================ ; return done_scene: rts ;============================ ; set color ;============================ ; color is A*2h set_color: ; make top and bottom byte the same lsr ; shift back down and #$f sta COLOR asl asl asl asl adc COLOR sta COLOR ; special case as we are encoded differently from ; the actions lda #1 ; we were one byte long bne update_pointer_already_in_a ; bra bytes_used: .byte 0,0,4,3 ; END, CLEAR, BOX, HLIN .byte 3,2,2,1 ; VLIN, PLOT, HLIN_ADD, HLIN_ADD_LSAME .byte 1,3,2,2 ; HLIN_ADD_RSAME, BOX_ADD, BOX_ADD_LSAME .byte 2,2 ; BOX_ADD_RSAME, VLIN_ADD draw_table_l: .byte <(clear_screen),<(draw_box),<(draw_hlin),<(draw_vlin) .byte <(draw_plot) .byte <(draw_hlin_add),<(draw_hlin_add_lsame),<(draw_hlin_add_rsame) .byte <(draw_box_add),<(draw_box_add_lsame),<(draw_box_add_rsame) .byte <(draw_vlin_add) draw_table_h: .byte >(clear_screen),>(draw_box),>(draw_hlin),>(draw_vlin) .byte >(draw_plot) .byte >(draw_hlin_add),>(draw_hlin_add_lsame),>(draw_hlin_add_rsame) .byte >(draw_box_add),>(draw_box_add_lsame),>(draw_box_add_rsame) .byte >(draw_vlin_add) ;================================= ;================================= ; clear screen ;================================= ;================================= clear_screen: lda COLOR sta clear_all_color+1 jmp clear_all ; tail call ;================================= ;================================= ; draw box ;================================= ;================================= ; blurgh. Cases ; Y1=EVEN, Y2=ODD -> loop Y1/2 to Y2/2, inclusive ; Y1=ODD, Y2=ODD -> HLIN, loop (Y1/2)+1 to Y2/2 inclusive ; Y1=EVEN, Y2=EVEN-> loop Y1/2 to (Y2/2)-1, HLIN ; Y1=ODD, Y2=EVEN -> HLIN, loop (Y1/2)+1 to (Y2/2)-1, HLIN ; 2/3 case, 1 to 1 ; 3/5 case, (>1) 2 to 2 ; 2/4 case, 1 to 1 (<2) ; 3/4 case, 2 to 1 (!) ; 3/6 case, 2 to 2 draw_box: lda (INL),Y sta X1 iny lda (INL),Y sta Y1 iny draw_box_common_x2: lda (INL),Y sta X2 ;================================== ; draw box common ;================================== draw_box_common: iny lda (INL),Y sta Y2 ; keep even though not necessary lsr ; if even, go to one less ; else, fine bcs odd_bottom_draw_box even_bottom_draw_box: sec sbc #1 odd_bottom_draw_box: sta draw_box_yend_smc+1 ; see if we start at multiple of two lda Y1 lsr tay bcc even_draw_box_start ; we're odd, need to call HLIN jsr hlin_mask_odd iny even_draw_box_start: draw_box_yloop: draw_box_yend_smc: cpy #0 bcc bbbb beq bbbb jmp done_draw_box_yloop ; bge bbbb: lda gr_offsets_l,Y sta draw_box_xloop_smc+1 lda gr_offsets_h,Y clc adc DRAW_PAGE sta draw_box_xloop_smc+2 lda COLOR ldx X2 draw_box_xloop: draw_box_xloop_smc: sta $400,X dex cpx X1 bpl draw_box_xloop ; bge (signed) iny jmp draw_box_yloop done_draw_box_yloop: ; done ; if Y2 was even we need to fixup and draw one more line lda Y2 lsr bcs definitely_odd_bottom jsr hlin_mask_even definitely_odd_bottom: ; done rts ;================================= ;================================= ; draw hlin ;================================= ;================================= draw_hlin: lda (INL),Y sta X1 iny lda (INL),Y sta X2 iny lda (INL),Y sta Y1 ; needed for HLIN_ADD ;=================================== ;=================================== ; hlin common code ;=================================== ;=================================== ; X1, X2 set up ; Y-coord is in A ; Y is A/2 hlin_common: lsr tay bcc hlin_mask_even hlin_mask_odd: lda #$0F .byte $2C ; bit trick hlin_mask_even: lda #$F0 sta MASK eor #$FF and COLOR sta COLOR2 lda gr_offsets_l,Y sta draw_hlin_l_xloop_smc+1 sta draw_hlin_s_xloop_smc+1 lda gr_offsets_h,Y clc adc DRAW_PAGE sta draw_hlin_l_xloop_smc+2 sta draw_hlin_s_xloop_smc+2 ldx X2 draw_hlin_xloop: draw_hlin_l_xloop_smc: lda $400,X and MASK ora COLOR2 draw_hlin_s_xloop_smc: sta $400,X dex cpx X1 bpl draw_hlin_xloop ; bge done_hlin_xloop: rts ;================================= ;================================= ; draw hlin add ;================================= ;================================= ; increment Y1 draw_hlin_add: lda (INL),Y sta X1 iny draw_hlin_add_lsame: lda (INL),Y sta X2 hlin_inc_y1: inc Y1 lda Y1 jmp hlin_common ;================================= ;================================= ; draw hlin add_lsame ;================================= ;================================= ; increment Y1 ; use old left value ;draw_hlin_add_lsame: ; lda (INL),Y ; sta X2 ; jmp hlin_inc_y1 ;================================= ;================================= ; draw hlin add_rsame ;================================= ;================================= ; increment Y1 ; use old right value draw_hlin_add_rsame: lda (INL),Y sta X1 jmp hlin_inc_y1 ;================================= ;================================= ; draw box add ;================================= ;================================= ; increment Y2, put into Y1 draw_box_add: lda Y2 sta Y1 inc Y1 lda (INL),Y sta X1 iny jmp draw_box_common_x2 ;================================= ;================================= ; draw box add_lsame ;================================= ;================================= ; increment Y2, store in Y1 ; use old X1 value draw_box_add_lsame: lda Y2 sta Y1 inc Y1 jmp draw_box_common_x2 ;================================= ;================================= ; draw box add_rsame ;================================= ;================================= ; increment Y2, put in Y1 ; use old right value X2 draw_box_add_rsame: lda Y2 sta Y1 inc Y1 lda (INL),Y sta X1 jmp draw_box_common ;================================= ;================================= ; draw vlin add ;================================= ;================================= draw_vlin_add: inc X1 ; X1 is prev_X1+1 bne draw_vlin_skip_x1 ; bra ;================================= ;================================= ; draw vlin ;================================= ;================================= draw_vlin: lda (INL),Y sta X1 iny draw_vlin_skip_x1: lda (INL),Y sta Y1 iny lda (INL),Y sta Y2 ;================================ draw_vlin_common: lda Y2 lsr ; if even, go to one less ; else, fine bcs odd_bottom_vlin even_bottom_vlin: sec sbc #1 odd_bottom_vlin: sta vlin_yend_smc+1 ; handle top ; see if we start at multiple of two lda Y1 lsr tay ; needed! Sets Y for vlin_yloop bcc even_vlin_start odd_vlin_start: ; we're odd, need to call PLOT lda Y1 jsr plot_common iny ; update Y for vlin_yloop even_vlin_start: vlin_yloop: vlin_yend_smc: cpy #0 bcc cccc beq cccc jmp done_vlin_yloop ; cccc: lda gr_offsets_l,Y sta vlin_xloop_smc+1 lda gr_offsets_h,Y clc adc DRAW_PAGE sta vlin_xloop_smc+2 lda COLOR ldx X1 vlin_xloop_smc: sta $400,X iny jmp vlin_yloop ; done done_vlin_yloop: ; if Y2 was even we need to fixup and draw one more line lda Y2 lsr bcs definitely_odd_vlin lda Y2 jmp plot_common ; plot_mask_even (tail call) definitely_odd_vlin: ; done rts ;================================= ;================================= ; draw plot ;================================= ;================================= draw_plot: lda (INL),Y sta X1 iny lda (INL),Y sta Y1 ; needed for HLIN_ADD ; fallthrough ;=================================== ;=================================== ; plot common code ;=================================== ;=================================== ; X-coord in X1 ; Y-coord in A ; Y is Y-coord/2 at end plot_common: lsr ; need Y-coord/2 because 2 rows per byte tay bcc plot_mask_even plot_mask_odd: lda #$0F .byte $2C ; bit trick plot_mask_even: lda #$F0 sta MASK eor #$FF and COLOR sta COLOR2 lda gr_offsets_l,Y sta plot_l_smc+1 sta plot_s_smc+1 lda gr_offsets_h,Y clc adc DRAW_PAGE sta plot_l_smc+2 sta plot_s_smc+2 ldx X1 plot_l_smc: lda $400,X and MASK ora COLOR2 plot_s_smc: sta $400,X rts ;=========================== ; 16-bit increment of INL ; inline this? inc_inl: inc INL bne done_inc_inl inc INH done_inc_inl: rts ;.include "gr_fast_clear.s" gr_offsets_l: .byte <$400,<$480,<$500,<$580,<$600,<$680,<$700,<$780 .byte <$428,<$4a8,<$528,<$5a8,<$628,<$6a8,<$728,<$7a8 .byte <$450,<$4d0,<$550,<$5d0,<$650,<$6d0,<$750,<$7d0 gr_offsets_h: .byte >$400,>$480,>$500,>$580,>$600,>$680,>$700,>$780 .byte >$428,>$4a8,>$528,>$5a8,>$628,>$6a8,>$728,>$7a8 .byte >$450,>$4d0,>$550,>$5d0,>$650,>$6d0,>$750,>$7d0 ;0123456789012345678901234567890123456789