home *** CD-ROM | disk | FTP | other *** search
/ The Party 1994: Try This At Home / disk_image.bin / source / 3drotate / 3drotate.asm next >
Assembly Source File  |  1993-02-25  |  23KB  |  742 lines

  1. ─────────────────────────────────────────────────────────────────────────────
  2. ;
  3. ;     TITLE: 3d rotate
  4. ;WRITTEN BY: DRAEDEN /VLA CODER /iCE VGA CODER
  5. ;       FOR: Phantasm, (206) 232-5912
  6. ;               The first programing oriented board to hit the 206 area.
  7. ;               Any questions regarding this or ANY code in ANY programming
  8. ;               language can, and will be answered on Phantasm.
  9. ;               Send messages to 'Draeden' or post in the VLA programming
  10. ;               section.
  11. ;
  12. ;            The Deep (TDT/VLA), (305) ???-????
  13. ;               Our first distribution site.  Messages will also be answered
  14. ;               if posted at this location.
  15. ;               Send messages to 'The Kabal'.
  16. ;
  17. ;      DATE: 02/25/93
  18. ;
  19. ;     NOTES: Compiled with TASM 2.51, TLINK 4.0
  20. ;            Must have a 386 or better to run, Moderate speed.
  21. ;            This program was chosen as an example because it utilizes
  22. ;            a lot of the neat little tricks you can do in assembly,
  23. ;            mainly Structures (STRUC), Unions (UNION), INCLUDEs,
  24. ;            the REPT macro, and the DUP() macro.  It also introduces
  25. ;            palette rotates in a less-than-boring application.
  26. ;
  27. ;ASSOCIATED FILES:
  28. ;
  29. ;       BWPRINT.ASM =>  Displays signed and unsigned bytes, words, or
  30. ;                    >  double words
  31. ;
  32. ;       SINCOS.DW   =>  Contains data for the sine and cosine operations
  33. ;
  34. ;       3DROTATE.TXT=>  A text file that further explains palette rotates
  35. ;                    >  and the basic 3d stuff.
  36. ;
  37. ;       MAKE.BAT    =>  The file that'll put it all together into an .EXE
  38. ;
  39. ─────────────────────────────────────────────────────────────────────────────
  40.     
  41.     DOSSEG          ;tells compiler to sort segments according to the
  42.                     ;DOS standards- code, data, stack
  43.     .MODEL SMALL
  44.     .STACK 200h     ;sets up a 512 byte stack
  45.     .DATA           ;starts the data segment (empty)
  46.     .CODE           ;starts the code segment
  47.     .386            ;tells compiler to allow 386 instructions
  48.     ASSUME CS:@CODE, DS:@CODE
  49.                     ;tells compiler to assume offsets are taken from
  50.                     ;the code segment
  51.     LOCALS          ;turns local labels on eg. @@local:
  52.  
  53. ─────────────────────────────────────────────────────────────────────────────
  54.  
  55. ;=== GLOBALS  -used to link multiple programs together
  56.  
  57. GLOBAL  PrintByte:PROC, PrintWord:PROC, PrintBig:PROC
  58.     ;above is for the file BWPRINT.ASM
  59.  
  60. ─────────────────────────────────────────────────────────────────────────────
  61.  
  62. ;=== Data Includes -include physically puts the file in this one on compile
  63.                     
  64. INCLUDE sincos.dw       ;Labels SINE: and COSINE: contains sine(0-255)*256
  65.  
  66. ─────────────────────────────────────────────────────────────────────────────
  67.  
  68. ;=== DATA Structures
  69.     
  70.     Angle_Union     UNION
  71.         B       db  0
  72.         W       dw  0
  73.     Angle_Union     ENDS    ;creates a new data type (eg. DW, DB, DD) called
  74.                             ;Angle_Union. Used just like in C
  75.     Point_Struc     STRUC
  76.         X       dw  ?
  77.         Y       dw  ?
  78.         Z       dw  ?
  79.                 dw  0       ;a blank area to buffer it out to 8 bytes
  80.                             ; this is done so that access to each point
  81.                             ; is rapid; I can use a SHL XX,3 instead of
  82.                             ; a imul XX,6  saving a few cycles...
  83.     Point_Struc     ENDS    ;Create a structure (or a record)
  84.  
  85. ─────────────────────────────────────────────────────────────────────────────
  86.  
  87. ;=== DATA
  88.  
  89. INCXV       EQU   3b00h   ;scan code/ascii code for f1
  90. DECXV       EQU   3c00h   ;f2
  91. INCYV       EQU   3d00h   ;f3
  92. DECYV       EQU   3e00h   ;f4
  93. INCZV       EQU   3f00h   ;f5
  94. DECZV       EQU   4000h   ;f6
  95. INCDV       EQU   4100h   ;f7
  96. DecDV       EQU   4200h   ;f8
  97. StopRot     EQU   3920h   ;space bar
  98. ZeroAN      EQU   1c0dh   ;enter key
  99.  
  100. IncPV1      EQU   0231h   ;"1"
  101. DecPV1      EQU   0332h   ;"2"
  102. IncPV2      EQU   0433h   ;"3"
  103. DecPV2      EQU   0534h   ;"4"
  104.  
  105. MaxLag      EQU   15      ;for now, leave at 15
  106.  
  107. MinDist     EQU   200
  108. MaxDist     EQU   10000
  109. Distance    dw    300
  110. DistanceVel dw    0
  111.  
  112. STPS        EQU   10      ;size of each step
  113. NST         EQU   100/STPS
  114. NumPts      EQU   NST*NST*NST/2   ;the number of points the program 
  115.                                   ; will rotate and display
  116.  
  117.   ;uses nested rept macros to build a solid cube
  118. XYZcord  LABEL Point_Struc
  119.     i=-25
  120.     REPT NST/2
  121.       j=-50
  122.       REPT NST
  123.         k=-50
  124.         REPT NST
  125.           Point_Struc <i, j, k>
  126.           k=k+STPS
  127.         ENDM
  128.         j=j+STPS
  129.       ENDM
  130.       i=i+STPS
  131.     ENDM
  132.  
  133. RotCord     Point_Struc NumPts DUP(<>)    ;holds rotated cordinates
  134.  
  135. HeadDi      dw    0
  136. OldDi       dw    NumPts*MaxLag DUP (0)   ;holds old di for quick erasing
  137.                                           ;for MaxLag stored frames
  138. OffToCurDi  dw    offset OldDi            ;points to the correct frame
  139.                                           ;to erase and fill
  140. Zan         Angle_Union <?,?>
  141. Yan         Angle_Union <?,?>   ; the '?' defaults to zero, but you can't
  142. Xan         Angle_Union <?,?>   ;specify in a Union
  143. PathAn1     Angle_Union <?,?>
  144. PathAn2     Angle_Union <?,?>
  145.                                 
  146. ZanVel      db    1             ;angle velocities
  147. YanVel      db    3
  148. XanVel      db   -2
  149. P1Vel       db    1
  150. P2Vel       db    3
  151.  
  152. PreAddX     dw    0             ;amount to ADD to each X, Y & Z >BEFORE<
  153. PreAddY     dw    0             ;the distance transforms
  154. PreAddZ     dw    0             ;causes the change to be scaled
  155.  
  156. PostAddX    dw  160             ;amount to ADD to each X & Y >AFTER<
  157. PostAddY    dw  100             ;the distance transforms
  158.  
  159. Palette     db  3 dup (0)
  160.             db  14 dup (60,40,30)    
  161.  
  162.             db  63,0,0
  163.             db  2,0,0
  164.             db  7,0,0
  165.             db  9,0,0
  166.             db 12,0,0
  167.             db 15,0,0
  168.             db 17,0,0
  169.             db 20,0,0
  170.             db 22,0,0
  171.             db 25,0,0
  172.             db 30,0,0
  173.             db 35,0,0
  174.             db 40,0,0
  175.             db 45,0,0
  176.             db 50,0,0
  177.             db 63,0,0
  178.  
  179. PalTmp      db  32*3 DUP(0)
  180.  
  181. Color       db  15
  182.  
  183. AngleMsg    db  "Ang: $"
  184. AngleVelMsg db  "Vel: $"
  185. Control     db  "Control the angular velocity by hitting F1-F6 and 1 & 2",13,10
  186.             db  "The distance is controlled by F7 & F8.  Hit a key to start.$"
  187. Credits     db  13,10,"Coded by Draeden of VLA",13,10,"$"
  188.  
  189. ─────────────────────────────────────────────────────────────────────────────
  190. ;=== Code Includes  ;none.
  191. ─────────────────────────────────────────────────────────────────────────────
  192.  
  193. ;=== SUBROUTINES
  194.     
  195.     ;DESTROYS: ax,dx,si,di,es,ds
  196.     ;Input: BX= X CX= Y BP= Z
  197.     ;OutPut:BX= X CX= Y BP= Z
  198. RotateXYZ proc near
  199.     mov     ax,cs
  200.     mov     ds,ax                       ; X-rotation
  201.                                         ; Y := cos(Xan) * y - sin(Xan) * z
  202.                                         ; Z := sin(Xan) * y + cos(Xan) * z
  203.     mov     si,[Xan.W]
  204.     add     si,si                       ; si = angle x
  205.     mov     ax,[Cosine+si]              ; ax = cos(angle x)
  206.     imul    cx                          ; ax = cos(angle x) * y
  207.     mov     di,dx
  208.     shl     edi,16
  209.     mov     di,ax                       ; store for later use
  210.     mov     ax,[Sine+si]                ; ax = sin(angle x)
  211.     imul    bp                          ; ax = sin(angle x) * z
  212.     shl     edx,16
  213.     mov     dx,ax
  214.     sub     edi,edx                     ; di = di-ax = cos(vx)*y - sin(vz)*z
  215.     sar     edi,8                       ; remove the (co)sin "256-factor"
  216.     mov     es,di                       ; es = x-coordinate
  217.  
  218.     mov     ax,[sine+si]                ; ax = sin(angle x)
  219.     imul    cx                          ; ax = sin(angle x) * y
  220.     mov     di,dx
  221.     shl     edi,16
  222.     mov     di,ax
  223.     mov     ax,[cosine+si]              ; ax = cos(angle x)
  224.     imul    bp                          ; ax = cos(angle x) * z
  225.     shl     edx,16
  226.     mov     dx,ax
  227.     add     edi,edx                     ; di = di-ax = sin(vx)*y + cos(vx)*z
  228.     sar     edi,8                       ; remove the (co)sin "256-factor"
  229.  
  230.     mov     cx,es                       ; update y
  231.     mov     bp,di                       ; update z
  232.  
  233.                                         ; Y-rotation
  234.                                         ; X :=  cos(vy) * xc + sin(vy) * zc
  235.                                         ; Z := -sin(vy) * xc + cos(vy) * zc
  236.     mov     si,[Yan.W]
  237.     add     si,si                       ; si = angle y
  238.     mov     ax,[Cosine+si]              ; ax = cos(angle y)
  239.     imul    bx                          ; ax = cos(angle y) * x
  240.     mov     di,dx
  241.     shl     edi,16
  242.     mov     di,ax                       ; store for later use
  243.     mov     ax,[Sine+si]                ; ax = sin(angle y)
  244.     imul    bp                          ; ax = sin(angle y) * z
  245.     shl     edx,16
  246.     mov     dx,ax
  247.     add     edi,edx                     ; di = di+ax = cos(vy)*x + sin(vy)*z
  248.     sar     edi,8                       ; remove the (co)sin "256-factor"
  249.     mov     es,di                       ; es = x-coordinate
  250.  
  251.     mov     ax,[Sine+si]                ; ax = sin(angle y)
  252.     neg     ax                          ; ax =-sin(angle y)
  253.     imul    bx                          ; ax =-sin(angle y) * x
  254.     mov     di,dx
  255.     shl     edi,16
  256.     mov     di,ax
  257.     mov     ax,[Cosine+si]              ; ax = cos(angle y)
  258.     imul    bp                          ; ax = cos(angle y) * z
  259.     shl     edx,16
  260.     mov     dx,ax
  261.     add     edi,edx                     ; di = di-ax = sin(vy)*x - cos(vy)*z
  262.     sar     edi,8                       ; remove the (co)sin "256-factor"
  263.  
  264.     mov     bx,es                       ; update x
  265.     mov     bp,di                       ; update z
  266.  
  267.                                         ; Z-rotation
  268.                                         ; X := cos(vz) * xc - sin(vz) * yc
  269.                                         ; Y := sin(vz) * xc + cos(vz) * yc
  270.     mov     si,[Zan.W]
  271.     add     si,si                       ; si = angle z
  272.     mov     ax,[Cosine+si]              ; ax = cos(angle z)
  273.     imul    bx                          ; ax = cos(angle z) * x
  274.     mov     di,dx
  275.     shl     edi,16
  276.     mov     di,ax
  277.     mov     ax,[Sine+si]                ; ax = sin(angle z)
  278.     imul    cx                          ; ax = sin(angle z) * y
  279.     shl     edx,16
  280.     mov     dx,ax
  281.     sub     edi,edx                     ; di = di-ax = cos(vz)*x - sin(vz)*y
  282.     sar     edi,8                       ; remove the (co)sin "256-factor"
  283.     mov     es,di                       ; es = x-coordinate
  284.  
  285.     mov     ax,[Sine+si]                ; ax = sin(angle z)
  286.     imul    bx                          ; ax = sin(angle z) * x
  287.     mov     di,dx
  288.     shl     edi,16
  289.     mov     di,ax
  290.     mov     ax,[Cosine+si]              ; ax = cos(angle z)
  291.     imul    cx                          ; ax = cos(angle z) * y
  292.     shl     edx,16
  293.     mov     dx,ax
  294.     add     edi,edx                     ; di = di+ax = sin(vz)*x+cos(vz)*y
  295.     sar     edi,8                       ; remove the (co)sin "256-factor"
  296.  
  297.     mov     bx,es                       ; update x
  298.     mov     cx,di                       ; update y
  299.     
  300.     ret
  301. RotateXYZ   ENDP
  302.  
  303.     ;rotates all points and saves them
  304. RotateBox   PROC NEAR
  305.     pushad          ;saves EVERYTHING (extended registers, too), except flags
  306.     mov     ax,cs
  307.     mov     ds,ax
  308.     mov     es,ax
  309.  
  310.     mov     di,0    ;point counter
  311. @@DoNextPoint:
  312.     ;Input: BX= X CX= Y BP= Z
  313.     ;OutPut:BX= X CX= Y BP= Z
  314.  
  315.     mov     bx,[XYZcord.X +di]   ;load in cordinates to rotate
  316.     mov     cx,[XYZcord.Y +di]
  317.     mov     bp,[XYZcord.Z +di]
  318.  
  319.     push    di
  320.     call    RotateXYZ
  321.     pop     di
  322.  
  323.     mov     [RotCord.X +di],bx  ;save rotated cordinates IN A DIFFERENT PLACE
  324.     mov     [RotCord.Y +di],cx
  325.     add     bp,[Distance]
  326.     mov     [RotCord.Z +di],bp
  327.  
  328.     add     di,8            ;size of each entry
  329.     cmp     di,NumPts*8     ;are we done, yet?
  330.     jb      @@DoNextPoint   ;No. Do another
  331.     
  332.     popad
  333.     ret
  334. RotateBox   ENDP
  335.  
  336.     ;draws the dots to the screen
  337. DrawBox     PROC NEAR
  338.     pusha               ;saves only non extended registers
  339.     mov     ax,0a000h   ;segment to VGA memory
  340.     mov     es,ax
  341.     mov     ax,cs
  342.     mov     ds,ax
  343.     
  344.     mov     bp,0        ;point counter
  345.     mov     al,[Color]
  346.     mov     bx,[OffToCurDi]
  347. @@DoNextPoint:
  348.     mov     si,bp
  349.     add     si,si
  350.     shl     si,2        ;si= bp*8
  351.     
  352.     mov     ax,[HeadDi]
  353.     add     al,16
  354.  
  355.     mov     di,cs:[bx]
  356.     cmp     BYTE PTR es:[di],al ;makes sure that we only erase the dots we
  357.                                 ;are sposed to.. works OK, BUT because we
  358.                                 ;erase and draw to the same frame, a dot 
  359.                                 ;that we just drew in this loop could be 
  360.                                 ;erase, causing black spots in the object
  361.                                 ;zoom it out too see what I'm saying
  362.     jne     NotMineDontErase
  363.     mov     BYTE PTR es:[di],0  ;clear out old point
  364.  
  365. NotMineDontErase:
  366.  
  367.     ;pixel location = ScreenWidth*Ypos + Xpos = 320 * (Y+AddY) + X + AddX
  368.     mov     cx,[RotCord.Z +si]
  369.     add     cx,[PreAddZ]
  370.     
  371.     mov     ax,[RotCord.Y +si]
  372.     add     ax,[PreAddY]
  373.     movsx   dx,ah
  374.     shl     ax,8
  375.     idiv    cx              ;you are witnessing the evils of depth emulation-
  376.     add     ax,[PostAddY]   ; the divide that you just can't get rid of
  377.     mov     di,ax
  378.     cmp     di,200
  379.     jae     DontDraw
  380.     imul    di,320
  381.  
  382.     mov     ax,[RotCord.X +si]
  383.     add     ax,[PreAddX]
  384.     movsx   dx,ah
  385.     shl     ax,8
  386.     idiv    cx              ;Aaarrrgghh! Another one!
  387.     add     ax,[PostAddX]
  388.     cmp     ax,320
  389.     jae     DontDraw
  390.     add     di,ax
  391.     mov     [bx],di
  392.  
  393.     mov     ax,[HeadDi]
  394.     add     al,16
  395.     stosb
  396. RESUMEDRAW:
  397.     add     bx,2
  398.     inc     bp
  399.     cmp     bp,NumPts       ;are we done, yet?
  400.     jb      @@DoNextPoint  ;No. Do another
  401.  
  402.     ;adjust head pointer
  403.     call    ChangePalette
  404.  
  405.     inc     [HeadDi]
  406.     cmp     [HeadDi],MaxLag
  407.     jb      NotAtEnd
  408.     mov     [HeadDi],0
  409. NotAtEnd:
  410.     mov     bx,[Headdi]
  411.     add     bx,bx
  412.     imul    bx,NumPts
  413.     add     bx,offset OldDi
  414.     mov     [OffToCurDi],bx
  415.  
  416.     popa
  417.     ret
  418. DontDraw:
  419.     mov     byte ptr [bx],0
  420.     jmp     short RESUMEDRAW
  421. DrawBox     ENDP
  422.  
  423. ChangePalette   PROC NEAR
  424.     pusha
  425.     mov     ax,cs
  426.     mov     ds,ax
  427.     mov     es,ax
  428.  
  429.     mov     si,offset Palette+3*15
  430.     mov     di,offset PalTmp
  431.     mov     bp,[HeadDi]
  432.  
  433.     mov     cx,bp     ;this bit of code is a quick way to
  434.     add     bp,bp     ;
  435.     add     bp,cx     ;multiply bp by 3
  436.     
  437.     add     di,bp     ;sets up for copy #1
  438.     mov     cx,16*3
  439.     sub     cx,bp
  440.     rep     movsb     ;copies block #1
  441.  
  442.     or      bp,bp
  443.     je      NoBlock2
  444.  
  445.     mov     di,offset PalTmp
  446.     mov     cx,bp
  447.     rep     movsb
  448.  
  449. NoBlock2:
  450.     mov     al,16             ;we start the write at color #16
  451.     mov     dx,03c8h
  452.     out     dx,al
  453.     inc     dx
  454.     mov     si,offset PalTmp
  455.     mov     cx,16*3           ;write 16 colors (3 bytes per color)
  456.     rep     outsb
  457.  
  458.     popa
  459.     ret
  460. ChangePalette   ENDP
  461.  
  462.     ;DESTROYS: flags and AX
  463.     ;updates all the distances, angles, ect...
  464. AddAngles PROC NEAR
  465.     mov     ax,[DistanceVel]
  466.     add     [Distance],ax
  467.     cmp     [Distance],MinDist
  468.     jge     DistMinOk
  469.     mov     [DistanceVel],0
  470.     mov     [Distance],MinDist
  471. DistMinOk:
  472.     cmp     [Distance],MaxDist
  473.     jle     DistMaxOk
  474.     mov     [DistanceVel],0
  475.     mov     [Distance],MaxDist
  476. DistMaxOk:
  477.     mov     al,[P1Vel]
  478.     add     [PathAn1.b],al
  479.     mov     al,[P2Vel]
  480.     add     [PathAn2.b],al
  481.  
  482.     mov     al,[ZanVel]
  483.     add     [Zan.b],al
  484.     mov     al,[YanVel]
  485.     add     [Yan.b],al
  486.     mov     al,[XanVel]
  487.     add     [Xan.b],al      ;note that by just increasing the byte part, the 
  488.                             ;ranging is automatic (stays in 0-255 range)
  489.  
  490.     mov     bx,[PathAn1]    ;this little section of code fixes up the
  491.     add     bx,bx           ;path that the object travels
  492.     mov     ax,[Sine+bx]    ;PathAn1 controls the X-Z PreAdds and 
  493.     mov     cx,[Cosine+bx]  ;PathAn2 controls PreYadd
  494.     sar     ax,3            ;Because the sine and cosine chart are
  495.     sar     cx,4            ;multiplied by 256, dividing by 8 and 16
  496.     mov     [PreAddX],ax    ;is the same as multiplying the (co)sine by 
  497.     mov     [PreAddZ],cx    ;32 and 16 respectivly
  498.                             ;this gives the object a slightly nauseating
  499.     mov     bx,[PathAn2]    ;bobbing pattern
  500.     add     bx,bx
  501.     mov     ax,[Sine+bx]
  502.     sar     ax,4
  503.     mov     [PreAddY],ax
  504.     ret
  505. AddAngles ENDP
  506.  
  507.     ;DESTROYS: AX,BX,DX, FLAGS
  508.     ;puts all the text up top
  509. DisplayStuff PROC NEAR
  510.     mov     ah,2
  511.     mov     bx,0
  512.     mov     dx,0
  513.     int     10h         ;set cursor pos to (dl,dh) on page BX
  514.  
  515.     mov     ah,9
  516.     mov     dx,offset AngleMsg
  517.     int     21h
  518.  
  519.     mov     al,[Xan.B]
  520.     clc                 ;says print it unsigned
  521.     call    PrintByte
  522.     mov     al,[Yan.B]
  523.     clc                 ;says print it unsigned
  524.     call    PrintByte
  525.     mov     al,[Zan.B]
  526.     clc                 ;says print it unsigned
  527.     call    PrintByte
  528.     mov     ax,[Distance]
  529.     clc                 ;says print it unsigned
  530.     call    PrintWord
  531.     
  532.     mov     al,[PathAn1.B]
  533.     clc                 ;says print it unsigned
  534.     call    PrintByte
  535.     mov     al,[PathAn2.B]
  536.     clc                 ;says print it unsigned
  537.     call    PrintByte
  538.     
  539.     mov     ah,2
  540.     mov     bx,0
  541.     mov     dx,0100h
  542.     int     10h         ;set cursor pos to (dl,dh) on page BX
  543.  
  544.     mov     ah,9
  545.     mov     dx,offset AngleVelMsg
  546.     int     21h
  547.  
  548.     mov     al,[XanVel]
  549.     stc                 ;says print it signed
  550.     call    PrintByte
  551.     mov     al,[YanVel]
  552.     stc                 ;says print it signed
  553.     call    PrintByte
  554.     mov     al,[ZanVel]
  555.     stc                 ;says print it signed
  556.     call    PrintByte
  557.     mov     ax,[DistanceVel]
  558.     stc                 ;says print it signed
  559.     call    PrintWord
  560.  
  561.     mov     al,[P1Vel.B]
  562.     stc                 ;says print it signed
  563.     call    PrintByte
  564.     mov     al,[P2Vel.B]
  565.     stc                 ;says print it signed
  566.     call    PrintByte
  567.  
  568.     ret
  569. DisplayStuff ENDP
  570.  
  571.     ;DESTROYS: a bunch of registers
  572.     ;does all the keyboard oriented stuff..
  573.     ;clears carry if we are to continue, sets it if we are to quit
  574. DoKeyInput PROC NEAR
  575.     mov     ah,11h
  576.     int     16h         ;has a key been pressed? Z flag is set if not
  577.     jnz     GetTheKey
  578.     clc                 ;we continue
  579.     ret
  580.  
  581. GetTheKey:
  582.     mov     ah,10h      ;a key has been pressed, 
  583.     int     16h         ; get it in AX (al= ascii, ah=scan code)
  584.  
  585.     cmp     al,27       ;was it the ESCAPE key?
  586.     jne     KeepGoing
  587.     stc                 ;we signal a quit
  588.     ret
  589.  
  590. KeepGoing:              ;despite its apparent ungainly look, this
  591.     cmp     ax,INCXV    ;is very fast..as little as 2 clocks for each
  592.     je      DoINCXV     ;unsuccessful compare on the 486 and 5 clocks on
  593.     cmp     ax,DECXV    ;the 386... A rather quick way to do it...
  594.     je      DoDECXV
  595.     cmp     ax,INCYV
  596.     je      DoINCYV
  597.     cmp     ax,DECYV
  598.     je      DoDECYV
  599.     cmp     ax,INCZV
  600.     je      DoINCZV
  601.     cmp     ax,DECZV
  602.     je      DoDECZV
  603.     cmp     ax,INCDV
  604.     je      DoIncDV
  605.     cmp     ax,DECDV
  606.     je      DoDecDV
  607.     cmp     ax,ZEROAN
  608.     je      DoZeroAn
  609.     cmp     ax,STOPROT
  610.     je      DoStopRot
  611.  
  612.     cmp     ax,INCPV1
  613.     je      DoIncPv1
  614.     cmp     ax,DECPV1
  615.     je      DoDecPv1
  616.     cmp     ax,INCPV2
  617.     je      DoIncPv2
  618.     cmp     ax,DECPV2
  619.     je      DoDecPv2
  620.  
  621.     clc               ;no valid keypress... Continue
  622.     ret
  623.  
  624. DoINCXV:
  625.     inc     [XanVel]
  626.     clc
  627.     ret
  628. DoINCYV:
  629.     inc     [YanVel]
  630.     clc
  631.     ret
  632. DoINCZV:
  633.     inc     [ZanVel]
  634.     clc
  635.     ret
  636. DoDECXV:
  637.     dec     [XanVel]
  638.     clc
  639.     ret
  640. DoDECYV:
  641.     dec     [YanVel]
  642.     clc
  643.     ret
  644. DoDECZV:
  645.     dec     [ZanVel]
  646.     clc
  647.     ret
  648. DoINCDV:
  649.     inc     [DistanceVel]
  650.     clc
  651.     ret
  652. DoDECDV:
  653.     dec     [DistanceVel]
  654.     clc
  655.     ret
  656. DoStopRot:
  657.     mov     [XanVel],0
  658.     mov     [YanVel],0
  659.     mov     [ZanVel],0
  660.     mov     [DistanceVel],0
  661.     clc
  662.     ret
  663. DoZeroAn:
  664.     mov     [Xan.W],0
  665.     mov     [Yan.W],0
  666.     mov     [Zan.W],0
  667.     clc
  668.     ret
  669. DoINCPv1:
  670.     inc     [P1Vel]
  671.     clc
  672.     ret
  673. DoDECPv1:
  674.     dec     [P1Vel]
  675.     clc
  676.     ret
  677. DoINCPv2:
  678.     inc     [P2Vel]
  679.     clc
  680.     ret
  681. DoDECPv2:
  682.     dec     [P2Vel]
  683.     clc
  684.     ret
  685.  
  686. DoKeyInput ENDP
  687. ─────────────────────────────────────────────────────────────────────────────
  688.  
  689. ;=== CODE
  690.  
  691. START:
  692.     mov     ax,cs
  693.     mov     ds,ax
  694.     mov     es,ax
  695.  
  696.     mov     ah,9              ;print a dollar sign terminating string
  697.     mov     dx,offset control
  698.     int     21h 
  699.  
  700.     mov     ah,0
  701.     int     16h             ;wait for a keypress
  702.  
  703.     mov     ax,0013h                ;set 320x200x256 mode
  704.     int     10h
  705.     
  706.     mov     dx,offset Palette       ;ES:DX points to palette data
  707.     mov     ax,1012h                ; WRITE palette 
  708.     mov     bx,0                    ;start at color 0                   
  709.     mov     cx,16                   ; and write 16 of 'em
  710.     int     10h
  711.  
  712. MainLoop:
  713.     call    RotateBox
  714.     call    AddAngles
  715.  
  716.     mov     dx,3dah
  717. VRT:
  718.     in      al,dx
  719.     test    al,8
  720.     jnz     VRT         ;wait until Verticle Retrace starts
  721. NoVRT:
  722.     in      al,dx
  723.     test    al,8
  724.     jz      NoVRT       ;wait until Verticle Retrace Ends
  725.  
  726.     call    DrawBox  
  727.     call    DisplayStuff
  728.     call    DoKeyInput
  729.     jnc     MainLoop     ;jump if carry is clear
  730.     
  731. ByeBye:    
  732.     mov     ax,0003h    ;set 80x25x16 text
  733.     int     10h
  734.     push    cs
  735.     pop     ds
  736.     mov     ah,9
  737.     mov     dx,offset credits
  738.     int     21h
  739.     mov     ax,4c00h    ;return control to DOS
  740.     int     21h
  741. END START
  742.