123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683 |
- .TEXT
-
- ;-------------------------------------------------------------------------
- pitch set 320/2 ; should be multiple of two
- xmaxpz set 319
- ymaxpz set 199
-
- benchdiv set 0
-
- ;-------------------------------------------------------------------------*
- ; LINES
- ;-------------------------------------------------------------------------*
- ; d0......x1
- ; d1......y1
- ; d2......x2
- ; d3......y2
- ; a0......ecran
- ;-------------------------------------------------------------------------*
-
- ;-------------------------------------------------------------------------*
-
- line:
- cmp.w d1,d3 ;* On ordonne les coordonnees
- bge.s line_yordered ;*verticales ;provisoirement y2 > y1
- exg.l d0,d2 ;* pour le clip vertical
- exg.l d1,d3 ;*
- line_yordered:
- tst.w d3 ;* Si l'ordonnee la plus grande
- bge.s line_y2positive ;*est ;negative (y2 < 0) on trace la droite
-
- ; moveq.l #0,d3 ;* entre x1 et x2 (passe xor oblige)
- ; moveq.l #0,d1 ;* On se branche au niveau du clip
- ; bra.s clipx ;*horizontal
- ; tcr
- rts
- ; /tcr
-
- line_y2positive:
- tst.w d1 ;* Si l'ordonnee la plus petite
- bge.s clipy2 ;*negative et l'autre positive
- ;
- ; On calcule l'intersection avec le
- ; bord superieur
- ; clipy
- move.w d0,d5 ;*
- sub.w d2,d5 ;* d5 = x1-x2
- ;
- move.w d3,d6 ;*
- sub.w d1,d6 ;* d6 = y2-y1
-
- .IFNE benchdiv
- not.w $ffff8240 ;.w *
- .ENDC
-
- muls.w d1,d5 ;* (x1-x2) * y1
- divs.w d6,d5 ;* (x1-x2) * y1 / (y2-y1)
-
- .IFNE benchdiv
- not.w $ffff8240 ;.w *
- .ENDC
-
- add.w d0,d5 ;* (x1-x2) * y1 / (y2-y1) + x1
- ; d5: abscisse d'intersection
- movem.w d0-d3/d5/d6,-(sp)
- move.l a0,-(sp) ;*
- moveq.l #0,d1 ;*
- moveq.l #0,d3 ;*
- move.w d5,d2
-
- ;
- ; tcr
- ; bsr.s clipx ;*On trace le bout de droite en haut
- ; /tcr
-
- ; de l'ecran horizontalement
- movea.l (sp)+,a0 ;*
- movem.w (sp)+,d0-d3/d5/d6 ;* (passe xor oblige)
-
- move.w d5,d0 ;* On trace le bout de droite
- moveq.l #0,d1 ;* restant sur l'ecran
- ; coordonnees non inversees
-
- clipy2:
- cmpi.w #ymaxpz,d1 ;* Si l'ordonnee la plus petite
- bgt.s return ;*est superieure … ymax
-
- cmpi.w #ymaxpz,d3 ;* Si l'ordonnee la plus grande>ymax
- ble.s clipx ;*et l'autre <ymax
-
- ; On calcule l'intersection avec le
- ; bord superieur
- sub.w d0,d2 ;* d2 = x2-x1
- sub.w d1,d3 ;* d3 = y2-y1
- ;
- move.w #ymaxpz,d5 ;*
- sub.w d1,d5 ;* d1 = y1-ymax
-
- .IFNE benchdiv
- not.w $ffff8240 ;.w *
- .ENDC
-
- muls.w d5,d2 ;* (x2-x1) * (y1-ymax)
- divs.w d3,d2
-
- .IFNE benchdiv
- not.w $ffff8240 ;.w *
- .ENDC
-
- add.w d0,d2 ;* (x2-x1) * (y1-ymax) / (y2-y1)+x1
- ; d2: abscisse d'intersection
- move.w #ymaxpz,d3 ;*
-
- ;----------------------------
- ; clipx
- ;----------------------------
-
- ; clipx1 --------------------
-
- clipx:
- cmp.w d2,d0 ;*
- ble.s clipx_ok1 ;*Si ;x1 > x2: Echange x1 x2 & y1 y2
- exg.l d2,d0 ;*
- exg.l d3,d1
- clipx_ok1:
- tst.w d2 ;* if d2 < 0 => do nothing
- bge.s clipx_ok2 ;
- return:
- rts ;*
- clipx_ok2:
- move.w d0,d7 ;* if x1 < 0 => store to fix length when displaying
- blt.s clipx_ok3
- moveq.l #0,d7
- clipx_ok3:
-
- ; clipx2 --------------------
- cmpi.w #xmaxpz,d0 ;* Si l'abscisse la plus petite
- bgt.s return ;*est ;superieure à xmax
- ; => on trace pas
- cmpi.w #xmaxpz,d2 ;* Si l'abscisse la plus grande > xmax
- ble.s trace
- ; On calcule l'intersection avec le
- ; bord superieur
- sub.w d0,d2 ;* d2 = x2-x1
- sub.w d1,d3 ;* d3 = y2-y1
- ;
- move.w #xmaxpz,d5 ;*
- sub.w d0,d5 ;* d0 = xmax-x1
-
- .IFNE benchdiv
- not.w $ffff8240 ;.w *
- .ENDC
-
- muls.w d5,d3 ;* (y2-y1) * (xmax-x1)
- divs.w d2,d3 ;* (y2-y1) * (xmax-x1) / (x2-x1)
-
- .IFNE benchdiv
- not.w $ffff8240 ;.w *
- .ENDC
-
- add.w d1,d3 ;* (y2-y1) * (xmax-x1) / (x2-x1)+y1
- ; d3: ordonnee d'intersection
- move.w #xmaxpz,d2 ;*
-
- ; tcr - try to avoid lines at screen edge
- rts
- ; /tcr
-
- ;----------------------------
- ; display
- ;----------------------------
-
- ; here we have d0,d1,d2,d3,d7 => x1, y1, x2, y2, lengthfix from x1 clip
-
- trace:
- lea -pitch,a2 ;
- ; movea.l #-pitch,a2
- sub.w d2,d0 ;* d0: largeur
- ; beq.s return ;* if dx = 0 => do nothing
- neg.w d0 ;*
-
- ; d0.w: -dx,a2.l: -pitch (-160)
-
- sub.w d3,d1 ;* d1: hauteur
-
- ; d1.w: dy,a2.l: -pitch(-160)
-
- ;beq h_line ; *if dy = 0 => hline
- ;blt.s trace_ok ;
- ble.s trace_ok
- lea pitch,a2 ;* if dy negative => invert address increment ¨Illegal adressing mode
- ; movea.l #pitch,a2
- neg.w d1 ;* abs (dy)
-
- ; d1.w = abs(dy), a2.l=pitch(160)
-
- trace_ok:
- neg.w d1 ;*
- ; d1 = abs(dy)
- lea pitchmul(pc),a1 ;* compute start address : a0 += y2 * pitch
- add.w d3,d3 ;*
-
- ; d3 = 2*y
-
- move.w 0(a1,d3.w),d3 ;*
- ; d3 = pitch*y
- ; add.w d3,d3 * (pitch / 2) * 2
- adda.w d3,a0
-
- ; a0 += pitch*y, start address of line
-
-
- ; at this point:
- ; d0.w: -dx
- ; d1.w: abs(dy)
-
- cmp.w d0,d1 ;* Compare dx & dy
- ; blt.s horizontal ;* => dx > dy => horizontal routine
- ; bgt verticalpz ;* => dy > dx => vertical routine
- bgt vertbresen
- beq d45 ;* => equal => 45 routine
-
- ;
- ; Dx>Dy
- ;------------------------------------------------------------------
- horizontal:
-
- swap.w d1 ;* dy*65536
- sub.w d1,d1 ;*
-
- .IFNE benchdiv
- not.w $ffff8240 ;.w *
- .ENDC
-
- divu.w d0,d1 ;* d1: increment dy*65536/dx
-
- .IFNE benchdiv
- not.w $ffff8240 ;.w *
- .ENDC
-
- add.w d7,d0 ;* fix length according to x1 clip
-
- lea line_display_horiz(pc),a3 ;* compute routine adresses range
- movea.l a3,a4 ;*
-
- add.w d2,d2 ;* start address : get values at x2 * 4
- add.w d2,d2
- move.l line_display_htab(pc,d2.w),d7
-
- adda.w d7,a0 ;* compute offset into routine
- swap.w d7
- adda.w d7,a3 ;* add x2 address offset to a0
-
- add.w d0,d0 ;* end address into routine : x2 * 4 + length * 4
- add.w d0,d0
- sub.w d0,d2
- adda.w line_display_htab(pc,d2.w),a4
-
- movem.w precharge(pc),d0/d2-d7
-
- movea.w (a4),a5 ;* backup opcode
- move.w #$4e75,(a4) ;* put an rts into the routine
- jsr (a3)
- move.w a5,(a4) ;* restore overwritten opcode
-
- rts
-
-
- precharge:
- .DC.w 1 ;* d0
- .DC.w 4 ;* d2
- .DC.w 8 ;* d3
- .DC.w 32 ;* d4
- .DC.w -32768 ;* d5
- .DC.w 64 ;* d6
- .DC.w 128 ;* d7
-
- line_display_htab:
-
- screenpz set 0
- opcode set (pitch/8)*2+(pitch*2)*8
-
- .REPT pitch/8
-
- ; 8 times
- opcode set opcode-8
- .DC.w opcode
- .DC.w screenpz
- opcode set opcode-8
- .DC.w opcode
- .DC.w screenpz
- opcode set opcode-8
- .DC.w opcode
- .DC.w screenpz
- opcode set opcode-8
- .DC.w opcode
- .DC.w screenpz
- opcode set opcode-8
- .DC.w opcode
- .DC.w screenpz
- opcode set opcode-8
- .DC.w opcode
- .DC.w screenpz
- opcode set opcode-8
- .DC.w opcode
- .DC.w screenpz
-
- screenpz set screenpz+1
-
- opcode set opcode-8
- .DC.w opcode
- .DC.w screenpz
-
- ; 8 times
- opcode set opcode-8
- .DC.w opcode
- .DC.w screenpz
- opcode set opcode-8
- .DC.w opcode
- .DC.w screenpz
- opcode set opcode-8
- .DC.w opcode
- .DC.w screenpz
- opcode set opcode-8
- .DC.w opcode
- .DC.w screenpz
- opcode set opcode-8
- .DC.w opcode
- .DC.w screenpz
- opcode set opcode-8
- .DC.w opcode
- .DC.w screenpz
- opcode set opcode-8
- .DC.w opcode
- .DC.w screenpz
- opcode set opcode-8
- .DC.w opcode
- .DC.w screenpz
-
- opcode set opcode-2
- screenpz set screenpz+7
-
- .ENDR
-
- ;------------------------------------------------------------------
- ; Dx<Dy
- ;------------------------------------------------------------------
-
- vertbresen:
- ; bresenham, also for dx = 0
- ; d0: dx
- ; d1: abs(dy)
- ; a2: pitch / -pitch (address offset for next line)
- move.l a2,d6
- ; d6: pitch / -pitch
- ; dont know if necessary
- ; add.w d7,d0
- add.w d2,d2
- add.w d2,d2
- ; d2: 4*x2
- lea table2(pc),a1
- move.l 0(a1,d2.w),d4
- adda.w d4,a0
- ; start in at the correct x-word
- swap.w d4
- ; correct bit mask for pixel in d4 (starting from the right)
- move.w d1,d5
- ; d1: dy = number of lines
- ; here: need to know the block size
- lsl.w #4,d5 ; *16
- add.w d1,d5
- add.w d1,d5
- neg.w d5
- ; d2: err, initialized as abs(dy)/2
- move.w d1,d2
- lsr.w #1,d2
-
- lea bres_blocks(pc),a3
- jmp 0(a3,d5.w)
-
- .REPT ymaxpz+1
- ; eor.w d4,(a0) ;* Affichage point
- or.w d4,(a0)
- adda.l d6,a0 ;* adr affichage-160 (trace a l'envers)
- sub.w d0,d2
- bge.s *+12
- add.w d1,d2
- add.w d4,d4 ;* on decale de 1 le bit tournant
- bcc.s *+6
- subq.l #8,a0 ;* adr affichage-8 (trace a l'envers)
- moveq.l #1,d4
- ; this block has 18 bytes
- .ENDR
- bres_blocks:
-
- rts
-
-
-
- verticalpz:
- move.l a2,d6
-
- ; d6.l: pitch or -pitch
-
- ; move.w d1,d6
-
- lsl.l #8,d1
- andi.l #$ffff00,d1
-
- ; andi.l #$ffff,d1
-
- ; d1.l: abs(dy)*256
-
- .IFNE benchdiv
- not.w $ffff8240 ;.w *
- .ENDC
-
- divu.w d0,d1 ;* d1: increment dx*65536/dy
-
- ; d1 lower: abs(dy)*256 / dx, upper: remainder
- ; d0: -dx (still)
-
- ;test: d1: dy/dx (minimum 1!)
-
- .IFNE benchdiv
- not.w $ffff8240 ;.w *
- .ENDC
-
- ; add clip length correction from the left
- add.w d7,d0
-
- ; move.w d6,d7
- ; move.l a2,d6
- ; d2: x2
-
- add.w d2,d2
- add.w d2,d2
- ; d2: 4*x2
- lea table2(pc),a1
- move.l 0(a1,d2.w),d4
- adda.w d4,a0
-
- ; a0: screen address at the correct word
-
- ; lea 0(a0,d4.w),a0
- swap.w d4
- ; d4.w: bitmask for the correct pixel (in x)
-
- move.l d6,d2
- move.l d1,d3
- lsr.w #8,d3
- ; d3: (abs(dy) * 256 / dx) / 256
-
- .IFNE benchdiv
- not.w $ffff8240 ;.w *
- .ENDC
-
- ; muls.w d3,d6
-
- .IFNE benchdiv
- not.w $ffff8240 ;.w *
- .ENDC
-
- ; move.w d7,d0 ; dy
- move.w d0,d5 ;* compute jmp distance
- lsl.w #5,d0 ; *32
- add.w d5,d5 ; *2
- ; added tcr
- ; add.w d5,d5
- ; add.w d5,d5 ; d5 *8 in total -> 24 bytes
- ; end addition
- add.w d5,d0
- neg.w d0
-
- ;move.w d7,d3
- ;move.w a5,d3
- ; move.w d3,d7 ; number of lines on same level
-
- move.w #-32768,d5
- ; move.w #$8000,d5
-
- lea vertical_display(pc),a3
- jmp 0(a3,d0.w)
-
- .REPT ymaxpz+1
- ; eor.w d4,(a0) ;* Affichage point
- or.w d4,(a0)
- adda.l d6,a0 ;* adr affichage-160 (trace a l'envers)
-
- add.w d4,d4 ;* on decale de 1 le bit tournant
- bcc.s *+6 ;* Si abscisse bit > 15
- subq.l #8,a0 ;* adr affichage-8 (trace a l'envers)
- moveq.l #1,d4
- ; dont know what this was for...
- ; nop
- ; nop
- ; nop
- ; add.b d1,d5 ;* Incremente le taux d'erreur
- ; bcc.s *+4 ;* Si bit carry , taux > 1 unite (65536)
- ; adda.l d2,a0 ;*
- ;
- ; this block has 34 bytes
- .ENDR
-
- vertical_display:
-
- rts
-
-
- ;
- ; Dx=Dy
- ;------------------------------------------------------------------
- diago:
- .REPT 8
- ;eor.w d4,(a0) ;* Affiche le point
- or.w d4,(a0)
- adda.l a2,a0 ;* Mvt vert
- add.w d4,d4 ;* Mvt hori
- bcc.s *+6 ;*Incremente ;adr si abscisse mod 16 = 0
- subq.l #8,a0 ;*
- moveq.l #1,d4 ;*
- .ENDR
- saut3:
- dbra d1,diago ; * Longueur ¨Illegal extension
-
- rts
-
- d45:
- ;moveq.l #$FFF0,d5
- ;and.w d2,d5
- ;lsr.w #1,d5
- ;add.w d5,a0
-
- add.w d2,d2
- add.w d2,d2
- lea table2(pc),a1
- move.l 0(a1,d2.w),d4
- ;adda.w d4,a0
- lea 0(a0,d4.w),a0
- swap.w d4
-
- add.w d7,d0
- add.w d7,d1
-
- andi.w #7,d0
- neg.w d0
-
- add.w d0,d0 ;* let's do the mul 12 manually
- add.w d0,d0
- move.w d0,d7
- add.w d7,d7
- add.w d7,d0
-
- lsr.w #3,d1
- jmp saut3(pc,d0.w)
-
- line_display_horiz:
-
- .REPT pitch/8
-
- subq.l #7,a0 ; decrement address by 7
-
- ;eor.b d0,(a0) ; bit 0
- or.b d0,(a0)
- add.w d1,d5
- bcc.s *+4
- adda.l a2,a0
-
- ;bchg.b d0,(a0) ; bit 1
- bset.b d0,(a0)
- add.w d1,d5
- bcc.s *+4
- adda.l a2,a0
-
- ;eor.b d2,(a0) ; bit 2
- or.b d2,(a0)
- add.w d1,d5
- bcc.s *+4
- adda.l a2,a0
-
- ;eor.b d3,(a0) ; bit 3
- or.b d3,(a0)
- add.w d1,d5
- bcc.s *+4
- adda.l a2,a0
-
- ;bchg.b d2,(a0) ; bit 4
- bset.b d2,(a0)
- add.w d1,d5
- bcc.s *+4
- adda.l a2,a0
-
- ;eor.b d4,(a0) ; bit 5
- or.b d4,(a0)
- add.w d1,d5
- bcc.s *+4
- adda.l a2,a0
-
- ;eor.b d6,(a0) ; bit 6
- or.b d6,(a0)
- add.w d1,d5
- bcc.s *+4
- adda.l a2,a0
-
- ;eor.b d7,(a0) ; bit 7
- or.b d7,(a0)
- add.w d1,d5
- bcc.s *+4
- adda.l a2,a0
-
- ;eor.b d0,-(a0) ; bit 0 + decrement address by one
- or.b d0,-(a0)
- add.w d1,d5
- bcc.s *+4
- adda.l a2,a0
-
- ;bchg.b d0,(a0) ; bit 1
- bset.b d0,(a0)
- add.w d1,d5
- bcc.s *+4
- adda.l a2,a0
-
- ;eor.b d2,(a0) ; bit 2
- or.b d2,(a0)
- add.w d1,d5
- bcc.s *+4
- adda.l a2,a0
-
- ;eor.b d3,(a0) ; bit 3
- or.b d3,(a0)
- add.w d1,d5
- bcc.s *+4
- adda.l a2,a0
-
- ;bchg.b d2,(a0) ; bit 4
- bset.b d2,(a0)
- add.w d1,d5
- bcc.s *+4
- adda.l a2,a0
-
- ;eor.b d4,(a0) ; bit 5
- or.b d4,(a0)
- add.w d1,d5
- bcc.s *+4
- adda.l a2,a0
-
- ;eor.b d6,(a0) ; bit 6
- or.b d6,(a0)
- add.w d1,d5
- bcc.s *+4
- adda.l a2,a0
-
- ;eor.b d7,(a0) ; bit 7
- or.b d7,(a0)
- add.w d1,d5
- bcc.s *+4
- adda.l a2,a0
-
- .ENDR
-
- rts
-
- .DATA
-
- ;-------------------------------------------------------------------------*
- ; Section data
- ;-------------------------------------------------------------------------*
-
- pitchmul:
- var set 0
- .REPT ymaxpz+2
- .DC.w var
- var set var+pitch
- .ENDR
- table2:
- var set 0
- .REPT pitch/8
- .DC.w $8000,var,$4000,var,$2000,var,$1000,var
- .DC.w $0800,var,$0400,var,$0200,var,$0100,var
- .DC.w $0080,var,$0040,var,$0020,var,$0010,var
- .DC.w $0008,var,$0004,var,$0002,var,$0001,var
- var set var+8
- .ENDR
-
|