;		   ----====> Omniscent <====----
;
;
;   Omniscent was done by Pinker of SANCTION for the Mekka '97. The song
;   was written by Nyphton. It place XXX out of XXX.
;
;   Special thanks in alphabetical order :
;
;       Andreas Mautsch     (beta testing)
;       Axel Scheel Meyer   (MACM sources, nice IRC chat's)
;       Christian Cohnen    (for his help on perspective texture mapping and
;	   		designing world and script)
;       Daniel Weinand	    (song)
;       Funk                (for give me the idea trying a 4K Descent)
;       Stephanie Schepers  (moral and food support ;-) )
;
;       and all other SANCTION dudes for supporting this product !

                .386
                .387
                ideal
                ASSUME 	cs:Code,ds:Code

SEGMENT CODE PUBLIC use16
		org   100h
;==============================================================================
;		   constants
;==============================================================================

                GMPort		= 0331h
		CMD_NOTEON      = 090h
		CMD_NOTEOFF     = 080h
                CMD_CHANGEPARAM = 0B0h
		CMD_CHANGEPRG   = 0C0h
                MOD_ALLNOTESOFF = 07Bh
                MAXFACES	= 400
                MAXPOINTS	= 400
                SONGSPEED   	= 29
                XMAX		= 320
                YMIN		= 21
	  	YMAX		= 179
        	SUBRANGE	= 16
                ASPECT_RATIO	EQU 1.2
                CENTERX		= 160
                CENTERY		= 100

;==============================================================================
;		   structures
;==============================================================================
struc channel
 del		dw	?
 trk		db	?
 ln		db	?
 adr		dw	?
ends

struc matrix
		dd	9 dup (?)
ends

struc vector
 x		dd	?
 y		dd	?
 z		dd	?
ends

struc point
 x		dw	?
 y		dw	?
 z		dw	?
 s		dw	?
ends

struc face
		dw	5 dup (?)
ends

struc object
 panz		dw	?
 fanz		dw	?
 p		point	MAXPOINTS dup (?)
 f		face	MAXFACES dup (?)
ends

struc edges
 x		dd	?
 u		dd	?
 v		dd	?
 w		dd	?
 s		dd	?
ends

struc edge
 p		vector  ?
 py		dd	?
 e		edges	?
ends

struc poly
		edge    5 dup (?)
ends

;==============================================================================
;		      macros
;==============================================================================
;***********************************************
;* descript. : start timer interrupt 70/s      *
;* parameter : none			       *
;* sideeffect: all		 	       *
;* back      : none			       *
;* length    : 27 bytes			       *
;***********************************************
macro		startTimer
                mov     ax,03508h
                int     21h
                mov     [word ptr Old08Irqseg],es
                mov     [word ptr Old08Irqofs],bx
                mov     ax,02508h
                mov     dx,offset irqHandler08
                int     21h
                mov     bx,3409			; 350 ticks per second
                call    setTimer
endm

;***********************************************
;* descript. : stop timer interrupt            *
;* parameter : none			       *
;* sideeffect: all		 	       *
;* back      : none			       *
;* length    : 16 bytes			       *
;***********************************************
macro		stopTimer
                push    ds
                xor     bx,bx                   ; set timer to default
                call    setTimer		; 18.2 ticks per second
                mov     ax,02508h               ; restore old IRQ-vector
                lds     dx,[Old08Irqptr]
                int     21h
                pop     ds
endm

;***********************************************
;* descript. : start keyboard handler          *
;* parameter : none			       *
;* sideeffect: all		 	       *
;* back      : none			       *
;* length    : 4 bytes		 	       *
;***********************************************
macro		startKBDHandler
                mov     ax,03509h
                int     21h
                mov     [word ptr Old09Irqseg],es
                mov     [word ptr Old09Irqofs],bx
                mov     ax,02509h
                mov     dx,offset irqHandler09
                int     21h
endm

;***********************************************
;* descript. : stop keyboard handler           *
;* parameter : none			       *
;* sideeffect: all		               *
;* back      : none		               *
;* length    : 4 Bytes		               *
;***********************************************
macro		stopKBDHandler
                push    ds
                mov     ax,02509h               ; restore old IRQ-vector
                lds     dx,[Old09Irqptr]        ;
                int     21h
                pop     ds
endm

;***********************************************
;* descript. : zero null-initialized data      *
;* parameter : none			       *
;* sideeffect: all		               *
;* back      : none		               *
;* length    : ??? bytes		       *
;***********************************************
macro		nullData
                mov	di,offset nullstart
                mov	cx,nullend-nullstart
                xor	al,al
                rep	stosb
endm

;***********************************************
;* descript. : set textmode		       *
;* parameter : none		               *
;* sideeffect: all		               *
;* back      : none		               *
;* length    : 5 bytes		               *
;***********************************************
macro		set80x25
                mov     ax,03h
                int     10h
endm

;***********************************************
;* descript. : set gfx-mode 320x200            *
;* parameter : none		               *
;* sideeffect: all		               *
;* back      : none		               *
;* length    : 6 bytes		               *
;***********************************************
macro		set320x200
                mov     ax,13h
                int     10h
endm

;***********************************************
;* descript. : calculate a smooth colorrange   *
;* parameter : none             	       *
;* sideeffect: all              	       *
;* back	     : none                	       *
;* length    : 50		               * 
;***********************************************
macro		makePalette
              	push    ds
               	pop     es
	        mov     bx,3
mPcolor:        mov	si,offset colors
                mov     di,offset palette
                xor	dh,dh
                lodsb
                movzx	cx,al
mPouter:       	push    cx
                mov     cl,[byte ptr si]
                mov     ah,[byte ptr si+bx]
                sub     ax,dx
                push    dx
                cwd
                idiv    cx
                pop     dx
mPinner:        add     dx,ax
                mov     [byte ptr es:di+bx-1],dh
                add     di,3
                loop    mPinner
                add     si,4
    	        pop     cx
                loop    mPouter
        	dec     bx
            	jne     short mPcolor
endm

;***********************************************
;* descript. : reset the GM-Port and switch to *
;*             UART mode.		       *
;* parameter : none			       *
;* sideeffect: dx,al		               *
;* back      : none		               *
;* length    : 26 bytes		               *
;***********************************************
macro		resetGM
                mov	dx,GMPort
    		mov   	ax,00FFh
    		out   	dx,al
resGMbusy1:     dec	ah
                je	short rGMerror       ;{ timeout }
                in	al,dx		 ;{ read acknowledge }
            	test	al,80h
                jnz	short resGMbusy1
		dec	dx
	        in	al,dx
                cmp	al,0FEh
                jne	short rGMerror
                inc  	dx                   ;{ switch into UART mode }
resGMbusy2: 	in	al,dx
		test	al,40h
        	jnz	short resGMbusy2
	    	mov   	al,03Fh
        	out	dx,al
rGMerror:
endm		resetGM

;***********************************************
;* descript. : mute midi channels 0..15        *
;* parameter : none                	       *
;* sideeffect: ax,cx		               *
;* back		 : none                	       *
;* length    : ??? bytes		       *
;***********************************************
macro		silence
		mov	cx,15
Siloop:         mov	ax,cx
                add     al,CMD_CHANGEPARAM
                call    writeGM
                mov     al,MOD_ALLNOTESOFF
                call    writeGM
                xor     al,al
                call    writeGM
                loop	Siloop
Sinosound:
endm		silence

;***********************************************
;* descript. : create the reactor wall texture *
;* parameter : none		               *
;* sideeffect: ax,bx,cx,di,es                  *
;* back      : none			       *
;* length    : 45 bytes		               *
;***********************************************
macro		reactorWall
                mov	es,[word ptr tseg]
        	xor	di,di
        	mov	cx,4096
rsmloop:	mov	ax,di
                test	al,8
                jle	short rsnonot1
            	not	al
rsnonot1:  	and	al,15
                mov	bx,ax
                mov	ax,di
            	shr	ax,6
            	test	al,8
            	jle	short rsnonot2
            	not	al
rsnonot2:   	and	al,15
                cmp	al,bl
            	jle	short rstakeal
            	mov	ax,bx
rstakeal:	add	al,224
            	stosb
                loop	rsmloop
endm		reactorWall

;***********************************************
;* descript. : calc background-fractal         *
;* parameter : none		               *
;* sideeffect: ax,cx,di,es		       *
;* back      : none			       *
;* length    : 34 bytes			       *
;***********************************************
macro		createFrac2
                mov	es,[word ptr tseg+36]
                mov     al,20
                call	setFrac
                mov	di,64
                mov     cx,4096-64
cF1loop:	mov     bx,4
                call    rnd
                add     al,[byte ptr es:di-64]
                add     al,[byte ptr es:di-63]
                dec   	ax
                shr	ax,1
                stosb
                loop   	cF1loop
endm		createFrac2

;***********************************************
;* descript. : calc random noise fractal       *
;* parameter : none		               *
;* sideeffect: ax,bx,cx,si,di,es               *
;* back      : none			       *
;* length    : 25 bytes			       *
;***********************************************
macro		createFrac3
                mov	es,[word ptr tseg+38]
                mov	al,3
                call	setFrac
                mov     cx,4096
