Ассемблер под Windows №26

Начинаем писать графический движок


Доброго времени суток, уважаемые подписчики. В сегодняшнем выпуске мы начнём писать наш движок (пока только графическую его часть), причём начнём мы с того, что НЕ зависит от всех крутостей движка, начнём мы с создания окна!


Первое моё решение в создании этого проекта было то, что я решил делать несколько динамических библиотек, которые и будут являться движком. Принимая это решение, я руководился следующим:
- Динамическую библиотеку легче добавить в любой проект.
- Динамические библиотеки легче обновлять по одной.
- Динамические библиотеки могут быть легко выгружены, ели какой-то элемент не будет востребован.
Как я уже упомянул, начнём мы с самого начала, первая библиотека будет носить имя 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

  .686
  .model flat

  public _AsmGLResizeScene@8
  public _AsmGLWindow@40

;Определяем сегмент неинициализированных данных
asmGL SEGMENT public USE32 'bss'
CamBack     dq ?
CamHeight   dq ?
CamSide     dq ?
aspect      dq ?
SizeRW      dd ?
CamAngle    dd ?
hWnd        dd ?
hHook       dd ?
hDC         dd ?
PixelFormat dd ?
glHDC       dd ?
PrimQueue   dd ?
msg_        MSG <?>
ExitFlag    db ?
asmGL ENDS

;Сегмент инициализированных данных и кода
_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

;Инициализированные данные
ClearDepth dq 1.0f
fovy       dq 45.0f
zFar       dq 100.0f
zNear      dq 0.1f

white_ dd 1.0
       dd 1.0
       dd 1.0
       dd 0.5
alpha  dd 0.5f

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 она сохраняет адрес функции окна юзера в личном пространстве и пересылает ему все сообщения, оставляя за собой возможность корректировать их. Это даст нам возможность контролировать ситуации, когда из-за каких либо причин движок может отказать. Функции-приложения рассмотрим в следующем уроке, так как достаточно сложны, чтобы рассматривать их отдельно.


На сегодня это всё. Если есть какие вопросы, пишите. Пишите на Dark_Lord@RusFAQ.ru или Dark_Lord@land.ruю

Сайт управляется системой uCoz