home *** CD-ROM | disk | FTP | other *** search
- ; **************************************************************************
- ; 3D FixedPoint (8.8) Retarded vectors - I got the idea from the PANIC demo
- ; Jon Beltran de Heredia, Aug'93
- ; This will work under any PC with a VGA card. Learn all .386'ers!
- ; Version 1.0: Vectors fade out rotating palette, & there's objs morphing
- ; Ah! And in the last moment, I made it 'explode' in the end
- ; Originally inspired on code by Bios/<ode∩aτion 1993 Mar-93
- ; **************************************************************************
-
- .MODEL SMALL
- .STACK
- ; --------------------------------------------------------------------------
- ; Here we have global data
- ; --------------------------------------------------------------------------
- .DATA
-
- ; Limit for the number of vectors of the object
- MAX_LINES EQU 20d ; Maximum number of lines that form one object
- MAX_POINTS EQU 20d ; Maximum number of points that form one object
-
- ; These values setup the projection environment
- HAng DW 0 ; Spin of the object (rotation around its vert. axis)
- VAng DW 0 ; The objects 'leans' down this angle
- deltaX DW 0 ; \
- deltaY DW 0 ; | The object translates after rotation
- deltaZ DW 200d ; /
- dPP DW 200d ; Distance from the viewpoint to the projection plane
-
- ; ===========================================================================
- ; These variables describe the shape of the current object
- NPoints DW 8 ; # of points that form the CURRENT object
- NLines DW 12 ; # of lines that form the CURRENT object
- LPointsPtr DW ? ; OFFSET in DS of the local coors. of the points, in 3D
- ObjLines DW 0,1 ; Pairs of vertex-indices that determine the edges
- DW 1,2 ; (or, in demo-slang, the 'vectors')
- DW 2,3
- DW 3,0
- DW 4,5
- DW 5,6
- DW 6,7
- DW 7,4
- DW 0,4
- DW 1,5
- DW 2,6
- DW 3,7
- ; ===========================================================================
- ; This table describes the set of objects
- NObjects DW 6
- ObjDefs DW OFFSET Obj0Pts, OFFSET Obj1Pts, OFFSET Obj2Pts
- DW OFFSET Obj3Pts, OFFSET Obj4Pts, OFFSET Obj5Pts
- ; ---------------------------------------------------------------------------
- ; These values model the shape of the objects. The only difference betwen them
- ; is the coors. of the vertices, being the lines all the same.
- ; ---------------------------------------------------------------------------
- Obj0Pts DW 8 DUP (0,0,0)
-
- Obj1Pts DW 00,-50, 00
- DW 00,-50, 00
- DW 00,-50, 00
- DW 00,-50, 00
- DW 00, 50, 00
- DW 00, 50, 00
- DW 00, 50, 00
- DW 00, 50, 00
-
- Obj2Pts DW -50,-50,-50
- DW 50,-50,-50
- DW 50,-50, 50
- DW -50,-50, 50
- DW 00, 50, 00
- DW 00, 50, 00
- DW 00, 50, 00
- DW 00, 50, 00
-
- Obj3Pts DW -50,-50,-50
- DW 50,-50,-50
- DW 50,-50, 50
- DW -50,-50, 50
- DW -50, 50,-50
- DW 50, 50,-50
- DW 50, 50, 50
- DW -50, 50, 50
-
- Obj4Pts DW 50,-50,-50
- DW 50,-50, 50
- DW -50,-50, 50
- DW -50,-50,-50
- DW -50, 50,-50
- DW 50, 50,-50
- DW 50, 50, 50
- DW -50, 50, 50
-
- Obj5Pts DW -50,-50,-50
- DW 50,-50,-50
- DW 50,-50, 50
- DW -50,-50, 50
- DW -50, 50,-50
- DW 50, 50,-50
- DW 50, 50, 50
- DW -50, 50, 50
-
- ; ---------------------------------------------------------------------------
-
- ; These coordinates are calculated by ProjectPoints, via F3Dto2D:
- ; ---
- ; Points that compose the current object, as from the observer coordinate
- ; system. We store the projected X and Y coordinates only.
- ScrPoints DW MAX_POINTS DUP (0,0)
- ; ---
-
- ; Nice ( :-? ) goodbye message (well, not so nice as those from Iguana)
- ByeText LABEL BYTE
- DB '3D FixedPoint Retarded-Vectors...', 0Dh, 0Ah
- DB 'Coded by Jon Beltran de Heredia - Aug93', 0Dh, 0Ah
- DB 'Got the idea from the PANIC demo', 0Dh, 0Ah
- DB 'We gonna beat the Finnish & the Swedish out of the PC scene!! ;-)',0Dh,0Ah
- DB 'Original inspiration from code by Bios/<ode∩aτion',0Dh,0Ah
- DB 'Credits go to:', 0Dh, 0Ah
- DB ' * Jare/Iguana for the line drawing code', 0Dh, 0Ah
- DB ' * Draeden/VLA for the starfield idea', 0Dh, 0Ah
- DB ' * Bios/<ode∩aτion for the original 3D engine design', 0Dh, 0Ah
- DB 'Greetings to all you guys in the Spanish PC Scene!', 0Dh, 0Ah
- DB 'Very Special Greetings go to:', 0Dh, 0Ah
- DB ' * Jare/Iguana (I really liked your Inconexia!)', 0Dh, 0Ah
- DB ' * Bios/<ode∩aτion (we are dying to see your demo)',0Dh,0Ah
- DB ' * Aitor Garay (what are you waiting for to start coding demos?)', 0Dh, 0Ah
- DB ' * & to everyone in Fido conferences PROASM_E and R34.DEMOS... keep on it!!!'
- DB '$'
-
- ;SinTable created by Jon Beltran de Heredia
- ;Sines are in 8.8 fixedpoint, from 0 degree to 360+90 degree (in order to
- ; calculate the cosines with the same table)
- SinTbl LABEL WORD
- dw 0,4,9,13,18,22,27,31,36,40,44,49,53,58,62
- dw 66,71,75,79,83,88,92,96,100,104,108,112,116,120,124
- dw 128,132,136,139,143,147,150,154,158,161,165,168,171,175,178
- dw 181,184,187,190,193,196,199,202,204,207,210,212,215,217,219
- dw 222,224,226,228,230,232,234,236,237,239,241,242,243,245,246
- dw 247,248,249,250,251,252,253,254,254,255,255,255,256,256,256
- dw 256,256,256,256,255,255,255,254,254,253,252,251,250,249,248
- dw 247,246,245,243,242,241,239,237,236,234,232,230,228,226,224
- dw 222,219,217,215,212,210,207,204,202,199,196,193,190,187,184
- dw 181,178,175,171,168,165,161,158,154,150,147,143,139,136,132
- dw 128,124,120,116,112,108,104,100,96,92,88,83,79,75,71
- dw 66,62,58,53,49,44,40,36,31,27,22,18,13,9,4
- dw 0,-4,-9,-13,-18,-22,-27,-31,-36,-40,-44,-49,-53,-58,-62
- dw -66,-71,-75,-79,-83,-88,-92,-96,-100,-104,-108,-112,-116,-120,-124
- dw -128,-132,-136,-139,-143,-147,-150,-154,-158,-161,-165,-168,-171,-175,-178
- dw -181,-184,-187,-190,-193,-196,-199,-202,-204,-207,-210,-212,-215,-217,-219
- dw -222,-224,-226,-228,-230,-232,-234,-236,-237,-239,-241,-242,-243,-245,-246
- dw -247,-248,-249,-250,-251,-252,-253,-254,-254,-255,-255,-255,-256,-256,-256
- dw -256,-256,-256,-256,-255,-255,-255,-254,-254,-253,-252,-251,-250,-249,-248
- dw -247,-246,-245,-243,-242,-241,-239,-237,-236,-234,-232,-230,-228,-226,-224
- dw -222,-219,-217,-215,-212,-210,-207,-204,-202,-199,-196,-193,-190,-187,-184
- dw -181,-178,-175,-171,-168,-165,-161,-158,-154,-150,-147,-143,-139,-136,-132
- dw -128,-124,-120,-116,-112,-108,-104,-100,-96,-92,-88,-83,-79,-75,-71
- dw -66,-62,-58,-53,-49,-44,-40,-36,-31,-27,-22,-18,-13,-9,-4
- dw 0,4,9,13,18,22,27,31,36,40,44,49,53,58,62
- dw 66,71,75,79,83,88,92,96,100,104,108,112,116,120,124
- dw 128,132,136,139,143,147,150,154,158,161,165,168,171,175,178
- dw 181,184,187,190,193,196,199,202,204,207,210,212,215,217,219
- dw 222,224,226,228,230,232,234,236,237,239,241,242,243,245,246
- dw 247,248,249,250,251,252,253,254,254,255,255,255,256,256,256,256
-
- ; --------------------------------------------------------------------------
- ; Macros to profile the minidemo
- ; --------------------------------------------------------------------------
- SetBorder2 MACRO Color
- push ax
- push dx
- cli ; So that the flip-flop isn't
- ; uninit-ed by some IRQ...
- mov dx,3DAh
- in al,dx ; Init the flip-flop for the
- ; attribute controller
- mov dx,3C0h ; Attribute controller port
- mov al,31h ; Overscan reg, don't switch ray off
- out dx,al ; Write Register #
- mov al,Color
- out dx,al ; Write Border Color
- sti
- pop dx
- pop ax
- ENDM
-
- SetBorder MACRO Color ; To profile
- ;SetBorder2 Color
- ENDM
-
- ; **************************************************************************
- ; Beginning of the code for the minidemo, functions...
- ; **************************************************************************
- ; --------------------------------------------------------------------------
- ; Function to calculate the values for the rotation 3*3 matrix from the
- ; current values of HAng and VAng. Uses sine table.
- ; --------------------------------------------------------------------------
- .DATA
- ; Sine and cosine of HAng and VAng, and their products
- _sh DW ?
- _sv DW ?
- _ch DW ?
- _cv DW ?
- _shsv DW ?
- _chcv DW ?
- _shcv DW ?
- _chsv DW ?
-
- .CODE
- Calc PROC
- mov bx,HAng
- shl bx,1
- mov ax,SinTbl[bx]
- mov _sh,ax
- mov ax,SinTbl[bx+180] ; cos(alfa) = sin(alfa+90)
- mov _ch,ax
- mov bx,VAng
- shl bx,1
- mov ax,SinTbl[bx]
- mov _sv,ax
- mov ax,SinTbl[bx+180]
- mov _cv,ax
- imul _ch
- mov byte ptr _chcv,ah
- mov byte ptr _chcv+1,dl
- mov ax,_sh
- imul _sv
- mov byte ptr _shsv,ah
- mov byte ptr _shsv+1,dl
- mov ax,_sh
- imul _cv
- mov byte ptr _shcv,ah
- mov byte ptr _shcv+1,dl
- mov ax,_sv
- imul _ch
- mov byte ptr _chsv,ah
- mov byte ptr _chsv+1,dl
- ret
- Calc ENDP
-
- ; --------------------------------------------------------------------------
- ; Function to project a triad of words, representing the local coordinates
- ; of a vertex of the object, to obtain the 2D screen coords, using the
- ; values for the rotation matrix calculated by the 'Calc' function.
- ; --------------------------------------------------------------------------
- ; Transformation used:
- ;
- ; [ x'] ( ch -sh*sv -sh*cv ) [ x ]
- ; [ y'] = ( 0 cv -sv ) * [ y ]
- ; [ z'] ( sh ch*sv ch*cv ) [ z ]
- ;
- ; Where 'ch','sh', 'cv' and 'sv' stand for the sines and cosines of HAng & VAng
- ; --------------------------------------------------------------------------
- .CODE
- F3Dto2D PROC ; takes word ptr [si],[si+2] and [si+4] as 3D coords, projects
- ; 'em and stores 2D projected coords in word ptr [di],[di+2]
- lodsw
- imul _ch
- mov bx,ax
- lodsw
- neg ax
- imul _shsv
- add bx,ax
- lodsw
- neg ax
- imul _shcv
- add bx,ax
- mov cl,8
- sar bx,cl ; must be 'sar' and not 'shr', 'cos it might be neg...
- sub si,4 ; starting with the 'y' coordinate
- lodsw
- imul _cv
- mov bp,ax
- lodsw
- neg ax
- imul _sv
- add bp,ax
- mov cl,8
- sar bp,cl
- sub si,6
- lodsw
- imul _sh
- mov cx,ax
- lodsw
- imul _chsv
- add cx,ax
- lodsw
- imul _chcv
- add cx,ax
- mov cl,8
- sar cx,cl
- add cx,deltaZ
- mov ax,bx
- add ax,deltaX
- imul dPP
- idiv cx
- add ax,160d ; center in screen
- stosw
-
- mov ax,bp
- add ax,deltaY
- imul dPP
- idiv cx
- neg ax
- add ax,100d ; center in screen
- stosw
- ret
- F3Dto2D ENDP
-
- ; --------------------------------------------------------------------------
- ; Function to project the vertices of the object, using the current values
- ; of HAng and VAng, and store them in OPoints
- ; --------------------------------------------------------------------------
- ProjectPoints PROC
- call Calc ; Calculate the sines and cosines
- mov si,LPointsPtr
- mov di,OFFSET ScrPoints
- mov cx,NPoints
- L0: push cx
- call F3Dto2D
- pop cx
- loop L0 ; Loop to project all points
- ret
- ProjectPoints ENDP
-
- ; --------------------------------------------------------------------------
- ; Function to draw the lines specified in OPoints.
- ; Buffers the vectors, for later fadin'-out
- ; --------------------------------------------------------------------------
- .DATA
- ; Number of retarded vectors
- N_RETARD EQU 7 ; Number of vectors drawn in different shades of red
- ; Buffers to store the retarded vectors for later erasing after fade-out
- ; First, BYTE stores the color in which it was drawn
- OldLines0 DB 0
- DW MAX_LINES DUP (0,0,0,0)
- OldLines1 DB 0
- DW MAX_LINES DUP (0,0,0,0)
- OldLines2 DB 0
- DW MAX_LINES DUP (0,0,0,0)
- OldLines3 DB 0
- DW MAX_LINES DUP (0,0,0,0)
- OldLines4 DB 0
- DW MAX_LINES DUP (0,0,0,0)
- OldLines5 DB 0
- DW MAX_LINES DUP (0,0,0,0)
- OldLines6 DB 0
- DW MAX_LINES DUP (0,0,0,0)
- OldLinesBuffers DW OFFSET OldLines0, OFFSET OldLines1
- DW OFFSET OldLines2, OFFSET OldLines3
- DW OFFSET OldLines4, OFFSET OldLines5
- DW OFFSET OldLines6
-
- MaxRed DB ? ; Maximum intensity red
- NextFreeBuffer DW 0 ; In the beginning, there're no occupied buffers
- FlagEraseLines DW 0 ; Don't erase lines - will get nonzero when all bufs
- ; are filled
-
- .CODE
- DrawLines PROC
- mov di,NextFreeBuffer
- shl di,1
- mov di,OldLinesBuffers[di] ; Pointer to buffer for the new vectors
- mov al,[MaxRed]
- stosb ; Store the color in which we'll draw
- mov cx,NLines ; Number of vectors to store and draw
- mov si,OFFSET ObjLines ; Pointer to vector array
- DL2: push cx
- lodsw ; Number of first vertex of line...
- shl ax,1
- shl ax,1
- mov bx,ax
- mov ax,ScrPoints[bx] ; Load its X coordinate
- stosw ; Store in the buffer
- mov x1,ax ; Store for the line-drawing function
- mov ax,ScrPoints[bx+2] ; Load its Y coordinate
- stosw ; Store in the buffer
- mov y1,ax ; Store for the line-drawing function
- lodsw ; Num of second vertex of this line...
- shl ax,1
- shl ax,1
- mov bx,ax
- mov ax,ScrPoints[bx] ; Load its X coordinate
- stosw ; Store in the buffer
- mov x2,ax ; Store for the line-drawing function
- mov ax,ScrPoints[bx+2] ; Load its Y coordinate
- stosw ; Store in the buffer
- mov y2,ax ; Store for the line-drawing function
- mov ah,[MaxRed] ; Maximum intensity red
- push bx ; Preserve pointer to line array
- call Line ; Draw the vector
- pop bx ; Restore ptr to line array
- pop cx ; Restore vector counter
- loop DL2
- mov ax,[NextFreeBuffer] ; Calc. index (0-6) of next free buf
- inc ax
- sub ax,7
- jnz DL3
- mov [FlagEraseLines],1 ; From now on, there're lines to erase
- mov [NextFreeBuffer],ax
- ret
- DL3: add ax,7
- mov [NextFreeBuffer],ax
- ret
- DrawLines ENDP
-
- EraseLines PROC
- mov ax,[FlagEraseLines]
- or ax,ax
- jz ELSExit
- mov si,[NextFreeBuffer] ; NextFreeBuffer is the buf with the
- ; oldest vectors
- shl si,1
- mov si,OldLinesBuffers[si] ; Address of the buffer
- lodsb ; Get the color of the vectors to erase
- mov bl,al ; Keep it in bl
- mov cx,NLines ; Use NLines as a counter
- L2: push cx
- lodsw ; Get X1 coordinate...
- mov x1,ax
- lodsw ; Get Y1 coordinate...
- mov y1,ax
- lodsw ; Get X2 coordinate...
- mov x2,ax
- lodsw ; Get Y2 coordinate...
- mov y2,ax
- mov ah,bl ; Get red shade to erase
- mov al,0 ; Erase with black
- push bx ; Preserve vectors color
- call ELine ; Erase the vector
- pop bx
- pop cx ; Restore vector counter
- loop L2
- ELSExit:
- ret
- EraseLines ENDP
-
- ; --------------------------------------------------------------------------
- ; Line drawing based upon code by Javier Arevalo (Jare/Iguana)
- ; --------------------------------------------------------------------------
- ; Input: AH is the color, coors are in the following vars
- .DATA
- MulBy320 LABEL WORD
- I = 0
- REPT 200d
- DW I*320d
- I = I + 1
- ENDM
- x1 DW ?
- x2 DW ?
- y1 DW ?
- y2 DW ?
- LVar1 DW 0 ; Increment for DI when there is overflow
- LVar2 DW 0 ; Inc. for DI when there isn't overflow
- AdjDown DW ? ; Lookup Bresenham's algorithm
- DW 0 ; There isn't AdjDown w/o overflow
-
- VGASeg DW 0A000h
- .CODE
- Line PROC
- mov BYTE PTR cs:[ColorByte],ah
- push es
- push bp
- push cx
- push si
- push di
- mov ax,[y1]
- mov bx,[y2]
- mov cx,[x1]
- mov si,[x2]
- cmp ax,bx
- jc SHORT LL1
- xchg cx,si
- xchg ax,bx
- LL1:
- ; (cx,ax) = upper point
- ; (si,bx) = the other one
- sub bx,ax ; deltaY
- mov di,ax
- add di,di
- mov di,MulBy320[di]
- add di,cx
- sub si,cx
- mov ax,1
- jnc SHORT LL2
- neg ax
- neg si
- LL2: cmp si,bx ; cmp deltaX,deltaY
- jnc short LL3
- ; so deltaX < deltaY
- mov dx,si
- mov si,ax ; Minor inc.
- mov ax,320 ; Major inc.
- jmp SHORT LL4
- LL3: ; so deltaX > deltaY
- mov dx,bx
- mov bx,si
- mov si,320 ; Minor inc.
- LL4: mov cx,bx
- or cx,cx
- jnz SHORT LL5
- jmp LExit
- LL5: ; Now: AX == Major displacement (every pixel does this).
- ; SI == Minor (only done when decimal part overflows).
- add si,ax
- mov [LVar1],si
- mov si,OFFSET LVar2
- mov [si],ax
- ; Now: ax == nothing
- ; bx == major axis width
- ; cx == major axis width
- ; dx == minor axis width
- ; si == OFFSET LVar2
- ; di == ScreenPtr
- ; bp == nothing
- mov bp,bx
- neg bp ; bp == -major axis width (to round)
- mov ax,bp ; ax == -major a.w.
- add ax,ax ; ax *= 2
- mov AdjDown,ax
- add dx,dx ; dx == 2*minor a. w. (AdjUp)
- mov es,[VGASeg]
- inc cx ; To draw all the pixels
- mov bx,cx
- mov ax,cx
- add ax,0Fh
- mov cl,4
- shr ax,cl
- mov cx,ax ; cx = # of complete 16 pel groups + 1
- and bx,00001111b ; cx = # of ungrouped pixels
- shl bx,1
- mov al,0FFh
- ColorByte = $-1
- jmp WORD PTR LineJmpTbl[bx]
-
- LineDumpPixel MACRO p
- LineLoop&p:
- mov BYTE PTR es:[di],al
- add bp,dx
- sbb bx,bx
- add bx,bx
- add di,[si+bx]
- add bp,[si + bx + OFFSET AdjDown + 2 - OFFSET LVar2]
- ENDM
-
- LineLoop:
- I = 0
- REPT 16
- LineDumpPixel %I
- I = I + 1
- ENDM
- dec cx
- jz SHORT LExit
- jmp LineLoop
- LExit: pop di
- pop si
- pop cx
- pop bp
- pop es
- ret
- Line ENDP
-
- .DATA
- LineJmpTbl LABEL WORD
- LineDumpLabel MACRO p
- DW LineLoop&p
- ENDM
- DW LineLoop0
- I = 15
- REPT 15
- LineDumpLabel %I
- I = I - 1
- ENDM
-
-
- ; --------------------------------------------------------------------------
- ; Line erasing based upon code by Javier Arevalo (Jare/Iguana)
- ; --------------------------------------------------------------------------
- ; Input: AH is the color to erase, coors are in the x1,x2,y1,y2 vars
- ; AL is the color with which to erase
- ; All data is stored in the variables of the previous routine
- .CODE
- ELine PROC
- mov BYTE PTR cs:[CompColorByte],ah
- mov BYTE PTR cs:[EraseColorByte],al
- push es
- push bp
- push cx
- push si
- push di
- mov ax,[y1]
- mov bx,[y2]
- mov cx,[x1]
- mov si,[x2]
- cmp ax,bx
- jc SHORT EL1
- xchg cx,si
- xchg ax,bx
- EL1:
- ; (cx,ax) = upper point
- ; (si,bx) = the other one
- sub bx,ax ; deltaY
- mov di,ax
- add di,di
- mov di,MulBy320[di]
- add di,cx
- sub si,cx
- mov ax,1
- jnc SHORT EL2
- neg ax
- neg si
- EL2: cmp si,bx ; cmp deltaX,deltaY
- jnc short EL3
- ; so deltaX < deltaY
- mov dx,si
- mov si,ax ; Minor inc.
- mov ax,320 ; Major inc.
- jmp SHORT EL4
- EL3: ; so deltaX > deltaY
- mov dx,bx
- mov bx,si
- mov si,320 ; Minor inc.
- EL4: mov cx,bx
- or cx,cx
- jnz SHORT EL5
- jmp LExit
- EL5: ; Now: AX == Major displacement (every pixel does this).
- ; SI == Minor (only done when decimal part overflows).
- add si,ax
- mov [LVar1],si
- mov si,OFFSET LVar2
- mov [si],ax
- ; Now: ax == nothing
- ; bx == major axis width
- ; cx == major axis width
- ; dx == minor axis width
- ; si == OFFSET LVar2
- ; di == ScreenPtr
- ; bp == nothing
- mov bp,bx
- neg bp ; bp == -major axis width (to round)
- mov ax,bp ; ax == -major a.w.
- add ax,ax ; ax *= 2
- mov AdjDown,ax
- add dx,dx ; dx == 2*minor a. w. (AdjUp)
- mov es,[VGASeg]
- inc cx
- mov bx,cx
- mov ax,cx
- add ax,0Fh
- mov cl,4
- shr ax,cl
- mov cx,ax ; cx = # of complete 16 pel groups + 1
- and bx,00001111b ; cx = # of ungrouped pixels
- shl bx,1
- mov ah,0FFh
- CompColorByte = $-1
- mov al,0
- EraseColorByte = $ - 1
- jmp WORD PTR ELineJmpTbl[bx]
-
- ELineDumpPixel MACRO p
- LOCAL @@1
- ELineLoop&p:
- cmp BYTE PTR es:[di],ah
- jne @@1
- mov BYTE PTR es:[di],al
- @@1: add bp,dx
- sbb bx,bx
- add bx,bx
- add di,[si+bx]
- add bp,[si + bx + OFFSET AdjDown + 2 - OFFSET LVar2]
- ENDM
-
- ELineLoop:
- I = 0
- REPT 16
- ELineDumpPixel %I
- I = I + 1
- ENDM
- dec cx
- jz SHORT ELExit
- jmp ELineLoop
- ELExit: pop di
- pop si
- pop cx
- pop bp
- pop es
- ret
- ELine ENDP
-
- .DATA
- ELineJmpTbl LABEL WORD
- ELineDumpLabel MACRO p
- DW ELineLoop&p
- ENDM
- DW ELineLoop0
- I = 15
- REPT 15
- ELineDumpLabel %I
- I = I - 1
- ENDM
-
- ; ---------------------------------------------------------------------------
- ; Function to set the DAC palette RGB values, to put the hi-est red in MaxRed
- ; ---------------------------------------------------------------------------
- .DATA
- Palette LABEL BYTE
- I = 0
- REPT N_RETARD ; Shades of red, from 1 to N_RETARD
- I = I + (63/(N_RETARD-1) - 1)
- DB I,0,0
- ENDM
- I = 0 ; Repeat the same values
- REPT N_RETARD ; Shades of red, from 1 to N_RETARD
- I = I + (63/(N_RETARD-1) - 1)
- DB I,0,0
- ENDM
-
- .CODE
- SetPal PROC
- cli
- mov dx,3C8h ; DAC palette port
- mov al,1 ; Start writing RGBs from color index 1
- out dx,al
- inc dx ; To write the color data (RGBs)
- mov si,OFFSET Palette
- mov bx,7
- sub bl,[MaxRed]
- add si,bx
- add si,bx
- add si,bx
- mov cx,N_RETARD ; Number of colors
- L4: lodsb ; Get red component
- out dx,al ; Send it to the DAC
- lodsb ; Get green component
- out dx,al ; Send it to the DAC
- lodsb ; Get blue component
- out dx,al ; Send it to the DAC
- loop L4 ; Do it for the N_RETARD shades
- sti
- ret
- SetPal ENDP
-
- ; --------------------------------------------------------------------------
- ; Function to rotate the palette, to fade out the vectors
- ; ---------------------------------------------------------------------------
- RotatePal PROC
- mov al,MaxRed
- inc al
- cmp al,8
- je WrapPal
- mov MaxRed,al
- call SetPal
- ret
- WrapPal:
- mov MaxRed,1
- call SetPal
- ret
- RotatePal ENDP
-
- ; --------------------------------------------------------------------------
- ; Function to setup object data, morphing them with linear interpolation
- ; ---------------------------------------------------------------------------
- ; Input:
- ; To force morphing: AX == object # (0 to NObjects-1)
- ; To keep on: AX == -1
- .DATA
- MORPHING EQU 1
- DO_NOTHING EQU 0
- State DB 0
- CurrentObject DW 0
- DestObject DW 0
- MorphingCoors DW 8 DUP (?,?,?)
- Increments DW 8 DUP (?,?,?)
- MorphCount DW ?
-
- .CODE
- SetupObject PROC
- inc ax
- jz KeepOn
- dec ax
- mov [State],MORPHING
- mov [MorphCount],10h ; Intermediate steps
- mov [DestObject],ax ; Object to which to morph
- mov [LPointsPtr],OFFSET MorphingCoors
- mov [DestObject],ax
- mov ax,ds
- mov es,ax
- mov si,[CurrentObject]
- add si,si
- mov si,ObjDefs[si]
- mov di,OFFSET MorphingCoors
- mov cx,[NPoints]
- mov dx,cx
- add cx,cx
- add cx,dx
- rep movsw ; Morphing coors start thus
- mov si,[DestObject]
- add si,si
- mov si,ObjDefs[si] ; Where're the coors for the obj?
- mov bx,[CurrentObject]
- add bx,bx
- mov bx,ObjDefs[bx]
- mov di,OFFSET Increments
- ; Now, si -> Increments; bx -> current coors; di -> increments
- mov bp,[NPoints]
- mov cl,4 ; For the sar
- SO1: lodsw
- sub ax,[bx]
- add ax,8
- sar ax,cl
- stosw
- lodsw
- add ax,8
- sub ax,[bx+2]
- sar ax,cl
- stosw
- lodsw
- add ax,8
- sub ax,[bx+4]
- sar ax,cl
- stosw
- add bx,6
- dec bp
- jnz SO1
- ret
- KeepOn:mov al,[State]
- cmp al,MORPHING
- jne SOExit
- mov ax,[MorphCount]
- or ax,ax
- jnz SO2
- mov [State],DO_NOTHING
- mov bx,[DestObject]
- mov [CurrentObject],bx
- add bx,bx
- mov bx,ObjDefs[bx]
- mov [LPointsPtr],bx
- ret
- SO2: mov si,OFFSET Increments
- mov di,OFFSET MorphingCoors
- mov cx,[NPoints]
- SO3: lodsw ; Load increment
- add [di],ax
- lodsw
- add [di+2],ax
- lodsw
- add [di+4],ax
- add di,6
- loop SO3
- dec MorphCount
- SOExit: ret
- SetupObject ENDP
- ; ===========================================================================
- ; Note: the code for the starfield and the palette managing for the explosion
- ; is quite messy, as I did it in 2 or 3 hours. I won't bother commenting it
- ; 'cuz I assume it's quite easy to understand. Forgive me for being lazy!
- ; ===========================================================================
-
- ; ---------------------------------------------------------------------------
- ; Functions to keep a starfield in the background while we do the ret-vect
- ; ---------------------------------------------------------------------------
- NUM_STARS = 200h
- Z_SPEED = 25
- FAR_Z = 1000h
- .DATA
- StarsPalette LABEL BYTE
- I = 63
- REPT 16
- DB 3 DUP (I)
- I = I - 4
- ENDM
- DB 0,0,0
- EVEN
- RndNum LABEL WORD
- dw -206, -27, 117, 202,-197, 158, 96, 118,-164, 92
- dw 126,-174,-194,-184,-144, 141, 75, -12, 56, 201
- dw -94, -95, -54, 153,-149, 191, 205, 88, 123, 52
- dw -103, -10,-138, -61, 197, 111, 180, 199, 94,-145
- dw 181, -85,-143, 172,-172, 50,-136, 69, -45,-101
- dw 33,-148, 113, -38, -55, 37, 64, 157,-117, 98
- dw 127, -22, -33, -88,-205, -80, 154, 43, 121,-104
- dw 34, 39, 31,-201,-175, 76, 79,-102,-162, 135
- dw 73, 138, 174, 165, 29,-116, -18,-153, -74, 177
- dw -189, 194,-180,-169, 77, 128, -44,-156, 80, 130
- dw -92,-125,-187, 106, -31,-105, -37, 124, -97,-130
- dw -168, 195,-154,-163,-106, 173, 48, 27,-142, 163
- dw -185, 119, -83, 136,-203, 132, 107, 186, -35, 14
- dw -161,-110, 114, -53, -58, -15,-124, 26, 97, 25
- dw -122, 10, 155, -41, -68, -76, 208, 169, 206,-140
- dw -72, 38, 204, -14, 23, 99,-190,-118, -62, -60
- dw -24, 22, -21, 188, 47, 167, 15,-112, 83, 185
- dw -198,-178, 189, 78,-182, 148,-159, 17, 145,-133
- dw 57,-209, 12, 44, -81,-195, -40, -17,-188, -69
- dw 11,-192,-171, 187, -78,-114,-176,-207, 24, 108
- dw -89, 116,-179, 82, 149, 160, 104,-127, -25, 151
- dw -141, -43, -51, 46, 200, 20, 171,-119,-107,-193
- dw -66, 86,-181, -77, 32,-158, -71,-139, 147, -28
- dw -34, 61,-177, 120, 36, 137, 159, 41, -57, -46
- dw 71,-186,-135, -50, -47, 178, 133, -42, -99, 58
- dw -157, 152, 190, 95,-137, -67, 110,-210,-146, -19
- dw -32, 183, 21,-196, 125, 45, 60, 90,-132,-111
- dw -64, 28,-123, 30, -96, -29, -91,-113, 166, 74
- dw -73, 156, -59,-200, -63, 193, 140,-151, 66, 115
- dw 62, 59,-191,-160, 54, 35, 67, -48,-126, 131
- dw 161,-155, 81, -16, 192, 168, -86,-109, 40, 203
- dw 49, 139, 175,-129, 112, 134,-208, 122, -20, 63
- dw 198,-165, -49, -90, 18, 13,-152, -13, 150, 87
- dw -167, 196, 70, 51, -65,-121, 184,-147, 42, 100
- dw 129, -98, 144,-128, -75, 182, 109, -79, 93, 65
- dw -23, 55, 68, -70, 164, -26, 207,-150, -52,-134
- dw 101, 102,-166, -30, -56, -87,-108, 142,-100, 105
- dw -82, -93,-199, 85, 143, 209, 176, -11, 72,-120
- dw 84,-173, 146,-115, 53, 170, 103,-183, 89, 16
- dw -202, -84, -39,-170, 19,-204,-131, 162, 91, -36
-
- XRndIndex DW 0
- YRndIndex DW 30h ; Arbitrary
- StarsX DW NUM_STARS DUP (0)
- StarsY DW NUM_STARS DUP (0)
- StarsZ DW NUM_STARS DUP (0)
- StarsDI DW NUM_STARS DUP (0)
- NumCurrentStars DW 0
- ErrorMsg DB 'There has been an internal error. Please report!', '$'
-
- .CODE
- InitStars PROC
- cli
- mov dx,3C8h ; DAC palette port
- mov al,10h ; Start writing RGBs from color index 16d
- out dx,al
- inc dx ; To write the color data (RGBs)
- mov si,OFFSET StarsPalette
- mov cx,11h ; Number of colors
- L5: lodsb ; Get red component
- out dx,al ; Send it to the DAC
- lodsb ; Get green component
- out dx,al ; Send it to the DAC
- lodsb ; Get blue component
- out dx,al ; Send it to the DAC
- loop L5 ; Do it for the 11h shades
- sti
- ret
- InitStars ENDP
-
- AddStar PROC
- mov ax,[NumCurrentStars]
- cmp ax,NUM_STARS
- jne DoAdd
- jmp DontAdd
- DoAdd:
- mov ax,ds
- mov es,ax
- mov di,OFFSET StarsZ
- mov cx,NUM_STARS
- xor ax,ax
- repne scasw
- je NotInternalError
- mov ax,0003
- int 10h
- mov dx,OFFSET ErrorMsg
- mov ah,9
- int 21h
- mov ax,4CFFh
- int 21h
- NotInternalError:
- mov cl,3
- mov bx,di
- sub bx,2 + OFFSET StarsZ
- mov [WORD PTR di-2],FAR_Z
- mov si,[XRndIndex]
- mov ax,RndNum[si]
- shl ax,cl
- mov StarsX[bx],ax
- mov si,[YRndIndex]
- mov ax,RndNum[si]
- shl ax,cl
- mov StarsY[bx],ax
- mov ax,[XRndIndex]
- mov bx,[YRndIndex]
- add ax,2
- cmp ax,400d
- jne DontWrapXRnd
- mov ax,0
- DontWrapXRnd:
- add bx,2
- cmp bx,400d
- jne DontWrapYRnd
- mov bx,0
- add ax,2
- cmp ax,400d
- jne DontWrapXRnd2
- mov ax,0
- DontWrapXRnd2:
- DontWrapYRnd:
- cmp ax,bx
- jne XAndYNotEqual
- add ax,2
- cmp ax,400d
- jne DontWrapXRnd3
- mov ax,0
- DontWrapXRnd3:
- XAndYNotEqual:
- mov [XRndIndex],ax
- mov [YRndIndex],bx
- inc [NumCurrentStars]
- DontAdd:
- ret
- AddStar ENDP
-
- DisplayStars PROC
- mov di,OFFSET StarsZ
- mov cx,NUM_STARS
- DSOtherStar:
- mov ax,ds
- mov es,ax
- xor ax,ax
- repe scasw ; Find first nonzero StarZ
- jne DSDontExit
- jmp DSExit
- DSDontExit:
- push di
- push cx
- mov bx,di
- sub bx,2 + OFFSET StarsZ
- mov ax,0A000h
- mov es,ax
- mov di,StarsDI[bx]
- cmp BYTE PTR es:[di],10h
- jb DontEraseStar
- mov BYTE PTR es:[di],0
- DontEraseStar:
- mov cx,StarsZ[bx] ; Get coor Z
- cmp cx,1
- jne DontTerminate
- mov StarsZ[bx],0
- dec [NumCurrentStars]
- jmp DSContinue
- DontTerminate:
- mov ax,StarsX[bx]
- cwd
- mov dl,ah
- mov ah,al
- idiv cx ; Get screen coordinate X
- add ax,160d ; To center the stars
- cmp ax,320d
- jl DontKill1
- mov StarsZ[bx],1
- jmp DSContinue
- DontKill1:
- cmp ax,0
- jg DontKill2
- mov StarsZ[bx],1
- jmp DSContinue
- DontKill2:
- mov si,ax
- mov ax,StarsY[bx]
- cwd
- mov dl,ah
- mov ah,al
- idiv cx ; Get screen coor. Y
- add ax,100d
- cmp ax,200d
- jl DontKill3
- mov StarsZ[bx],1
- jmp DSContinue
- DontKill3:
- cmp ax,0
- jg DontKill4
- mov StarsZ[bx],1
- jmp DSContinue
- DontKill4:
- mov di,ax
- add di,di
- mov ax,MulBy320[di]
- add si,ax
- mov StarsDI[bx],si
- cmp BYTE PTR es:[si],0
- jne DontDrawStar
- mov al,ch ; StarZ/100h
- add al,10h
- mov BYTE PTR es:[si],al
- DontDrawStar:
- DSContinue:
- pop cx
- pop di
- jmp DSOtherStar
- DSExit:
- ret
- DisplayStars ENDP
-
- AdvanceStars PROC
- mov di,OFFSET StarsZ
- mov cx,NUM_STARS
- ASOtherStar:
- mov ax,ds
- mov es,ax
- xor ax,ax
- repe scasw ; Find first nonzero StarZ
- je ASExit
- push di
- push cx
- mov bx,di
- sub bx,2 + OFFSET StarsZ
- mov ax,StarsZ[bx]
- sub ax,Z_SPEED
- cmp ax,2
- jge DontKill5
- mov StarsZ[bx],1
- jmp ASContinue
- DontKill5:
- mov StarsZ[bx],ax
- ASContinue:
- pop cx
- pop di
- jmp ASOtherStar
- ASExit:
- ret
- AdvanceStars ENDP
-
- ; --------------------------------------------------------------------------
- ; Functions to fade palette to all 3Fhs, to simulate exploding
- ; ---------------------------------------------------------------------------
- .DATA
- NextColor LABEL BYTE
- I = 0
- REPT 3Ch
- DB I + 4
- I = I + 1
- ENDM
- DB 3Fh,3Fh,3Fh,3Fh
- PrevColor LABEL BYTE
- DB 0,0,0,0
- I = 0
- REPT 3Ch
- DB I
- I = I + 1
- ENDM
- TempPalette LABEL BYTE
- DB 0,0,0
- DB 7 DUP (3Fh,0,0)
- DB 8 DUP (0,0,0)
- I = 63
- REPT 16
- DB 3 DUP (I)
- I = I - 4
- ENDM
- DB 0,0,0
- EndExplode DB 0
- .CODE
- AdvancePal PROC
- cli
- mov ax,ds
- mov es,ax
- mov di,OFFSET TempPalette
- xor bh,bh
- REPT 3 * 21h
- mov bl,[di]
- mov al,NextColor[bx]
- stosb
- ENDM
- mov dx,3C8h
- xor al,al
- out dx,al
- inc dx ; To write the data
- mov si,OFFSET TempPalette
- REPT 3 * 21h
- lodsb
- out dx,al
- ENDM
- sti
- cmp [TempPalette],3Fh
- jne AP1
- mov [EndExplode],1
- AP1:
- ret
- AdvancePal ENDP
-
- DecreasePal PROC
- cli
- mov ax,ds
- mov es,ax
- mov di,OFFSET TempPalette
- xor bh,bh
- REPT 3 * 21h
- mov bl,[di]
- mov al,PrevColor[bx]
- stosb
- ENDM
- mov dx,3C8h
- xor al,al
- out dx,al
- inc dx ; To write the data
- mov si,OFFSET TempPalette
- REPT 3 * 21h
- lodsb
- out dx,al
- ENDM
- sti
- ret
- DecreasePal ENDP
-
-
- ; **************************************************************************
- ; **************************************************************************
- ; At last, here we have the main loop (looks like Pascal, doesn't it? 8-D).
- ; **************************************************************************
- ; **************************************************************************
- .DATA
- Phi DW ?
- RadiusX DW 100d
- RadiusY DW 100d
- RadiusZ DW 200d
- CenterX DW 0
- CenterY DW 0
- CenterZ DW 600d
-
- .CODE
- Main PROC
- cld
- mov ax,@DATA
- mov ds,ax
- mov es,ax
- mov ax,13h
- int 10h ; Sets standard 320x200x256
- mov MaxRed,7
- call SetPal ; Load values for the palette - red shades
- call InitStars ; Load values for the palette - white shades
- mov ax,1
- ObjLoop:push ax ; Loops for all objects
- call SetupObject
- mov cx,2 ; Numbwer of turns for each object
- RotLoop:push cx
- mov ax,0 ; Obj starts with no angle (that is, far away)
- PhiLoop:mov [Phi],ax ; Store NEW value of angle
- mov bx,ax
- add bx,bx
- mov cx,[RadiusZ]
- mov ax,SinTbl[bx+180d] ; Get 100h * cos(Phi)
- imul cx
- mov al,ah
- mov ah,dl
- add ax,[CenterZ]
- mov [deltaZ],ax
- mov cx,[RadiusX]
- mov ax,SinTbl[bx] ; Get 100h * sin(phi)
- neg ax
- imul cx
- mov al,ah
- mov ah,dl
- add ax,[CenterX]
- mov [deltaX],ax
- mov cx,[RadiusY]
- add bx,bx
- sub bx,720d
- jnc M1
- add bx,720d
- M1: mov ax,SinTbl[bx] ; Get 100h * sin(phi)
- neg ax
- imul cx
- mov al,ah
- mov ah,dl
- add ax,[CenterY]
- mov [deltaY],ax
- mov ax,[Phi]
- mov [HAng],ax
- add ax,ax
- sub ax,360d
- jnc M2
- add ax,360d
- M2: mov [VAng],ax
- mov ax,-1
- call SetupObject ; Performs morphing if necessary
- call ProjectPoints ; Calc new ScrPoints (projected coordinates)
- SetBorder 15
- call DrawLines ; Draws new lines
- SetBorder 13
- call EraseLines ; Erases lines from oldest buffer
- SetBorder 0
- mov dx,3DAh
- WaitVR1:in al,dx
- and al,8
- jz WaitVR1 ; We wait till a vertical retrace
- WaitDE: in al,dx
- and al,1
- jnz WaitDE ; We wait till the vert. retr ends
- REPT 5
- call AddStar
- ENDM
- call DisplayStars
- call AdvanceStars
- mov dx,3DAh
- WaitVR2:in al,dx
- and al,8
- jz WaitVR2 ; Wait again till a vert. retr.
- ; We animate every two frames (that's, at
- ; 35 Hz) 'cos otherwise it's too fast!
- call RotatePal ; Rotate the palette, to fade out the vectors
- mov ax,Phi
- add ax,3
- cmp ax,360d ; Have we returned to the original spin?
- jae ExitPhiLoop ; If not, keep on the same way
- jmp PhiLoop
- ExitPhiLoop:
- pop cx
- dec cx
- jz ExitRotLoop
- jmp RotLoop
- ExitRotLoop:
- pop ax ; Current obj number
- inc ax
- cmp ax,NObjects
- je ExitObjLoop
- jmp ObjLoop ; Only 5 times to and fro
- ExitObjLoop:
- mov ax,0
- call SetupObject ; Morph into nothing
- mov ax,0 ; Obj starts with no angle (that is, far away)
- PhiLoop2:mov [Phi],ax ; Store NEW value of angle
- mov bx,ax
- add bx,bx
- mov cx,[RadiusZ]
- mov ax,SinTbl[bx+180d] ; Get 100h * cos(Phi)
- imul cx
- mov al,ah
- mov ah,dl
- add ax,[CenterZ]
- mov [deltaZ],ax
- mov cx,[RadiusX]
- mov ax,SinTbl[bx] ; Get 100h * sin(phi)
- neg ax
- imul cx
- mov al,ah
- mov ah,dl
- add ax,[CenterX]
- mov [deltaX],ax
- mov cx,[RadiusY]
- add bx,bx
- sub bx,720d
- jnc M3
- add bx,720d
- M3: mov ax,SinTbl[bx] ; Get 100h * sin(phi)
- neg ax
- imul cx
- mov al,ah
- mov ah,dl
- add ax,[CenterY]
- mov [deltaY],ax
- mov ax,[Phi]
- mov [HAng],ax
- add ax,ax
- sub ax,360d
- jnc M4
- add ax,360d
- M4: mov [VAng],ax
- mov ax,-1
- call SetupObject ; Performs morphing if necessary
- call ProjectPoints ; Calc new ScrPoints (projected coordinates)
- SetBorder 15
- call DrawLines ; Draws new lines
- SetBorder 13
- call EraseLines ; Erases lines from oldest buffer
- SetBorder 0
- mov dx,3DAh
- WaitVR3:in al,dx
- and al,8
- jz WaitVR3 ; We wait till a vertical retrace
- mov dx,3DAh
- WaitDE2:in al,dx
- and al,1
- jnz WaitDE2 ; We wait till the vert. retr ends
- REPT 5
- call AddStar
- ENDM
- call DisplayStars
- call AdvanceStars
- mov dx,3DAh
- WaitVR4:in al,dx
- and al,8
- jz WaitVR4 ; Wait again till a vert. retr.
- ; We animate every two frames (that's, at
- ; 35 Hz) 'cos otherwise it's too fast!
- call AdvancePal ; To do the explosion
- cmp [EndExplode],1
- je ExitPhiLoop2 ; If not, keep on the same way
- mov ax,[Phi]
- add ax,3
- jmp PhiLoop2
- ExitPhiLoop2:
- mov cx,10h ; Fade out palette in 10h frames
- FadeOutLoop:
- push cx
- mov dx,3DAh
- WaitNVR:in al,dx
- test al,1
- jnz WaitNVR
- WaitVR5:in al,dx
- test al,8
- jz WaitVr5
- call DecreasePal
- pop cx
- loop FadeOutLoop
- mov ax,3
- int 10h ; Set a wildly unknow video mode
- mov ah,9
- mov dx,offset ByeText
- int 21h ; Use undoc. DOS function to print string
- mov ax,4C00h
- int 21h ; Exit to MeSsy-DOS
- Main ENDP
-
- END Main