;
; Startup and OpenGL setup code.
; Changed to a triangle fan at the last minute, for a 16 byte saving
; over what we had in the speech.
;
; Author:
;	s_tec
;

%define fullscreen

%include "win32n.inc"
%include "nasmgl.inc"

%imacro import 2
		extern	%2
%define %1 [%2]
%endmacro

;-----------------------------------------------------------------------------
; Import and export:
;-----------------------------------------------------------------------------

		global	_main
		global	s_main_t
		global	s_main_dt

		;gdi32.dll:
		import	ChoosePixelFormat,	__imp__ChoosePixelFormat@8
		import	SetPixelFormat,		__imp__SetPixelFormat@12
		import	SwapBuffers,		__imp__SwapBuffers@4

		;glu32.dll:
		import	gluPerspective,		__imp__gluPerspective@32

		;kernel32.dll:
		import	ExitProcess,		__imp__ExitProcess@4

		;opengl32.dll:
		import	wglCreateContext,	__imp__wglCreateContext@4
		import	wglMakeCurrent,		__imp__wglMakeCurrent@8
		import	glBegin,		__imp__glBegin@4
		import	glClear,		__imp__glClear@4
		import	glClearDepth,		__imp__glClearDepth@8
		import	glColor3f,		__imp__glColor3f@12
		import	glDepthFunc,		__imp__glDepthFunc@4
		import	glEnable,		__imp__glEnable@4
		import	glEnd,			__imp__glEnd@0
		import	glLoadIdentity,		__imp__glLoadIdentity@0
		import	glMatrixMode,		__imp__glMatrixMode@4
		import	glRotatef,		__imp__glRotatef@16
		import	glTranslatef,		__imp__glTranslatef@12
		import	glVertex3f,		__imp__glVertex3f@12

		;user32.dll:
		import	ChangeDisplaySettings,	__imp__ChangeDisplaySettingsA@8
		import	CreateWindowEx,		__imp__CreateWindowExA@48
		import	GetAsyncKeyState,	__imp__GetAsyncKeyState@4
		import	GetDC,			__imp__GetDC@4
		import	ShowCursor,		__imp__ShowCursor@4
%ifdef debug
		import	PeekMessage,		__imp__PeekMessageA@20
		import	DispatchMessage,	__imp__DispatchMessageA@4
%endif

;-----------------------------------------------------------------------------
; Constants:
;-----------------------------------------------------------------------------

		;Demo constants:
k_main_x	equ	800			;Demo width
k_main_y	equ	600			;Demo height

;-----------------------------------------------------------------------------
; Unitialized data:
;-----------------------------------------------------------------------------
		section .bss
%ifdef debug
s_main_msg:	resb	MSG_size
%endif

s_rtri:		resd	1
s_rquad:	resd	1
		
;-----------------------------------------------------------------------------
; Initialized data:
;-----------------------------------------------------------------------------
		section	.data

%ifdef fullscreen
s_main_mode:		;Display mode:
.dmDeviceName		times	CCHDEVICENAME db 0
.dmSpecVersion		dw	0
.dmDriverVersion	dw	0
.dmSize			dw	DEVMODE_size
.dmDriverExtra		dw	0
.dmFields		dd	DM_PELSWIDTH|DM_PELSHEIGHT
.dmOrientation		dw	0
.dmPaperSize		dw	0
.dmPaperiLength		dw	0
.dmPaperWidth		dw	0
.dmScale		dw	0
.dmCopies		dw	0
.dmDefaultSource	dw	0
.dmPrintQuality		dw	0
.dmColor		dw	0
.dmDuplex		dw	0
.dmYResolution		dw	0
.dmTTOption		dw	0
.dmCollate		dw	0
.dmFormName		times	32 db 0
.dmLogPixels		dw	0
.dmBitsPerPel		dd	0
.dmPelsWidth		dd	k_main_x
.dmPelsHeight		dd	k_main_y
.dmDisplayFlags		dd	0
.dmDisplayFrequency	dd	0
.dmDisplayOrientation	dd	0
%endif
			;The main window's class:
s_main_class:		db	'static', 0
			align	4, db 0

