Metropoli BBS
VIEWER: stars.asm MODE: TEXT (LATIN1)
;**************************************************************************
;
;
;  640x480x256 SVGA Star field
;
; By Adam Seychell
;
;**************************************************************************
.386
.model flat , C
.stack

X_RANGE		  =     128000
X_RANGE_n2        =     17
X_BOUNDRY	  =     X_RANGE/2

Y_RANGE		  =     800h
Y_RANGE_n2        =     11
Y_BOUNDRY	  =     256000/2

Z_RANGE		  =     256000*4
Z_RANGE_n2        =     20
Z_BOUNDRY	  =     Z_RANGE
STARS_TO_PLOT	  =     4000
NUM_STARS         =     1000h
NUM_STARS_2n      =     11
VERT_RES          =     480
HORZ_RES          =     640
HORZ_RES_2n1      =     7
HORZ_RES_2n2      =     9
HORZ_RES_2n3      =     0
;VIDEO_MODE        =     105h   ; 1024x768x256
;VIDEO_MODE        =     103h   ; 800x600x256
VIDEO_MODE        =     101h   ; 640x480x256
VERT_OFFSET       =     VERT_RES/2
HORZ_OFFSET       =     HORZ_RES/2



BANKS_USED        =     (( (VERT_RES * HORZ_RES) / 65536 ) + 1)

include keys.inc
include vesa.inc

Data_3D_Point STRUC
X       DD ?
Y       DD ?
Z       DD ?
Data_3D_Point ENDS

EXTERN  Debug_Run               :Near
EXTERN  Debug                   :Near
EXTERN  StarColorTable		:Dword
EXTERN  Random			:Near
EXTERN  Random_Number		:Dword
EXTERN  Randomize		:Near
;EXTERN  Sin			:Dword ; 1024 DWORD sin table {-7fffh..7fffh}

.CODE

SIN	label   Dword
include	    SIN.TAB	; 1024 DWORD sin table {-7fffh..7fffh}
StarField       	Data_3D_Point  NUM_STARS  DUP  (<?,?,?>)
PosBufferCounter        DD  BANKS_USED DUP (?,?)

Look                    Data_3D_Point <0,0,20000>
StepSpeed               Data_3D_Point <0,0,0>
Angle			Data_3D_Point <0,0,0>
StepAngle               Data_3D_Point <0,0,0>
HideShow_State          DD  0
HideShow_StateCntr      DD  0

Key                     DB  0
mesg			db  10,10,10,10,10,10
			db  '           Q = forward',10,13
			db  '           A = reverse',10,13
			db  '           Space = stop',10,13
			db  '           Cursor keys move up/down/left/right.',10,13
			db  '           <  > rotate.',10,13
                        db  '$'
UpArrow_key_Flag		Byte	0
LeftArrow_key_Flag          Byte    0
RightArrow_key_Flag         Byte    0
DownArrow_key_Flag          Byte    0
Q_key_Flag                  Byte    0
A_key_Flag                  Byte    0
I_key_Flag                  Byte    0
M_key_Flag                  Byte    0
J_key_Flag                  Byte    0
K_key_Flag                  Byte    0
_33_key_Flag                Byte    0
_34_key_Flag	            Byte    0
SpaceBar_key_Flag           Byte    0



.DATA

PosBuffer               Label Dword
rept BANKS_USED*2
DD  NUM_STARS  DUP (?)
endm
DistanceBuffer          Label Dword
rept BANKS_USED*2
DD  NUM_STARS  DUP (?)
endm
VideoPtr                DD ?
Point			Data_3D_Point <>
OldIRQ1_vect            DD ?,?

.CODE





;
;  Macro to print some text on the screem
;
Print MACRO string
local @text,@skip
    mov edx,offset @text
    mov ah,9
    int 21h
    jmp @skip
@text db string,13,10,36
@skip:
ENDM

wait_retrace MACRO
        mov     dx,3DAh
@@:     in      al,dx
        test    al,8
        jz @b
ENDM
Multiply MACRO Shift1 ,Shift2 , Shift3
IFNB <Shift3>
     IFE Shift3 EQ 0
        mov     ecx,eax
        shl     ecx,Shift3
     ENDIF
ENDIF
IFNB <Shift2>
     IFE Shift2 EQ 0
        mov     edx,eax
        shl     edx,Shift2
     ENDIF
ENDIF
        shl     eax,Shift1
IFNB <Shift3>
     IFE Shift3 EQ 0
        add     eax,ecx
     ENDIF
