.386
.MODEL FLAT, STDCALL

Beep PROTO, FREQ:DWORD, DUR:DWORD
GetStdHandle PROTO STDCALL :DWORD

GetConsoleWindow PROTO STDCALL
WriteConsoleA PROTO STDCALL :DWORD,:DWORD,:DWORD,:DWORD,:DWORD
	;_In_             HANDLE  hConsoleOutput,
	;_In_       const VOID    *lpBuffer,
	;_In_             DWORD   nNumberOfCharsToWrite,
	;_Out_opt_        LPDWORD lpNumberOfCharsWritten,
	;_Reserved_       LPVOID  lpReserved

ReadConsoleInputA PROTO STDCALL :DWORD,:DWORD,:DWORD,:DWORD
	;_In_  HANDLE        hConsoleInput,
	;_Out_ PINPUT_RECORD lpBuffer,
	;_In_  DWORD         nLength,
	;_Out_ LPDWORD       lpNumberOfEventsRead

GetNumberOfConsoleInputEvents PROTO STDCALL :DWORD,:DWORD
	;_In_  HANDLE  hConsoleInput,
	;_Out_ LPDWORD lpcNumberOfEvents

SetConsoleCursorPosition PROTO STDCALL :DWORD,:DWORD
	;_In_ HANDLE hConsoleOutput,
	;_In_ COORD  dwCursorPosition

Sleep PROTO STDCALL :DWORD
	;DWORD MS WAIT

SetConsoleMode PROTO STDCALL :DWORD,:DWORD
	;_In_ HANDLE hConsoleHandle,
	;_In_ DWORD  dwMode

SystemFunction036 PROTO STDCALL :DWORD, :DWORD
	;[out] PVOID RandomBuffer,
	;[in]  ULONG RandomBufferLength

FRAMERATE EQU 16
MAXTIME EQU 03

.DATA
	HANDLE DWORD ?
	HANDLEIN DWORD ?
	LEN DWORD ?
	BUFFER BYTE 64 DUP(?)
	READLEN DWORD ?

	NEWLINE BYTE 10, 13	;\n\r

	SKYWIDTH EQU 11
	BLUE BYTE 1BH, "[2;34;40m"
	SOLID BYTE 219	;SOLID BLOCK
	DARKYELLOW BYTE 1BH, "[2;33;41m"
	MESH BYTE 220	;BOTTOM HALF BLOCK
	WORLD BYTE 48 DUP (55H)
	FALLTIMER BYTE 0

	;PLAYER
	PLAYERPOSOFFSET EQU 15
	PLAYER BYTE 1BH, "[2;97;44m", 127, 1BH, "[0m", 16	;CHARACTER (15B), X POSITION
	INPUTKEY BYTE ?
	STATE BYTE 0
	SCORE BYTE 4 DUP (0)
	
	TITLEVAR BYTE 1BH, "]0;DOOMSDAY", 07H, 1BH, "[?25l", 0

.CODE
START:
	;GET CONSOLE (OUT):
	PUSH -11	;get STD_OUTPUT_HANDLE 
	CALL GetStdHandle	;RETURNS IN EAX
	MOV HANDLE, EAX
	;GET CONSOLE (IN):
	PUSH -10	;get STD_INPUT_HANDLE 
	CALL GetStdHandle	;RETURNS IN EAX
	MOV HANDLEIN, EAX

	;SET CONSOLE MODE ENSURING ANSI INPUT IS ALLOWED
	MOV EAX, 05H	;ENABLE VIRTUAL TERMINAL
	PUSH EAX
	PUSH HANDLE
	CALL SetConsoleMode

	;SET CONSOLE TITLE & CURSOR OFF WITHT ANSI STRING
	LEA EAX, [TITLEVAR]
	MOV LEN, 20
	CALL WRITEBUFFER

	AWAITKEY:
		;BEEP FIRST:
		PUSH 500
		PUSH 500
		CALL BEEP
	;READ
	WAITFORKEY:
	CALL READKEY
	CMP AL, 13	;ENTER
	JNE WAITFORKEY
	MOV BUFFER, AL
	LEA EAX, [BUFFER]
	CALL WRITECHAR

	;RESET:
		;RESET: STATE, WORLD, SCORE
	MOV STATE, 0
	LEA EDX, [SCORE]
	XOR EAX, EAX
	MOV [EDX], EAX
	MOV ECX, SIZEOF WORLD
	MOV EDX, OFFSET WORLD

	CLEARWORLD:
		XOR AL, AL
		MOV [EDX], AL
		INC EDX
		LOOP CLEARWORLD

	GAMEPLAY:
	;RESET CURSOR POSITION
	PUSH 0
	PUSH HANDLE
	CALL SetConsoleCursorPosition

	;GET INPUT:
	CALL READKEY
	MOV INPUTKEY, AL
	CALL WRITESCORE
	CALL WRITENEWLINE
	CALL MOVEROIDS
	CALL DRAWWORLD
	CALL DRAWPLAYER

	;CHECK STATE
	MOV AL, STATE
	CMP AL, 00H
	JNE AWAITKEY

	CALL WRITENEWLINE
	;TIME KEEPING
	CALL WAITFRAME	;WAIT FOR NEXT FRAME TIME
	JMP GAMEPLAY
	;GAME WILL LOOP, NO NEED TO END

