home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Programmierung / SOURCE.mdf / programm / msdos / asm / 3dvect25 / 3d1.asm < prev    next >
Encoding:
Assembly Source File  |  1993-09-06  |  41.6 KB  |  1,487 lines

  1. ; 3d vector routines - fast sort method
  2. ;
  3. ; - objects sorted and drawn through makeobjs routine.
  4. ; - objects cannot enter inside one another
  5. ; - maxsurfs and maxpoints can be kept low - set to largest object requirement
  6. ;
  7. ; to use:
  8. ;
  9. ;          call look_at_it           ; make camera look at selected object
  10. ;          call setsincose           ; set rotation multipliers for eye
  11. ;          call makeobjs             ; plot all objects on current page
  12. ;          call instant_mouse        ; plot mouse
  13. ;          call flip_page            ; flip video pages
  14. ;          call clear_fill           ; clear other screen
  15. ;          call resetupd             ; reset update for borders
  16. ;          call updvectors           ; move objects around, rotate them
  17.  
  18.             .386p
  19.  
  20. code32     segment para public use32
  21.            assume cs:code32, ds:code32
  22.  
  23. ; define externals
  24.  
  25.            extrn objbase:dword     ; object lists and bitmap lists are
  26.            extrn bitbase:dword     ; external! set to 0 if none
  27.            extrn bitx:dword        ; x and y sizes for 3d conversion
  28.            extrn bity:dword
  29.  
  30.            include pmode.inc       ; protected mode externals
  31.            include xmouse.inc      ; xmode mouse externals
  32.            include xmode.inc       ; xmode externals by matt pritchard
  33.  
  34.            include macros.inc
  35.            include equ.inc
  36.  
  37.            include vars1.inc
  38.            include arctan.inc      ; inverse tan
  39.            include sin.inc         ; sin/cosin table
  40.            include math.inc        ; rotate, cos,sin,arctan...
  41.            include xscale.inc
  42.            include poly.inc        ; common ploygon stuff
  43.  
  44. ; 3d.inc - 3d and vector handling routines
  45.  
  46.            public move_si
  47.            public newfollow
  48.            public resetupd
  49.            public makeobjs
  50.            public make1obj
  51.            public look_at_it
  52.            public calc_angles
  53.            public get_displacement
  54.            public put_object
  55.            public set_angle
  56.            public set_shape
  57.            public set_object_on
  58.            public set_object_off
  59.            public set_makeorder
  60.            public dv_middle
  61.            public sort_list
  62.            public drawvect
  63.  
  64.            align 4
  65.  
  66. loadpoints:
  67.            mov bl,userotate[si]
  68.  
  69.            shl si,1
  70.            mov di,whatshape[si]   ; get shape, bp = z distance
  71.            shl di,2               ; four resolutions
  72.            mov eax,zad
  73.            cmp eax, smalla        ; check if too far to see detail anyway
  74.            jl s viewhi
  75.            inc di                 ; use resolution b
  76.            cmp eax, smallb
  77.            jl s viewhi
  78.            inc di                 ; use resolution c
  79.            cmp eax, smallc
  80.            jl s viewhi
  81.            inc di                 ; use resolution d
  82. viewhi:
  83.            shl di,2
  84.            mov edi,objbase[di]
  85.            mov ax,[edi]
  86.            mov numpoints,ax
  87.            mov ax,[edi+2]
  88.            mov numsides,ax
  89.            add edi,4
  90.  
  91.            xor si,si              ; reset xp pointer
  92.  
  93.            cmp bl,0
  94.            jne np13               ; use different loop if no rotation
  95. np12:
  96.            movsx ebx,w [edi]      ; x
  97.            movsx ecx,w [edi+2]    ; y
  98.            movsx ebp,w [edi+4]    ; z
  99.  
  100.            push edi si
  101.            call rotate            ; rotate
  102.            add ebp,zad
  103.  
  104.            cmp ebp,ztruncate
  105.            jge s ntrunct
  106.            mov ebp,ztruncate
  107. ntrunct:
  108.            add ebx,xad
  109.            add ecx,yad
  110.            call make3d
  111.            pop si edi
  112.            mov [xp+si],bx
  113.            mov [yp+si],cx
  114.            mov [zp+si],bp
  115.            add si,2               ; inc xp indexer
  116.            add edi,6              ; inc input pointer
  117.            dec numpoints
  118.            jne s np12
  119.  
  120.            ret                    ; edi exits with pointer to sides
  121. np13:
  122.            movsx ebx,w [edi]      ; x
  123.            movsx ecx,w [edi+2]    ; y
  124.            movsx ebp,w [edi+4]    ; z
  125.  
  126.            push edi si
  127.  
  128.            call erotate           ; rotation matrix already set up!
  129.  
  130.            add ebp,zad
  131.  
  132.            cmp ebp,ztruncate
  133.            jge s ntrunct2
  134.            mov ebp,ztruncate
  135. ntrunct2:
  136.            add ebx,xad
  137.            add ecx,yad
  138.            call make3d
  139.            pop si edi
  140.            mov [xp+si],bx
  141.            mov [yp+si],cx
  142.            mov [zp+si],bp
  143.            add si,2               ; inc xp indexer
  144.            add edi,6
  145.            dec numpoints
  146.            jne s np13
  147.  
  148.            ret
  149.  
  150.            align 4
  151.  
  152. ; handle loading of bitmap from object list
  153. ;
  154. ; eg   dw 32,8,5,50,60 ;command is 32,point 8, bitmap 5, x&y scaling of 50,60
  155.  
  156. ld_special:
  157.            lodsw                  ; get from si, first is point
  158.            shl ax,1
  159.            stosw                  ; put in sides table
  160.  
  161.            mov dx,bp              ; save indexer
  162.            mov bp,ax              ; get point indexers
  163.            mov ax,[zp+bp]
  164.            mov zeds[bx],ax        ; set zed for sort.
  165.            mov bp,dx
  166.  
  167.            movsw                  ; get bitmap type
  168.            movsw                  ; get x then y scaling
  169.            movsw
  170.  
  171.            cmp zad,64000          ; bitmaps farther than 65536 screw up
  172.            jge skipit             ; you can't see them anyway. prevent overflow
  173.            jmp ln2
  174.  
  175.            align 4
  176. loadsides:
  177.            mov showing,0          ; reset counter/indexer
  178.  
  179.            mov esi,edi            ; edi = pointer to side object data
  180.            xor ebp,ebp            ; indexer to first point
  181.            mov edi,offset sides   ; get ready for lodsw and stosw
  182.            xor bx,bx
  183. ld_lp:
  184.            lodsw                  ; get command word
  185.            mov commands[bx],ax
  186.            mov cx,ax              ; save for later test
  187.  
  188.            mov order[bx],bx       ; set order to 0,2,4,6,8...
  189.  
  190.            test ax,32             ; if bitmap, do special load
  191.            jnz ld_special
  192.  
  193.            lodsw                  ; get colour, high byte is other side
  194.            mov surfcolors[bx],ax  ; save colour
  195.  
  196.            lodsw                  ; get from si, first is unconditinal
  197.            shl ax,1
  198.            stosw                  ; put in di
  199.            mov dx,ax
  200. ld_loop:
  201.            lodsw                  ; get from si
  202.            shl ax,1
  203.            stosw                  ; put in di
  204.  
  205.            cmp ax,dx              ; check all after first point
  206.            jne s ld_loop
  207.  
  208.            push ebp
  209.            push esi
  210.            push bx
  211.  
  212.            mov di,bp              ; adjust bp into appropriate indexer
  213.            mov bp,[sides+di+0]    ; get point indexers
  214.            mov dx,[zp+bp]         ; get at least one z value, should be max
  215.            mov zeds[bx],dx        ; but any will do.
  216.  
  217.            test cx,2+16+64        ; check if always visable
  218.            jnz its_line
  219.  
  220.            mov bx,[sides+di+4]
  221.  
  222.            mov dx,[xp+bp]         ; first point
  223.            mov ax,[yp+bp]
  224.            mov esq,ax             ; memory
  225.  
  226.            mov bp,[sides+di+2]
  227.            mov si,[xp+bp]         ; second point
  228.            mov ax,[yp+bp]
  229.            mov dsq,ax             ; memory
  230.  
  231.            mov bp,bx
  232.            mov di,[xp+bp]         ; third point
  233.            mov bp,[yp+bp]
  234.  
  235.            call checkfront        ; check if side is visable using p1,2,3
  236.  
  237.            pop bx
  238.            pop esi                ; return object data pointer
  239.            pop ebp                ; return where we are in sides list
  240.  
  241.            cmp ecx,0+1            ; +1 makes small objects look better
  242.            jle ln2                ; cx>-1 if side visible, skip if not
  243.            test commands[bx],4    ; test to use other colour
  244.            jz s skipit            ; miss this side...
  245.            mov ax,surfcolors[bx]  ; get new colour
  246.            xchg ah,al             ; flip to other colour
  247.            mov surfcolors[bx],ax  ; save colour
  248.            shr commands[bx],3     ; use new steel texture bit
  249. ln2:
  250.            inc showing            ; another side added...
  251.            add bx,2
  252.            add ebp,maxpolys*2     ; bump ebp to next block
  253. skipit:
  254.            mov edi,ebp            ; set di for next stosw
  255.            add edi,offset sides
  256.  
  257.            dec numsides           ; count for next side
  258.            jne ld_lp
  259.  
  260.            ret
  261. its_line:
  262.            pop bx esi ebp
  263.            jmp s ln2
  264.  
  265.            align 4
  266.  
  267. ; make object si - routine assumes object is ON
  268.  
  269. make1obj:
  270. ;          mov zedthis,32767      ; set z for sort in case of abort
  271. ;
  272. ;          test onoff[si],255     ; check on/off
  273. ;          jz s ci6q
  274.  
  275.            push si
  276.  
  277.            shl si,2               ; si = dword
  278.  
  279.            mov ebx,xs[si]         ; displacement
  280.            sub ebx,eyex
  281.            mov ecx,ys[si]
  282.            sub ecx,eyey
  283.            mov ebp,zs[si]
  284.            sub ebp,eyez
  285.  
  286.            shr ebx,8              ; account for decimal places
  287.            test ebx,00800000h
  288.            jz s pm_1
  289.            or ebx, 0ff000000h
  290. pm_1:
  291.            shr ecx,8
  292.            test ecx,00800000h
  293.            jz s pm_2
  294.            or ecx, 0ff000000h
  295. pm_2:
  296.            shr ebp,8
  297.            test ebp,00800000h
  298.            jz s pm_3
  299.            or ebp, 0ff000000h
  300. pm_3:
  301.            cmp ebx,-maxz          ; check if within visible space
  302.            jl s noa2              ; if object miles away, don't bother
  303.            cmp ebx,maxz
  304.            jg s noa2
  305.  
  306.            cmp ebp,-maxz
  307.            jl s noa2
  308.            cmp ebp,maxz
  309.            jg s noa2
  310.  
  311.            cmp ecx,-maxz
  312.            jl s noa2
  313.            cmp ecx,maxz
  314.            jng s mo_misout
  315.  
  316.            align 4
  317. noa2:
  318.            pop si
  319.            ret
  320.  
  321. mo_misout:
  322.            call zsolve            ; figure out camera displacement
  323.  
  324.            cmp esi,minz           ; check if behind camera, miminum dist.
  325.            jl s noa2
  326.  
  327. ;          cmp esi,32767          ; rare case, far plane in front of far blimp,
  328. ;          jle s pm_notseg        ; plane may appear behind blimp, but for
  329. ;          mov esi,32767          ; that split second, who cares!
  330. ;pm_notseg:
  331.  
  332.            call xsolve
  333.            mov xad,edi            ; store 3d offsets
  334.            call make3dx
  335.  
  336.            cmp edi,xmit           ; tolerance is max object size/ratio
  337.            jl s noa2
  338.            cmp edi,xmat
  339.            jge s noa2
  340.  
  341.            call ysolve            ; solve y and set correct regs
  342.            mov yad,ecx
  343.            call make3dy           ; now make object farther in 3d (cheat)
  344.  
  345.            cmp ecx,ymit
  346.            jl s noa2
  347.            cmp ecx,ymat
  348.            jge s noa2
  349.  
  350.            mov zad,ebp
  351.            mov zedthis,bp         ; store z for next sort
  352.  
  353.            pop si                 ; pop original object number
  354.  
  355.            mov al,userotate[si]
  356.            test al,32+64          ; check if bitmap or point
  357.            jnz s mo_special
  358.  
  359.            cmp al,0               ; test to call compound routine
  360.            jne s mk_skipc         ; skip if anything other than full rotations
  361.  
  362.            movzx esi,si
  363.            shl si,1               ; si = word
  364.            call compound          ; full rotation object, calc. matrix
  365.            shr si,1
  366. mk_skipc:
  367.            call loadpoints        ; load points and rotate, exit di=sides
  368.            call loadsides         ; now load sides, starting at di
  369.            call sort_list         ; sort surfaces
  370.            jmp  drawvect          ; draw surfaces and exit
  371. noa:
  372.            ret
  373.  
  374. ; if userotate = 2 then draw bitmap at location x,y,z
  375.  
  376.            align 4
  377.  
  378. mo_special:
  379.            test al,64             ; check if point
  380.            jnz mo_ispoint
  381.  
  382.            push bx cx             ; save actual center of bitmap
  383.  
  384.            mov ebx,xad            ; calc size of bitmap
  385.            mov ecx,yad
  386.  
  387.            shl si,1               ; si = word
  388.            movzx edx,vxs[si]      ; get addition for bitmap size
  389.            sub ebx,edx
  390.            sub ecx,edx
  391.  
  392.            mov si,whatshape[si]
  393.            shl si,2               ; si = dword
  394.            sub ebx,bitx[si]
  395.            sub ecx,bity[si]       ; ebx,ecx = top corner of bitmap in 3d
  396.  
  397.            mov eax,bitbase[si]
  398.            mov bitmap,eax
  399.  
  400.            call make3d            ; ebx,ecx = top corner of bitmap in 2d
  401.  
  402.            if useborders eq yes
  403.  
  404.            cmp cx,yupdate+0
  405.            jge s up_no12
  406.            mov yupdate+0,cx
  407. up_no12:
  408.            cmp bx,xupdate+0
  409.            jge s up_no32
  410.            mov xupdate+0,bx
  411. up_no32:
  412.            endif
  413.  
  414.            pop bp ax              ; bp = y, ax = x center
  415.            sub bp,cx              ; bp = y height/2
  416.            sub ax,bx              ; ax = x width/2
  417.  
  418.            if useborders eq yes
  419.            mov dx,cx
  420.            mov di,bx
  421.            endif
  422.  
  423.            add bx,xcent
  424.            add cx,ycent
  425.            mov destx,bx
  426.            mov desty,cx
  427.  
  428.            shl bp,1
  429.            shl ax,1
  430.  
  431.            mov destheight,bp
  432.            mov destwidth,ax
  433.  
  434.            if useborders eq yes
  435.            add dx,bp
  436.            add di,ax
  437.  
  438.            cmp dx,yupdate+2
  439.            jng s up_no42
  440.            mov yupdate+2,dx
  441. up_no42:
  442.            cmp di,xupdate+2
  443.            jng s up_no22
  444.            mov xupdate+2,di
  445. up_no22:
  446.            endif
  447.  
  448.            jmp  xscale2
  449. noa7:
  450.            ret
  451. mo_ispoint:
  452.            cmp bx,xmins            ; draw single point/bullet
  453.            jl s noa7
  454.            cmp bx,xmaxs
  455.            jge s noa7
  456.            cmp cx,ymins
  457.            jl s noa7
  458.            cmp cx,ymaxs            ; ymaxs1 if larger pixel
  459.            jge s noa7
  460.  
  461.            mov edi, current_page   ; point to active vga page
  462.            add bx,xcent
  463.            add cx,ycent
  464.  
  465.            mov si,cx
  466.            shl si,1
  467.            mov ax,[si+fastimultable] ; get offset to start of line
  468.  
  469.            mov cx, bx              ; copy to extract plane # from
  470.            shr bx, 2               ; x offset (bytes) = xpos/4
  471.            add bx, ax              ; offset = width*ypos + xpos/4
  472.  
  473.            mov ax, map_mask_plane1 ; map mask & plane select register
  474.            and cl, plane_bits      ; get plane bits
  475.            shl ah, cl              ; get plane select value
  476.            out_16 sc_index, ax     ; select plane
  477.  
  478.            movzx ebx,bx
  479.            mov [edi+ebx],b bulletcolour ; draw pixel, red or yellow is good
  480. ;          add edi,xactual/4
  481. ;          mov [edi+ebx],b bulletcolour2 ; draw larger bullet/pixel
  482.  
  483. ; if drawing larger pixel, change above code to this!
  484. ;          cmp cx,ymaxs1
  485. ;          jge s noa7
  486.  
  487.            ret
  488.  
  489.            align 4
  490.  
  491. ; draw vectors from sides list.
  492. ; number of "sides" is "showing"
  493.  
  494. dv_none2:
  495.            ret
  496. drawvect:
  497.            cmp showing,0          ; no sides visible?
  498.            je s dv_none2
  499.  
  500.            mov whichside,0        ; start at side 0
  501.            mov bp,order[0]        ; indexer to sides
  502. dv_loop2:
  503.            test commands[bp],16+32+64 ; test if line, point or bitmap
  504.            jnz dv_testit          ; yes, do faster line routine
  505.  
  506.            shl bp,mult
  507.            mov dx,[sides+bp]      ; first point is end flag
  508. dv_loop1:
  509.            mov si,[sides+bp]      ; get point, shl 1 not needed, pre-shl'ed
  510.            mov ax,[xp+si]
  511.            mov bx,[yp+si]
  512.            mov x1,ax
  513.            mov y1,bx
  514.  
  515.            mov si,[sides+bp+2]    ; get next point
  516.  
  517.            cmp si,dx              ; test if last = first, therefore done
  518.            pushf
  519.  
  520.            mov ax,[xp+si]
  521.            mov bx,[yp+si]
  522.  
  523.            mov x2,ax
  524.            mov y2,bx
  525.  
  526.            push bp dx
  527.            call fakeline          ; draw next line
  528.            pop dx bp
  529.  
  530.            add bp,2               ; bump to next pointer now
  531.            popf                   ; was this point equal to the first point?
  532.            jne s dv_loop1         ; no, draw more lines
  533.  
  534.            mov si,whichside       ; set colour for this side
  535.            mov si,order[si]
  536.            mov ax,surfcolors[si]
  537.            mov colq,al
  538.  
  539.            mov bx,commands[si]    ; use register which we can access low byte
  540.            and bl,1               ; strip steel command bit
  541.            sub bl,1
  542.            mov steel,bl
  543.  
  544.            call poly_fill
  545.  
  546. dv_return:
  547.            add whichside,2        ; bump bp to next block of points
  548.            mov bp,whichside
  549.            mov bp,order[bp]       ; get sort order
  550.            dec showing            ; count for all sides
  551.            jne dv_loop2
  552. dv_none:
  553.            ret
  554.  
  555.            align 4
  556. dv_testit:
  557.            mov ax,commands[bp]    ; perform command, return to dv_return
  558.            test ax,16
  559.            jnz dv_doline
  560.            test ax,64
  561.            jnz dv_dopoint
  562.  
  563. ; draw bitmap at location x,y,z if userotate = 32 or command = 32
  564.  
  565.            shl bp,mult
  566.            push bp
  567.  
  568.            movzx ebx,[sides+4+bp]
  569.            movzx ecx,[sides+6+bp]
  570.  
  571.            mov si,[sides+2+bp]
  572.            shl si,2               ; si = dword
  573.            add ebx,bitx[si]
  574.            add ecx,bity[si]       ; ebx,ecx = top corner of bitmap in 3d
  575.  
  576.            mov eax,bitbase[si]
  577.            mov bitmap,eax
  578.  
  579.            mov si,[sides+0+bp]
  580.            mov bp,[zp+si]
  581.  
  582.            call make3d            ; ebx,ecx = difference from center
  583.  
  584.            pop bp
  585.  
  586.            mov si,[sides+0+bp]    ; get point
  587.            mov ax,[xp+si]
  588.            mov bp,[yp+si]
  589.  
  590.            sub ax,bx              ; bx = x width/2  ax, bp = top corner
  591.            sub bp,cx              ; cx = y height/2
  592.  
  593.            if useborders eq yes
  594.  
  595.            cmp bp,yupdate+0
  596.            jge s up_nq12
  597.            mov yupdate+0,bp
  598. up_nq12:
  599.            cmp ax,xupdate+0
  600.            jge s up_nq32
  601.            mov xupdate+0,ax
  602. up_nq32:
  603.            mov di,ax
  604.            mov dx,bp
  605.  
  606.            endif
  607.  
  608.            add ax,xcent
  609.            add bp,ycent
  610.            mov destx,ax
  611.            mov desty,bp
  612.  
  613.            shl bx,1
  614.            shl cx,1
  615.  
  616.            mov destwidth,bx
  617.            mov destheight,cx
  618.  
  619.            if useborders eq yes
  620.            add di,bx
  621.            add dx,cx
  622.  
  623.            cmp dx,yupdate+2
  624.            jng s up_nq42
  625.            mov yupdate+2,dx
  626. up_nq42:
  627.            cmp di,xupdate+2
  628.            jng s up_nq22
  629.            mov xupdate+2,di
  630. up_nq22:
  631.            endif
  632.  
  633.            call xscale2
  634. noq7:
  635.            jmp dv_return
  636.  
  637.            align 4
  638.  
  639. dv_dopoint:
  640.            mov dx,surfcolors[bp]   ; get colour of point
  641.  
  642.            shl bp,mult
  643.            mov si,[sides+bp]       ; get point x,y
  644.            mov bx,[xp+si]
  645.            mov cx,[yp+si]
  646.  
  647.            cmp bx,xmins            ; check if on screen
  648.            jl s noq7
  649.            cmp bx,xmaxs
  650.            jge s noq7
  651.            cmp cx,ymins
  652.            jl s noq7
  653.            cmp cx,ymaxs            ; ymaxs1 if larger pixel
  654.            jge s noq7
  655.  
  656.            mov edi, current_page   ; point to active vga page
  657.  
  658.            if useborders eq yes
  659.  
  660.            cmp cx,yupdate+0
  661.            jge s up_no16
  662.            mov yupdate+0,cx
  663. up_no16:
  664.            cmp bx,xupdate+0
  665.            jge s up_no36
  666.            mov xupdate+0,bx
  667. up_no36:
  668.            cmp cx,yupdate+2
  669.            jng s up_no46
  670.            mov yupdate+2,cx
  671. up_no46:
  672.            cmp bx,xupdate+2
  673.            jng s up_no26
  674.            mov xupdate+2,bx
  675. up_no26:
  676.            endif
  677.  
  678.            add bx,xcent
  679.            add cx,ycent
  680.  
  681.            mov bp,dx               ; save colour
  682.  
  683.            mov si,cx
  684.            shl si,1
  685.            mov ax,[si+fastimultable] ; get offset to start of line
  686.  
  687.            mov cx, bx              ; copy to extract plane # from
  688.            shr bx, 2               ; x offset (bytes) = xpos/4
  689.            add bx, ax              ; offset = width*ypos + xpos/4
  690.  
  691.            mov ax, map_mask_plane1 ; map mask & plane select register
  692.            and cl, plane_bits      ; get plane bits
  693.            shl ah, cl              ; get plane select value
  694.            out_16 sc_index, ax     ; select plane
  695.  
  696.            movzx ebx,bx
  697.            mov ax,bp               ; re-get colour
  698.            mov [edi+ebx],al        ; draw pixel, low is top, high is bottom
  699. ;          add edi,xactual/4
  700. ;          mov [edi+ebx],ah        ; draw larger bullet/pixel (high byte)
  701.  
  702. ; if drawing larger pixel, change above code to this!
  703. ;          cmp cx,ymaxs1
  704. ;          jge s noa7
  705.  
  706.            jmp dv_return
  707.  
  708.            align 4
  709.  
  710. ; clipped line, only callable from draw_vect!
  711. ; similar routine to fakeline but faster,  more  accurate  and  draws  directly
  712. ; to screen (current_page).
  713. ;
  714. ; this routine will always return to dv_return but you could replace those with
  715. ; ret's and make this routine  callable  from  places   other  than  draw_vect.
  716. ; if  you  do  this,  make  sure  you  re-direct  the  draw_vect    routine  to
  717. ; call dv_doline, jmp dv_return.  for now, set showing=1 and  load  dx,cx,ax,bx
  718. ; with x1,y1,x2,y2 and call dv_middle.  thats if you really need a clipped line
  719. ; draw routine.
  720.  
  721. dv_doline:
  722.            shl bp,mult
  723.            mov si,[sides+bp]      ; get first point
  724.            mov dx,[xp+si]
  725.            mov cx,[yp+si]
  726.  
  727.            mov si,[sides+bp+2]    ; second point
  728.            mov ax,[xp+si]
  729.            mov bx,[yp+si]
  730. dv_middle:
  731.            cmp bx,cx              ; flip order of points if drawing up
  732.            jg s r_okorder
  733.            xchg bx,cx
  734.            xchg ax,dx
  735. r_okorder:
  736.            mov x1,dx
  737.            mov y1,cx
  738.            mov x2,ax
  739.            mov y2,bx
  740.  
  741.            if useborders eq yes
  742.  
  743.            cmp cx,yupdate+0       ; update borders for clearing routine
  744.            jg s r_up_no1
  745.            mov yupdate+0,cx
  746. r_up_no1:
  747.            cmp bx,yupdate+2
  748.            jng s r_up_no2
  749.            mov yupdate+2,bx
  750. r_up_no2:
  751.            mov bx,ax
  752.            mov ax,dx
  753.            mov dx,xupdate+0
  754.            mov cx,xupdate+2
  755.  
  756.            cmp ax,dx
  757.            jge s r_up_no3
  758.            dec ax
  759.            mov xupdate+0,ax
  760.            mov dx,ax
  761.            inc ax
  762. r_up_no3:
  763.            cmp bx,cx
  764.            jle s r_up_no4
  765.            inc bx
  766.            mov xupdate+2,bx
  767.            mov cx,bx
  768.            dec bx
  769. r_up_no4:
  770.            cmp bx,dx
  771.            jge s r_up_no5
  772.            dec bx
  773.            mov xupdate+0,bx
  774. r_up_no5:
  775.            cmp ax,cx
  776.            jle s r_up_no6
  777.            inc ax
  778.            mov xupdate+2,ax
  779. r_up_no6:
  780.            mov ax,x2              ; ax=x
  781.            sub ax,x1
  782.            mov bx,y2              ; bx=y
  783.            sub bx,y1
  784.  
  785.            elseif not useborders eq yes
  786.  
  787.            sub ax,dx
  788.            sub bx,cx
  789.  
  790.            endif
  791.  
  792.            mov si,whichside       ; set colour for this line
  793.            mov si,order[si]
  794.            mov dx,surfcolors[si]
  795.            mov colq,dl
  796.  
  797.            mov dx,ymaxs
  798.            cmp y1,dx
  799.            jge dv_return
  800.  
  801.            mov rise,bx
  802.            movsx ebx,bx
  803.            cmp ebx,0
  804.            jne s r_nsliver
  805.  
  806.            mov bx, y1
  807.            cmp bx, ymins          ; draw sliver, avoid divide by zero
  808.            jl dv_return
  809.            cmp bx, dx             ; dx = ymax
  810.            jge dv_return
  811.  
  812.            add bx,ycent
  813.            mov si,bx
  814.            shl si,1
  815.            movzx eax,[si+fastimultable] ; get offset to start of line
  816.            mov edi, current_page
  817.            add edi, eax           ; edi = starting y location
  818.  
  819.            mov rise,1
  820.  
  821.            mov dx, x1             ; from here...
  822.            mov si, x2             ;            ..to here
  823.  
  824.            cmp si,xmins
  825.            jge s u_nou3
  826.            mov si,xmins
  827. u_nou3:
  828.            cmp si,xmaxs
  829.            jl s u_noq3
  830.            mov si,xmaxs1
  831. u_noq3:
  832.            jmp r_splint           ; re-enter draw later in code
  833.  
  834.            align 4
  835. r_nsliver:
  836.            shl eax,16
  837.            cdq
  838.            idiv ebx
  839.            mov ebp,eax            ; ebp = slope*65536 (allows decimals)
  840.  
  841.            mov ax,ymins
  842.            cmp y1,ax              ; check if above screen
  843.            jge s r_li_abov1
  844.            sub ax,y1              ; ax = abs(difference of ymin-y1)
  845.            sub rise,ax            ; dec counter
  846.            jle dv_return          ; line totally off screen
  847.  
  848.            movsx eax,ax           ; prepare for 32bit mul
  849.            imul ebp
  850.            shr eax,16             ; get top word
  851.            add x1,ax              ; set new x1,y1 pair
  852.            mov ax,ymins
  853.            mov y1,ax
  854.  
  855. r_li_abov1:
  856.            mov bx,y1              ; bx distance from top of screen
  857.            add bx,ycent
  858.            mov si,bx              ; calculate screen address
  859.            shl si,1
  860.            movzx eax,[si+fastimultable] ; get offset to start of line
  861.            mov edi, current_page
  862.            add edi,eax            ; edi = starting y location
  863.  
  864.            movsx edx,x1
  865.            shl edx,16
  866.            mov cx,rise
  867.            mov ax,y1
  868.            add ax,cx              ; will line go off bottom of screen?
  869.            cmp ax,ymaxs
  870.            jl s r_linep           ; no...
  871.            sub ax,ymaxs           ; yes, truncate cx for early exit
  872.            sub rise,ax
  873.            jle dv_return
  874. r_linep:
  875.            mov eax,edx
  876.            movzx ecx,cx
  877.  
  878.            mov esi,edx
  879.            shr esi,16
  880.  
  881.            cmp si,xmins
  882.            jge s r_nou
  883.            mov si,xmins
  884. r_nou:
  885.            cmp si,xmaxs
  886.            jl s r_noq
  887.            mov si,xmaxs1
  888. r_noq:
  889.            align 4
  890.  
  891. r_lineloop:
  892.            add eax,ebp             ; main line drawing loop!!! (for lines)
  893.            mov edx,eax
  894.            shr edx,16
  895. r_splint:
  896.            cmp dx,xmins
  897.            jge s u_nou
  898.            mov dx,xmins
  899.            cmp dx,si
  900.            je r_mis
  901. u_nou:
  902.            cmp dx,xmaxs
  903.            jl s u_noq
  904.            mov dx,xmaxs1
  905.            cmp dx,si
  906.            je r_mis
  907. u_noq:
  908.            push dx edi ebp eax     ; save for next line
  909.            cmp dx,si
  910.            jle s r_no_switch
  911.            xchg dx,si
  912. r_no_switch:
  913.  
  914.            add dx,xcent
  915.            add si,xcent
  916.  
  917.            mov ax,dx
  918.            mov bx,si
  919.            mov x2,si
  920.  
  921.            shr dx,2                ; dx/4 = bytes into line
  922.            movzx edx,dx
  923.            add edi,edx             ; di = addr of upper-left corner
  924.  
  925.            movzx ecx,bx            ; cx = x2 (pixel position)
  926.            shr cx,2                ; cx/4 = bytes into line
  927.  
  928.            cmp dx,cx               ; start and end in same band?
  929.            je  rf_one_band_only    ; if so, then special processing
  930.  
  931.            sub cx,dx               ; cx = # bands -1
  932.            mov si,ax               ; si = plane#(x1)
  933.            and si,plane_bits       ; if left edge is aligned then
  934.            jz s rf_l_plane_flush   ; no special processing..
  935.  
  936. ; draw "left edge" of 1-3 pixels...
  937.  
  938.            out_8 sc_data, left_clip_mask[si] ; set left edge plane mask
  939.  
  940.            mov al,colq             ; get fill color
  941.            mov [edi], al           ; fill in left edge pixels
  942.  
  943.            inc edi                 ; point to middle (or right) block
  944.            dec cx                  ; reset cx instead of jmp s rf_right
  945.  
  946. rf_l_plane_flush:
  947.            inc cx                  ; add in left band to middle block
  948.  
  949. ; di = addr of 1st middle pixel (band) to fill
  950. ; cx = # of bands to fill -1
  951.  
  952. rf_right:
  953.            mov si,bx               ; get xpos2
  954.            and si,plane_bits       ; get plane values
  955.            cmp si,0003             ; plane = 3?
  956.            je s rf_r_edge_flush    ; hey, add to middle
  957.  
  958. ; draw "right edge" of 1-3 pixels...
  959.  
  960.            out_8 sc_data, right_clip_mask[si]  ; right edge plane mask
  961.  
  962.            mov esi,edi             ; get addr of left edge
  963.            add esi,ecx             ; add width-1 (bands)
  964.            dec esi                 ; to point to top of right edge
  965.  
  966.            mov al,colq             ; get fill color
  967.  
  968. rf_right_loop:
  969.            mov [esi], al           ; fill in right edge pixels
  970.  
  971.            dec cx                  ; minus 1 for middle bands
  972.            jz s rf_exit            ; uh.. no middle bands...
  973.  
  974. rf_r_edge_flush:
  975.  
  976. ; di = addr of upper left block to fill
  977. ; cx = # of bands to fill in (width)
  978.  
  979.            out_8 sc_data, all_planes ; write to all planes
  980.  
  981.            mov dx, xactual/4       ; dx = di increment
  982.            sub dx, cx              ;  = screen_width-# planes filled
  983.  
  984.            mov al, colq            ; get fill color
  985.            mov ah, al              ; colour is in high and low for stosw
  986.            push ax                 ; make colour 32 bit
  987.            shl eax,16
  988.            pop ax
  989.  
  990. rf_middle_loop:
  991.            shr cx,1                ; use doubleword transfer
  992.            jnc s rf_ord
  993.            stosb                   ; if cx odd, store byte first
  994.            jcxz s rf_exit          ; no words after stosb
  995. rf_ord:
  996.            shr cx,1
  997.            jnc rf_dord
  998.            stosw
  999.            jcxz s rf_exit          ; no doublewords after stosw
  1000. rf_dord:
  1001.            rep stosd               ; fill in entire line
  1002.  
  1003.            jmp s rf_exit           ; outa here, for this line
  1004.  
  1005. rf_one_band_only:
  1006.            mov si,ax                  ; get left clip mask, save x1
  1007.            and si,plane_bits          ; mask out row #
  1008.            mov al,left_clip_mask[si]  ; get left edge mask
  1009.            mov si,bx                  ; get right clip mask, save x2
  1010.            and si,plane_bits          ; mask out row #
  1011.            and al,right_clip_mask[si] ; get right edge mask byte
  1012.  
  1013.            out_8 sc_data, al       ; clip for left & right masks
  1014.  
  1015.            mov al, colq            ; get fill color
  1016.            mov [edi], al           ; fill in pixels
  1017. rf_exit:
  1018.            pop eax ebp edi si      ; pop screen left address
  1019. r_mis:
  1020.            add edi, xactual/4
  1021.            dec rise
  1022.            jg r_lineloop
  1023.  
  1024.            jmp dv_return           ; re-enter draw_vect
  1025.  
  1026. ; bubble sort for sides
  1027.  
  1028. ; sort is not perfect since many sides can use the same point.
  1029. ; if this point is the first point in the list and therefore zeds[] uses
  1030. ; the same point for sort, the routine may mess up when plotting at some
  1031. ; acute angles.  if you ever notice this, you are way too picky.
  1032.  
  1033.            align 4
  1034.  
  1035. minusd equ offset zeds - offset order
  1036.  
  1037. sort_list:
  1038.            movzx esi,showing
  1039.            cmp si,1               ; if only one surface, exit
  1040.            jle qke
  1041.  
  1042.            shl si,1               ; si = word
  1043.            add esi,o order
  1044.  
  1045.            align 4
  1046. nextcx:
  1047.            sub esi,2              ; point to last word in order[] table
  1048.  
  1049.            mov ebp,esi            ; set order pointer
  1050.            mov bx,w [esi]         ; get order[si]
  1051.  
  1052.            mov edi,esi
  1053.            add edi,minusd
  1054.            mov cx,w [edi]         ; get zeds[si]
  1055.  
  1056.            align 4
  1057. nextdx:
  1058.            sub edi,2
  1059.            sub ebp,2
  1060.  
  1061.            cmp cx,w [edi]         ; zeds is point from side, should be max z
  1062.            jle s donothing
  1063.            xchg cx,w [edi]        ; don't flip entire side, just indexers to it
  1064.            xchg bx,w [ebp]
  1065. donothing:
  1066.            cmp ebp,o order        ; check bp = 0
  1067.            jne s nextdx
  1068.  
  1069.            mov [esi + minusd],cx
  1070.            mov [esi],bx
  1071.  
  1072.            cmp esi,o order + 2
  1073.            jne s nextcx
  1074. qke:
  1075.            ret
  1076.  
  1077.            align 4
  1078.  
  1079. set_makeorder:
  1080.  
  1081.            i=0
  1082.            rept maxobjects        ; macro to produce unrolled loop
  1083.            mov makeorder+i*2,i    ; set makeorder to 0,1,2,3,4
  1084.            i=i+1
  1085.            endm
  1086.  
  1087.            ret
  1088.  
  1089.            align 4
  1090.  
  1091. makeobjs:                         ; make all objects, unrolled loop
  1092.            i=0
  1093.  
  1094.            rept maxobjects
  1095.            local itsoff
  1096.  
  1097.            mov ax,32767           ; in case of abort
  1098.            movzx esi,makeorder+i*2
  1099.            test onoff[si],255     ; check on/off
  1100.            jz s itsoff
  1101.  
  1102.            call make1obj
  1103.            mov ax,zedthis         ; get z and save for re_sort
  1104. itsoff:
  1105.            mov finalzed+i*2,ax
  1106.  
  1107.            i=i+1
  1108.            endm
  1109.  
  1110. ;           jmp re_sort            ; sort based on last z
  1111.  
  1112. ; bubble sort for entire objects, fastest when already sorted (assumed)
  1113.  
  1114. ;           align 4
  1115.  
  1116. re_sort:
  1117.            mov ecx,maxobjects-1
  1118.            mov dx,-2
  1119.            xor bx,bx              ; sort flag
  1120. nextccx:
  1121.            add dx,2
  1122.            mov si,maxobjects*2-2
  1123. nextddx:
  1124.            sub si,2
  1125.  
  1126.            mov ax,finalzed[si+2]
  1127.            cmp ax,finalzed[si]
  1128.            jle s donotng
  1129.            xchg ax,finalzed[si]   ; don't flip entire object, just indexers
  1130.            xchg ax,finalzed[si+2]
  1131.            mov ax,makeorder[si+2]
  1132.            xchg ax,makeorder[si]
  1133.            xchg ax,makeorder[si+2]
  1134.            inc bx                 ; flag that one sorted
  1135. donotng:
  1136.            cmp si,dx
  1137.            jnle s nextddx
  1138.  
  1139.            cmp bx,0               ; re-sort until no more sorts
  1140.            loopne s nextccx
  1141. quickex:
  1142.            ret
  1143.  
  1144.            align 4
  1145.  
  1146. look_at_it:                       ; force camera to look at object wherelook
  1147.  
  1148.            mov si,wherelook
  1149.            cmp si,no
  1150.            je s noat              ; get out, no object to look at (-1=flag)
  1151.  
  1152.            mov di,maxobjects
  1153.            call calc_angles
  1154.            mov eyeay,bx
  1155.            mov eyeax,ax
  1156. noat:
  1157.            ret
  1158.  
  1159. ; calculate angles between objects si and di.  angles are from point of view
  1160. ; of di.
  1161.  
  1162. calc_angles:
  1163.            shl si,2               ; si = dword
  1164.            shl di,2
  1165.            call get_displacement
  1166. calc_middle:
  1167.            shr ebx,8              ; account for decimal places
  1168.            test ebx,00800000h
  1169.            jz s pm_7
  1170.            or ebx, 0ff000000h
  1171. pm_7:
  1172.            shr ecx,8
  1173.            test ecx,00800000h
  1174.            jz s pm_8
  1175.            or ecx, 0ff000000h
  1176. pm_8:
  1177.            shr ebp,8
  1178.            test ebp,00800000h
  1179.            jz s pm_9
  1180.            or ebp, 0ff000000h
  1181. pm_9:
  1182.            cmp ebx,-maxz          ; check if within visible space
  1183.            jl  noaq               ; object miles away, don't bother
  1184.            cmp ebx,maxz           ; could divide by some high number
  1185.            jg  noaq               ; and try again.  shr not good because
  1186.                                   ; ecx,ebx,ebp must be sign extended
  1187.            cmp ebp,-maxz
  1188.            jl  noaq
  1189.            cmp ebp,maxz
  1190.            jg  noaq
  1191.  
  1192.            cmp ecx,-maxz
  1193.            jl  noaq
  1194.            cmp ecx,maxz
  1195.            jg  noaq
  1196.  
  1197.            push ecx ebx ebp
  1198.  
  1199.            mov ecx,ebx            ; first get z,x plane, (y angle)
  1200.            mov eax,ebp
  1201.  
  1202.            cmp eax,16384          ; if object miles away, shr and re-check
  1203.            jle s lk_oktab1
  1204.            shr eax,3
  1205.            shr ecx,3
  1206.            jmp s lk_oktab4        ; re-check to test if in space
  1207.            align 4
  1208. lk_oktab1:
  1209.            cmp ecx,16384          ; if object miles away, shr and re-check
  1210.            jle s lk_oktab2
  1211.            shr eax,3
  1212.            shr ecx,3
  1213.            jmp s lk_oktab4        ; re-check to test if in space
  1214.            align 4
  1215. lk_oktab2:
  1216.            cmp eax,-16384         ; if object miles away, shr and re-check
  1217.            jge s lk_oktab3
  1218.            shr eax,3
  1219.            shr ecx,3
  1220.            jmp s lk_oktab4        ; re-check to test if in space
  1221.            align 4
  1222. lk_oktab3:
  1223.            cmp ecx,-16384         ; if object miles away, shr and re-check
  1224.            jge s lk_oktab4
  1225.            shr eax,3
  1226.            shr ecx,3
  1227.            jmp s lk_oktab4        ; re-check to test if in space
  1228.            align 4
  1229. lk_oktab4:
  1230.            cmp eax,0
  1231.            je lk_right_above      ; check arctan(cx/0)
  1232.  
  1233.            call arctan
  1234. lk_resume:
  1235.            mov dsq,ax           ; save y angle
  1236.            call cosign            ; set up 32bit sin/cos multipliers
  1237.            mov vycos,eax
  1238.            mov ax,dsq
  1239.            call sign
  1240.  
  1241.            pop ebp ebx            ; now compute sqr(z^2+x^2) through y rotation
  1242.  
  1243.            imul ebx               ; use angle from calculation above
  1244.            shrd eax,edx,14
  1245.            mov edi,eax
  1246.            mov eax,vycos
  1247.            imul ebp
  1248.            shrd eax,edx,14
  1249.            add eax,edi            ; di = new z = run
  1250.  
  1251.            pop ecx                ; cx = rise
  1252.  
  1253.            cmp eax,16384          ; if object miles away, shr and re-check
  1254.            jle s lk_oktap1
  1255.            shr eax,3
  1256.            shr ecx,3
  1257.            jmp s lk_oktap4        ; re-check to test if in space
  1258.            align 4
  1259. lk_oktap1:
  1260.            cmp ecx,16384          ; if object miles away, shr and re-check
  1261.            jle s lk_oktap2
  1262.            shr eax,3
  1263.            shr ecx,3
  1264.            jmp s lk_oktap4        ; re-check to test if in space
  1265.            align 4
  1266. lk_oktap2:
  1267.            cmp eax,-16384         ; if object miles away, shr and re-check
  1268.            jge s lk_oktap3
  1269.            shr eax,3
  1270.            shr ecx,3
  1271.            jmp s lk_oktap4        ; re-check to test if in space
  1272.            align 4
  1273. lk_oktap3:
  1274.            cmp ecx,-16384         ; if object miles away, shr and re-check
  1275.            jge s lk_oktap4
  1276.            shr eax,3
  1277.            shr ecx,3
  1278.            jmp s lk_oktap4        ; re-check to test if in space
  1279.            align 4
  1280. lk_oktap4:
  1281.            cmp eax,0
  1282.            je s noaq
  1283.  
  1284.            call arctan            ; get ax=arctan(y/sqr(z^2+x^2))
  1285.  
  1286.            mov bx,dsq             ; bx = y angle , ax = x angle
  1287. noaq:
  1288.            ret
  1289.  
  1290.            align 4
  1291.  
  1292. lk_right_above:
  1293.            mov ax,vys[si]         ; camera directly above object, use old y
  1294.            jmp lk_resume
  1295.  
  1296.            align 4
  1297.  
  1298. get_displacement:
  1299.            mov ebx,xs[si]         ; get displacement of si to di
  1300.            sub ebx,xs[di]
  1301.            mov ecx,ys[si]
  1302.            sub ecx,ys[di]
  1303.            mov ebp,zs[si]
  1304.            sub ebp,zs[di]
  1305.            ret
  1306.  
  1307.            align 4
  1308.  
  1309. ; new follow, si = object for new follow, di = time to get there.
  1310.  
  1311. newfollow:
  1312.            mov wfollow,si         ; save in case object is accelerating
  1313.            mov oldspeed,di
  1314.            mov wherelook,no       ; disable look_at_si routine
  1315.  
  1316.            shl si,1
  1317.            mov ax,lcount[si]
  1318.            cmp ax,di              ; if di>lcount, shorten to lcount
  1319.            ja s nx
  1320.            mov di,ax
  1321. nx:
  1322.            movzx edi,di
  1323.  
  1324.            shl si,1               ; si = dword
  1325.  
  1326.            mov eax,xadds[si]      ; figure out where object will be di*frames
  1327.            imul edi
  1328.            add eax,xs[si]
  1329.            mov ebx,eax
  1330.  
  1331.            mov eax,yadds[si]
  1332.            imul edi
  1333.            add eax,ys[si]
  1334.            mov ecx,eax
  1335.  
  1336.            mov eax,zadds[si]
  1337.            imul edi
  1338.            add eax,zs[si]
  1339.            mov ebp,eax
  1340.  
  1341.            mov di,oldspeed
  1342.            mov ax,eyelcount
  1343.            cmp ax,di              ; if di>lcount, shorten to lcount
  1344.            ja s tx
  1345.            mov di,ax
  1346. tx:
  1347.            movzx edi,di
  1348.  
  1349.            mov eax,eyexadds
  1350.            imul edi               ; figure out where camera will be di*frames
  1351.            add eax,eyex
  1352.            sub ebx,eax            ; get displacement to eye
  1353.  
  1354.            mov eax,eyeyadds
  1355.            imul edi
  1356.            add eax,eyey
  1357.            sub ecx,eax
  1358.  
  1359.            mov eax,eyezadds
  1360.            imul edi
  1361.            add eax,eyez
  1362.            sub ebp,eax
  1363.  
  1364.            call calc_middle       ; jump in middle of angle computation
  1365.  
  1366.            mov di,bx
  1367.  
  1368.            sub ax,eyeax           ; get difference from where we are now
  1369.            sub di,eyeay
  1370.  
  1371.            add ax,followtol       ; check if already looking at it
  1372.            cmp ax,followtol*2
  1373.            ja s calcit
  1374.  
  1375.            add di,followtol
  1376.            cmp di,followtol*2
  1377.            jb just_look_at_it_now_instead_of_calculating
  1378.            sub di,followtol
  1379. calcit:
  1380.            sub ax,followtol
  1381.  
  1382.            mov si,oldspeed        ; ax=x angle, di=y angle, si=# frames
  1383.            cwd
  1384.            push dx                ; save sign extend
  1385.            idiv si                ; x/time
  1386.            pop dx
  1387.            cmp ax,0
  1388.            jne s n0
  1389.            shl dx,1
  1390.            mov ax,dx
  1391.            inc ax                 ; ax = 1 or ax = -1
  1392. n0:
  1393.            mov eyevxadds,ax
  1394.  
  1395.            mov ax,di
  1396.            cwd
  1397.            push dx
  1398.            idiv si                ; y/time
  1399.            pop dx
  1400.            cmp ax,0               ; check if zero slope, must have some...
  1401.            jne s n1
  1402.            shl dx,1               ; dx = fffe (-2) or 0
  1403.            mov ax,dx
  1404.            inc ax                 ; ax = 1 or ax = -1
  1405. n1:
  1406.            mov eyevyadds,ax
  1407.  
  1408.            mov eyeacount,si
  1409.            shr oldspeed,1         ; if need to try again, time/2
  1410. noau:
  1411.            ret
  1412.  
  1413. just_look_at_it_now_instead_of_calculating:
  1414.            mov ax,wfollow
  1415.            mov wherelook,ax       ; already looking at object, now follow it
  1416.            mov wfollow,no
  1417.            ret
  1418.  
  1419. ; move object si from wherever it is now to ebx,ecx,ebp in di frames
  1420. ; move is 32 bit, make sure high words of registers are set!
  1421. ; time to get there is 16 bit. (if you need more, think! 65535 frames at
  1422. ; 1/30 frames a sec is 36 minutes!)
  1423.  
  1424. move_si:
  1425.            shl si,2               ; si = dword
  1426.            sub ebx,xs[si]
  1427.            sub ecx,ys[si]
  1428.            sub ebp,zs[si]
  1429.  
  1430.            movzx edi,di
  1431.  
  1432.            mov eax,ebx            ; 32 bit moves
  1433.  
  1434.            cdq
  1435.            idiv edi
  1436.            mov xadds[si],eax
  1437.  
  1438.            mov eax,ecx
  1439.            cdq
  1440.            idiv edi
  1441.            mov yadds[si],eax
  1442.  
  1443.            mov eax,ebp
  1444.            cdq
  1445.            idiv edi
  1446.            mov zadds[si],eax
  1447.  
  1448.            shr si,1               ; si = word
  1449.  
  1450.            mov lcount[si],di
  1451.            shr si,1               ; restore original si
  1452.  
  1453.            ret
  1454.  
  1455. put_object:
  1456.            shl si,2
  1457.            mov xs[si],ebx
  1458.            mov ys[si],ecx
  1459.            mov zs[si],ebp
  1460.            shr si,2
  1461.            ret
  1462.  
  1463. set_angle:
  1464.            shl si,1
  1465.            mov vxs[si],bx
  1466.            mov vys[si],cx
  1467.            mov vzs[si],bp
  1468.            shr si,1
  1469.            ret
  1470. set_shape:
  1471.            shl si,1
  1472.            mov whatshape[si],ax
  1473.            shr si,1
  1474.            ret
  1475.  
  1476. set_object_on:
  1477.            mov onoff[si],1
  1478.            ret
  1479.  
  1480. set_object_off:
  1481.            mov onoff[si],0
  1482.            ret
  1483.  
  1484. code32     ends
  1485.            end
  1486.  
  1487.