cF3loop:        mov     bx,4096
                call    rnd
                mov     di,ax
                inc     [byte ptr es:di]
                loop    cF3loop
endm		createFrac3

;***********************************************
;* descript. : init stars (positions and state)*
;* parameter : none			       *
;* sideeffect: eax,bx,cx,edx,si,di,es          *
;* back      : none		               *
;* length    : 27 bytes		               *
;***********************************************
macro		initStars
                push	ds
                pop	es
  	        mov	cx,30
                mov	di,offset stars
iSloop:         mov	bx,256
                call    rnd
                stosb
		mov	bx,4096-64*5
                add	bx,128
                call	rnd
                add	ax,64
                stosw
                loop	iSloop
endm		initStars

;***********************************************
;* descript. : add effects to fractals	       *
;* parameter : none		               *
;* sideeffect: ax,bx,cx,di,es		       *
;* back      : none		               *
;* length    : 73 bytes		               *
;***********************************************
macro		effects
                mov	cx,26
                mov	si,offset aE
effmloop:	push	cx
                mov	bl,[si]			; mseg+effect
                mov	dl,bl
                shr	dl,4
                and	bx,15
                add	bx,bx
                mov	es,[word ptr tseg+bx]
		movzx	cx,[byte ptr si+2]	; y1
effyloop:       movzx	bx,[byte ptr si+1]      ; x1
effxloop:	mov	di,cx
		shl	di,6
		add	di,bx
		mov	al,dl
		dec	al
		je	short effect1
		dec	al
		je	short effect2
effect3:	mov	ax,bx
                add	ax,cx
		and	al,4
		je	short effdonot
		mov	al,152
effdonot:	jmp	short effect1
effect2:	mov	al,[es:di]
effect1:	add	al,[byte ptr si+5]	; value
		mov	[es:di],al
		inc	bx
		cmp	bl,[si+3]      		; x2
		jle     short effxloop
		inc	cx
		cmp	cl,[si+4]               ; y2
		jle	short effyloop
                add	si,6
                pop	cx
                loop	effmloop
endm		effects

;***********************************************
;* descript. : copy fractals and add value     *
;* parameter : none		               *
;* sideeffect: al,cx,di,es,fs		       *
;* back      : none		               *
;* length    : 40 bytes		               *
;***********************************************
macro		addFractals
		mov	si,offset aF
        	mov	dl,4
aFloop:		movzx	bx,dl
                mov	es,[word ptr tseg+bx]
                lodsw
                mov	bl,al
                mov 	fs,[word ptr tseg+bx]
                xor	di,di
        	mov	cx,4096
aFiloop:	mov	al,[fs:di]
		add	al,ah
		stosb
            	loop	aFiloop
                inc	dx
                inc	dx
		cmp	dl,30
		jle	short aFloop
endm		addFractals

;***********************************************
;* descript. : calculate and initalize textures*
;* parameter : none			       *
;* sideeffect: al,cx,di,es,fs		       *
;* back      : none			       *
;* length    : 40 bytes		 	       *
;***********************************************
macro		addLava
                mov	es,[word ptr tseg+22]
                mov     di,4095
                mov	cx,20
                mov	al,94
aLyloop:	push	cx
                shl	cx,3
aLxloop:        push	di
                push	ax
         	mov	bx,64
            	call	rnd
                sub	di,ax
                pop	ax
                stosb
                pop	di
                loop	aLxloop
	        pop	cx
                dec	al
                sub	di,64
                loop	aLyloop
endm		addLava

;***********************************************
;* descript. : calculate and initalize textures*
;* parameter : none		               *
;* sideeffect: al,cx,di,es,fs		       *
;* back      : none		               *
;* length    : 40 bytes		               *
;***********************************************
macro		initTextures
                mov	bx,34
		push	800
       	 	push	5
        	call	createFrac1
                mov	bx,32
		push	112
        	push	15
        	call	createFrac1
        	createFrac2
        	createFrac3
      		initStars
        	reactorWall
                addFractals
                effects
                addlava
endm		initTextures

;***********************************************
;* descript. : cycle "range" colors at "base"  *
;* parameter : none		               *
;* sideeffect: ax,(bl),cx,si,di,es             *
;* back      : none			       *
;* length    : 16 bytes (20 bytes)             *
;***********************************************
macro		colorCycle
                base=6*32
                range=32

		push	ds
                pop	es
                mov	di,offset palette+(base*3)
                mov	si,di

                lodsw
;               mov	bl,[si]			; works only with fire (no blue)
                inc	si
                mov	cx,(range*3-3)
                rep	movsb
                stosw
;               mov	[di],bl			; works only with fire (no blue)
endm		colorCycle

;***********************************************
;* descript. : animate the stars	       *
;* parameter : none			       *
;* sideeffect: ax,bx,cx,dl,si,di,es            *
;* back      : none			       *
;* length    : 58 bytes			       *
;***********************************************
macro		animStars
		base=7*32

                mov	es,[word ptr tseg+2]
                call	clearFrac

		mov	cl,30
                mov	bx,offset stars
aSoloop:        dec	[byte ptr bx]
                mov	ah,[byte ptr bx]
                and     ah,63
            	cmp	ah,31
            	jbe	short aSnonot
                not	ah
                and     ah,31
aSnonot:        shr	ah,1
                mov	di,[word ptr bx+1]
	        push	cx
                push	bx

                mov	dx,64-5
                mov	cx,base*256+0
                call	setstarbob

                pop	bx
                pop	cx
        	add	bx,3
                loop	aSoloop
endm		animStars

;***********************************************
;* descript. : calculate shading tab           *
;* parameter : none		               *
;* sideeffect: ax,bl,cx,di,es                  *
;* back      : none		               *
;* length    : 45 bytes		               *
;***********************************************
macro		calcShadeTab
                push	ds
                pop	es
                mov	di,offset shadetab
		xor	bl,bl
cSolp:		inc	bl
		xor	cx,cx
cSilp1:        	mov	al,cl
		and	al,31
                mul	bl
                add	ax,ax
                mov	al,cl
                and	al,224
                add	al,ah
                stosb
		inc	cl
                cmp	cl,192
        	jne	short cSilp1
cSilp2:        	mov	al,cl
                stosb
 		inc	cl
        	jne	short cSilp2
		cmp	bl,128
                jne	short cSolp
endm		calcShadeTab

;***********************************************
;* descript. : expand a song       	       *
;* parameter : si:song base adress	       *
;* sideeffect: ax,bx,cx,dx,si,di               *
;* back      : none                	       *
;* length    : 40 bytes		               *
;***********************************************
macro		expandSong
                mov	si,offset credits
                mov	bx,offset channels
                mov	di,offset songdata
EPSwhile:	lodsw
                dec	al
                js      short EPSendwhile
                mov	[(channel ptr bx).trk],al
                add	al,CMD_CHANGEPRG
                call	setinstr
                mov	[(channel ptr bx).adr],di
               	call	expand
                xor	al,al
                stosb
                add	bx,6
                inc	[word ptr tracks]
                jmp	short EPSwhile
EPSendwhile:
endm		expandSong

;***********************************************
;* descript. : parse the script,rotate and move*
;* parameter : none                	       *
;* sideeffect: all		               *
;* back      : none		               *
;* length    : ??? bytes		       *
;***********************************************
macro		scriptIt
                mov	cx,[word ptr ticker]
                mov	[word ptr ticker],0
                or	cx,cx
                je      sItickerNull
sImloop:        push	cx
                mov	si,offset zspeed
                dec	[word ptr si+10]
                jns	short sIwaitTimer
		mov	bx,[word ptr si+8]
		mov	al,[byte ptr script+bx]
		or	al,al
		je	exit
		mov	bx,ax
		and	bl,7
		mov	[byte ptr si+12],bl
		dec     bl
		jne	short sInegateTurn
		neg     [word ptr zstep]
sInegateTurn:	and	ax,000f8h
		add	ax,ax
		mov	[word ptr si+10],ax
		inc	[word ptr si+8]
sIwaitTimer:	mov	al,[byte ptr si+12]
		cbw
                dec	ax
		jne	short sInoturn
                mov	bx,[word ptr zstep]
		add     [word ptr si+6],bx
sInoturn:	mov	cx,3
sIrotateLoop:	dec	ax
		jne	short sInoIncrement
		inc	[word ptr si]
sInoIncrement:	dec	ax
		jne	short sInoDecrement
		dec	[word ptr si]
sInoDecrement:	inc	si
		inc	si
		loop	sIrotateLoop

		mov	si,offset zspeed+2
		mov	cl,3
sIpushloop:	lodsw
                sar	ax,2
		push	ax
                loop	sIpushloop

		imul	ax,[word ptr si-4],16
                push	ax
                call	calcRotMat

		mov	cl,3
		xor	si,si
sImoveLoop:	fld	[dword ptr owmat+24+si]
		fimul	[word ptr zspeed]
                fidiv	[word ptr CONST1792]
                fadd	[dword ptr ob+si]
                fstp	[dword ptr ob+si]
                add	si,4
		loop	sImoveLoop
                pop	cx
                dec	cx
                jne     sImloop
sItickerNull:
endm		scriptit

