;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; A firework demo                                         ;
; Programmed by Yaniv LEVIATHAN                           ;
; http://yaniv.leviathanonline.com                        ;
; Converted to DexOS, By Dex                              ;
; Assemble with                                           ;
; c:\fasm firework.asm firework.dex                       ;
; NOTE: Needs MMX & SSE                                   ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
BlackMenuStartX = 194					  ;                              
BlackMenuStartY = 90					  ;
format binary as 'gex'					  ;
use32							  ;
	ORG   0x800000					  ;
	jmp   start					  ;
	db    'DEX4'					  ;
;=======================================================  ;
; Global defines.                                         ;
;=======================================================  ;
	NUM_PARTS	= 150				  ;
	X_OFFSET	= 0				  ;
	Y_OFFSET	= 2				  ;
	X_SPEED_OFFSET	= 4				  ;
	Y_SPEED_OFFSET	= 6				  ;
	COLOR_OFFSET	= 8				  ;
	PART_SIZE	= 10				  ;
start:							  ;
	mov	ax,18h					  ;
	mov	ds,ax					  ;
	mov	es,ax					  ;
	mov	[CountPalette],0			  ;
;=======================================================  ;
; Get calltable address.                                  ;
;=======================================================  ;
	mov	edi,Functions				  ; fill the function table
	mov	al,0					  ; so we have some usefull functions
	mov	ah,0x0a 				  ;
	int	50h					  ;
;=======================================================  ;
; Load vesa info.                                         ;
;=======================================================  ;
	call	[LoadVesaInfo]				  ;
	mov	edi,VESA_Info				  ;
	mov	ecx,193 				  ;
	cld						  ;
	cli						  ;
	rep	movsd					  ;
	sti						  ;
;=======================================================  ;
; Decode Dif                                              ;
;=======================================================  ;
	mov	esi,file_area_Menu			  ;
	mov	edi,Menu_Buffer 			  ;
	mov	ecx,MainBuffer				  ;
	mov	ebx,3					  ;
	int	40h					  ;
	jc	exit					  ;

;=======================================================  ;
; get menu buffer address                                 ;
;=======================================================  ;
	mov	ebx,1					  ; 
	int	40h					  ;                                       
	mov	dword[MenuBuffer],esi			  ;
;=======================================================  ;
; Move the background image to our buffer                 ;
;=======================================================  ;
	call	MoveBuffer				  ;
							  ;
	mov	eax,BlackMenuStartX			  ; start X
	mov	ecx,BlackMenuStartY			  ; start Y 
	mov	esi,Menu_Buffer 			  ; source image
	mov	edi,MainBuffer				  ; dest image
	mov	ebx,6					  ; 
	int	40h					  ;
							  ;
	call	BuffToScreenScr 			  ;
	mov	edi, Palette1
	xor	eax, eax
  red_loop:
	stosd
	stosd
	add	eax, 0x040000
	and	eax, 0xFFFFFF
	jnz	red_loop

	mov	eax, 63*4*65536
@@:
	stosd
	stosd
	add	ax, 0x0404
	jnc	@b 

	mov	edi, Palette2
	xor	eax, eax
  Green_loop:
	stosd
	stosd
	add	eax, 0x0400
	and	eax, 0xFFFF
	jnz	Green_loop
	xor	eax,eax
	mov	ah,252 
@@:
	stosd
	stosd
	add	eax, 0x040004
	mov	ah,252
	jnc	@b 

	mov	edi, Palette3
	xor	eax, eax
  Blue_loop:
	stosd
	stosd
	add	eax, 0x000004
	and	eax, 0xFF
	jnz	Blue_loop
	xor	eax,eax
	mov	al, 252
@@:
	stosd
	stosd
	add	eax, 0x040400
	mov	al,252
	jnc	@b 
    
  zero_buffer:
	mov	ecx, 320*200
	mov	edi,buffer
	xor	eax, eax
	rep	stosb