s_main_format:		;Pixel format (40 bytes):
.nSize:			dw	0
.nVersion:		dw	0
.dwFlags:		dd	PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER
.iPixelType:		db	0
.cColorBits:		db	0
.cRedBits:		db	0
.cRedShift:		db	0
.cGreenBits:		db	0
.cGreenShift:		db	0
.cBlueBits:		db	0
.cBlueShift:		db	0
.cAlphaBits:		db	0
.cAlphaShift:		db	0
.cAccumBits:		db	0
.cAccumRedBits:		db	0
.cAccumGreenBits:	db	0
.cAccumBlueBits:	db	0
.cAccumAlphaBits:	db	0
.cDepthBits:		db	16
.cStencilBits:		db	0
.cAuxBuffers:		db	0
.iLayerType:		db	0
.bReserved:		db	0
.dwLayerMask:		dd	0
.dwVisibleMask:		dd	0
.dwDamageMask:		dd	0

s_f0p2:			dd	0.2
s_f0p15:		dd	0.15

;-----------------------------------------------------------------------------
; _main
; Program entry point
;-----------------------------------------------------------------------------
		section	.text
_main:
%ifdef fullscreen
		;Go to fullscreen mode:
		push	CDS_FULLSCREEN		;dwflags
		push	s_main_mode		;lpDevMode
		call	ChangeDisplaySettings

		;Create the window:
		push	0			;lpParam
		push	0			;hInstance
		push	0			;hMenu
		push	0			;hWndParent
		push	0			;nHeight
		push	0			;nWidth
		push	0			;y
		push	0			;x
		push	WS_POPUP|WS_VISIBLE|WS_CLIPSIBLINGS|WS_MAXIMIZE ;dwStyle
		push	0			;lpWindowName
		push	s_main_class		;lpClassName
		push	0			;dwExStyle
		call	CreateWindowEx
		mov	esi, eax
%else
		;Create the window:
		push	0			;lpParam
		push	0			;hInstance
		push	0			;hMenu
		push	0			;hWndParent
		push	k_main_y		;nHeight
		push	k_main_x		;nWidth
		push	0			;y
		push	100			;x
		push	WS_POPUP|WS_VISIBLE|WS_CLIPSIBLINGS ;dwStyle
		push	0			;lpWindowName
		push	s_main_class		;lpClassName
		push	0			;dwExStyle
		call	CreateWindowEx
		mov	esi, eax
%endif

;-----------------------------------------------------------------------------
; OpenGL setup
;-----------------------------------------------------------------------------

		;Get the device context:
		push	esi
		call	GetDC
		mov	esi, eax

		;Hide the mouse:
		push	0
		call	ShowCursor

		;Set up the pixel format:
		push	s_main_format		;ppfd
		push	esi			;hdc
		call	ChoosePixelFormat
		push	s_main_format		;ppfd
		push	eax			;iPixelFormat
		push	esi			;hdc
		call	SetPixelFormat

		;Set up the rendering context:
		push	esi			;hdc
		call	wglCreateContext
		push	eax			;hglrc
		push	esi			;hdc
		call	wglMakeCurrent

;-----------------------------------------------------------------------------
; OpenGL options
;-----------------------------------------------------------------------------

		;Projection matrix:
		push	GL_PROJECTION		;mode
		call	glMatrixMode

		;Set up the transform:
		call	glLoadIdentity
		push	0x40590000		;zFar = 100.0
		push	0x00000000
		push	0x3fb99999		;zNear = 0.1
		push	0x99999999
		push	0x3ff55555		;aspect = 800/600 = 1.3333
		push	0x55555555
		push	0x40468000		;fovy = 45.0
		push	0x00000000
		call	gluPerspective

		;Modelview matrix:
		push	GL_MODELVIEW		;mode
		call	glMatrixMode

		;Depth setup:
		push	0x3ff00000		;depth = 1
		push	0x00000000
		call	glClearDepth
		push	GL_DEPTH_TEST		;cap
		call	glEnable
		push	GL_LEQUAL		;func
		call	glDepthFunc

;-----------------------------------------------------------------------------
; _main_loop
; Demo rendering loop
;-----------------------------------------------------------------------------
_main_loop:
		;Render the demo:
		call	_render

		;Copy to the display:
		push	esi			;hdc
		call	SwapBuffers