;***********************************************
;* descript. : rotate all points from o -> rp  *
;* parameter : none                	       *
;* sideeffect: all		               *
;* back      : none		               *
;* length    : 65 bytes		               *
;***********************************************
macro		rotation
                mov	cx,[word ptr o.panz]
		mov	si,offset o.p
        	mov     di,offset rp
rotmlp:         mov	bx,offset wmat
		mov	dx,3
rotilp:		fild	[word ptr si+0]
                fsub	[(vector ptr ob).x]
                fmul    [dword ptr bx+0]
    		fild	[word ptr si+2]
                fsub	[(vector ptr ob).y]
                fmul    [dword ptr bx+4]
    		fild	[word ptr si+4]
                fsub	[(vector ptr ob).z]
                fmul    [dword ptr bx+8]
                fadd
                fadd
                fstp	[dword ptr di]
                add	di,4
                add	bx,12
                dec	dx
                jne   	short rotilp
                add     si,8
            	loop	rotmlp
endm		rotation

;***********************************************
;* descript. : sort faces by z-koord	       *
;* parameter : none		               *
;* sideeffect: ax,bx,cx,dx,si,di,es            *
;* back      : none		               *
;* length    : 50 bytes		               *
;***********************************************
macro		sortFaces
                push	ds
                pop	es
                mov	di,offset facei
	        push	di 		; facei
                mov	si,offset o.f
                mov	ax,si                	; pointer to faces
                mov	cx,[word ptr o.fanz]
sFmloop:        fldz
                push	cx
                mov	cx,4
sFiloop:	imul	bx,[word ptr si],12
                inc	si
		inc	si
		fsub	[(vector ptr rp+bx).z]
                loop	sFiloop
                pop	cx

		fistp	[word ptr di]
                inc	di
                inc	di
                stosw
                add	ax,10
		inc	si
                inc	si
                loop	sFmloop
                push	di			; facei+4*(o.fanz-1)
                call	qsort
endm		sortFaces

;***********************************************
;* descript. : animate the door  	       *
;* parameter : none		               *
;* sideeffect: ax,cx,si,di,es                  *
;* back      : none		               *
;* length    : 63 bytes		               *
;***********************************************
macro		animDoor
    		mov	ax,[word ptr doortimer]
                or	ax,ax
		jns	short aDnounder
            	xor	ax,ax
                jmp	short alreadydrawed
aDnounder:      cmp	[byte ptr once],0
                jne	short alreadydrawed
                inc	[byte ptr once]
                push	ax
	        starbackground
                pop	ax
alreadydrawed:	cmp	ax,24
                jle	short aDnoover
                mov	ax,24
aDnoover:       shl	ax,6
		push	ds
                mov	es,[word ptr tseg+26]
                mov	ds,[word ptr tseg+30]
		mov	si,ax
                xor	di,di
                mov	cx,1024
                rep	movsw
                mov	si,2048
                sub	si,ax
                push	si
                mov	ch,4
                rep	movsw
                pop	di
                mov	cx,ax
                xor	ax,ax
                rep	stosw
                pop	ds
endm		animDoor

;***********************************************
;* descript. : play a tick of the song	       *
;* parameter : none                	       *
;* sideeffect: ax,bx,cx,dx,si		       *
;* back      : none                	       *
;* length    : 64 bytes		               *
;***********************************************
macro		playsong
    		mov	cx,[word ptr tracks]
                mov	si,offset channels
PSmloop:        dec	[(channel ptr si).del]
                jg	short PSdelayed
		mov	ax,[word ptr (channel ptr si).trk]
                add	al,CMD_NOTEOFF
		call	setnote
                mov	bx,[(channel ptr si).adr]
                mov	ah,127
                cmp	[byte ptr bx],0
		je	short PStrackend
		mov	ah,[byte ptr bx]
		mov	[(channel ptr si).ln],ah
		mov	al,[(channel ptr si).trk]
		add	al,CMD_NOTEON
		call	setnote
                mov	al,[byte ptr bx+1]
                mov	bl,SONGSPEED
                mul	bl
PStrackend:	mov	[(channel ptr si).del],ax
		add	[(channel ptr si).adr],2
PSdelayed:	add	si,6
		loop	PSmloop
PSnosound:
endm		playsong

;***********************************************
;* descript. : dump palette to CRT             *
;* parameter : bl:intensity (0..255)           *
;* sideeffect: ax,es,di,cx,dx                  *
;* back      : none		               *
;* length    : 27		               *
;***********************************************
macro		setPalette2
               	xor     al,al
               	mov     dx,03c8h
               	out     dx,al
               	inc     dx
               	mov     si,offset palette
               	mov     cx,768
                rep 	outsb
endm		setPalette2

;***********************************************
;* descript. : clear starbackground            *
;* parameter : none		               *
;* sideeffect: ax,es,di,cx,dx                  *
;* back      : none		               *
;* length    : ???		               *
;***********************************************
macro		cls
                push	ds
                mov	es,[word ptr bseg]
                push	0a000h
                pop	ds
                mov	si,320*5
                xor	di,di
		mov	cx,32000
clsloop:	lodsb
	        stosb
	        stosb
                loop	clsloop
                pop	ds
endm		cls

;***********************************************
;* descript. : draw starbackground             *
;* parameter : none		               *
;* sideeffect: ax,es,di,cx,dx                  *
;* back      : none		               *
;* length    : ???		               *
;***********************************************
macro		starbackground
                mov	es,[word ptr bseg]
                mov	cx,100
starbackloop:	push	cx
                mov	bx,320*155
                call	rnd
                add	ax,320*20
                mov	di,ax
                and	ah,7
                mov	dx,320-5
                mov	cx,0002h
                call	setstarbob
                pop	cx
                loop	starbackloop
endm		starbackground

;=============================================================================
;               entry point
;=============================================================================
;***********************************************
;* descript. : entry point		       *
;* parameter : none		               *
;* sideeffect: all		               *
;* back      : none		               *
;* length    : ??? bytes	               *
;***********************************************
proc		start
                mov     ax,cs                  	;
                mov	ds,ax			; packer kills ds !!!!!
                mov     di,offset vseg
		add     ax,01000h
                stosw		; virtuel screen address
                add	ax,01000h
                stosw		; starbackground address
                add	ax,01000h
                mov     cx,20
segloop:        stosw		  	; texture adresses
        	inc	ah
                loop    segloop

                nullData			;  ES = DS !!!
                resetGM
		expandSong	          	;  ES = DS !!!
                call createWorld		;  ES = DS !!!
		Set320x200

                xchg	ah,al
                mov	bx,0001ch
                mov	bp,offset omniscent
                mov	cx,omniend-omniscent
                mov	dx,00106h
                int	10h
                add	bp,cx
                mov	cl,sancend-sanction
                mov	dx,00c01h
                int	10h

                makePalette
                initTextures
                calcShadetab
                mov     [word ptr oldstack],sp
                startTimer
                startKBDhandler
                cls
mainloop:	setPalette2
		scriptIt
		animdoor
                push	ds
                mov	es,[word ptr vseg]
                mov	ds,[word ptr bseg]
                call	copyseg
                pop	ds
                rotation
                sortfaces

 		mov	cx,[word ptr o.fanz]
                mov	si,offset facei
drawloop:       lodsw
		lodsw
		mov	bx,ax
		pusha
                call	drawclippedface
                popa
                loop	drawloop
                push	ds
                push	0a000h
                pop	es
                mov	ds,[word ptr vseg]
                call	copyseg
                pop	ds
		jmp	mainloop

exit:           push    cs
                pop     ds
                mov     sp,[word ptr oldstack]
                silence
                stopKBDhandler
                stopTimer
                set80x25
     		ret
endp

;==============================================================================
;		interupt handler
;==============================================================================
;***********************************************
;* descript. : timer routine                   *
;* parameter : none		               *
;* sideeffect: none		               *
;* back      : none		               *
;* length    : 12 bytes		               *
;***********************************************
proc		irqHandler08	far
                pusha
                push	ds
                push	es

                push	cs
                pop	ds

                playsong
                inc	[word ptr ticker]
                inc	[byte ptr twice]
                and	[byte ptr twice],7
                jne	short iH08notyet
                colorCycle
                animstars
                inc     [word ptr doortimer]
iH08notyet:	mov     al,20h
                out     20h,al

                pop	es
                pop	ds
                popa
                iret
endp		irqHandler08

;***********************************************
;* descript. : keyboard- / breakhandler	       *
;* parameter : none		               *
;* sideeffect: none		               *
;* back      : none		               *
;* length    : 12 bytes		               *
;***********************************************
proc		irqHandler09	far
                push    ax
                mov     al,20h
                out     20h,al
                in      al,60h
		dec     al
                pop     ax
                je      exit
                iret
endp		irqHandler09

;==============================================================================
;		debugging and test routines
;==============================================================================
;==============================================================================
;		sub routines
;==============================================================================
;***********************************************
;* descript. : draw a the starbob	       *
;* parameter : ds,es: source seg,dest seg      *
;* sideeffect: ax,cx,si,di	               *
;* back      : none		               *
;* length    : ??? bytes		       *
;***********************************************
proc		setstarbob
                mov	si,offset bob
                mov	bl,5
yloop:          mov	bh,5
xloop:          lodsb
                sub	al,ah
  		jle	short aSnodraw
		add	al,ch
		shl	al,cl
		mov	[byte ptr es:di],al