ENDIF
IFNB <Shift2>
     IFE Shift2 EQ 0
        add     eax,edx
     ENDIF
ENDIF
ENDM



;---------------------------------------
; Keyboard interrupt handler
;---------------------------------------
KBRD_handler PROC
        push    ebx
        push    eax
        push    ds
        mov     ax,SEG Key
        mov     ds,ax
        in      al,60h
        mov     Key,al
        mov	bl,al
        shr	bl,7
        xor	bl,1
        and	al,7fh
        .if 	al == UpArrow_key
        mov	UpArrow_key_Flag,BL
        .elseif al == LeftArrow_key
        mov	LeftArrow_key_Flag,BL
        .elseif al == RightArrow_key
	mov  RightArrow_key_Flag,BL
        .elseif al == DownArrow_key
	mov  DownArrow_key_Flag,BL
        .elseif al == Q_key
	mov Q_key_Flag,BL
        .elseif al == A_key
 	mov A_key_Flag,BL
        .elseif al == I_key
	mov I_key_Flag,BL
        .elseif al == M_key
	mov M_key_Flag,BL
        .elseif al == J_key
	mov J_key_Flag,BL
        .elseif al == K_key
	mov K_key_Flag,BL
        .elseif al == 33h	; <
	mov _33_key_Flag,BL
        .elseif al == 34h	; >
	mov _34_key_Flag,BL
        .elseif al == SpaceBar_key
	mov SpaceBar_key_Flag,BL
        .endif
        mov     al,20h
        out     20h,al
        pop     ds
        pop     eax
        pop     ebx
        iretd
KBRD_handler ENDP
;---------------------------------------------
CHANGE_ACTIVE_BUFFER proc
        .IF     HideShow_StateCntr == 0
           mov  HideShow_StateCntr,  BANKS_USED * 4
        .Else
           mov  HideShow_StateCntr, 0
        .Endif

        .IF     HideShow_State == 0
           mov  HideShow_State, NUM_STARS * BANKS_USED * 4
        .Else
           mov  HideShow_State, 0
        .Endif
        ret
CHANGE_ACTIVE_BUFFER ENDP


;-================  Rotate each 3D dot in the 3D data ============

;        X = x cos(é) - y sin(é)	Rotate around the Z axis
;        Y = y cos(é) + x sin(é)

;        X = x cos(é) - z sin(é)	Rotate around the Y axis
;        Z = z cos(é) + x sin(é)

;        Z = z cos(é) - y sin(é)	Rotate around the X axis
;        Y = y cos(é) + z sin(é)

; where X,Y,Z   are the new positions
;   é   is the angel to rotate it by
;   x,y,z   is the origonal positions



;-------------------------------------------------------
;       rotate around the  Z axis
;-------------------------------------------------------
Rotate_About_Z 	MACRO

 ;--------- X = x cos(é) - y sin(é) ---------

        mov     eax,[Angle.Z]		; get é
        shr	eax,6
	and     eax,03ffh   		; Rap around 1024 bytes.
	mov	ebx,[SIN+eAX*4]		; get SIN(é)
        add	eax,256     		; add 90 deg to get COS
	and     eax,03ffh   		; Rap around 1024 bytes.
	mov	edi,[SIN+eAX*4]		; get COS(é)

	mov	eax,Point.X
	IMUL    edi
	shrd	eax,edx,13
        mov     ebp,eax
        mov	eax,Point.Y
 	IMUL    ebx
	shrd	eax,edx,13
        sub     ebp,eax


;--------- Y = y cos(é) + x sin(é) -----------
        mov	eax,Point.Y
	IMUL    edi
	shrd	eax,edx,13
        mov     ecx,eax
        mov	eax,Point.X
	IMUL    ebx
	shrd	eax,edx,13
        add     ecx,eax

        MOV     Point.Y,ECX		;store the rotated points
	MOV	Point.X,EBP
ENDM


;-------------------------------------------------------
;       rotate around the  Y axis
;-------------------------------------------------------
Rotate_About_Y 	MACRO

  ;        X = x cos(é) - z sin(é)
  ;
        mov     eax,[Angle.Y]		; get é
        and	eax,03ffh
	mov	ebx,[SIN+eAX*4]		; get SIN(é)
        add	eax,256     		; add 90 deg to get COS
	and     eax,03ffh   		; Rap around 1024 bytes.
	mov	edi,[SIN+eAX*4]		; get COS(é)

	mov	eax,StarField.X[ ESI]
	IMUL    edi
	shrd	eax,edx,13
        mov     ebp,eax
        mov	eax,StarField.Z[ ESI]
 	IMUL    ebx
	shrd	eax,edx,13
        sub     ebp,eax

   ;        Z = z cos(é) + x sin(é)
   ;
        mov	eax,StarField.Z[ESI]
	IMUL    edi
	shrd	eax,edx,13
        mov     ecx,eax
        mov	eax,StarField.X[ ESI]
	IMUL    ebx
	shrd	eax,edx,13
        add     ecx,eax

        MOV     StarField.Z[ ESI],ECX		;store the rotated points
	MOV	StarField.X[ ESI],EBP
