PROG	SEGMENT 'CODE'
	ORG 100h
	ASSUME CS:PROG, DS:PROG, SS:PROG 
JUMPS

FPS_METER	= 1	;Показать в конце фпс'ы
SHOW_PALETTE	= 0	;Вывести на экран палитру

STACK_SIZE	EQU 1024		;размер стека
LEN_OF_PROG	EQU (LAST_BYTE)/16+102h
MAIN proc
include dos.mac
;CODE
	MOV AX,LAST_BYTE-16	;set stack
	MOV SP,AX

	ReallocMem DS,LEN_OF_PROG
	JC NO_MEM
	AllocMem 4000
	JC NO_MEM
	MOV BUFF0_PTR,AX

	MOV BX,81h
	MOV CL,[BX-1]
	XOR AH,AH
PARSE_LOOP:
	OR CL,CL
	JZ EX_PARSE
	MOV AL,[BX]
	CMP AL,'i'
	JNZ PARSE_L1
	OR AH,80h
	JMP END_PARSE_LOOP
PARSE_L1:
	CMP AL,'I'
	JNZ PARSE_L2
	OR AH,80h
	JMP END_PARSE_LOOP
PARSE_L2:
	SUB AL,'1'
	CMP AL,0
	JB END_PARSE_LOOP
	CMP AL,3
	JA END_PARSE_LOOP
	AND AH,80h
	OR AH,AL
END_PARSE_LOOP:
	INC BX
	DEC CL
	JMP PARSE_LOOP
EX_PARSE:
	TEST AH,80h
	JZ DEF_OPT
	MOV DRAW_PROC,OFFSET [INTEL_OPT]
DEF_OPT:
	AND AH,3
	MOV BL,AH
	XOR BH,BH
	SHL BX,1
	MOV AX,[BX+PAL_PROC_TABLE]
	MOV PAL_PROC,AX

	MOV AX,13h
	INT 10h
	CALL INIT_SCREEN

if FPS_METER
	XOR AH,AH
	INT 1Ah
	MOV WORD PTR B_TIME,DX
	MOV WORD PTR B_TIME+2,CX
endif

MAIN_LOOP:
	CALL UPDATE_SCREEN
if FPS_METER
.386
	INC FRAME_COUNTER
.8086
endif
	MOV AH,1
	INT 16h
	JZ MAIN_LOOP
	MOV AH,0
	INT 16h
	SUB AL,'1'
	CMP AL,0
	JL EX_KEY
	CMP AL,3
	JA EX_KEY

	XOR BH,BH
	MOV BL,AL
	SHL BX,1
	MOV AX,[BX+PAL_PROC_TABLE]
	CALL AX
	JMP MAIN_LOOP
EX_KEY:
	MOV AX,3h
	INT 10h
if FPS_METER
	XOR AH,AH
	INT 1Ah
	SUB DX,WORD PTR B_TIME
	SBB CX,WORD PTR B_TIME+2
.386
	ROL ECX,16
	MOV CX,DX
	MOV EAX,FRAME_COUNTER
	MOV EBX,91
	MUL EBX
	MOV EBX,5
	DIV EBX
	XOR EDX,EDX
	DIV ECX
.8086
	LEA DI,STR_+4
	XOR BL,BL
	CALL PRINT_DEC16_
	PrintDos STR_
endif

	JMP EX
NO_MEM:	PrintDos NoMem
EX:
	PrintDos Using
	INT 20h
MAIN endp

INIT_SCREEN proc
	CALL [PAL_PROC]
	PUSH ES
	XOR AX,AX
	CLD
	MOV ES,BUFF0_PTR
	XOR DI,DI
	MOV CX,32000
	REP STOSW
	POP ES

if SHOW_PALETTE
	MOV AX,0A000h
	PUSH ES
	MOV ES,AX
	XOR DI,DI
	CLD

	MOV CX,200
INIT_SCREEN_LO02:
	MOV DX,256
	MOV AL,0
INIT_SCREEN_LO03:
	MOV ES:[DI],AL
	INC DI
	INC AL
	JNZ INIT_SCREEN_LO03
	ADD DI,64
	DEC CX
	JNZ INIT_SCREEN_LO02

	XOR AH,AH
	INT 16h
	XOR DI,DI
	XOR AX,AX
	CLD
	MOV CX,32000
	REP STOSW
	POP ES
endif
	RET
INIT_SCREEN endp

SET_PAL_FLAME0 proc
	XOR AX,AX
	XOR BX,BX