aSnodraw:	inc	di
                dec	bh
                jne	short xloop
		add	di,dx
		dec	bl
		jne	short yloop
		ret
endp		setstarbob

;***********************************************
;* descript. : copy 16000 longs ds --> es      *
;* parameter : ds,es: source seg,dest seg      *
;* sideeffect: ax,cx,si,di	               *
;* back      : none		               *
;* length    : ??? bytes		       *
;***********************************************
proc		copyseg
 		xor  	di,di
    		xor  	si,si
    		mov  	cx,16000
    		rep 	movsd
                ret
endp		copyseg

;***********************************************
;* descript. : expand a part of the song       *
;* parameter : si:base adress		       *
;* sideeffect: si,ax		               *
;* back      : ax=si:new baseadress            *
;* length    : 31 bytes		               *
;***********************************************
proc		expand
EPwhile:        mov	cl,[byte ptr si]
                or	cl,cl
                je	short EPendwhile
                jns     short EPnote
EPcall: 	push	cx
                push	si
                inc	si
                call	expand
                pop	si
                pop	cx
		inc	cl
		jne	short EPcall
		mov	si,ax
		jmp	short EPwhile
EPnote:         movsw
                jmp	short EPwhile
EPendwhile:     inc	si
                mov	ax,si
                ret
endp		expand

;***********************************************
;* descript. : recursive index quicksort       *
;* parameter : l,r:stack left and right border *
;* sideeffect: ax,bx,cx,dx,si,di               *
;* back      : none		               *
;* length    : 63 bytes		               *
;***********************************************
proc		qsort
                pop	ax		; get adress
                pop	cx		; get 2. param r
                pop	bx              ; get 1. param l
                push	ax              ; store adress

                cmp     cx,bx
                jle     short QSendrek
		mov	si,bx
		mov	di,cx
		mov	dx,[word ptr si]
QSrepeat:
QSwhile1:	cmp     [word ptr si],dx
		jle     short QSwhile2
		add 	si,4
		jmp     short QSwhile1

QSwhile2:	cmp     [word ptr di],dx
		jnl     short QSwhile2e
                sub	di,4
		jmp     short QSwhile2
QSwhile2e:
		cmp     si,di
                jg      short QSnoswap
                lodsd
                xchg    eax,[dword ptr di]
                mov     [dword ptr si-4],eax
                sub	di,4
QSnoswap: 	cmp     si,di
                jle     short QSrepeat

		push    si
                push    cx
                push    bx
                push    di
                call    qsort
                call    qsort
QSendrek:	ret
endp		qsort

;***********************************************
;* descript. : returns a pseudo random number  *
;* parameter : bx=range		               *
;* sideeffect: eax,edx,si		       *
;* back      : ax=rnd(range)                   *
;* length    : 19 bytes		               *
;***********************************************
proc		rnd
                mov     si,offset randommul
                lodsd		   ; randommul
                mul     [dword ptr si]      ; randomseed
                inc     eax
                mov     [dword ptr si],eax  ; randomseed
                lodsw
                lodsw
                mul     bx
                xchg    ax,dx
                ret
endp 		rnd

;***********************************************
;* descript. : set timer speed to 1193180/AX   *
;*             interrupts per second           *
;* parameter : bx		               *
;* sideeffect: ax		               *
;* back      : none		               *
;* length    : 11 bytes		               *
;***********************************************
proc		setTimer
                mov	al,36h
                out	43h,al
                mov	al,bl
                out	40h,al
                mov	al,bh
                out	40h,al
                ret
endp		setTimer

;***********************************************
;* descript. : send a byte to the GM-Port      *
;* parameter : al:midi command                 *
;* sideeffect: dx		               *
;* back      : none		               *
;* length    : 13 bytes		               *
;***********************************************
proc		writeGM
                mov	dx,GMPort
		push	ax
                xor	ax,ax
busy:		dec	ah
		jz      short timeOut
                in	al,dx
                test    al,40h
                jnz	short busy
timeOut:        pop	ax
                dec	dx
                out	dx,al
		ret
endp

;***********************************************
;* descript. : send NOTEON command, volume 127 *
;* parameter : al:channel;ah:note              *
;* sideeffect: dx,al		               *
;* back      : none		               *
;* length    : 9 bytes		               *
;***********************************************
proc	    	setNote
		call  	setInstr
   	 	mov   	al,127
   		call  	WriteGM
                ret
endp

;***********************************************
;* descript. : send CHANGEPRG command	       *
;* parameter : al:channel;ah:instrument        *
;* sideeffect: dx,al		               *
;* back      : none		               *
;* length    : 9 bytes		               *
;***********************************************
proc		setInstr
                call  	writeGM
                mov   	al,ah
                call  	writeGM
                ret
endp

;***********************************************
;* descript. : clear/set the fractal es: to al *
;* parameter : al,es		               *
;* sideeffect: ax,cx,di,es  	               *
;* back      : none			       *
;* length    : 10 bytes		               *
;***********************************************
proc		clearFrac
		xor	ax,ax
setFrac:        xor	di,di
                mov	cx,4096
                rep	stosb
                ret
endp		clearFrac

;***********************************************
;* descript. : calc shade bob fractal          *
;* parameter : es:seg;num,rad:stack            *
;* sideeffect: all			       *
;* back      : none			       *
;* length    : 109 bytes		       *
;***********************************************
proc		createFrac1
arg		rad:word,num:word=RET_BYTES
                push	bp
                mov	bp,sp
		
                mov	es,[word ptr tseg+bx]
                call	clearFrac

                mov   	si,offset Circletab
                mov 	dx,[rad]
                mov	al,dl
                imul    dl
                mov	di,ax
                mov	cx,dx
                add	cx,cx
CCTloop:	mov   	al,dl
                imul  	dl
                neg   	ax
                add   	ax,di
                mov	[si],ax
		fild    [word ptr si]
		fsqrt
		fistp   [word ptr si]
                inc   	si
                inc   	si
                dec   	dx
                loop  	CCTloop

                mov     cx,[num]
SBloop1:	push    cx
		mov     bx,4096
                call    rnd
                mov     di,ax
                mov     si,offset circletab
                mov     cx,[rad]
                add     cx,cx
SBloop2:        push    cx
		lodsw
                mov     cx,ax
                add     cx,cx
                je      short SBskip
                push	di
		sub     di,ax
SBloop3:	and	di,4095
		inc     [byte ptr es:di]
		inc     di
		loop	SBloop3
		pop	di
SBskip:		add	di,64
		pop	cx
		loop	SBloop2
		pop	cx
                loop	SBloop1
                pop	bp
                ret	RET_BYTES
endp	createFrac1

;***********************************************
;* descript. : draw a perpective-texturemapped *
;*	       and g.-shaded n-sided polygon   *
;* parameter : far ptr to poly, sides, textnum *
;* sideeffect: all			       *
;* back      : none			       *
;* length    : 700 bytes		       *
;***********************************************
proc		scansubtextpoly
arg		col:word,n:word,pol:word=RET_BYTES
local		edg:edges:3,del:edges:3,mx1:word,mx2:word,miny:word,maxy:word,y:word,l:word,r:word,uu1:word,vv1:word,uu2:word,vv2:word,ddu:word,ddv:word,dy:dword=AUTO_SIZE

                enter	AUTO_SIZE,0

                mov	ax,-32767
                mov	bx,ax
                mov	si,ax
                neg	ax
                mov	dx,ax

                mov	di,[word ptr pol]
                xor	cx,cx
minmax:        	cmp	ax,[word ptr (edge ptr di+2).e.x]
                jle	short noswap1
                mov	ax,[word ptr (edge ptr di+2).e.x]
noswap1:   	cmp	bx,[word ptr (edge ptr di+2).e.x]
                jge	short noswap2
                mov	bx,[word ptr (edge ptr di+2).e.x]
noswap2:       	cmp	dx,[word ptr (edge ptr di).py]
                jle	short noswap3
                mov	dx,[word ptr (edge ptr di).py]
                mov	[word ptr l],cx
                mov	[word ptr r],cx
noswap3: 	cmp	si,[word ptr (edge ptr di).py]
		jge	short noswap4
		mov	si,[word ptr (edge ptr di).py]
noswap4:	add	di,36
		inc	cx
		cmp	cx,[word ptr n]
		jne 	short minmax

		cmp 	bx,0
                jl	exitDraw
		cmp 	ax,XMAX
                jg	exitDraw

		cmp 	si,YMIN
                jl	exitDraw
		cmp 	dx,YMAX
                jg	exitDraw
               	mov	[word ptr miny],dx
                mov	[word ptr maxy],si

		;{ unten clippen }
                cmp	[word ptr maxy],YMAX
                jle	short noclipdown
		mov	[word ptr maxy],YMAX
noclipdown:
                mov	ax,[word ptr miny]
                cmp	ax,[word ptr maxy]
                je	exitDraw
                mov	[word ptr y],ax
  	        mov	bx,[word ptr col]
                add	bx,bx

            	mov	es,[word ptr vseg]
                mov	fs,[word ptr tseg+bx]

for: 		mov	ax,[word ptr y]
                cmp     ax,[word ptr maxy]
                jg	exitDraw