ENDM


;-------------------------------------------------------
;       rotate around the  X axis
;-------------------------------------------------------
Rotate_About_X 	MACRO

;        Z = z cos(é) - y sin(é)

        mov     eax,[Angle.X]		; get é
        and	eax,03ffh
	mov	ebx,[SIN+eAX*4]		; get SIN(é)
        add	eax,256     		; add 90 deg to get COS
	and     eax,03ffh   		; Rap around 1024 bytes.
	mov	edi,[SIN+eAX*4]		; get COS(é)

	mov	eax,[StarField.Z+ ESI]
	IMUL    edi
	shrd	eax,edx,13
        mov     ebp,eax
        mov	eax,[StarField.Y+ ESI]
 	IMUL    ebx
	shrd	eax,edx,13
        sub     ebp,eax


;        Y = y cos(é) + z sin(é)

        mov	eax,[StarField.Y+ ESI]
	IMUL    edi
	shrd	eax,edx,13
        mov     ecx,eax
        mov	eax,[StarField.Z+ ESI]
	IMUL    ebx
	shrd	eax,edx,13
        add     ecx,eax

        MOV     [StarField.Y+ ESI],ECX		;store the rotated points
	MOV	[StarField.Z+ ESI],EBP
ENDM


;------------------------------------------------------------------------
;
;  READ 3D DATA AND CALCULATE PIXELS ON THE SCREEN
;
;------------------------------------------------------------------------
Calc_Positions PROC
        mov     esi,0

