;**************************************************************************
;
;
; 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