while1:         mov	ax,[word ptr y]
		cmp     ax,[word ptr maxy]
                jge	short while2
		mov	si,[word ptr pol]
		imul	bx,[word ptr l],36
		add	si,bx
		cmp	ax,[word ptr (edge ptr si).py]
		jne	short while2

		mov	bx,[word ptr l]
		dec	bx
		jge	short nounder
		mov	bx,[word ptr n]
		dec	bx
nounder:	mov	[word ptr l],bx
		xor	di,di
		call	calcDeltas
		jmp	short while1

while2:		mov	ax,[word ptr y]
		cmp     ax,[word ptr maxy]
		jge	short exitwhile2
		mov	si,[word ptr pol]
		imul	bx,[word ptr r],36
		add	si,bx
		cmp	ax,[word ptr (edge ptr si).py]
		jne	short exitwhile2

		mov	bx,[word ptr r]
		inc	bx
                cmp	bx,[word ptr n]
		jl	short noover
        	xor	bx,bx
noover:		mov	[word ptr r],bx
		mov	di,20
		call	calcDeltas
		jmp	short while2
exitwhile2:
		;{ oben clippen }
    	        cmp	[word ptr y],YMIN
		jl	clipup
		xor	ebx,ebx
		xor	ecx,ecx
		mov	bx,[word ptr (edges ptr edg+2).x]
		mov	[word ptr mx1],bx
                mov	cx,[word ptr (edges ptr edg+20+2).x]
                mov	[word ptr mx2],cx
                sub	cx,bx
		je      exitol
		cmp	[word ptr mx2],0
                jle	exitol
		cmp	[word ptr mx1],xmax
                jg	exitol

                neg	bx
                jns	short myelse
                xor	bx,bx
                jmp	short myendif
myelse:         mov	[word ptr mx1],0
myendif:	mov	di,16
addloop1:   	;{ deltas berechnen }
		mov	eax,[dword ptr edg+di+20]
		sub	eax,[dword ptr edg+di]
		cdq
		jcxz    short nodivbyzero
		idiv	ecx
		mov	[dword ptr del+di+40],eax
nodivbyzero:	;{ links clippen }
		mov	eax,[dword ptr del+di+40]
		imul	ebx
		add	eax,[dword ptr edg+di]
		mov	[dword ptr edg+di+40],eax
		sub	di,4
		jne	short addloop1

		mov	ax,[word ptr del+40+16]
		mov	[word ptr cs:dels_pos+1],ax
		;{ rechts clippen }
	        cmp	[word ptr mx2],XMAX
		jle	short norightclip
	    	mov	[word ptr mx2],XMAX
norightclip:	imul	di,[word ptr y],320
		add	di,[word ptr mx1]

		mov	bx,256
		mov	eax,[(edges ptr edg+40).u]
		imul	ebx
		idiv	[(edges ptr edg+40).w]
		mov	[word ptr uu2],ax
		mov	eax,[(edges ptr edg+40).v]
		imul	ebx
		idiv	[(edges ptr edg+40).w]
		mov	[word ptr vv2],ax

outloop:	mov	cx,[word ptr mx2]
		sub	cx,[word ptr mx1]
 		jle	exitol
		cmp	cx,SUBRANGE
		jle	short lastSeg
            	mov	cx,SUBRANGE
lastSeg:        mov	eax,[dword ptr vv2]	;{ uu1:=uu2 }
		mov	[dword ptr vv1],eax	;{ vv1:=vv2 }

		mov	eax,[(edges ptr del+40).u]
		imul	ecx
		add	[(edges ptr edg+40).u],eax
		mov	eax,[(edges ptr del+40).v]
		imul	ecx
		add	[(edges ptr edg+40).v],eax
		mov	eax,[(edges ptr del+40).w]
		imul	ecx
		add	[(edges ptr edg+40).w],eax

		mov	bx,256
		mov	eax,[(edges ptr edg+40).u]
		imul	ebx
		idiv	[(edges ptr edg+40).w]
		mov	[word ptr uu2],ax
		mov	eax,[(edges ptr edg+40).v]
		imul	ebx
		idiv	[(edges ptr edg+40).w]
		mov	[word ptr vv2],ax

		mov	ax,[word ptr uu2]
		sub	ax,[word ptr uu1]
		cwd
		idiv	cx
		mov	[word ptr cs:ddu_pos+2],ax

		mov	ax,[word ptr vv2]
		sub	ax,[word ptr vv1]
		cwd
		idiv	cx
		mov	[word ptr cs:ddv_pos+2],ax

	        mov	si,[word ptr vv1]
		mov	dx,[word ptr uu1]
                mov	ax,[word ptr edg+40+16]
innerloop: 	mov	bx,si
		xor	bl,bl
		shr	bx,2
		add	bl,dh
		mov  	bl,[byte ptr fs:bx]
		or      bl,bl
		je	short dels_pos
		mov	bh,ah
		mov     bl,[byte ptr shadetab+bx]
		mov	[byte ptr es:di],bl
dels_pos:       add	ax,01111h	;{word ptr dels}
ddu_pos:	add	dx,01111h	;{word ptr ddu }
ddv_pos:	add	si,01111h	;{word ptr ddv }
		inc	di
		loop	innerloop
		mov	[word ptr edg+40+16],ax
		add	[word ptr mx1],SUBRANGE
                jmp	outloop
exitol:
clipup:		mov	di,36
addloop:	mov	eax,[dword ptr del+di]
		add	[dword ptr edg+di],eax
		sub	di,4
		jns	short addloop
		inc	[word ptr y]
                jmp	for
exitDraw:       leave
                ret	RET_BYTES

  ;***********************************************
  ;* descript. : calc deltas for vertical interp.*
  ;* parameter : none			         *
  ;* sideeffect: all		 	         *
  ;* length    : ??? bytes		         *
  ;***********************************************
  proc		calcDeltas
		imul	dx,bx,36
		mov	bx,si
		mov	si,[word ptr pol]
		add	si,dx
		mov	ax,[word ptr si+12]
		sub	ax,[word ptr y]
		movsx	eax,ax
		mov	[dword ptr dy],eax
		mov	cx,5
  cDloop:	mov	edx,[dword ptr bx+16]
	    	mov	[dword ptr edg+di],edx
                mov	eax,[dword ptr si+16]
		sub	eax,edx
		cdq
		cmp	[word ptr dy],0
		je	short cDskip
		idiv    [dword ptr dy]
		mov	[dword ptr del+di],eax
  cDskip:	add	di,4
		add	si,4
		add	bx,4
		loop    cDloop
		ret
  endp		calcDeltas

endp		scansubtextpoly

;***********************************************
;* descript. : clip a poly at the viewplane,   *
;*             project and draw it	       *
;* parameter : bx:adress of the face	       *
;* sideeffect: all		 	       *
;* back      : none			       *
;* length    : ??? bytes		       *
;***********************************************
proc		drawclippedface
local		d:word,h:word,j:word,col:word,is_in:byte,p0:poly,p2:poly=AUTO_SIZE

		enter	AUTO_SIZE,0
        	mov	si,offset uvtab
        	xor	di,di
		mov	cx,4
dcFinitloop:	push	bx
		mov	bx,[bx]

               	push	bx
		imul	bx,bx,12
		add	bx,offset rp
           	mov	eax,[dword ptr bx]
           	mov	[dword ptr p0+di+0],eax

		mov	eax,[dword ptr bx+4]
         	mov	[dword ptr p0+di+4],eax

 		fld	[dword ptr bx+8]
        	fst	[dword ptr p0+di+8]
        	fistp	[word ptr h]
		pop	bx

		mov	ax,[word ptr h]
		add     ax,512
		js	dCFbackclip
		cmp	ax,511
		jle	short intensityOK
 		mov	ax,511
intensityOK:
                shl	bx,3
		xor	edx,edx
		shl	ax,7
		mul	[word ptr (object ptr o+bx+6).p]
		mov	[dword ptr p0+di+32],edx

		xor	ah,ah
		mov	al,[si+4]
		shl	eax,16
           	mov	[dword ptr p0+di+24],eax

		lodsb
        	shl	eax,16
          	mov	[dword ptr p0+di+20],eax

		pop	bx
		inc	bx
		inc	bx
		add	di,36
                loop	dCFinitloop
                mov	ax,[bx]
                mov	[word ptr col],ax

		xor	bx,bx
                mov	[word ptr j],bx
                fld	[dword ptr p0+108+8]
                ftst
                fstsw	ax
                fstp	st(0)
                sahf
                jae	short isFalse
                dec	bx
isFalse:	mov	[byte ptr is_in],bl
                xor	si,si
                xor	di,di
forloop:	fld	[dword ptr p0+si+8]
		ftst
		fstsw	ax
		fstp	st(0)
		sahf
		jae 	short elseFall
		cmp	[byte ptr is_in],0ffh
		je      short inside
    		call	clipsub
		not	[byte ptr is_in]	; { OUT / IN }
inside:		push	di
		push	si
		lea	di,[word ptr p2+di]
		lea	si,[word ptr p0+si]
		push	ss
		pop	es
		push	ds
		push	ss
		pop	ds
		mov	cx,18
		rep	movsw			; { IN / IN }
		pop	ds

		pop	si
		pop	di
		add	di,36
		inc	[word ptr j]
		jmp	short dCFendIf
