123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642 |
- ; DRAW using bresenhams algorithm and screen positioning
- ; Copyleft (k) 2010 by J. Rodriguez (a.k.a. Boriel) http://www.boriel.com
- ; vim:ts=4:et:sw=4:
- ; Y parameter in A
- ; X parameter in high byte on top of the stack
- ;
- #include once <error.asm>
- #include once <in_screen.asm>
- #include once <cls.asm>
- #include once <SP/PixelDown.asm>
- #include once <SP/PixelUp.asm>
- #include once <SP/PixelLeft.asm>
- #include once <SP/PixelRight.asm>
- ;
- ;; DRAW PROCEDURE
- ;- PROC
- ;- LOCAL __DRAW1
- ;- LOCAL __DRAW2
- ;- LOCAL __DRAW3
- ;- LOCAL __DRAW4, __DRAW4_LOOP
- ;- LOCAL __DRAW5
- ;- LOCAL __DRAW6, __DRAW6_LOOP
- ;- LOCAL __DRAW_ERROR
- ;- LOCAL DX1, DX2, DY1, DY2
- ;- LOCAL __INCX, __INCY, __DECX, __DECY
- ;- LOCAL P_FLAG
- ;- P_FLAG EQU 23697
- __DRAW_ERROR:
- ;- jp __OUT_OF_SCREEN_ERR
- DRAW:
- ;; ENTRY POINT
- ;- LOCAL PIXEL_ADDR
- ;- LOCAL COORDS
- ;- LOCAL __DRAW_SETUP1, __DRAW_START, __PLOTOVER, __PLOTINVERSE
- lda z80_e ;- ex de,hl ; DE = Y OFFSET
- ldx z80_l
- stx z80_e
- sta z80_l
- lda z80_d
- ldx z80_h
- stx z80_d
- sta z80_h
- ;- pop hl ; return addr
- ;- ex (sp), hl ; CALLEE => HL = X OFFSET
- ;- ld bc, (COORDS)
- ;- ld a, c
- ;- add a, l
- ;- ld l, a
- ;- ld a, h
- ;- adc a, 0 ; HL = HL + C
- ;- ld h, a
- ;- jr nz, __DRAW_ERROR ; if a <> 0 => Out of Screen
- ;- ld a, b
- ;- add a, e
- ;- ld e, a
- ;- ld a, d
- ;- adc a, 0 ; DE = DE + B
- ;- ld d, a
- ;- jr nz, __DRAW_ERROR ; if a <> 0 => Out of Screen
- ;- ld a, 191
- ;- sub e
- ;- jr c, __DRAW_ERROR ; Out of screen
- ;- ld h, e ; now H,L = y2, x2
- __DRAW:
- ; __FASTCALL__ Entry. Plots from (COORDS) to coord H, L
- ;- push hl
- ;- ex de, hl ; D,E = y2, x2;
- ;- ld a, (P_FLAG)
- ;- ld c, a
- ;- bit 2, a ; Test for INVERSE1
- ;- jr z, __DRAW_SETUP1
- ;- ld a, 2Fh ; CPL
- ;- ld (__PLOTINVERSE), a
- ;- ld a, 0A6h ; and (hl)
- ;- jp __DRAW_START
- __DRAW_SETUP1:
- ;- xor a ; nop
- ;- ld (__PLOTINVERSE), a
- ;- ld a, 0B6h ; or (hl)
- ;- bit 0, c ; Test for OVER
- ;- jr z, __DRAW_START
- ;- ld a, 0AEh ; xor (hl)
- __DRAW_START:
- ;- ld (__PLOTOVER), a ; "Pokes" last operation
- lda z80_c ;- exx
- ldx z80_cp
- stx z80_c
- sta z80_cp
- lda z80_b
- ldx z80_bp
- stx z80_b
- sta z80_bp
- lda z80_e
- ldx z80_ep
- stx z80_e
- sta z80_ep
- lda z80_d
- ldx z80_dp
- stx z80_d
- sta z80_dp
- lda z80_l
- ldx z80_lp
- stx z80_l
- sta z80_lp
- lda z80_h
- ldx z80_hp
- stx z80_h
- sta z80_hp
- ;- ld bc, (COORDS) ; B'C' = y1, x1
- ;- ld d, b ; Saves B' in D'
- ;- ld a, 191
- ;- LOCAL __PIXEL_ADDR
- __PIXEL_ADDR EQU 22ACh
- ;- call __PIXEL_ADDR
- ;; Now gets pixel mask in A register
- ;- ld b, a
- ;- inc b
- ;- xor a
- ;- scf
- ;- LOCAL __PIXEL_MASK
- __PIXEL_MASK:
- ;- rra
- ;- djnz __PIXEL_MASK
- ;- ld b, d ; Restores B' from D'
- ;- pop de ; D'E' = y2, x2
- lda z80_c ;- exx
- ldx z80_cp
- stx z80_c
- sta z80_cp
- lda z80_b
- ldx z80_bp
- stx z80_b
- sta z80_bp
- lda z80_e
- ldx z80_ep
- stx z80_e
- sta z80_ep
- lda z80_d
- ldx z80_dp
- stx z80_d
- sta z80_dp
- lda z80_l
- ldx z80_lp
- stx z80_l
- sta z80_lp
- lda z80_h
- ldx z80_hp
- stx z80_h
- sta z80_hp
- ; At this point: D'E' = y2,x2 coords
- ; B'C' = y1, y1 coords
- ;- ex af, af' ; Saves A reg for later
- ; A' = Pixel mask
- ; H'L' = Screen Address of pixel
- ;- ld bc, (COORDS) ; B,C = y1, x1
- ;- ld a, e
- ;- sub c ; dx = X2 - X1
- ;- ld c, a ; Saves dx in c
- ;- ld a, 0Ch ; INC C opcode
- ;- ld hl, __INCX ; xi = 1
- ;- jr nc, __DRAW1
- ;- ld a, c
- ;- neg ; dx = X1 - X2
- ;- ld c, a
- ;- ld a, 0Dh ; DEC C opcode
- ;- ld hl, __DECX ; xi = -1
- __DRAW1:
- ;- ld (DX1), a
- ;- ld (DX1 + 2), hl ; Updates DX1 call address
- ;- ld (DX2), a
- ;- ld (DX2 + 2), hl ; Updates DX2 call address
- ;- ld a, d
- ;- sub b ; dy = Y2 - Y1
- ;- ld b, a ; Saves dy in b
- ;- ld a, 4 ; INC B opcode
- ;- ld hl, __INCY ; y1 = 1
- ;- jr nc, __DRAW2
- ;- ld a, b
- ;- neg
- ;- ld b, a ; dy = Y2 - Y1
- ;- ld a, 5 ; DEC B opcode
- ;- ld hl, __DECY ; y1 = -1
- __DRAW2:
- ;- ld (DY1), a
- ;- ld (DY1 + 2), hl ; Updates DX1 call address
- ;- ld (DY2), a
- ;- ld (DY2 + 2), hl ; Updates DX2 call address
- ;- ld a, b
- ;- sub c ; dy - dx
- ;- jr c, __DRAW_DX_GT_DY ; DX > DY
- ; At this point DY >= DX
- ; --------------------------
- ; HL = error = dY / 2
- ;- ld h, 0
- ;- ld l, b
- ;- srl l
- ; DE = -dX
- ;- xor a
- ;- sub c
- ;- ld e, a
- ;- sbc a, a
- ;- ld d, a
- ; BC = DY
- ;- ld c, b
- ;- ld b, h
- lda z80_c ;- exx
- ldx z80_cp
- stx z80_c
- sta z80_cp
- lda z80_b
- ldx z80_bp
- stx z80_b
- sta z80_bp
- lda z80_e
- ldx z80_ep
- stx z80_e
- sta z80_ep
- lda z80_d
- ldx z80_dp
- stx z80_d
- sta z80_dp
- lda z80_l
- ldx z80_lp
- stx z80_l
- sta z80_lp
- lda z80_h
- ldx z80_hp
- stx z80_h
- sta z80_hp
- ;- scf ; Sets Carry to signal update ATTR
- ;- ex af, af' ; Brings back pixel mask
- ;- ld e, a ; Saves it in free E register
- ;- jp __DRAW4_LOOP
- __DRAW3: ; While c != e => while y != y2
- lda z80_c ;- exx
- ldx z80_cp
- stx z80_c
- sta z80_cp
- lda z80_b
- ldx z80_bp
- stx z80_b
- sta z80_bp
- lda z80_e
- ldx z80_ep
- stx z80_e
- sta z80_ep
- lda z80_d
- ldx z80_dp
- stx z80_d
- sta z80_dp
- lda z80_l
- ldx z80_lp
- stx z80_l
- sta z80_lp
- lda z80_h
- ldx z80_hp
- stx z80_h
- sta z80_hp
- ;- add hl, de ; error -= dX
- ;- bit 7, h ;
- lda z80_c ;- exx ; recover coordinates
- ldx z80_cp
- stx z80_c
- sta z80_cp
- lda z80_b
- ldx z80_bp
- stx z80_b
- sta z80_bp
- lda z80_e
- ldx z80_ep
- stx z80_e
- sta z80_ep
- lda z80_d
- ldx z80_dp
- stx z80_d
- sta z80_dp
- lda z80_l
- ldx z80_lp
- stx z80_l
- sta z80_lp
- lda z80_h
- ldx z80_hp
- stx z80_h
- sta z80_hp
- ;- jr z, __DRAW4 ; if error < 0
- lda z80_c ;- exx
- ldx z80_cp
- stx z80_c
- sta z80_cp
- lda z80_b
- ldx z80_bp
- stx z80_b
- sta z80_bp
- lda z80_e
- ldx z80_ep
- stx z80_e
- sta z80_ep
- lda z80_d
- ldx z80_dp
- stx z80_d
- sta z80_dp
- lda z80_l
- ldx z80_lp
- stx z80_l
- sta z80_lp
- lda z80_h
- ldx z80_hp
- stx z80_h
- sta z80_hp
- ;- add hl, bc ; error += dY
- lda z80_c ;- exx
- ldx z80_cp
- stx z80_c
- sta z80_cp
- lda z80_b
- ldx z80_bp
- stx z80_b
- sta z80_bp
- lda z80_e
- ldx z80_ep
- stx z80_e
- sta z80_ep
- lda z80_d
- ldx z80_dp
- stx z80_d
- sta z80_dp
- lda z80_l
- ldx z80_lp
- stx z80_l
- sta z80_lp
- lda z80_h
- ldx z80_hp
- stx z80_h
- sta z80_hp
- ;- ld a, e
- DX1: ; x += xi
- inc z80_c ;- inc c
- jsr __INCX ;- call __INCX ; This address will be dynamically updated
- ;- ld e, a
- __DRAW4:
- DY1:
- ; y += yi
- inc z80_b ;- inc b
- jsr __INCY ;- call __INCY ; This address will be dyncamically updated
- ;- ld a, e ; Restores A reg.
- jsr __FASTPLOT ;- call __FASTPLOT
- __DRAW4_LOOP:
- ;- ld a, b
- ;- cp d
- ;- jp nz, __DRAW3
- ;- ld (COORDS), bc
- rts ;- ret
- __DRAW_DX_GT_DY: ; DX > DY
- ; --------------------------
- ; HL = error = dX / 2
- ;- ld h, 0
- ;- ld l, c
- ;- srl l ; HL = error = DX / 2
- ; DE = -dY
- ;- xor a
- ;- sub b
- ;- ld e, a
- ;- sbc a, a
- ;- ld d, a
- ; BC = dX
- ;- ld b, h
- lda z80_c ;- exx
- ldx z80_cp
- stx z80_c
- sta z80_cp
- lda z80_b
- ldx z80_bp
- stx z80_b
- sta z80_bp
- lda z80_e
- ldx z80_ep
- stx z80_e
- sta z80_ep
- lda z80_d
- ldx z80_dp
- stx z80_d
- sta z80_dp
- lda z80_l
- ldx z80_lp
- stx z80_l
- sta z80_lp
- lda z80_h
- ldx z80_hp
- stx z80_h
- sta z80_hp
- ;- ld d, e
- ;- scf ; Sets Carry to signal update ATTR
- ;- ex af, af' ; Brings back pixel mask
- ;- ld e, a ; Saves it in free E register
- ;- jp __DRAW6_LOOP
- __DRAW5: ; While loop
- lda z80_c ;- exx
- ldx z80_cp
- stx z80_c
- sta z80_cp
- lda z80_b
- ldx z80_bp
- stx z80_b
- sta z80_bp
- lda z80_e
- ldx z80_ep
- stx z80_e
- sta z80_ep
- lda z80_d
- ldx z80_dp
- stx z80_d
- sta z80_dp
- lda z80_l
- ldx z80_lp
- stx z80_l
- sta z80_lp
- lda z80_h
- ldx z80_hp
- stx z80_h
- sta z80_hp
- ;- add hl, de ; error -= dY
- ;- bit 7, h ; if (error < 0)
- lda z80_c ;- exx ; Restore coords
- ldx z80_cp
- stx z80_c
- sta z80_cp
- lda z80_b
- ldx z80_bp
- stx z80_b
- sta z80_bp
- lda z80_e
- ldx z80_ep
- stx z80_e
- sta z80_ep
- lda z80_d
- ldx z80_dp
- stx z80_d
- sta z80_dp
- lda z80_l
- ldx z80_lp
- stx z80_l
- sta z80_lp
- lda z80_h
- ldx z80_hp
- stx z80_h
- sta z80_hp
- ;- jr z, __DRAW6 ;
- lda z80_c ;- exx
- ldx z80_cp
- stx z80_c
- sta z80_cp
- lda z80_b
- ldx z80_bp
- stx z80_b
- sta z80_bp
- lda z80_e
- ldx z80_ep
- stx z80_e
- sta z80_ep
- lda z80_d
- ldx z80_dp
- stx z80_d
- sta z80_dp
- lda z80_l
- ldx z80_lp
- stx z80_l
- sta z80_lp
- lda z80_h
- ldx z80_hp
- stx z80_h
- sta z80_hp
- ;- add hl, bc ; error += dX
- lda z80_c ;- exx
- ldx z80_cp
- stx z80_c
- sta z80_cp
- lda z80_b
- ldx z80_bp
- stx z80_b
- sta z80_bp
- lda z80_e
- ldx z80_ep
- stx z80_e
- sta z80_ep
- lda z80_d
- ldx z80_dp
- stx z80_d
- sta z80_dp
- lda z80_l
- ldx z80_lp
- stx z80_l
- sta z80_lp
- lda z80_h
- ldx z80_hp
- stx z80_h
- sta z80_hp
- DY2: ; y += yi
- ;- inc b
- jsr __INCY ;- call __INCY ; This address will be dynamically updated
- __DRAW6:
- lda z80_e ;- ld a,e
- sta z80_a
- DX2: ; x += xi
- ;- inc c
- jsr __INCX ;- call __INCX ; This address will be dynamically updated
- lda z80_a ;- ld e,a
- sta z80_e
- jsr __FASTPLOT ;- call __FASTPLOT
- __DRAW6_LOOP:
- lda z80_c ;- ld a,c ; Current X coord
- sta z80_a
- ;- cp d
- ;- jp nz, __DRAW5
- ;- ld (COORDS), bc
- rts ;- ret
- PIXEL_ADDR EQU 22ACh
- COORDS EQU 5C7Dh
- __DRAW_END:
- lda z80_c ;- exx
- ldx z80_cp
- stx z80_c
- sta z80_cp
- lda z80_b
- ldx z80_bp
- stx z80_b
- sta z80_bp
- lda z80_e
- ldx z80_ep
- stx z80_e
- sta z80_ep
- lda z80_d
- ldx z80_dp
- stx z80_d
- sta z80_dp
- lda z80_l
- ldx z80_lp
- stx z80_l
- sta z80_lp
- lda z80_h
- ldx z80_hp
- stx z80_h
- sta z80_hp
- rts ;- ret
- ;
- ;; Given a A mask and an HL screen position
- ;; return the next left position
- ;; Also updates BC coords
- __DECX EQU SP.PixelLeft
- ;; Like the above, but to the RIGHT
- ;; Also updates BC coords
- __INCX EQU SP.PixelRight
- ;; Given an HL screen position, calculates
- ;; the above position
- ;; Also updates BC coords
- __INCY EQU SP.PixelUp
- ;; Given an HL screen position, calculates
- ;; the above position
- ;; Also updates BC coords
- __DECY EQU SP.PixelDown
- ;; Puts the A register MASK in (HL)
- __FASTPLOT:
- __PLOTINVERSE:
- ;- nop ; Replace with CPL if INVERSE 1
- __PLOTOVER:
- ldy #$00 ;- or (hl)
- ora (z80_hl),y
- ; Replace with XOR (hl) if OVER 1 AND INVERSE 0
- ; Replace with AND (hl) if INVERSE 1
- lda z80_a ;- ld (hl),a
- ldy #$00
- sta (z80_hl),y
- ldx z80_ap ;- ex af, af' ; Recovers flag. If Carry set => update ATTR
- sta z80_ap
- txa
- lda z80_e ;- ld a,e ; Recovers A reg
- sta z80_a
- bcc *+3 ;- ret nc
- rts
- lda z80_l ;- push hl
- pha
- lda z80_h
- pha
- lda z80_e ;- push de
- pha
- lda z80_d
- pha
- ;; gets ATTR position with offset given in SCREEN_ADDR
- lda z80_h ;- ld a,h
- sta z80_a
- ;- rrca
- ;- rrca
- ;- rrca
- and #$03 ;- and $03
- ora #$18 ;- or $18
- lda z80_a ;- ld h,a
- sta z80_h
- lda SCREEN_ADDR ;- ld de,(SCREEN_ADDR)
- sta z80_e
- lda SCREEN_ADDR+1
- sta z80_d
- ;- add hl,de ;; Final screen addr
- LOCAL PO_ATTR_2
- PO_ATTR_2 EQU 0BE4h ; Another entry to PO_ATTR
- jsr PO_ATTR_2 ;- call PO_ATTR_2 ; This will update attr accordingly. Beware, uses IY
- pla ;- pop de
- sta z80_d
- pla
- sta z80_e
- pla ;- pop hl
- sta z80_h
- pla
- sta z80_l
- ;- LOCAL __FASTPLOTEND
- __FASTPLOTEND:
- ora z80_a ;- or a ; Resets carry flag
- ldx z80_ap ;- ex af, af' ; Recovers A reg
- sta z80_ap
- txa
- lda z80_e ;- ld a,e
- sta z80_a
- rts ;- ret
- ;- ENDP
|