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

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