elseFall:	cmp	[byte ptr is_in],0ffh
		jne     short outside
		call	clipsub
		not	[byte ptr is_in]	; { IN / OUT }
outside:
dCFendif:	add	si,36
		cmp	si,4*36
                jne	short forloop

                mov	cx,[word ptr j]
                cmp	cx,2
                jl	dCFnodraw
                xor	di,di
dCFloop:	fild	[word ptr CONST13]	;{ projection }
		fsub	[dword ptr p2+di+8]
		fidiv	[word ptr CONST160]

		fld	[dword ptr p2+di+4]
		fdiv	st(0),st(1)
		fiadd	[word ptr CONST100]
		fistp	[dword ptr p2+di+12]

		fld	[dword ptr p2+di]
		fmul	[dword ptr ASPECT_PLACE]
		fdiv	st(0),st(1)
		fiadd	[word ptr CONST160]
		frndint
		fimul	[dword ptr CONST65536]
		fistp	[dword ptr p2+di+16]

		fild	[dword ptr p2+di+20]
		fdiv	st(0),st(1)
		fistp	[dword ptr p2+di+20]

		fild	[dword ptr p2+di+24]
		fdiv	st(0),st(1)
		fistp	[dword ptr p2+di+24]

		fild	[dword ptr CONST65536]
		fdiv	st(0),st(1)
		fistp	[dword ptr p2+di+28]

		fstp	st(0)
		add	di,36
                loop    dCFloop

                lea	di,[dword ptr p2]
                push	di
                push	[word ptr j]
                push	[word ptr col]
                call	scansubtextpoly
dCFnodraw:
dcFbackclip:    leave
                ret

  proc		clipsub
		push	si
		push	di
                lea	ax,[word ptr si-36]
		cmp	ax,0
		jge     short cSnounder
		mov	ax,108
  cSnounder:	fld	[dword ptr p0+si+8]
		fld	st(0)
		xchg	ax,di
		fsub	[dword ptr p0+di+8]
		xchg	ax,di
		fdiv

		mov	bx,offset cliptab
		mov	cx,6
  dCFclipLoop2:	xchg	ax,di
		fld     [dword ptr p0+di]
		xchg	ax,di
		fsub    [dword ptr p0+si]
		fmul	st(0),st(1)
		fadd	[dword ptr p0+si]
		fstp	[dword ptr p2+di]

		mov	dl,[bx]
		inc	bx
		xor	dh,dh
		add	di,dx
		add	si,dx
		add	ax,dx
		loop	dCFclipLoop2
		fstp	st(0)
		pop	di
		pop	si
		inc	[word ptr j]
		add	di,36
		ret
  endp		clipsub
endp		drawclippedface

;***********************************************
;* descript. : rotate point over one axis      *
;* parameter : st(0):angle, [ds:si] ptr to     *
;*	       1.koord.,[ds:bx] ptr to 2.koord.*
;* sideeffect: empty copro-stack               *
;* back      : none			       *
;* length    : 35 bytes			       *
;***********************************************
proc		rotateAxis
                fldpi   			;{ PI,a}
                fmul    			;{ PI*a}
		fidiv   [dword ptr CONST65536]	;{ PI*a/65536}
		fsincos                	        ;{ cos,sin}
                fld     st(0)			;{ cos,cos,sin}
     		fmul    [dword ptr si]          ;{ y*cos,cos,sin}
                fld     st(2)			;{ sin,y*cos,cos,sin}
                fmul    [dword ptr bx]          ;{ z*sin,y*cos,cos,sin}
                fsubp   st(1),st		;{ y*cos-z*sin,cos,sin}
                fxch	st(2)			;{ sin,cos,y*cos-z*sin}
                fmul    [dword ptr si]		;{ y*sin,cos,y*cos-z*sin}
                fxch    st(1)			;{ cos,y*sin,y*cos-z*sin}
                fmul    [dword ptr bx]		;{ z*cos,y*sin,y*cos-z*sin}
                faddp   st(1),st		;{ y*sin+z*cos,y*cos-z*sin}
       	        fstp    [dword ptr bx]         	;{ y*cos-z*sin}
           	fstp    [dword ptr si]          ;{}
                ret
endp		rotateAxis

;***********************************************
;* descript. : rotate point		       *
;* parameter : a,b,c:angles,adr:address        *
;* sideeffect: all		 	       *
;* back      : none			       *
;* length    : 44 bytes			       *
;***********************************************
proc		XYZRotate
ARG		adr:word,c:word,b:word,a:word=RET_BYTES
                push	bp
                mov	bp,sp
                mov	di,[word ptr adr]
                fild	[word ptr a]
                lea	bx,[word ptr di+8]
                lea	si,[word ptr di+4]
                call	rotateAxis
                fild	[word ptr b]
                lea	bx,[word ptr di]
                lea	si,[word ptr di+8]
                call	rotateAxis
                fild	[word ptr c]
                lea	bx,[word ptr di+4]
                lea	si,[word ptr di]
                call	rotateAxis
                pop	bp
                ret	RET_BYTES
endp		XYZRotate

;***********************************************
;* descript. : create identity matrix	       *
;* parameter : ds:di address                   *
;* sideeffect: cx,di		   	       *
;* back      : none			       *
;* length    : --- bytes		       *
;***********************************************
macro		identityMat
		mov	ch,2
iMolp:		mov  	cl,2
iMilp:		fldz
		cmp	ch,cl
		jne	short iMwritezero
		fstp	st(0)
		fld1
iMwritezero:	fstp	[dword ptr di]
		add	di,4
		dec	cl
		jns	short iMilp
                dec	ch
                jns	short iMolp
endm		identityMat

;***********************************************
;* descript. : calculate world matrix	       *
;* parameter : x-,y-,z-angle,neig:stack	       *
;* sideeffect: all		 	       *
;* back      : none			       *
;* length    : 132 bytes		       *
;***********************************************
proc		calcRotMat
arg		neig:word,zw:word,yw:word,xw:word=RET_BYTES
                push	bp
                mov	bp,sp

                mov	di,offset nwmat
                identityMat
		xor	di,di
cRMolp:		push	di
		push	[word ptr xw]
		push	[word ptr yw]
		push	[word ptr zw]
		add	di,offset nwmat
		push	di
		call	xyzrotate
		pop	di
		xor	bx,bx
cRMilp:		fld	[dword ptr nwmat+di]
		fmul	[dword ptr owmat+bx]
		fld	[dword ptr nwmat+di+4]
		fmul	[dword ptr owmat+bx+12]
		fld	[dword ptr nwmat+di+8]
		fmul	[dword ptr owmat+bx+24]
		fadd
		fadd
		fst 	[dword ptr owmat+di+bx]
		fstp	[dword ptr wmat+di+bx]
		add	bx,4
		cmp	bl,12
		jne	short cRMilp
                add	di,12
                cmp	di,36
                jne	short cRMolp

		mov	si,offset wmat
                mov	cx,3
cRMneigloop:	fild	[word ptr neig]
	        lea	bx,[word ptr si+12]
		call	rotateAxis
		add	si,4
                loop	cRMneigloop
                pop	bp
                ret	RET_BYTES
endp		calcRotMat

;***********************************************
;* descript. : create the world		       *
;* parameter : none			       *
;* sideeffect: all		               *
;* back      : none		               *
;* length    : ??? bytes		       *
;***********************************************
proc		createWorld
local		direc:word,shade:word=AUTO_SIZE;
                enter	AUTO_SIZE,0

                mov	si,offset world
                mov	cx,4
cWworldLoop:	push	cx
		push	si
		mov	di,offset p
		mov	bx,offset pr
		mov	si,offset print
		mov	cl,15
cWinitStartRoom:
		push	cx
		mov	cl,3
cWinnerLoop:	lodsb
		cbw
		stosw
		fild	[word ptr di-2]
		fstp	[dword ptr bx]
		add	bx,4
		loop	cWinnerLoop
		pop	cx
		mov	ax,127*256
		stosw
		loop	cWinitStartRoom
		pop	si

cWmainLoop:	lodsb
		cmp	al,255
		je	cWexit

		mov	bh,al
		and	bx,07000h
		add	bh,15
		mov	[word ptr shade],bx
		and	ax,000fh
		mov	[word ptr direc],ax

		xor	bx,bx
cWsideLoop:	test	bl,4
		je      short cWfirstNibble
		lodsb
		and	al,15
		jmp 	short cWsecondNibble
cWfirstNibble:	mov	al,[si]
		shr	al,4
cWsecondNibble: xor	ah,ah
		dec	ax
		js	short cWnoWall
		imul	di,[word ptr o.fanz],10
		add	di,offset o.f
		inc	[word ptr o.fanz]
		mov	[word ptr di+8],ax

		push	bx
		push	si
		mov	cl,4
cWaddPointloop:	movsx	si,[byte ptr cube+bx]
		add	si,offset p

	        push	di
		mov	di,offset o.p
		push	cx
		mov	cx,[word ptr o.panz]
		xor	ax,ax
		jcxz    short cWfirstPoint