DRAWPLAYER PROC
	;CHECK INPUT:
	MOV AL, INPUTKEY
	CMP AL, 37	;LEFT ARROW
	JNE CHECKRIGHT
		;MOVE TO LEFT
		MOV AL, [PLAYER+PLAYERPOSOFFSET]
		DEC AL
		JMP BOTH
	CHECKRIGHT:
	CMP AL, 39	;RIGHT ARROW
	JNE CHECKCOLLISION
		;MOVE TO RIGHT
		MOV AL, [PLAYER+PLAYERPOSOFFSET]
		INC AL
	BOTH:
		AND AL, 1FH	;LIMIT TO 32
		MOV [PLAYER+PLAYERPOSOFFSET], AL


	
	CHECKCOLLISION:		; (WITH LAST 4 BYTES)
	LEA EDX, [WORLD+44]
	MOV EAX, [EDX]
	XOR EBX, EBX
	MOV BL, [PLAYER+PLAYERPOSOFFSET]
	MOV CL, 32
	SUB CL, BL
	ROL EAX, CL
	JNC PTOCONSOLE
		;GAMEOVER:
		INC STATE
		JMP ENDDRAWPLAYER
	
	PTOCONSOLE:
	;SET CONSOLE CURSOR TO PLAYER POSITION:
	XOR EAX, EAX
	MOV AL, 12
	ROL EAX, 10H
	OR AL, [PLAYER+PLAYERPOSOFFSET]
	PUSH EAX
	PUSH HANDLE
	CALL SetConsoleCursorPosition
	;DRAW PLAYER TO SCREEN:
	MOV LEN, PLAYERPOSOFFSET
	LEA EAX, [PLAYER]
	CALL WRITEBUFFER

	ENDDRAWPLAYER:
	RET
DRAWPLAYER ENDP

WRITESCORE PROC
	;INCREASE SCORE:
	LEA EDX, [SCORE+3]
	INCREASESCORE:
		MOV AL, [EDX]
		ADD AL, 01
		DAA
		MOV [EDX], AL
		JNC SCORETOCONSOLE
		DEC EDX
		JMP INCREASESCORE	;THIS IS A MEMORY LEAK HERE, BUT SCORE SHOULDNT EVER GET THAT HIGH
	SCORETOCONSOLE:
		MOV ECX, 04H
		LEA EDX, [SCORE]
		DRAWSCORE:
			MOV AL, [EDX]
			ROR AL, 04
			AND AL, 0FH
			ADD AL, 30H
			MOV [BUFFER], AL
			LEA EAX, BUFFER
			PUSH ECX
			PUSH EDX
			CALL WRITECHAR
			
			POP EDX
			MOV EAX, [EDX]
			AND AL, 0FH
			ADD AL, 30H
			MOV [BUFFER], AL
			LEA EAX, [BUFFER]
			PUSH EDX
			CALL WRITECHAR
			POP EDX
			POP ECX
			INC EDX
			LOOP DRAWSCORE
	RET
WRITESCORE ENDP

