Доброго времени суток, уважаемые подписчики. В сегодняшнем выпуске мы начнём писать наш движок (пока только графическую его часть), причём начнём мы с того, что НЕ зависит от всех крутостей движка, начнём мы с создания окна!
Первое моё решение в создании этого проекта было то, что я решил делать несколько динамических библиотек, которые и будут являться движком. Принимая это решение, я руководился следующим:
- Динамическую библиотеку легче добавить в любой проект.
- Динамические библиотеки легче обновлять по одной.
- Динамические библиотеки могут быть легко выгружены, ели какой-то элемент не будет востребован.
Как я уже упомянул, начнём мы с самого начала, первая библиотека будет носить имя AsmGL (может быть только пока) и осуществлять соединение программы и нашего движка. Для начала думаю наделить её лишь двумя функциями, AsmGLWindow и AsmGLResizeScene:
include opengl32.inc
include comctl32.inc
include def32.inc
include macros.inc
include kernel32.inc
include user32.inc
include gdi32.inc
include objects.inc
include glu32.inc
;Сегмент инициализированных данных и кода
_TEXT SEGMENT public USE32 'code'
_AsmGLWindow@40 proc
push ebp
mov ebp,esp
pusha
push dword ptr [ebp+2Ch]
push wcex.hInstance
push dword ptr [ebp+24h]
push dword ptr [ebp+20h]
push dword ptr [ebp+1Ch]
push dword ptr [ebp+18h]
push dword ptr [ebp+14h]
push dword ptr [ebp+10h]
push dword ptr [ebp+0Ch]
push dword ptr [ebp+08h]
push offset ClassName
push WS_EX_APPWINDOW or WS_EX_WINDOWEDGE
run CreateWindowExW
test eax,eax
jz error_AsmGLWindow
mov hWnd,eax
run GetDC, eax
mov hDC,eax
run ChoosePixelFormat, eax, offset pxl
mov PixelFormat,eax
run SetPixelFormat, hDC, eax, offset pxl
run wglCreateContext, hDC
mov glHDC,eax
run wglMakeCurrent, hDC, eax
mov esi,hWnd
run ShowWindow, esi, SW_SHOWNORMAL
run SetForegroundWindow, esi
run SetFocus, esi
run _AsmGLReSizeScene@8, dword ptr [ebp+18h], dword ptr [ebp+1ch]
run InitGL
mov edi,offset msg_
main_loop:
cmp ExitFlag,bl
jnz ProgramEnd
run PeekMessageW, edi, esi, ebx, ebx, PM_REMOVE
cmp msg_.message,WM_QUIT
jz ProgramEnd
test eax,eax
jz glReNew
run TranslateMessage, edi
run DispatchMessageW, edi
jmp short main_loop
glReNew:
run DrawGLScene
run SwapBuffers, HDC
jmp short main_loop
ProgramEnd:
mov ExitFlag,1
run KillGLWindow
run UnhookWindowsHookEx, hHook
popa
mov eax,msg_.message
pop ebp
ret 40
error_AsmGLWindow:
popa
null eax
pop ebp
ret 40
_AsmGLWindow@40 endp
_AsmGLResizeScene@8 proc
push ebp
mov ebp,esp
cmp [ebp+0Ch],ebx
jne h_ok
inc dword ptr [ebp+0Ch]
h_ok:
run glViewPort, ebx, ebx, dword ptr [ebp+08h], dword ptr [ebp+0Ch]
run glMatrixMode, GL_PROJECTION
run glLoadIdentity
fild dword ptr [ebp+08h]
fild dword ptr [ebp+0ch]
fdivp st(1),st(0)
fstp aspect
pushq zFar
pushq zNear
pushq aspect
pushq fovy
run gluPerspective
run glMatrixMode, GL_MODELVIEW
run glLoadIdentity
leave
ret 8
_AsmGLReSizeScene@8 endp
_start@12 proc
push ebp
mov ebp,esp
mov eax,[ebp+0Ch]
dec eax
jnz end_start
js process_detach
process_attach:
mov eax,[ebp+08h]
mov wcex.hInstance,eax
run RegisterAsmGLClass
test eax,eax
jz error_start
end_start:
pop ebp
null eax
inc eax
ret 12
process_detach:
run UnregisterClassW, offset ClassName, wcex.hInstance
jmp short end_start
error_start:
pop ebp
null eax
ret 12
_start@12 endp
RegisterAsmGLClass proc
push ebx
null ebx
run LoadIconW, ebx, IDI_APPLICATION
mov wcex.hIcon, eax
run LoadCursorW, ebx, IDC_ARROW
mov wcex.hCursor,eax
run RegisterClassExW, offset wcex
mov ClassAtom,eax
pop ebx
ret
RegisterAsmGLClass endp
AsmGLWndProc proc
push ebp
mov ebp,esp
cmp dword ptr [ebp+0ch],WM_CREATE
je create_proc
run GetWindowLong, dword ptr [ebp+08h], 0
pop ebp
test eax,eax
jz not_yet
jmp eax
not_yet:
jmp DefWindowProcW
create_proc:
run GetCurrentThreadId, ebx
run SetWindowsHookExW, WH_KEYBOARD, offset HotKeys, ebx, eax
mov ebx,[ebp+14h]
mov ebx,[ebx]
run SetWindowLong, dword ptr [ebp+08h], 0, ebx
mov eax,ebx
pop ebx
pop ebp
jmp eax
AsmGLWndProc endp
InitGL proc
run glEnable, GL_TEXTURE_2D
run glShadeModel, GL_SMOOTH
run glClearColor, ebx, ebx, ebx, alpha
pushq ClearDepth
run glClearDepth
run glEnable, GL_DEPTH_TEST
run glEnableClientState, GL_TEXTURE_COORD_ARRAY or GL_VERTEX_ARRAY
run glDepthFunc, GL_LEQUAL
run glHint, GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST
null eax
ret
InitGL endp
KillGLWindow proc
run wglMakeCurrent, ebx, ebx
run wglDeleteContext, glHDC
run ReleaseDC, hWnd, HDC
run DestroyWindow, hWnd
ret
KillGLWindow endp
;Другие функции, которые будем рассматривать позже
include HotKeys.asm
include Draw.asm
ClassAtom dd 0
pxl PIXELFORMATDESCRIPTOR <28h,01h,25h,0,10h,0,0,0,0,0,0,0,0,0,0,0,0,0,10h,0,0,0,0,0,0,0>
wcex WNDCLASSEX <30h,23h,offset AsmGLWndProc,0,4,?,?,?,6,0,offset ClassName,0>
ClassName db 'A',0,'s',0,'m',0,'G',0,'L',0,0,0
end _start@12
_TEXT ENDS
Не выделенные красным процедуры уже использовались в уроке 22, думаю, с ними проблем нет. Рассмотрим процедуры выделенные красным. Первая это точка входа в библиотеку, она вызывается в случае загрузки или выгрузки библиотеки (остальное нам не важно). Передаются ей следующие параметры: handle библиотеки, причина вызова и информацию о типе вызова. Функция _start@12 сохраняет handle библиотеки в своей переменной и если процесс загружает библиотеку, то регистрирует и, если выгружает, удаляет класс окна AmsGL. Следующая функция, RegisterAsmGLClass, регистрирует этот класс. Особого внимания заслуживает функция AsmGLWndProc. При передаче функции сообщения WM_CREATE она сохраняет адрес функции окна юзера в личном пространстве и пересылает ему все сообщения, оставляя за собой возможность корректировать их. Это даст нам возможность контролировать ситуации, когда из-за каких либо причин движок может отказать. Функции-приложения рассмотрим в следующем уроке, так как достаточно сложны, чтобы рассматривать их отдельно.