cWsearchPointLoop:	
		mov	edx,[dword ptr si]
		cmp	edx,[dword ptr di]
		jne	short cWdifferent
		mov	dx,[word ptr si+4]
		cmp	dx,[word ptr di+4]
		je	short cWpointExists
cWdifferent:	inc	ax
		add	di,8
		loop	cWsearchPointLoop
cWfirstPoint:
		movsd
		movsd
		inc	[word ptr o.panz]
cWpointExists:	pop	cx
		pop	di
		stosw
		inc	bx
		loop	cWaddPointLoop
		pop	si
		pop	bx
cWnoWall:	add	bx,4
		cmp	bx,24
		jne	short cWsideLoop

		imul	di,[word ptr direc],12
		mov	cl,3
		mov	bx,offset pr+96
cWaddStepLoop:	fld	[dword ptr bx+72]
		fadd	[dword ptr bx+di]
		fstp	[dword ptr bx+72]
		add	bx,4
		loop	cWaddStepLoop

		cmp	[byte ptr si-4],0
		jge	short cWsimpleRoom
		mov	bx,offset pr
		mov	cl,14
cWrotloop:	pusha
		mov	cl,3
		mov	dl,[si]
cWpushLoop:	shr	dl,1
		jnc	short cWnoRot
		mov	ah,[si]
		and	ax,0f000h
		push    ax
		jmp	short cWendIf
cWnoRot:	push	0
cWendIf:	loop	cWpushLoop
		push	bx
		call	xyzRotate
		popa
		add	bx,12
		loop	cWrotLoop
		inc	si
cWsimpleRoom:
		mov	bx,[word ptr direc]
		shl	bx,2
		mov	cl,4
cWpointCopyLoop:	
		pusha
		movsx	si,[byte ptr cube+bx]
		mov	ax,si
		add	si,offset p
		xor	bl,7
		movsx	di,[byte ptr cube+bx]
		add	di,offset p
		push	si
		movsd
		movsd
		pop	si

		mov	bx,ax
		shr	bx,1
		add	bx,ax
		mov	di,offset pr
		mov	cl,3
cWSround:	fld	[dword ptr di+bx]
		fadd	[dword ptr di+168]
		fistp	[word ptr si]
		add	di,4
		inc	si
		inc	si
		loop	cWSround
		mov	ax,[word ptr shade]
		mov	[word ptr si],ax
		popa
		inc	bx
		loop	cWpointCopyLoop
		jmp	cWmainLoop
cWexit:		pop	cx
                dec	cx
                jne	cWworldLoop
                leave
                ret
endp		createWorld

;=============================================================================
;               preinitialized data
;=============================================================================
ASPECT_PLACE	dd	ASPECT_RATIO
CONST13		dw	13
CONST100	dw	CENTERY
CONST160	dw	CENTERX
CONST1792	dw	1792
CONST65536	dd	65536
randommul	dd	134775813
randomseed	dd	4347
credits:
		db	 2, 80,-5
		db      -2,50,4,69,2,62,2,69,2,81,2,62,2,69,2,79,2,62,2,69,2
		db	81,2,62,2,69,2,79,2,81,2,0	; { pat 0,2,4,6,8 }
		db      -2,50,4,70,2,62,2,70,2,81,2,62,2,70,2,79,2,62,2,70,2
		db	82,2,62,2,70,2,79,2,82,2,0	; { pat 1,3,5,7,9 }
		db       0
		db      55,32,56,32			; { pat 10 }
		db      51,32,53,24,55,8                ; { pat 11 }
		db      57,32,50,32		 ; { pat 12 }
		db      60,48,58,8,57,8                 ; { pat 13 }
		db      55,64		   ; { pat 14 }
		db      -2,67,16,62,16,69,16,70,16,0	; { pat 15 }
		db      -2,70,16,69,16,62,16,65,16,0    ; { pat 16 }
		db       0
		db       4, 50,1,128,1,128              ;{ pat 0-3 }
		db      65,28,64,2,65,2,64,16,62,8,60,8 ;{ pat 4 }
		db      67,28,65,4,60,16,65,8,64,8      ;{ pat 5 }
		db      62,32,50,16,64,8,65,8           ;{ pat 6 }
		db      67,32,60,16,62,8,64,8           ;{ pat 7 }
		db      62,128		  ;{ pat 8,9 }
		db      67,128		  ;{ pat 10,11 }
		db     	67,16,64,16,66,16,64,8,66,8	;{ pat 12 }
		db     	72,48,70,16                 	;{ pat 13 }
		db     	67,32,55,32                 	;{ pat 14 }
		db     	-2,31,32,55,32,0                ;{ pat 15 }
		db      -2,26,32,50,32,0                ;{ pat 16 }
		db       0
		db       5, 89,-5,1,128,0		;{ pat 0-9 }
		db      67,8,74,24,68,8,75,24           ;{ pat 10 }
		db      63,8,70,24,60,8,69,16,67,8      ;{ pat 11 }
		db      62,8,69,16,67,8,62,8,66,24	;{ pat 12 }
		db      63,8,67,24,60,8,67,16,69,8	;{ pat 13 }
		db      55,8,67,24,43,8,50,24           ;{ pat 14 }
		db      -2,31,1,38,63,0                	;{ pat 15 }
		db      -2,26,1,33,63,0                	;{ pat 16 }
		db       0
		db	10,  0,-16,42,2,42,2,42,2,42,1,42,1,0 ;{ pat 0,1 }
		db     -16,36,2,42,2,42,2,42,1,42,1,0   ;{ pat 2,3 }
		db     -30,36,2,42,2,46,2,36,1,42,1,38,2
		db	42,2,46,2,38,1,42,1     	;{ pat 4-16 }
		db      36,2,38,2,36,2,42,1,42,1,38,2,42,2,46,2,38,1,42,1,0
		db     	 0
		db	 0

; colortable 65 bytes
colors 		db	16
                db      31,63,63,63
                db	 1, 0, 0, 0
                db      31,40,32,63
                db	 1, 0, 0, 0
                db      31,63, 0, 0
                db	 1, 6, 1, 0
                db      31,63,41,20
                db	 1, 0, 0, 0
                db      31,63,63, 8
                db	 1, 0, 0, 0
                db	31,56,56,63
                db	 1,63, 0, 0
                db      16,63,63, 0
                db      16,63, 0, 0
                db	 1,22, 5, 0
                db       7,63,56,17

; parameter for the texture effects 156 bytes
aE              db	013h,15,15,49,49,10
                db      013h,16,16,48,48,17
                db      013h,17,17,47,47,24
                db      013h,18,18,46,46,190
                db      013h,21,21,43,43,30
                db      025h,0,0,62,30,3
                db      025h,3,3,62,30,7
                db      025h,3,3,59,27,0FCh
                db      025h,0,32,62,62,3
                db      025h,3,35,62,62,7
                db      025h,3,35,59,59,0FCh
                db      025h,0,0,63,63,0FEh
                db      02Ch,0,10,63,15,0F6h
                db      02Ch,0,11,63,16,4
                db      02Ch,0,47,63,52,0F6h
                db      02Ch,0,48,63,53,4
                db      02Eh,19,24,44,39,5
                db      02Eh,20,25,44,39,0F4h
                db      02Eh,20,25,43,38,7
                db      03Eh,20,25,43,38,6
                db      02Fh,0,24,63,30,6
                db      02Fh,0,25,63,31,0FAh
                db      03Fh,0,25,63,30,6
                db      02Fh,0,32,63,38,6
                db      02Fh,0,33,63,39,0FAh
                db      03Fh,0,33,63,38,6

; parameter for fractaladd 28 bytes
aF:             db      34,192,38,1,38,1,38,0,32,0,32,32,32,64
                db	34,96,36,0,34,96,36,0,36,0,36,0,36,0

; star bob for the sparcling stars texture 25 bytes
bob:            db	0,0,3,0,0
                db	0,2,5,2,0
                db	3,5,7,5,3
                db	0,2,5,2,0
                db	0,0,3,0,0

cliptab:	db	4,4,12,4,8

uvtab:		db	0,0,63,63,63,0,0,63

cube:		db	1*8,5*8,6*8,2*8
                db      3*8,7*8,4*8,0*8
                db      2*8,6*8,7*8,3*8
                db      0*8,4*8,5*8,1*8
        	db	7*8,6*8,5*8,4*8
                db      0*8,1*8,2*8,3*8

print:		db	-32,-32,-32
                db       32,-32,-32
                db   	 32, 32,-32
                db  	-32, 32,-32
                db  	-32,-32, 32
                db       32,-32, 32
                db   	 32, 32, 32
                db  	-32, 32, 32
                db       64,  0,  0
                db      -64,  0,  0
                db        0, 64,  0
                db        0,-64,  0
                db        0,  0, 64
                db        0,  0,-64
                db	  0,  0,  0

; world contruction data 599 bytes
world:		db	071h,070h,000h,006h
                db	072h,000h,000h,006h
                db	071h,000h,070h,006h
                db	073h,007h,070h,006h
                db	073h,007h,000h,006h
                db	070h,007h,007h,006h
                db	074h,000h,007h,006h
                db	070h,000h,007h,040h
                db	072h,070h,007h,050h
                db	072h,070h,000h,050h
                db	071h,070h,070h,050h
                db	073h,000h,070h,040h
                db	071h,000h,000h,040h
                db	072h,000h,000h,050h
                db	071h,000h,070h,050h
                db	073h,007h,070h,046h
                db	073h,000h,000h,046h
                db	070h,007h,007h,046h
                db	072h,000h,007h,050h
                db	071h,000h,000h,000h
                db	071h,000h,000h,000h
                db	071h,000h,0bbh,056h
                db	070h,00Fh,0bbh,046h
                db	0FFh
                db	033h,000h,000h,000h
                db	0F0h,000h,007h,006h,0E4h
                db	0B0h,000h,0BBh,046h,0E4h
                db	090h,000h,0BBh,056h,0E4h
                db	090h,000h,0BBh,056h,0E4h
                db	030h,000h,0BBh,056h
                db	0F0h,000h,0BBh,056h,011h
                db	0F0h,000h,0BBh,046h,011h
                db	0B0h,000h,0BBh,056h,011h
                db	090h,000h,0BBh,056h,011h
                db	0B0h,000h,0BBh,056h,011h
                db	0F0h,000h,0BBh,056h,011h
                db	0F0h,000h,0BBh,046h,011h
                db	0B0h,000h,0BBh,056h,011h
                db	030h,000h,0BBh,056h
                db	010h,000h,0BBh,056h

                db	034h,000h,000h,000h
                db	032h,005h,000h,080h
                db	035h,005h,080h,080h
                db	035h,005h,080h,000h
                db	033h,005h,080h,008h
                db	033h,005h,000h,008h
                db	074h,005h,008h,008h
                db	074h,005h,000h,000h
                db	073h,005h,008h,080h
                db	075h,000h,000h,000h
                db	075h,005h,008h,088h
                db	070h,000h,000h,000h
                db	074h,064h,008h,008h
                db	074h,060h,008h,000h
                db	072h,064h,008h,080h
                db	005h,060h,000h,080h
                db	005h,060h,000h,000h
                db	002h,060h,000h,008h
                db	034h,060h,000h,008h
                db	034h,060h,000h,000h
                db	032h,060h,000h,080h
                db	035h,060h,000h,080h
                db	035h,060h,000h,000h
                db	032h,060h,000h,008h
                db	034h,035h,000h,008h
                db      014h,065h,000h,000h
                db      032h,035h,000h,080h
               	db      035h,035h,000h,080h
               	db      015h,065h,000h,000h
                db	032h,035h,000h,008h
                db	034h,035h,080h,008h
               	db      014h,065h,000h,000h
               	db      032h,035h,080h,080h
		db	075h,000h,000h,000h
		db	052h,065h,0E0h,077h
		db	032h,064h,00Eh,077h
		db	012h,065h,000h,077h
		db	000h,065h,000h,077h
		db	0FFh
		db	032h,000h,000h,000h
		db	0F0h,000h,000h,000h,014h
		db	0B0h,000h,000h,000h,014h
		db	030h,000h,000h,000h
		db	0F0h,000h,000h,000h,0F4h
		db	0F0h,000h,0DDh,056h,0F4h
		db	030h,000h,0DDh,046h
		db	030h,000h,0DDh,056h
		db	030h,000h,0DDh,056h
		db	032h,000h,000h,050h
		db	030h,00Ah,0A0h,050h
		db	033h,000h,0A0h,050h
		db	030h,000h,000h,050h
		db	032h,070h,000h,050h
		db	030h,000h,0A0h,050h
		db	033h,0A0h,0A7h,050h
		db	033h,000h,000h,000h
		db	031h,0A0h,07Ah,050h
		db	031h,000h,00Ah,050h
		db	031h,000h,00Ah,050h
		db	032h,00Ah,00Ah,050h
		db	035h,000h,000h,000h
		db	072h,00Ah,000h,000h
		db	070h,00Ah,0A0h,000h
		db	073h,000h,0A0h,000h
		db	070h,000h,000h,000h
		db	072h,000h,000h,000h
		db	070h,000h,0A0h,000h
		db	073h,0A0h,0A0h,000h
		db	073h,0A0h,000h,099h
		db	071h,0A0h,00Ah,000h
		db	071h,000h,00Ah,000h
                db	071h,000h,00Ah,000h
                db	075h,00Ah,00Ah,000h
                db	070h,00Ch,00Ch,003h
                db	070h,000h,00Ch,003h
                db	070h,000h,00Ch,003h
                db	072h,0C0h,07Ch,003h
                db	072h,000h,000h,000h
                db	071h,0C0h,0C7h,003h
                db	073h,000h,0C0h,003h
                db	071h,070h,000h,003h
                db	072h,000h,000h,003h
                db	071h,000h,0C0h,003h
                db	073h,00Ch,0C0h,003h
                db	071h,000h,000h,003h
                db	031h,00Ch,0CCh,0A3h
                db	0FFh
                db	032h,000h,000h,000h
                db	0F0h,000h,070h,006h,014h
                db	0B0h,000h,0DDh,046h,014h
                db	030h,000h,0DDh,056h
                db	0B2h,000h,00Dh,056h,0C4h
                db	032h,0DDh,000h,056h
                db	032h,0DDh,000h,056h
                db	032h,0DDh,000h,056h
                db	070h,000h,0F0h,056h
                db	070h,000h,0BBh,056h
                db	032h,0B0h,00Bh,046h
                db	072h,0BBh,000h,056h
                db	071h,0B0h,0B0h,056h
                db	071h,002h,011h,056h
                db	071h,022h,011h,056h
                db	031h,020h,011h,056h
                db	073h,00Bh,0B0h,056h
                db	073h,0BBh,000h,056h
                db	030h,00Bh,00Bh,046h
                db	030h,000h,0BBh,056h
                db	0FFh

; flying script	126 bytes
script:
;     7 6 5 4 3 2 1 0
;	  v v v v v c c c
;
;	  v = VALUE
;	  c = COMMAND
;
;	  0 = NOP
;	  1 = NEG ZSTEP
;	  2 = INC SPEED
;	  3 = DEC SPEED
;	  4 = INC XSTEP
;	  5 = DEC XSTEP
;	  6 = INC YSTEP
;	  7 = INC YSTEP

                db      0A1h,0f8h,0f8h,098h,0a1h,0A6h
                db      0F0h,0A7h,0B3h,037h,010h,036h
                db      050h,084h,085h,085h,084h,0F0h
                db      0F0h,0B2h,0A7h,0A6h,0A6h,0A7h
                db      0f3h,026h,070h,027h,080h,044h
                db      045h,077h,076h,0a6h,0b0h,061h
                db      061h,052h,0a7h,077h,030h,076h
                db      080h,0a2H,001h,041h,041h,001h
		db	0f5h,030h,0f4h,0b3h,0a4h,0f8h
		db	0a5h,0D0h,047h,046h,0F0h,0A6h
                db      080h,0A7h,070h,0A7h,010h,0A6h
                db      08eh,0f0h,050h,08fh,0b2h,0f8h
                db      0a3h,080h,08eh,0f0h,050h,08fh
                db      0b7h,010h,0b6h,0f0h,080h,0a6h
		db      0a7h,0f0h,087h,0F0h,070h,086h
		db      036h,0f0h,0f0h,090h,037h,083h
                db      02ch,0f0h,0f0h,0f0h,030h,02dh
		db	082h,030h,0b5h,0b4h,0f2h,0a6h
		db	030h,0a7h,083h,083h,0a6h,0f0h
		db	058h,0a7h,077h,076h,0f0h,0f0h
                db	0f0h,0f0h,0f8h,0f8h,000h
zstep		dw	1
doortimer	dw	-4250
omniscent	db	"OMNISCENT"
omniend:
sanction        db      "(C) DIRK KšPPERS"
sancend:
ob		vector	<-330.0,0.0,64.0>
owmat           vector  <0.0,-1.0,0.0>
		vector	<0.0,0.0,-1.0>
		vector	<1.0,0.0,0.0>

;=============================================================================
;        	null-initialized data
;=============================================================================
nullstart:
wmat            matrix	?
nwmat		matrix  ?

zspeed		dw	?
oxw		dw	?
oyw		dw	?
ozw		dw	?
scriptptr	dw	?
scriptanz	dw	?
scriptins	db	?
once		db	?
ticker		dw	?
tracks		dw	?
palette         db 	768 dup (?)
channels        db	16*6 dup (?)
o		object 	?
nullend:

;=============================================================================
;       	uninitialized data
;=============================================================================
oldstack        dw      ?
label			Old08IrqPtr dword
Old08Irqofs     dw      ?
Old08Irqseg     dw      ?
label			Old09IrqPtr dword
Old09Irqofs     dw      ?
Old09Irqseg     dw      ?
songdata	db	3605 dup (?)
root   		dw	?
circletab	dw	32 dup (?)
stars		db      90 dup (?)
twice		db	?
vseg		dw	?
bseg		dw	?
tseg   		dw	20 dup (?)
shadetab	db	256*128 dup (?)
p		dw	4*15 dup (?)
pr		dd	3*15 dup (?)
po		poly	?
rp		dd	3*MAXPOINTS dup (?)
facei		dd      MAXFACES dup (?)
ends		code
                end     start