MOVEROIDS PROC
	;CHECK TIMER:
	MOV AL, FALLTIMER
	CMP AL, MAXTIME
	JB ENDMOVEROIDS
		MOV FALLTIMER, 00H
	;SHIFT DOWN BY 4
	MOV ECX, 44
	LEA EDX, [WORLD+47]
	LEA EBX, [WORLD+43]
	SHIFT:
		MOV AL, [EBX]
		MOV [EDX], AL
		DEC EDX
		DEC EBX
		LOOP SHIFT

	;SET NEW FOUR:
		;GET RANDOM 32 BIT VAL
		LEA EAX, [BUFFER]
		PUSH 8
		PUSH EAX
		CALL SystemFunction036
		LEA EDX, [BUFFER]
		MOV EAX, [EDX]
		ADD EDX, 04
		AND EAX, [EDX]
		LEA EDX, [WORLD]
		MOV [EDX], EAX
	ENDMOVEROIDS:
	INC FALLTIMER
	RET
MOVEROIDS ENDP

DRAWWORLD PROC
	MOV ECX, SIZEOF WORLD
	MOV EDX, OFFSET WORLD
	MOV BH, 04H
	DRAWSLICE:
		MOV AH, 08H
		MOV AL, [EDX]
		
		BITROLL: 
		RCR AL, 01H
		PUSH EAX
		JC SKY 
			LEA EAX, BLUE
			JMP DRAWONWORLD
		SKY:
			LEA EAX, DARKYELLOW
		
		DRAWONWORLD:
		MOV LEN, SKYWIDTH			;SIZE OF COLOR WITH ONE CHAR BYTE
		MOV BUFFER, BL
			PUSH EBX
			PUSH EDX
			PUSH ECX
			CALL WRITEBUFFER
			POP ECX
			POP EDX
			POP EBX
			POP EAX
		DEC AH
		CMP AH, 00H
		JNE BITROLL
			DEC BH
			CMP BH, 00H
			JNE NEXTSLICE
			MOV BH, 04H
			;NEW LINE:
			PUSH EAX
			PUSH EBX
			PUSH EDX
			PUSH ECX
			CALL WRITENEWLINE
			POP ECX
			POP EDX
			POP EBX
			POP EAX
		NEXTSLICE:
		INC EDX
		LOOP DRAWSLICE

DRAWWORLD ENDP

WAITFRAME PROC
	PUSH FRAMERATE
	CALL Sleep	;REPLACE WITH BEEP LATER
	RET
WAITFRAME ENDP

WRITENEWLINE PROC
	MOV BL, NEWLINE
	MOV BUFFER, BL
	MOV BL, NEWLINE+1
	MOV BUFFER+1, BL
	MOV LEN, 2
	LEA EAX, [BUFFER]
	CALL WRITEBUFFER
	RET
WRITENEWLINE ENDP

;KERNEL32 FUNCTIONS:
WRITEBUFFER PROC	;STRING PNTR STORED IN EAX AND LENGTH TO WRITE IN LEN
	PUSH 0
	PUSH 0
	PUSH LEN
	PUSH EAX
	PUSH HANDLE
	CALL WriteConsoleA
	RET
WRITEBUFFER ENDP

WRITECHAR PROC	;CHAR TO WRITE POINTED TO IN EAX
	MOV LEN, 1
	CALL WRITEBUFFER
	RET
WRITECHAR ENDP

READKEY PROC
	;CHECK IF THERE ARE EVENTS TO BE READ:
	LEA EAX, [READLEN]
	PUSH EAX
	PUSH HANDLEIN
	CALL GetNumberOfConsoleInputEvents
	MOV EAX, READLEN
	CMP EAX, 00H
	JE ENDREADKEY

	;READ EVENTS:
	LEA EBX, [BUFFER]
	LEA EAX, [READLEN]
	PUSH EAX
	PUSH 1
	PUSH EBX
	PUSH HANDLEIN
	CALL ReadConsoleInputA
	MOV EAX, READLEN
	CMP EAX, 00H
	JE ENDREADKEY
	MOV AL, BUFFER
		;EVENT TYPE:
		CMP AL, 01H	;KEY_EVENT_RECORD
		JE CHECKKEYDOWN
		XOR EAX, EAX
		JMP ENDREADKEY
			CHECKKEYDOWN:
			;LOAD KEY:
			;CHECK IF HELD DOWN
			MOV AL, [BUFFER+4]
			CMP AL, 00
			JE ENDREADKEY
			;GET KEY CODE
			MOV AL, BUFFER+10
	ENDREADKEY:
	RET
READKEY ENDP

END START