;	MOV AX,0000h	;Reg=0,r=63
;	MOV BX,0000h	;g=63,b=63
SET_PAL_FLAME0_LO01:
	CALL SET_DAC_REG
	ADD AX,101h
;	INC AH
;	INC AL
	CMP AL,64
	JB SET_PAL_FLAME0_LO01
	DEC AH

SET_PAL_FLAME0_LO02:
	CALL SET_DAC_REG
	INC BL
	INC AL
	CMP AL,128
	JB SET_PAL_FLAME0_LO02
	DEC BL

SET_PAL_FLAME0_LO03:
	CALL SET_DAC_REG
	INC BH
	INC AL
	CMP AL,192
	JB SET_PAL_FLAME0_LO03
	DEC BH

SET_PAL_FLAME0_LO04:
	CALL SET_DAC_REG
	INC AL
	OR AL,AL
	JNZ SET_PAL_FLAME0_LO04
	MOV AX,1001h
	MOV BH,0
	INT 10h
	RET
SET_PAL_FLAME0 endp

SET_PAL_FLAME1 proc
	XOR AX,AX
	XOR BX,BX
;	MOV AX,0000h	;Reg=0,r=63
;	MOV BX,0000h	;g=63,b=63
SET_PAL_FLAME1_LO01:
	CALL SET_DAC_REG
	INC BH
	INC AL
	CMP AL,64
	JB SET_PAL_FLAME1_LO01
	DEC BH

SET_PAL_FLAME1_LO02:
	CALL SET_DAC_REG
	INC BL
	INC AL
	CMP AL,128
	JB SET_PAL_FLAME1_LO02
	DEC BL

SET_PAL_FLAME1_LO03:
	CALL SET_DAC_REG
	INC AH
	INC AL
	CMP AL,192
	JB SET_PAL_FLAME1_LO03
	DEC AH

SET_PAL_FLAME1_LO04:
	CALL SET_DAC_REG
	INC AL
	OR AL,AL
	JNZ SET_PAL_FLAME1_LO04
	MOV AX,1001h
	MOV BH,0
	INT 10h
	RET
SET_PAL_FLAME1 endp

SET_PAL_FLAME2 proc
	MOV AX,3F00h	;Reg=0,r=63
	MOV BX,3F3Fh	;g=63,b=63
SET_PAL_FLAME2_LO01:
	CALL SET_DAC_REG
	SUB BX,101h
;	DEC BH
;	DEC BL
	DEC AH
	INC AL
	CMP AL,64
	JB SET_PAL_FLAME2_LO01
	INC AH
	ADD BX,101h
;	INC BH
;	INC BL

SET_PAL_FLAME2_LO02:
	CALL SET_DAC_REG
	ADD AX,101h
;	INC AH
;	INC AL
	CMP AL,128
	JB SET_PAL_FLAME2_LO02
	DEC AH

SET_PAL_FLAME2_LO03:
	CALL SET_DAC_REG
	INC BL
	INC AL
	CMP AL,192
	JB SET_PAL_FLAME2_LO03
	DEC BL

SET_PAL_FLAME2_LO04:
	CALL SET_DAC_REG
	INC BH
	INC AL
	OR AL,AL
	JNZ SET_PAL_FLAME2_LO04
	MOV AX,1001h
	MOV BH,3Fh
	INT 10h
	RET
SET_PAL_FLAME2 endp

SET_PAL_FLAME3 proc
;	MOV AX,0000h	;Reg=0,r=63
	XOR AX,AX
	MOV BX,3F3Fh	;g=63,b=63
SET_PAL_FLAME3_LO01:
	CALL SET_DAC_REG
	SUB BX,101h
;	DEC BL
;	DEC BH
	INC AL
	CMP AL,64
	JB SET_PAL_FLAME3_LO01
	ADD BX,101h
;	INC BH
;	INC BL

SET_PAL_FLAME3_LO02:
	CALL SET_DAC_REG
	INC AH
	INC AL
	CMP AL,128
	JB SET_PAL_FLAME3_LO02
	DEC AH

SET_PAL_FLAME3_LO03:
	CALL SET_DAC_REG
	INC BL
	INC AL
	CMP AL,192
	JB SET_PAL_FLAME3_LO03
	DEC BL

SET_PAL_FLAME3_LO04:
	CALL SET_DAC_REG
	INC BH
	INC AL
	OR AL,AL
	JNZ SET_PAL_FLAME3_LO04
	MOV AX,1001h
	MOV BH,3Fh
	INT 10h
	RET
SET_PAL_FLAME3 endp

UPDATE_SCREEN proc
	PUSH ES DS
	MOV ES,BUFF0_PTR
	MOV CX,320/2;4
	MOV DI,64000-320
UPDATE_SCREEN_LO01:
	MOV AX,256-16
	CALL RND16
	ADD AX,16
	MOV AH,AL
	MOV ES:[DI],AX
	MOV ES:[DI-320],AX
;	MOV ES:[DI+2],AX
;	MOV ES:[DI-320+2],AX
;	MOV WORD PTR ES:[DI+4],0
;	MOV WORD PTR ES:[DI-320+4],0
;	MOV WORD PTR ES:[DI+6],0
;	MOV WORD PTR ES:[DI-320+6],0
	ADD DI,2;4
	LOOP UPDATE_SCREEN_LO01

	MOV AX,0A000h
	MOV ES,AX
	MOV DS,BUFF0_PTR
	MOV DI,320;1
	MOV SI,199;198

	CALL WORD PTR CS:[DRAW_PROC]
	POP ES DS
	RET
UPDATE_SCREEN endp

CX_OPT proc
CX_OPT_LO02:
	PUSH SI
	MOV CX,320/2;318
.386
	MOVZX BX,[DI+320]
CX_OPT_LO03:
	MOVZX AX,[DI]
	MOVZX DX,[DI+321]
	ADD BX,DX
	MOVZX DX,[DI+319]
	ADD AX,DX
	MOVZX DX,[DI+1]
	ADD AX,BX
	ADD DX,BX
	MOVZX BX,[DI+322]
	ADD DX,BX
	SHR AX,2
	SHR DX,2
	OR AL,AL
	JZ CX_OPT_L01
	DEC AL
CX_OPT_L01:
	MOV AH,DL
	OR DL,DL
	JZ CX_OPT_L02
	DEC AH
CX_OPT_L02:
	MOV [DI-320],AX
	MOV ES:[DI+320],AX
	ADD DI,2
;	DEC CX
;	JNZ CX_OPT_LO03
	LOOP CX_OPT_LO03
;	ADD DI,2
	POP SI
	DEC SI
	JNZ CX_OPT_LO02
	RET
.8086
CX_OPT endp

INTEL_OPT proc
INTEL_OPT_LO02:
	PUSH SI
	MOV CX,320/2;318
.386
	MOVZX BX,[DI+320]
	XOR DX,DX
INTEL_OPT_LO03:
	XOR AX,AX
	MOV AL,[DI]
	MOV DL,[DI+321]
	ADD BX,DX
	MOV DL,[DI+319]
	ADD AX,DX
	MOV DL,[DI+1]
	ADD AX,BX
	ADD DX,BX
	XOR BX,BX
	MOV BL,[DI+322]
	ADD DX,BX
	SHR AX,2
	SHR DX,2
	OR AL,AL
	JZ INTEL_OPT_L01
	DEC AL
INTEL_OPT_L01:
	MOV AH,DL
	OR DL,DL
	JZ INTEL_OPT_L02
	DEC AH
INTEL_OPT_L02:
	MOV [DI-320],AX
	MOV ES:[DI+320],AX
	ADD DI,2
	DEC CX
	JNZ INTEL_OPT_LO03
;	ADD DI,2
	POP SI
	DEC SI
	JNZ INTEL_OPT_LO02
	RET
.8086
INTEL_OPT endp

include random.asm
include vga_pal.asm
if FPS_METER
include prntd_16.asm
endif
;DATA
if FPS_METER
FRAME_COUNTER	DD ?
B_TIME		DD ?
endif
BUFF0_PTR	DW ?
DRAW_PROC	DW [CX_OPT]
PAL_PROC_TABLE	DW [SET_PAL_FLAME0],[SET_PAL_FLAME1],[SET_PAL_FLAME2],[SET_PAL_FLAME3]
PAL_PROC	DW ?

;MESSAGE
Using	DB 'flame [1|2|3|4][i]',13,10
	DB '1/2/3/4 - palette, i - pentium optimized',13,10
	DB 'Press 1/2/3/4 for change palette or other key to exit',13,10
	DB 'Flame by Ochkin Vadim ;)',13,10,'$'
NoMem	DB 'Not enough memory',13,10,'$'
if FPS_METER
STR_	DB 'FPS:_____',13,10,'$'
endif
ALIGN 2
LAST_BYTE	EQU $-MAIN+110h+STACK_SIZE

PROG	ENDS
	END MAIN