GetLoop01:


        mov     eax,StarField.Y[esi]
        mov	Point.Y,eax
        mov     eax,StarField.X[esi]
        mov	Point.X,eax

        mov     eax,StarField.Z[esi]
        mov	Point.Z,eax
	Rotate_About_Z

        mov	ebx,Point.Z
        add	ebx,Look.Z
        mov     edi,ebx
        cmp     ebx,1024
        jl      TooClose
        cmp     ebx,Z_BOUNDRY
        jg      TooFar


        mov     eax,Point.Y
        add     eax,Look.Y
        cmp	eax,Y_BOUNDRY
        jg      TooDown
        cmp	eax,-Y_BOUNDRY
        jl      TooUp
        shl     eax,11
	cdq
        idiv    ebx
        add     eax,VERT_OFFSET
        cmp     eax,VERT_RES
        ja      @@skipStar
        Multiply HORZ_RES_2n1, HORZ_RES_2n2, HORZ_RES_2n3
        mov     ecx,eax

        mov     eax,Point.X
        add     eax,Look.X
        cmp	eax,X_BOUNDRY
        jg      TooRight
        cmp	eax,-X_BOUNDRY
        jl      TooLeft
        shl     eax,11
        cdq
	idiv    ebx
	add     eax,HORZ_OFFSET
        cmp     eax,HORZ_RES
        ja      @@skipStar
        add     eax,ecx         ; Add X`,   EAX = screen offset



        mov     ebx,eax
        shr     ebx,16
        mov     ecx,ebx
        mov     edx,HideShow_StateCntr
        mov     ebx,PosBufferCounter[ecx*4+edx]
        inc     PosBufferCounter[ecx*4+edx]
        shl     ecx, NUM_STARS_2n + 2


						; GET COLOR
	sub	edi,1024
        shr	edi,5
        cmp     edi,7000
        jb @f
        mov     edi,7000 - 1
@@:
        mov     edx,StarColorTable[edi*8]
        mov     DistanceBuffer[ecx+ebx*8],edx
        mov     edx,StarColorTable[edi*8+4]
        mov     DistanceBuffer[ecx+ebx*8+4],edx

        add     ecx,HideShow_State
        And     Eax,0FFFFh
        Add     Eax,VideoPtr
        mov     PosBuffer[ecx+ebx*4],eax

@@skipStar:

        add     esi,SIZEOF Data_3D_Point
        cmp     esi,(SIZEOF Data_3D_Point) * STARS_TO_PLOT
        jb      GetLoop01
        Ret


TooClose:;----------------------------------------
        add     StarField.Z[esi],Z_RANGE
        call	Get_New_XY
        jmp     @@skipStar
TooFar:;----------------------------------------
        sub     StarField.Z[esi],Z_RANGE
        call	Get_New_XY
        jmp     @@skipStar
TooLeft:;----------------------------------------
        add	StarField.X[esi],X_RANGE
        call	Get_New_YZ
        jmp     @@skipStar
TooRight:;----------------------------------------
	sub	StarField.X[esi],X_RANGE
        call	Get_New_YZ
        jmp     @@skipStar
TooUp:;----------------------------------------
        add	StarField.Y[esi],Y_RANGE
        call	Get_New_XZ
        jmp     @@skipStar
TooDown:;----------------------------------------
	sub	StarField.Y[esi],Y_RANGE
        call	Get_New_XZ
        jmp     @@skipStar

Calc_Positions ENDP

;-------------------------------------------------
Get_New_XY PROC
	mov	cl,X_RANGE_n2
	call	Random
        sub	eax,X_RANGE/2
        add	StarField.X[esi],eax
	mov	cl,Y_RANGE_n2
	call	Random
        sub	eax,Y_RANGE/2
        add	StarField.Y[esi],eax
        ret
Get_New_XY ENDP
Get_New_YZ PROC
	mov	cl,Z_RANGE_n2
	call	Random
        sub	eax,Z_RANGE/2
        add	StarField.Z[esi],eax
	mov	cl,Y_RANGE_n2
	call	Random
        sub	eax,Y_RANGE/2
        add	StarField.Y[esi],eax
        ret
Get_New_YZ ENDP
Get_New_XZ PROC
	mov	cl,Z_RANGE_n2
	call	Random
        sub	eax,Z_RANGE/2
        add	StarField.Z[esi],eax
	mov	cl,X_RANGE_n2
	call	Random
        sub	eax,X_RANGE/2
        add	StarField.X[esi],eax
        ret
Get_New_XZ ENDP



;-------------------------------------------------------------------------
;                       	START
;-------------------------------------------------------------------------
Start PROC

Local	Red	:Dword
Local	Green 	:Dword
Local	Blue 	:Dword



        mov     bl,9            ; Install keyboard handler
        mov     ax,204h
        int     31h
        mov     OldIRQ1_vect[0],edx
        mov     OldIRQ1_vect[4],ecx
        mov     ax,205h
        mov     edx,Offset KBRD_handler
        mov     cx,cs
        int     31h

        mov	Random_Number,12345678h


;        call    Debug_Run       ; initalize debugger
;        call    Debug      ; initalize debugger


     ;
     ; Set VIDEO mode
     ;

      mov   ax,VIDEO_MODE
      call  CheckVbeMode
      jc    @@ModeNotFound
      mov   VideoPtr,eax

      call  SetVbeMode


    ;
    ;  Set Palette
    ;
	mov	dx,3C8h
        mov	al,0
	out	dx,al
        mov	dx,3C9h

        mov	ecx,3*2
@@:	out	dx,al
        loop @b

        mov	Red,0
        mov	Green,0
        mov	Blue,0
	mov	cl,128

ColorLoop:
        mov     eax,Red
        shr	eax,8
        and	al,3Fh
        out	dx,al
        mov     eax,Green
        shr	eax,8
        and	al,3Fh
        out	dx,al
        mov     eax,Blue
        shr	eax,8
        and	al,3Fh
        out	dx,al

        add	Red,128
        add	Green,128
        add	Blue,200

        .if	Blue >  64*256
         mov	Blue, 64*256 -1
        .endif

        dec	cl
	jnz	ColorLoop


        mov	esi,Offset mesg
@@: ;    mov	bx,003fh
    ;	mov	al,' '
    ;    mov	ah,9
    ;    mov	ecx,0
     ;   int	10h

        lodsb
        mov	ah,0eh
        mov	bx,008fh
	int	10h
        cmp	byte ptr [esi],'$'
        jne @b

;**************************************************************************
;**************************************************************************
MAIN_LOOP:

	CALL	Calc_Positions



        wait_retrace

        ;********************************************************
        ;************ plot/clear the new stars on the screen **********
        ;********************************************************

        mov     ebx,0
PlotLoop01:
        mov     dl,bl
        SetBank


        call    CHANGE_ACTIVE_BUFFER
        mov     eax,HideShow_StateCntr
        mov     Ecx,PosBufferCounter[ebx*4+eax]
        mov     PosBufferCounter[ebx*4+eax],0
       ;------------- clearing loop -------------------
       .IF    ECX != 0
                mov     esi,ebx
                shl     esi, NUM_STARS_2n + 2
                add     esi,Offset PosBuffer
                add     esi,HideShow_State
        clearloop02:
REPT 5
                dec     ecx
                mov     edi,[ecx*4+esi]
                mov     dword ptr [edi],0
                mov     dword ptr [edi+HORZ_RES],0
                jz  Cleardone
ENDM
                nop
                nop
                nop
                jmp     clearloop02
    Cleardone:

       .ENDIF



        call    CHANGE_ACTIVE_BUFFER
        mov     eax,HideShow_StateCntr
        mov     Ecx,PosBufferCounter[ebx*4+eax]

       ;------------- plotting loop -------------------
       .IF    ECX != 0

                mov     esi,ebx
                shl     esi, NUM_STARS_2n + 2
                lea     edi,[esi + Offset DistanceBuffer]
                add     esi,HideShow_State
                add     esi,Offset PosBuffer
        plotloop02:
REPT 5
                dec     ecx
                mov     edx,[ecx*4+esi]
                mov     eax,[ecx*8+edi]
                add     [edx],eax
                mov     eax,[ecx*8+edi+4]
                add     [edx+HORZ_RES],eax
                and	ecx,ecx
                jz  done
ENDM
                nop
                nop
                nop
                jmp     plotloop02
        done:
       .ENDIF


        inc     ebx
        cmp     ebx,BANKS_USED
        jb     PlotLoop01

        call    CHANGE_ACTIVE_BUFFER

;--------------------------------------------
; Read keys
;
;--------------------------------------------


        .if     Key == ESC_key
          jmp EXIT_MAIN_LOOP
        .endif
        .if	UpArrow_key_Flag
           Add  StepSpeed.Y, 1
        .endif
        .if LeftArrow_key_Flag
           Add  StepSpeed.X, 1
        .endif
        .if RightArrow_key_Flag
           Sub  StepSpeed.X, 1
        .endif
        .if DownArrow_key_Flag
           Sub  StepSpeed.Y, 1
        .endif
        .if Q_key_Flag
           Add  StepSpeed.Z, 1
        .endif
        .if A_key_Flag
           Sub  StepSpeed.Z, 1
        .endif
        .if I_key_Flag
           Add  StepAngle.Y, 1
        .endif
        .if M_key_Flag
           Sub  StepAngle.Y, 1
        .endif
        .if J_key_Flag
           Add  StepAngle.X, 1
        .endif
        .if K_key_Flag
           Sub  StepAngle.X, 1
        .endif
        .if _33_key_Flag	; <
           Add  StepAngle.Z, 1
        .endif
        .if _34_key_Flag	; >
           Sub  StepAngle.Z, 1
        .endif
        .if SpaceBar_key_Flag
           mov  StepSpeed.X,0
           mov  StepSpeed.Y,0
           mov  StepSpeed.Z,0
           mov  StepAngle.X,0
           mov  StepAngle.Y,0
           mov  StepAngle.Z,0
        .endif


        mov     eax, StepSpeed.X
        imul    eax
        cmp     StepSpeed.X,0
        jns @f
        neg	eax
@@:     sar	eax,2
        add     Look.X, eax
        mov     eax, StepSpeed.Y
        imul    eax
        cmp     StepSpeed.Y,0
        jns @f
        neg	eax
@@:     sar	eax,2
        add     Look.Y, eax
        mov     eax, StepSpeed.Z
        imul    eax
        cmp     StepSpeed.Z,0
        jns @f
        neg	eax
@@:     sar	eax,2
        add     Look.Z, eax

        mov     eax, StepAngle.X
        sar	eax,3
        add     Angle.X, eax
        mov     eax, StepAngle.Y
        sar	eax,3
        add     Angle.Y, eax
        mov     eax, StepAngle.Z
        add     Angle.Z, eax

        jmp MAIN_LOOP

EXIT_MAIN_LOOP:

      ; Return to TEXT mode
      ;
        mov     ax,3
        int     10h
        Jmp     Exit


@@ModeNotFound: ;<-----------------------------------------------------------
        Print 'VESA BIOS not found'
        jmp Exit

Exit: ;<---------------------------------------------------------------------

        mov     edx,OldIRQ1_vect[0]
        mov     ecx,OldIRQ1_vect[4]
        mov     ax,205h
        mov     bl,9
        int     31h

        mov     ax,4c00h
        int     21h

Start ENDP


end Start
[ RETURN TO DIRECTORY ]