%ifdef debug	;Process messages in debug mode:
		push	PM_REMOVE		;wRemoveMsg
		push	0			;wMsgFilterMax
		push	0			;wMsgFilterMin
		push	0			;hWnd
		push	s_main_msg		;lpMsg
		call	PeekMessage
		test	eax, eax
		jz	_main_loop
		push	s_main_msg		;lpmsg
		call	DispatchMessage
%endif
		;while (!GetAsyncKeyState(VK_ESCAPE)):
		push	VK_ESCAPE
		call	GetAsyncKeyState
		test	eax, eax
		jz	_main_loop

		;Clean up and exit:
.quit:		push	0			;uExitCode 
		call	ExitProcess

;-----------------------------------------------------------------------------
; Macros for the rendering code
;-----------------------------------------------------------------------------

%define z 0x00000000  ;0.0
%define p1 0x3f800000 ;+1.0
%define	n1 0xbf800000 ;-1.0
%define p5 0x3f000000 ;0.5

%macro color 3
		push	%3
		push	%2
		push	%1
		call	glColor3f
%endmacro

%macro vertex 3
		push	%3
		push	%2
		push	%1
		call	glVertex3f
%endmacro

;-----------------------------------------------------------------------------
; _render
; Draws the triangle and cube.
;-----------------------------------------------------------------------------
_render:
		;Clear the canvas:
		push	GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT
		call	glClear

		;Set up the transform:
		call	glLoadIdentity
		push	0xc0c00000		;z = -6.0
		push	0x00000000		;y = 0.0
		push	0xbfc00000		;x = -1.5
		call	glTranslatef
		push	0x00000000		;z = 0.0
		push	0x3f800000		;y = 1.0
		push	0x00000000		;z = 0.0
		push	dword[s_rtri]
		call	glRotatef

		;Render the triangle:
		push	GL_TRIANGLE_FAN		;mode
		call	glBegin
		color	p1, z,  z
		vertex	z,  p1, z
		color	z,  p1, z
		vertex	n1, n1, p1
		color	z,  z,  p1
		vertex	p1, n1, p1
		color	z,  p1, z
		vertex	p1, n1, n1
		color	z,  z,  p1
		vertex	n1, n1, n1
		color	z,  p1, z
		vertex	n1, n1, p1
		call	glEnd

		;Set up the transform:
		call	glLoadIdentity
		push	0xc0e00000		;z = -7.0
		push	0x00000000		;y = 0.0
		push	0x3fc00000		;x = 1.5
		call	glTranslatef
		push	0x3f800000		;z = 1.0
		push	0x3f800000		;y = 1.0
		push	0x3f800000		;z = 1.0
		push	dword[s_rquad]
		call	glRotatef

		;Render the quad:
		push	GL_QUADS		;mode
		call	glBegin
		color	z,  p1, z
		vertex	p1, p1, n1
		vertex	n1, p1, n1
		vertex	n1, p1, p1
		vertex	p1, p1, p1
		color	p1, p5, z
		vertex	p1, n1, p1
		vertex	n1, n1, p1
		vertex	n1, n1, n1
		vertex	p1, n1, n1
		color	p1, z,  z
		vertex	p1, p1, p1
		vertex	n1, p1, p1
		vertex	n1, n1, p1
		vertex	p1, n1, p1
		color	p1, p1, z
		vertex	p1, n1, n1
		vertex	n1, n1, n1
		vertex	n1, p1, n1
		vertex	p1, p1, n1
		color	z,  z,  p1
		vertex	n1, p1, p1
		vertex	n1, p1, n1
		vertex	n1, n1, n1
		vertex	n1, n1, p1
		color	p1, z,  p1
		vertex	p1, p1, n1
		vertex	p1, p1, p1
		vertex	p1, n1, p1
		vertex	p1, n1, n1
		call	glEnd

		fld	dword[s_rtri]
		fadd	dword[s_f0p2]
		fstp	dword[s_rtri]

		fld	dword[s_rquad]
		fadd	dword[s_f0p15]
		fstp	dword[s_rquad]

		ret