;=======================================================  ;
; Main Functions                                          ;
;=======================================================  ;
	db	0x0f, 0x31				  ;
	mov	[seed], eax				  ;
	xor	eax,eax 				  ;
	mov	ax,[ModeInfo_XResolution]		  ;
	shr	ax,1					  ;
	sub	ax,165					  ;
	mov	[WinStartX],eax 			  ;
	xor	eax,eax 				  ;
	mov	ax,[ModeInfo_YResolution]		  ;
	shr	ax,1					  ;
	sub	ax,70					  ;
	mov	[WinStartY],eax 			  ;
	call	GetWinBufferPointer			  ;
	jmp	MAIN
init_particle:
	db	0x0f, 0x31
	and	ax, 0x1F
	jnz	.dont_re_init_globals
	; init x
	call	rand
	xor	dx, dx
	mov	bx, 320
	div	bx
	shl	dx, 6
	mov	[global_x], dx
	; init y
	call	rand
	xor	dx, dx
	mov	bx, 200
	div	bx
	shl	dx, 6
	mov	[global_y], dx
  .dont_re_init_globals:
	; init x
	mov	dx, [global_x]
	mov	[ebp+X_OFFSET], dx
	; init y
	mov	dx, [global_y]
	mov	[ebp+Y_OFFSET], dx
	; init x speed
	call	rand
	and	ax, 31
	sub	ax, 15
	;shl    ax, 6
	mov	[ebp+X_SPEED_OFFSET], ax
	; init y speed
	call	rand
	and	ax, 31
	sub	ax, 15
	;shl    ax, 6
	mov	[ebp+Y_SPEED_OFFSET], ax
	; init color
	mov	ax, 255
	;call   rand
	;and    ax, 0xFF
	mov	[ebp+COLOR_OFFSET], ax
	ret
;=======================================================  ;
; Main                                                    ;
;=======================================================  ;
MAIN:
	mov	ecx, NUM_PARTS
	mov	ebp, particles
  .advance_particles:
	mov	ax, [ebp+X_OFFSET]
	mov	bx, [ebp+Y_OFFSET]

	sar	ax, 6
	sar	bx, 6

	cmp	ax, 5
	jb	.new_particle
	cmp	 ax, 315
	jge	.new_particle
	cmp	bx, 5
	jb	.new_particle
	cmp	bx, 195
	jge	.new_particle
	jmp	.part_ok
  .new_particle:
	call	init_particle
	jmp	.advance_particles

  .part_ok:
	shl	eax,16
	shr	eax,16
	mov	edi, eax
	add	edi,buffer
	mov	eax, 320
	mul	bx
	add	edi, eax
	mov	ax, [ebp+COLOR_OFFSET]
	stosb

	mov	ax, [ebp+X_OFFSET]
	mov	bx, [ebp+Y_OFFSET]
	add	ax, [ebp+X_SPEED_OFFSET]
	add	bx, [ebp+Y_SPEED_OFFSET]
	mov	[ebp+X_OFFSET], ax
	mov	[ebp+Y_OFFSET], bx

	db	0x0f, 0x31
	and	ax, 0x7F
	jnz	.dont_inc_y_speed
	inc	word [ebp+Y_SPEED_OFFSET]
  .dont_inc_y_speed:
	
	add    ebp, PART_SIZE
	loop   .advance_particles

	call   mmx_shade
	mov    eax, [blur_right_flag]
	and    eax, 0x800000
	jnz    .do_blur_right
	call   mmx_blur
	db     0x0f, 0x31
	and    ax, 1
	jz     .blur_ok
	jmp    .dont_blur
  .do_blur_right:
	call   mmx_blur_right
  .blur_ok:
	mov    eax, [blur_right_flag]
	add    eax,0x1000
	mov    [blur_right_flag],eax
  .dont_blur:

  .copy_buffer_to_video:

ColorLoop:
	inc    [CountPalette]
	cmp    [CountPalette],2000
	ja     NotRed
	call   Convert232bit1
	jmp    dobuffer

  NotRed:
	cmp    [CountPalette],4000
	ja     NotGreen

	call   Convert232bit2
	jmp    dobuffer
  NotGreen:
	cmp    [CountPalette],6000
	jb     ItsBlue
	mov    [CountPalette],0
	jmp    ColorLoop
  ItsBlue:
	call   Convert232bit3

  dobuffer:
	call   BuffToScreen
  .check_for_key:
	call   [KeyPressedNoWait]
	cmp    al,0
	je     MAIN
  exit:
	ret

;=======================================================  ;
; Misc. Functions                                         ;
;=======================================================  ;
mmx_shade:
	mov	ecx, 320*200/8
	mov	edi,buffer
	movq	mm1, [sub_mask]
.lop:
	movq	mm0, [es:edi]
	psubusb mm0, mm1
	movq	[es:edi], mm0
	add	edi, 8
	loop	.lop
	ret

mmx_blur:
	mov	ecx, (320*200-330*2)/8
	mov	edi, 328
	add	edi,buffer
.lop:
	movq	mm0, [es:edi]
	movq	mm1, [es:edi+1]
	movq	mm2, [es:edi-1]
	movq	mm3, mm0
	movq	mm4, [es:edi-320]
	movq	mm5, [es:edi+320]

	pavgb	mm0, mm1 ; mm0 = avg(cur,cur+1)
	pavgb	mm3, mm2 ; mm3 = avg(cur,cur-1)
	pavgb	mm4, mm5 ; mm4 = avg(cur+320,cur-320)
	pavgb	mm3, mm4 ; mm3 = avg(avg(cur,cur-1),avg(cur+320,cur-320))
	pavgb	mm0, mm3 ; mm0 = avg(avg(cur,cur+1),

	movq	[es:edi], mm0
	add	edi, 8
	loop	.lop
	ret

mmx_blur_right:
	mov	ecx, (320*200-330*2)/8
	mov	edi, 328
	add	edi,buffer
.lop:
	movq	mm0, [es:edi]
	movq	mm1, [es:edi+1]
	movq	mm2, [es:edi+320]
	movq	mm3, [es:edi+321]
	pavgb	mm0, mm1
	pavgb	mm3, mm2
	pavgb	mm0, mm3
	movq	[es:edi], mm0
	add	edi, 8
	loop	.lop
	ret


rand:
	mov    eax, [seed]
	imul   eax, 214013
	add    eax, 2531011
	mov    [seed], eax
	shr    eax, 16
	ret

Convert232bit1:
	pushad
	mov	edi,buffer2
	mov	esi,buffer
	mov	ecx,320*200
	cld
  lets_do_a_loop18bpp1: 				; mov data from bmp to buffer
	xor	eax,eax
	lodsb
	push	esi
	mov	esi,Palette1				; Convert palette to 32bpp
	shl	eax,2
	mov	eax,dword[Palette1 +eax]
	pop	esi
	stosd
	loop	lets_do_a_loop18bpp1
	popad
	ret

Convert232bit2:
	pushad
	mov	edi,buffer2
	mov	esi,buffer
	mov	ecx,320*200
	cld
lets_do_a_loop18bpp2:					; mov data from bmp to buffer
	xor	eax,eax
	lodsb
	push	esi
	mov	esi,Palette2				 ; Convert palette to 32bpp
	shl	eax,2
	mov	eax,dword[Palette2 +eax]
	pop	esi
	stosd
	loop	lets_do_a_loop18bpp2
	popad
	ret

Convert232bit3:
	pushad
	mov	edi,buffer2
	mov	esi,buffer
	mov	ecx,320*200
	cld
  lets_do_a_loop18bpp3: 				  ; mov data from bmp to buffer
	xor	eax,eax
	lodsb
	push	esi
	mov	esi,Palette3				  ; Convert palette to 32bpp
	shl	eax,2
	mov	eax,dword[Palette3 +eax]
	pop	esi
	stosd
	loop	lets_do_a_loop18bpp3
	popad
	ret
;=======================================================  ;
;  BuffToScreen.                                          ;
;=======================================================  ;
BuffToScreen:
	cmp	[ModeInfo_BitsPerPixel],24
	jne	Try32
	call	BuffToScreen24
	jmp	wehavedone24
Try32:
	cmp	[ModeInfo_BitsPerPixel],32
	jne	wehavedone24
	call	BuffToScreen32 
wehavedone24:
	ret
;=======================================================  ;
; BuffToScreen24                                          ;
;=======================================================  ;
BuffToScreen24:
	 pushad
	 push	 es
	 mov	 ax,8h
	 mov	 es,ax
	 mov	 edi,[VesaScreen] ;[ModeInfo_PhysBasePtr]
	 mov	 esi,buffer2
	 xor	 eax,eax
	 mov	 ecx,eax
	 mov	 ebx,eax
	 mov	 bx,[ModeInfo_XResolution]
	 sub	 ebx,320
	 mov	 [ImageXaddOn24],ebx
	 shl	 ebx,2
	 sub	 ebx,[ImageXaddOn24]
	 mov	 [ImageXaddOn],ebx
	 mov	 ecx,200

testloop24:
	 push	 ecx
	 mov	 ecx,320
	 cld
@@:
	 lodsd
	 ;dec    esi
	 stosd
	 dec	 edi
	 loop	 @b
	 add	 edi,[ImageXaddOn]
	 pop	 ecx
	 loop	 testloop24
	 pop	 es
	 popad
	 ret
;=======================================================  ;
; BuffToScreen32                                          ;
;=======================================================  ;
BuffToScreen32:
	 pushad
	 push	 es
	 mov	 ax,8h
	 mov	 es,ax
	 mov	 edi,[VesaScreen] 
	 mov	 esi,buffer2
	 xor	 eax,eax
	 mov	 ecx,eax
	 mov	 ebx,eax
	 mov	 bx,[ModeInfo_XResolution]
	 sub	 ebx,320
	 shl	 ebx,2
	 mov	 ecx,200
testloop32:
	 push	 ecx
	 mov	 ecx,320
	 cld
@@:	 lodsd

	 stosd
	 ;dec    esi
	 loop	 @b
	 add	 edi,ebx
	 pop	 ecx
	 loop	 testloop32
	 pop	 es
	 popad
	 ret
;=======================================================  ;
; GetWinBufferPointer.                                    ;
;=======================================================  ;
GetWinBufferPointer:					 
	push	eax					      
	push	ebx
	mov	eax,[WinStartX]
	mov	[WinBuffX],eax
	mov	ebx,[WinStartY]
	mov	[WinBuffY],ebx
	mov	edi,[ModeInfo_PhysBasePtr]				 
	xor	ebx,ebx
	mov	ebx,[WinBuffX]
	shl	ebx,2
	cmp	[ModeInfo_BitsPerPixel],24   
	jne	@F
	sub	ebx,[WinBuffX] 
@@:	  
	add	edi, ebx
	mov	ebx,[WinBuffY]
	xor	eax,eax
	mov	ax,[ModeInfo_XResolution] 
	shl	eax,2 
	     
	cmp	[ModeInfo_BitsPerPixel],24    
	jne	@f
	sub	ax,[ModeInfo_XResolution] 
@@:
	mul	ebx
	add	edi,eax
	mov	dword[VesaScreen],edi
	pop	ebx
	pop	eax
	ret

;=======================================================  ;
; BuffToScreen.                                           ;
;=======================================================  ;
BuffToScreenScr:					  ; test for 24bit or 32bit vesa
	cmp	[ModeInfo_BitsPerPixel],24		  ;
	jne	Try32Scr				  ;
	call	BuffToScreen24Scr			  ;
	jmp	wehavedone24Scr 			  ;
Try32Scr:						  ;
	cmp	[ModeInfo_BitsPerPixel],32		  ;
	jne	wehavedone24Scr 			  ;
	call	BuffToScreen32Scr			  ;
wehavedone24Scr:					  ;
@@:							  ;
	ret						  ;

;=======================================================  ;
; BuffToScreen32 (32bpp)                                  ;
;=======================================================  ;
BuffToScreen32Scr:					  ;
	 pushad 					  ;
	 push	 es					  ;
	 mov	 ax,8h					  ;
	 mov	 es,ax					  ;
	 mov	 edi,[ModeInfo_PhysBasePtr]		  ;
	 mov	 esi,MainBuffer 			  ;
	 xor	 eax,eax				  ;
	 mov	 ecx,eax				  ;
	 mov	 ax,[ModeInfo_XResolution]		  ;
	 mov	 cx,[ModeInfo_YResolution]		  ;
	 mul	 ecx					  ;
	 mov	 ecx,eax				  ;
	 cld						  ;
	 cli						  ;
	 rep	 movsd					  ;
	 sti						  ;
	 pop	 es					  ;
	 popad						  ;
	 ret						  ;

;=======================================================  ;
; BuffToScreen24 (24bpp)                                  ;
;=======================================================  ;
BuffToScreen24Scr:					  ;
	 pushad 					  ;
	 push	 es					  ;
	 mov	 ax,8h					  ;
	 mov	 es,ax					  ;
	 xor	 eax,eax				  ;
	 mov	 ecx,eax				  ;
	 mov	 ebx,eax				  ;
	 mov	 ax,[ModeInfo_YResolution]		  ;
	 mov	 ebp,eax				  ;
	 lea	 eax,[ebp*2+ebp]			  ;
	 mov	 edi,[ModeInfo_PhysBasePtr]		  ;
	 mov	 esi,MainBuffer 			  ;
	 cld						  ;
.l1:							  ;
	 mov	 cx,[ModeInfo_XResolution]		  ;
	 shr	 ecx,2					  ;
.l2:							  ;
	 mov	 eax,[esi]				  ;
	 mov	 ebx,[esi+4]				  ;
	 shl	 eax,8					  ;
	 shrd	 eax,ebx,8				  ;
	 stosd						  ;
							  ;
	 mov	 ax,[esi+8]				  ;
	 shr	 ebx,8					  ;
	 shl	 eax,16 				  ;
	 or	 eax,ebx				  ;
	 stosd						  ;
							  ;
	 mov	 bl,[esi+10]				  ;
	 mov	 eax,[esi+12]				  ;
	 shl	 eax,8					  ;
	 mov	 al,bl					  ;
	 stosd						  ;
							  ;
	 add	 esi,16 				  ;
	 loop	 .l2					  ;
							  ;
	 sub	 ebp,1					  ;
	 ja	.l1					  ;
							  ;
	 pop	 es					  ;
	 popad						  ;
	 ret						  ;


;=======================================================  ;
; Move buffer                                             ;
;=======================================================  ;
MoveBuffer:						  ;
	 pushad 					  ;
	 mov	esi,[MenuBuffer]			  ;
	 mov	edi,MainBuffer				  ;
	 mov	ecx,800*600				  ;
	 rep	movsd					  ;
	 popad						  ;
	 ret						  ;

;=======================================================  ;
; Data                                                    ;
;=======================================================  ;
VesaScreen    dd  0
ImageXaddOn24 dd  0
ImageXaddOn   dd  0
WinBuffY      dd  0
WinBuffX      dd  0
WinStartX     dd  0
WinStartY     dd  0
MenuBuffer    dd  0
CountPalette  dd  0


seed:	      dd 0
global_x:     dw 160*64
global_y:     dw 100*64
sub_mask:     dd 0x01010101, 0x01010101
;                             x, y, x_speed, y_speed, color
particles: times NUM_PARTS dw 0, 0, 0,	     0,       0
blur_right_flag: dd 0

align 4
file_area_Menu:
file   'Menu\Menu.dif'
file_area_Menu_FileEnd:
rd 1
align 4
Menu_Buffer:				rd  400*384+2
Menu_BufferT:				rd  400*384
include 'Dex.inc'
align 4 
Palette1	    rb 256*4
align 4 
Palette2	    rb 256*4
align 4 
Palette3	    rb 256*4
align 4 
buffer2 	 rd 640*400
align 4 
buffer		 rb 320*200
MainBuffer:
