home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Party 1994: Try This At Home
/
disk_image.bin
/
source
/
gallery
/
a_gallry.asm
< prev
next >
Wrap
Assembly Source File
|
1994-06-15
|
14KB
|
555 lines
; A_GALLRY.ASM -- Main program // A.R-M. 7/93
; (some minor mods, ARM 6/94)
; Assemble with /DSYNCHRO=0 to synchronize with DEMOVT's ticks
; =1 to synchronize with timer
; =2 to run w/o synchronization (when debugging)
; /DFRAMES =0 to count frames rendered (var PICTURECOUNT)
IFNDEF SYNCHRO
SYNCHRO = 2 ; (default: neither DemoVT nor timer)
ENDIF
Ideal
MODEL FarStack Compact, Pascal
Radix 10
P286
STACK 16384d ; actually, this program probably doesn't even
; use 1k of stack, but you can't trust residents!
MACRO DefWall south, west, north, east
IRP name, <south,west,north,east>
dw offset name, seg name
ENDM
ENDM
MACRO DefTex name
FARDATA S_&name
EXTRN W_&name : Byte
ENDM
INCLUDE "globals.inc"
INCLUDE "a_ray_t.inc"
CODESEG
;*EXTRN PonPaletaInicial : NEAR ; (last minute hack)
;*EXTRN PonPaletaFinal : NEAR
IF SYNCHRO EQ 0
EXTRN InitMusic : NEAR ; This is VT stuff...
EXTRN CallMusic : NEAR ; ...I don't understand it either! }:-)
EXTRN VTConnectTimer : NEAR
EXTRN VTDisconnectTimer : NEAR
EXTRN VTGetTickCounter : NEAR
EXTRN VTBeginSync : NEAR
EXTRN VTWaitForStart : NEAR
ENDIF
EXTRN RasterOff : NEAR
EXTRN RasterOn : NEAR
EXTRN InitPageMode : NEAR
EXTRN SetActivePage : NEAR
EXTRN SetViewPage : NEAR
EXTRN BlankPage : NEAR
EXTRN Render : NEAR
EXTRN EyeHeight : NEAR
EXTRN InitProjection : NEAR
EXTRN ReFloor : NEAR
EXTRN InitColumnMemory : NEAR
DATASEG
EXTRN FogDensity : Byte
ScriptPtr DD ? ; seg:ofs to script
IF SYNCHRO NE 0
TIMER DD ?
ENDIF
TIMER0 DD ? ; timer count when animation started
LastTimer DD ? ; last timer count (to avoid repeating same scene)
DONE DW ? ; =1 when end of script reached
CurPage DW 0 ; current page, I use pages 0,1,2 of the 0..3 available
;* YaCambiadaPaleta DB 0
LastEye DW 255d ; last eye height (to avoid recalculating proj parms)
LastFog DB 255d ; last fog density (3..10) (avoid loading new fog textures)
IFDEF FRAMES
PICTURECOUNT DW 0 ; this is only for speed measurements,
ENDIF ; it counts total no. of scenes generated
RAY SRay <> ; position&attitude of observer for ray trace
; * Assign textures to block walls *
; Each line defines 4 textures for SWNE walls of blocks with
; codes 1,2,3,... (0 is empty block)
; south west north east
MapTextures:
; 1 Exterior wall
DefWall w_outsid, w_outsid, w_outsid, w_outsid
; 2..6 "Inconexia" logo (or anything else)
DefWall w_pic9, w_outsid, w_outsid, w_outsid
DefWall w_pic9, w_outsid, w_outsid, w_outsid
DefWall w_pic9, w_outsid, w_outsid, w_outsid
DefWall w_pic9, w_outsid, w_outsid, w_outsid
DefWall w_pic9, w_outsid, w_outsid, w_outsid
; 7 Entrance wall
DefWall w_outsid, w_indoor, w_outsid, w_outsid
; 8 Indoor white wall
DefWall w_indoor, w_indoor, w_indoor, w_indoor
; 9 -dummy-
DefWall w_indoor, w_indoor, w_indoor, w_indoor
; 10: full screen (320x200 image)
DefWall w_indoor, w_finale, w_indoor, w_indoor
; 11.. pictures
DefWall w_pic1, w_pic1, w_pic1, w_pic1 ; 11
DefWall w_pic2, w_pic2, w_pic2, w_pic2 ; 12
DefWall w_indoor, w_pic3, w_indoor, w_indoor ; 13
DefWall w_indoor, w_indoor, w_pic4, w_indoor ; 14
DefWall w_pic5, w_pic5, w_pic5, w_pic5 ; 15
DefWall w_pic6, w_pic6, w_pic6, w_pic6 ; 16
DefWall w_pic7, w_pic7, w_pic7, w_pic7 ; 17
DefWall w_pic8, w_pic8, w_pic8, w_pic8 ; 18
DefWall w_pic9, w_pic9, w_pic9, w_pic9 ; 19
DefWall w_pic10,w_pic10,w_pic10,w_pic10 ; 20
DefWall w_pic11,w_pic11,w_pic11,w_pic11 ; 21
DefWall w_pic12,w_pic12,w_pic12,w_pic12 ; 22
DefWall w_pic13,w_pic13,w_pic13,w_pic13 ; 23
DefWall w_pic3, w_indoor, w_indoor, w_indoor ; 24-
; └─ end of DATASEG ─┘
; * Declare external texture maps * (these are FARDATA segs)
DefTex Outsid ; outdoors wall texture
DefTex Indoor ; indoors wall texture
DefTex Finale ; 320x200 unscaled picture to use in the end
DefTex Pic1 ; picture 1
DefTex Pic2 ; picture 2
DefTex Pic3 ; picture 3
DefTex Pic4 ; picture 4
DefTex Pic5 ; picture 5
DefTex Pic6 ; picture 6
DefTex Pic7 ; picture 7
DefTex Pic8 ; picture 8
DefTex Pic9 ; picture 9
DefTex Pic10 ; picture 10
DefTex Pic11 ; picture 11
DefTex Pic12 ; picture 12
DefTex Pic13 ; picture 13
; Script segment
FARDATA ScriptSeg
; key-frame info structure
STRUC SKey
Time dd ? ; time (no. counts)
Xpos dd ? ; X position (in 1/65536 units of map cell)
Ypos dd ? ; Y position
Angle dw ? ; bearing in 45°/256/16 units (/16 to avoid rounding errors)
Eye db ? ; eye height, 1..199
Fog db ? ; fog density (3..10)
ENDS
Script:
INCLUDE "data\script.inc" ; this is the script that will be executed
; code segment
CODESEG
IF SYNCHRO EQ 1
; Timer interrupt routine (obsolete)
OrgInt08 DD ?
TimerInt:
pushf
push ax
push ds
mov ax, seg TIMER
mov ds, ax
P386
add [TIMER],3 ; increment timer count (3 ≈ 50Hz/18.1Hz)
P286
pop ds
pop ax
popf
jmp [dword ptr cs:OrgInt08] ; continue w/ org int 8 routine...
; Install timer routine (obsolete)
PROC InstallTimer NEAR
USES ax, bx, dx, ds, es
; get original INT 08 vector
mov ax, 3508h
int 21h ; es:bx -> int8
mov [word ptr cs:OrgInt08], bx
mov [word ptr cs:OrgInt08+2], es
; intercept INT 08
mov ax,cs
mov ds,ax
mov dx, offset TimerInt
mov ax, 2508h
int 21h
ret
ENDP
; Remove timer routine from INT (obsolete)
PROC KillTimer NEAR
pusha
; restore INT 08
push ds
mov ax,[word ptr cs:OrgInt08+2]
mov dx, [word ptr cs:OrgInt08]
mov ds,ax
mov ax, 2508h
int 21h
pop ds
popa
ret
ENDP
ENDIF ; if SYNCHRO EQ 1
; Script Draw
PROC ScriptDraw NEAR
ARG Time : dWord
P386
LOCAL tmT0 : DWORD, T1mT0 : DWORD, DoRefloor : Byte
pushad
push fs
push [CurPage]
call SetActivePage ; set page where we'll draw...
mov edx, [Time] ; get time
lfs di, [ScriptPtr]
@@KeepUp:
add di,SIZE SKey
cmp [fs:di+SKey.Time],edx
jbe @@KeepUp
mov al, [fs:di+SKey.Fog]
cmp al, 255d
sete [byte ptr DONE]
sub di,SIZE SKey ; fs:di -> SKey w/ .Time <= Time
mov [word ptr ScriptPtr], di
mov eax, [fs:di+SKey.Time]
mov ebx, [fs:(di+SIZE SKey)+SKey.Time]
sub ebx, eax
mov [T1mT0], ebx ; T1-T0
mov ebx, [Time]
sub ebx, eax
mov [tmT0], ebx ; t-T0
; Plenty of mul's and div's here, but there's something like
; 50 times more of them per scene to calculate projection,
; and even so that only makes for a small fraction of total
; execution time, so hey, who cares! |-)
; interpolate Xpos:
mov eax, [fs:(di+SIZE SKey)+SKey.Xpos] ; eax = X1
mov ebx, [fs:di+SKey.Xpos] ; eax = X0
sub eax, ebx
imul [tmT0] ; eax = (X1-X0)(t-T0)
idiv [T1mT0] ; eax = (X1-X0)(t-T0)/(T1-T0)
add eax, ebx ; eax = (X1-X0)(t-T0)/(T1-T0)+X0 = X
mov bx, ax
shr bx,1 ; from 0..65535 to 0..32767
mov [RAY.FineX], bx
shr eax,16
mov [RAY.MapX], al
; interpolate Ypos:
mov eax, [fs:(di+SIZE SKey)+SKey.Ypos]
mov ebx, [fs:di+SKey.Ypos]
sub eax, ebx
imul [tmT0]
idiv [T1mT0]
add eax, ebx
mov bx, ax
shr bx,1
mov [RAY.FineY], bx
shr eax,16
mov [RAY.MapY], al
; interpolate Angle:
movzx eax, [fs:(di+SIZE SKey)+SKey.Angle]
movzx ebx, [fs:di+SKey.Angle]
sub eax, ebx
imul [tmT0]
idiv [T1mT0]
add eax, ebx
; shr eax,8 ; this has to do w/ the units used in script for angles
mov bx, ax
xor bh, bh
mov [RAY.Angle], bx
shr ax,8
and ax,0007
mov [RAY.Sector], ax
mov [DoRefloor], 0 ; won't load new floor texture if DoRefloor=0
; interpolate Eye height:
xor eax,eax
mov al, [fs:(di+SIZE SKey)+SKey.Eye]
xor ebx,ebx
mov bl, [fs:di+SKey.Eye]
sub eax, ebx
imul [tmT0]
idiv [T1mT0]
add eax, ebx
cmp ax, [LastEye]
je @@sameEye
mov [LastEye], ax
push ax
call EyeHeight
mov [DoRefloor], 1 ; new eye height needs new floor texture
@@sameEye:
; update Fog if necessary
mov al,[fs:di+SKey.Fog]
cmp al, [LastFog]
je @@sameFog
mov [LastFog], al
mov [FogDensity], al
mov [DoRefloor], 1 ; new fog density also needs new floor
@@sameFog:
cmp [DoRefloor],1
jne @@norefloor
call ReFloor
@@norefloor:
push [CurPage]
call SetActivePage
push offset RAY ; pos&att of observer
push offset MapTextures ; texture-map map ;-) address
call Render
mov ax, [CurPage]
push ax
call SetViewPage
inc ax ; next page
cmp ax,3 ; use only 0,1, and 2
jb @@1
xor ax, ax
@@1:
mov [CurPage],ax
pop fs
popad
ret
P286
ENDP
; === MAIN PROGRAM ===
STARTUPCODE
; initialize video mode
mov ax,13h ; enter VGA 320x200x256 mode
int 10h
call RasterOff ; Disable raster so we don't show
; garbage on screen while setting up
call InitPageMode ; initialize memory mapping
push 0
call SetActivePage
call BlankPage
push 0
call SetViewPage ; start w/ view page 0 (black)
;* call PonPaletaInicial
call RasterOn ; Done w/ setup, enable raster again.
call InitColumnMemory
; initialize projection
push WindowHeight ; screen height
push DistToScreen ; obs dist to screen
push 100d ; eye height
push WallHeight ; wall height
call InitProjection
call ReFloor
; start drawing on page 1
mov [CurPage],1
P386
; set pointer to beginning of script
mov [word ptr ScriptPtr+2], seg Script
mov [word ptr ScriptPtr], offset Script
; draw first frame
mov [LastTimer], 0ffffffffh
mov [TIMER0], 0
IF SYNCHRO EQ 1
mov [TIMER],0 ; reset TIMER
mov [DONE], 0 ; set DONE to false
call InstallTimer
ENDIF
IF SYNCHRO EQ 0
call InitMusic
or al,al
jz @@bail
; call VTdisconnectTimer
call VTconnectTimer
call VTBeginSync
call VTWaitForStart
call VTgetTickCounter
xor eax, eax
mov [TIMER0], eax
ENDIF
push 0
push 0
call ScriptDraw
@@SCRIPT_LOOP:
mov ah,1
int 16h
jnz @@LEAVE
IF SYNCHRO EQ 0
; REPT 16
; call CallMusic ; doctor's orders... :-?
; ENDM
call VTGetTickCounter
ELSE
IF SYNCHRO EQ 2
add [TIMER], 10d
ENDIF
mov eax, [TIMER]
ENDIF
;* cmp [YaCambiadaPaleta], 1
;* je @@salta
;* cmp eax, 1970d ; change pallete at 1970 ticks (hack)
;* jb @@salta
;* push eax
;* call PonPaletaFinal
;* pop eax
;* mov [YaCambiadaPaleta], 1
@@salta:
cmp eax, [LastTimer]
je @@SCRIPT_LOOP
mov [LastTimer], eax
sub eax, [TIMER0]
push eax
call ScriptDraw
IFDEF FRAMES
inc [PICTURECOUNT] ; count frames/sec
ENDIF
cmp [DONE],1
jne @@SCRIPT_LOOP
@@LEAVE:
IF SYNCHRO EQ 1
call KillTimer
ENDIF
IF SYNCHRO EQ 0
; call VTConnectTimer
ENDIF
@@bail:
mov ax,3 ; reset text mode
int 10h
mov ax,4c00h ; done
int 21h
END