mirror of
https://github.com/ApfelTeeSaft/Perfectium.git
synced 2026-08-26 19:33:36 +00:00
1238 lines
37 KiB
NASM
1238 lines
37 KiB
NASM
INCLUDE include\master.inc
|
|
|
|
; DrawList field offsets
|
|
DL_type EQU 000h
|
|
DL_pos_X EQU 004h
|
|
DL_pos_Y EQU 008h
|
|
DL_size_X EQU 00Ch
|
|
DL_size_Y EQU 010h
|
|
DL_color_R EQU 014h
|
|
DL_color_G EQU 018h
|
|
DL_color_B EQU 01Ch
|
|
DL_color_A EQU 020h
|
|
DL_name EQU 028h
|
|
DL_outline EQU 030h
|
|
DL_from_X EQU 034h
|
|
DL_from_Y EQU 038h
|
|
DL_to_X EQU 03Ch
|
|
DL_to_Y EQU 040h
|
|
DL_thickness EQU 044h
|
|
DL_SIZE EQU 048h ; 72 bytes per entry
|
|
|
|
DRAWLIST_COUNT EQU 128
|
|
|
|
; K2_DrawLine params offsets within [rsp+20h] block
|
|
KDL_A_X EQU 000h ; +0x20 in frame
|
|
KDL_A_Y EQU 004h
|
|
KDL_B_X EQU 008h
|
|
KDL_B_Y EQU 00Ch
|
|
KDL_THICK EQU 010h
|
|
KDL_COLOR_R EQU 014h
|
|
KDL_COLOR_G EQU 018h
|
|
KDL_COLOR_B EQU 01Ch
|
|
KDL_COLOR_A EQU 020h ; total = 0x24 bytes
|
|
|
|
; K2_DrawText params offsets within [rsp+20h] block
|
|
KDT_FONT EQU 000h ; UFont* (8)
|
|
KDT_STR_DATA EQU 008h ; FString.Data (8)
|
|
KDT_STR_NUM EQU 010h ; FString.Num (4)
|
|
KDT_STR_MAX EQU 014h ; FString.Max (4)
|
|
KDT_POS_X EQU 018h
|
|
KDT_POS_Y EQU 01Ch
|
|
KDT_CLR_R EQU 020h
|
|
KDT_CLR_G EQU 024h
|
|
KDT_CLR_B EQU 028h
|
|
KDT_CLR_A EQU 02Ch
|
|
KDT_KERNING EQU 030h ; float = 0.0f
|
|
KDT_SHADOW_R EQU 034h ; 4xfloat zeros
|
|
KDT_SHADOW_G EQU 038h
|
|
KDT_SHADOW_B EQU 03Ch
|
|
KDT_SHADOW_A EQU 040h
|
|
KDT_SOFF_X EQU 044h ; ShadowOffset.X = posX+1.0f
|
|
KDT_SOFF_Y EQU 048h ; ShadowOffset.Y = posY+1.0f
|
|
KDT_CENTREX EQU 04Ch ; bool
|
|
KDT_CENTREY EQU 04Dh ; bool = 1
|
|
KDT_OUTLINED EQU 04Eh ; bool
|
|
KDT_PAD EQU 04Fh
|
|
KDT_OUT_CLR_R EQU 050h
|
|
KDT_OUT_CLR_G EQU 054h
|
|
KDT_OUT_CLR_B EQU 058h
|
|
KDT_OUT_CLR_A EQU 05Ch ; = 0.30f
|
|
; total: 0x60 bytes
|
|
|
|
; Immediate float constants (IEEE 754)
|
|
F_0_0 EQU 000000000h ; 0.0f
|
|
F_1_0 EQU 03F800000h ; 1.0f
|
|
F_5_0 EQU 040A00000h ; 5.0f
|
|
F_10_0 EQU 041200000h ; 10.0f
|
|
F_12_5 EQU 041480000h ; 12.5f
|
|
F_0_30 EQU 03E99999Ah ; 0.30f (outline alpha)
|
|
|
|
.const
|
|
|
|
; FLinearColor blocks (R, G, B, A as REAL4)
|
|
clr_Win_Bg REAL4 0.009, 0.009, 0.009, 1.0 ; Window background
|
|
clr_Win_Hdr REAL4 0.10, 0.15, 0.84, 1.0 ; Window header
|
|
clr_Btn_Idle REAL4 0.10, 0.15, 0.84, 1.0 ; Button idle
|
|
clr_Btn_Hover REAL4 0.15, 0.20, 0.89, 1.0 ; Button hovered
|
|
clr_Btn_Active REAL4 0.20, 0.25, 0.94, 1.0 ; ButtonTab active
|
|
clr_White REAL4 1.0, 1.0, 1.0, 1.0 ; Text colour
|
|
clr_Outline REAL4 0.0, 0.0, 0.0, 0.30 ; Text outline
|
|
|
|
; Float scalars
|
|
f_0_5 REAL4 0.5
|
|
f_25_0 REAL4 25.0
|
|
|
|
szFn_K2DrawLineA DB "Function Engine.Canvas.K2_DrawLine", 0
|
|
szFn_K2DrawTextA DB "Function Engine.Canvas.K2_DrawText", 0
|
|
szObj_FontRoboto DB "Font Roboto.Roboto", 0
|
|
|
|
; Wide HWND search strings
|
|
szWC_UnrealWindow DB 'U',0,'n',0,'r',0,'e',0,'a',0,'l',0,'W',0,'i',0,'n',0,'d',0,'o',0,'w',0, 0,0
|
|
szWC_Fortnite DB 'F',0,'o',0,'r',0,'t',0,'n',0,'i',0,'t',0,'e',0,' ',0,' ',0, 0,0
|
|
|
|
.data?
|
|
|
|
; Canvas pointer (set by ZeroGUI_SetupCanvas)
|
|
ZG_canvas QWORD ?
|
|
|
|
; GUI state
|
|
ZG_hover_element BYTE ? ; bool: any element currently hovered
|
|
ZG_menu_pos_X REAL4 ? ; window top-left X
|
|
ZG_menu_pos_Y REAL4 ? ; window top-left Y
|
|
ZG_offset_x REAL4 ? ; column offset
|
|
ZG_offset_y REAL4 ? ; row offset (advances after each element)
|
|
ZG_first_elem_X REAL4 ? ; first element position X
|
|
ZG_first_elem_Y REAL4 ? ; first element position Y
|
|
ZG_last_elem_X REAL4 ? ; last element position X
|
|
ZG_last_elem_Y REAL4 ? ; last element position Y
|
|
ZG_last_size_X REAL4 ? ; last element size X
|
|
ZG_last_size_Y REAL4 ? ; last element size Y
|
|
ZG_curr_elem SDWORD ? ; current active drag element (-1 = none)
|
|
ZG_elem_count DWORD ? ; elements rendered this frame
|
|
ZG_sameLine BYTE ? ; next element on same row
|
|
ZG_pushY BYTE ? ; next element Y is overridden
|
|
ZG_pushYvalue REAL4 ? ; override Y value
|
|
ZG_dragPos_X REAL4 ? ; drag anchor offset X
|
|
ZG_dragPos_Y REAL4 ? ; drag anchor offset Y
|
|
|
|
; Cached UObject / UFunction pointers
|
|
ZG_pFn_K2DrawLine QWORD ?
|
|
ZG_pFn_K2DrawText QWORD ?
|
|
ZG_pFont QWORD ?
|
|
ZG_hWndFortnite QWORD ? ; FindWindow result (cached)
|
|
|
|
; PostRenderer draw list: 128 x 72 bytes
|
|
ZG_drawlist BYTE (128 * 72) DUP(?)
|
|
|
|
.code
|
|
|
|
; ZeroGUI__CursorPos (internal)
|
|
; Fills a caller-provided FVector2D with screen cursor position.
|
|
; In: RCX = FVector2D* (out) - pointer to {X:REAL4, Y:REAL4}
|
|
; Frame: 0 pushes + sub 38h -> RSP = 8-56 = -48 = 0
|
|
; [rsp+20h..+23h] = POINT.x
|
|
; [rsp+24h..+27h] = POINT.y
|
|
; [rsp+28h..+2Fh] = saved out*
|
|
ZeroGUI__CursorPos PROC
|
|
sub rsp, 38h
|
|
|
|
mov QWORD PTR [rsp+28h], rcx ; save out*
|
|
|
|
; GetCursorPos(&POINT)
|
|
lea rcx, [rsp+20h]
|
|
call GetCursorPos
|
|
|
|
; GetActiveWindow() -> HWND
|
|
call GetActiveWindow
|
|
|
|
; ScreenToClient(HWND, &POINT)
|
|
mov rcx, rax
|
|
lea rdx, [rsp+20h]
|
|
call ScreenToClient
|
|
|
|
; Convert LONG -> float, store in *out
|
|
mov rcx, QWORD PTR [rsp+28h]
|
|
cvtsi2ss xmm0, DWORD PTR [rsp+20h] ; x
|
|
movss DWORD PTR [rcx+0], xmm0
|
|
cvtsi2ss xmm0, DWORD PTR [rsp+24h] ; y
|
|
movss DWORD PTR [rcx+4], xmm0
|
|
|
|
add rsp, 38h
|
|
ret
|
|
ZeroGUI__CursorPos ENDP
|
|
|
|
|
|
; ZeroGUI__MouseInZone (internal)
|
|
; In: ECX=posX_bits, EDX=posY_bits, R8D=sizeX_bits, R9D=sizeY_bits
|
|
; Out: AL = 1 if cursor inside zone, 0 otherwise
|
|
; Frame: 0 pushes + sub 58h -> RSP = 8-88 = -80 = 0
|
|
; [rsp+20h..+27h] = FVector2D cursor_pos output
|
|
; [rsp+28h..+2Bh] = saved posX bits
|
|
; [rsp+2Ch..+2Fh] = saved posY bits
|
|
; [rsp+30h..+33h] = saved sizeX bits
|
|
; [rsp+34h..+37h] = saved sizeY bits
|
|
ZeroGUI__MouseInZone PROC
|
|
sub rsp, 58h
|
|
|
|
mov DWORD PTR [rsp+28h], ecx
|
|
mov DWORD PTR [rsp+2Ch], edx
|
|
mov DWORD PTR [rsp+30h], r8d
|
|
mov DWORD PTR [rsp+34h], r9d
|
|
|
|
lea rcx, [rsp+20h]
|
|
call ZeroGUI__CursorPos ; fills [rsp+20h] = {curX, curY}
|
|
|
|
; Load all values into XMM for comparison
|
|
movss xmm0, DWORD PTR [rsp+20h] ; curX
|
|
movss xmm1, DWORD PTR [rsp+24h] ; curY
|
|
movss xmm2, DWORD PTR [rsp+28h] ; posX
|
|
movss xmm3, DWORD PTR [rsp+2Ch] ; posY
|
|
movss xmm4, DWORD PTR [rsp+30h] ; sizeX
|
|
movss xmm5, DWORD PTR [rsp+34h] ; sizeY
|
|
|
|
comiss xmm0, xmm2 ; curX > posX?
|
|
jbe @@false
|
|
comiss xmm1, xmm3 ; curY > posY?
|
|
jbe @@false
|
|
addss xmm4, xmm2 ; posX + sizeX
|
|
comiss xmm0, xmm4 ; curX < posX+sizeX?
|
|
jae @@false
|
|
addss xmm5, xmm3 ; posY + sizeY
|
|
comiss xmm1, xmm5 ; curY < posY+sizeY?
|
|
jae @@false
|
|
|
|
mov al, 1
|
|
jmp @@done
|
|
@@false:
|
|
xor al, al
|
|
@@done:
|
|
add rsp, 58h
|
|
ret
|
|
ZeroGUI__MouseInZone ENDP
|
|
|
|
|
|
; ZeroGUI__DrawFilledRect (internal)
|
|
; Calls K2_DrawLine for each scanline (y from 0 to h-1).
|
|
; In: ECX=posX_bits, EDX=posY_bits, R8D=w_bits, R9D=h_bits
|
|
; [rsp+20h] = FLinearColor* (color - 4xREAL4 R,G,B,A)
|
|
; Out: none
|
|
;
|
|
; Frame: 2 pushes (RBX=canvas, RSI=fn) + sub 68h -> RSP = 8-16-104 = -112 = 0
|
|
; [rsp+0..+1F] = shadow
|
|
; [rsp+20h..+43h] = K2_DrawLine params (0x24 bytes)
|
|
; [rsp+20h] A.X, [rsp+24h] A.Y, [rsp+28h] B.X, [rsp+2Ch] B.Y
|
|
; [rsp+30h] Thickness, [rsp+34h..+43h] FLinearColor
|
|
; [rsp+44h..+47h] = pad
|
|
; [rsp+48h..+4Bh] = saved posX
|
|
; [rsp+4Ch..+4Fh] = saved posY
|
|
; [rsp+50h..+53h] = saved w
|
|
; [rsp+54h..+57h] = saved h
|
|
; [rsp+58h..+5Bh] = loop var i
|
|
; [rsp+5Ch..+5Fh] = pad
|
|
; [rsp+60h..+67h] = saved color*
|
|
; 5th arg (color*) from caller at [rsp+0A0h]:
|
|
; RSP_current = RSP_entry - 16 - 104 = RSP_entry - 120
|
|
; 5th arg at RSP_entry+20h = RSP_current + 120 + 32 = RSP_current + 0xA0
|
|
ZeroGUI__DrawFilledRect PROC
|
|
push rbx
|
|
push rsi
|
|
sub rsp, 68h
|
|
|
|
; Save inputs
|
|
mov DWORD PTR [rsp+48h], ecx
|
|
mov DWORD PTR [rsp+4Ch], edx
|
|
mov DWORD PTR [rsp+50h], r8d
|
|
mov DWORD PTR [rsp+54h], r9d
|
|
; Retrieve color* (5th arg from caller's [rsp+20h])
|
|
mov rax, QWORD PTR [rsp+0A0h]
|
|
mov QWORD PTR [rsp+60h], rax
|
|
|
|
; Init loop var i = 0.0f
|
|
xor eax, eax
|
|
mov DWORD PTR [rsp+58h], eax
|
|
|
|
; Load canvas
|
|
mov rbx, QWORD PTR [ZG_canvas]
|
|
test rbx, rbx
|
|
jz @@done
|
|
|
|
; Lazy-load K2_DrawLine UFunction*
|
|
mov rsi, QWORD PTR [ZG_pFn_K2DrawLine]
|
|
test rsi, rsi
|
|
jnz @@fn_ready
|
|
lea rcx, [szFn_K2DrawLineA]
|
|
call SDK_FindObject
|
|
mov QWORD PTR [ZG_pFn_K2DrawLine], rax
|
|
mov rsi, rax
|
|
test rsi, rsi
|
|
jz @@done
|
|
@@fn_ready:
|
|
|
|
; Set Thickness = 1.0f in params
|
|
mov DWORD PTR [rsp+30h], F_1_0
|
|
|
|
; Copy FLinearColor from color* into params at [rsp+34h]
|
|
mov rax, QWORD PTR [rsp+60h]
|
|
mov ecx, DWORD PTR [rax+0]
|
|
mov DWORD PTR [rsp+34h], ecx ; R
|
|
mov ecx, DWORD PTR [rax+4]
|
|
mov DWORD PTR [rsp+38h], ecx ; G
|
|
mov ecx, DWORD PTR [rax+8]
|
|
mov DWORD PTR [rsp+3Ch], ecx ; B
|
|
mov ecx, DWORD PTR [rax+12]
|
|
mov DWORD PTR [rsp+40h], ecx ; A
|
|
|
|
@@loop:
|
|
movss xmm0, DWORD PTR [rsp+58h] ; i
|
|
movss xmm1, DWORD PTR [rsp+54h] ; h
|
|
comiss xmm0, xmm1
|
|
jae @@done ; i >= h -> exit
|
|
|
|
; A = { posX, posY + i }
|
|
movss xmm2, DWORD PTR [rsp+48h] ; posX
|
|
movss xmm3, DWORD PTR [rsp+4Ch] ; posY
|
|
addss xmm3, xmm0 ; posY + i
|
|
movss DWORD PTR [rsp+20h], xmm2 ; A.X
|
|
movss DWORD PTR [rsp+24h], xmm3 ; A.Y
|
|
|
|
; B = { posX + w, posY + i }
|
|
movss xmm4, DWORD PTR [rsp+50h] ; w
|
|
addss xmm4, xmm2
|
|
movss DWORD PTR [rsp+28h], xmm4 ; B.X
|
|
movss DWORD PTR [rsp+2Ch], xmm3 ; B.Y
|
|
|
|
; ProcessEvent(canvas, K2_DrawLine, ¶ms)
|
|
mov rcx, rbx
|
|
mov rdx, rsi
|
|
lea r8, [rsp+20h]
|
|
call QWORD PTR [ProcessEvent]
|
|
|
|
; i += 1.0f
|
|
movss xmm0, DWORD PTR [rsp+58h]
|
|
mov eax, F_1_0
|
|
movd xmm1, eax
|
|
addss xmm0, xmm1
|
|
movss DWORD PTR [rsp+58h], xmm0
|
|
jmp @@loop
|
|
|
|
@@done:
|
|
add rsp, 68h
|
|
pop rsi
|
|
pop rbx
|
|
ret
|
|
ZeroGUI__DrawFilledRect ENDP
|
|
|
|
|
|
; ZeroGUI__DrawText (internal)
|
|
; Calls K2_DrawText via ProcessEvent.
|
|
; In: RCX = name (wchar_t*)
|
|
; EDX = posX bits (REAL4)
|
|
; R8D = posY bits (REAL4)
|
|
; R9 = FLinearColor* (render color)
|
|
; [rsp+20h] = bCentreX (BYTE, 0=left, 1=center)
|
|
; [rsp+28h] = bOutlined (BYTE)
|
|
;
|
|
; Frame: 4 pushes (RBX=name*, RBP=posX, RSI=posY, RDI=color*)
|
|
; + sub 0A8h (168) -> RSP = 8-32-168 = -192 = 0
|
|
; [rsp+0..+1F] = shadow
|
|
; [rsp+20h..+7Fh] = K2_DrawText params (0x60 bytes)
|
|
; [rsp+80h..+87h] = saved UFunction* for ProcessEvent
|
|
; [rsp+88h] = bCentreX (saved from 5th arg)
|
|
; [rsp+89h] = bOutlined (saved from 6th arg)
|
|
; 5th arg bCentreX at entry_RSP+0x28 = current_RSP+0xF0
|
|
; 6th arg bOutlined at entry_RSP+0x30 = current_RSP+0xF8
|
|
; (prologue=200 bytes; 200+0x28=0xF0, 200+0x30=0xF8)
|
|
ZeroGUI__DrawText PROC
|
|
push rbx
|
|
push rbp
|
|
push rsi
|
|
push rdi
|
|
sub rsp, 0A8h
|
|
|
|
mov rbx, rcx ; name*
|
|
mov ebp, edx ; posX bits
|
|
mov esi, r8d ; posY bits
|
|
mov rdi, r9 ; color*
|
|
|
|
; Save bCentreX and bOutlined from caller args
|
|
; prologue=200 bytes; 5th arg at entry_RSP+0x28 = current_RSP+0xF0
|
|
movzx eax, BYTE PTR [rsp+0F0h]
|
|
mov BYTE PTR [rsp+88h], al
|
|
movzx eax, BYTE PTR [rsp+0F8h]
|
|
mov BYTE PTR [rsp+89h], al
|
|
|
|
; Lazy-load UFont*
|
|
mov rax, QWORD PTR [ZG_pFont]
|
|
test rax, rax
|
|
jnz @@font_ready
|
|
lea rcx, [szObj_FontRoboto]
|
|
call SDK_FindObject
|
|
mov QWORD PTR [ZG_pFont], rax
|
|
@@font_ready:
|
|
mov QWORD PTR [rsp+20h + KDT_FONT], rax
|
|
|
|
; Lazy-load K2_DrawText UFunction*
|
|
mov rax, QWORD PTR [ZG_pFn_K2DrawText]
|
|
test rax, rax
|
|
jnz @@fn_ready
|
|
lea rcx, [szFn_K2DrawTextA]
|
|
call SDK_FindObject
|
|
mov QWORD PTR [ZG_pFn_K2DrawText], rax
|
|
@@fn_ready:
|
|
mov QWORD PTR [rsp+80h], rax
|
|
|
|
; Build FString from wchar_t* name
|
|
lea rcx, [rsp+20h + KDT_STR_DATA]
|
|
mov rdx, rbx ; wchar_t*
|
|
call FString_FromWideChar
|
|
|
|
; Fill remaining params
|
|
; ScreenPos
|
|
mov DWORD PTR [rsp+20h + KDT_POS_X], ebp
|
|
mov DWORD PTR [rsp+20h + KDT_POS_Y], esi
|
|
|
|
; RenderColor (copy 16 bytes from color*)
|
|
mov eax, DWORD PTR [rdi+0]
|
|
mov DWORD PTR [rsp+20h + KDT_CLR_R], eax
|
|
mov eax, DWORD PTR [rdi+4]
|
|
mov DWORD PTR [rsp+20h + KDT_CLR_G], eax
|
|
mov eax, DWORD PTR [rdi+8]
|
|
mov DWORD PTR [rsp+20h + KDT_CLR_B], eax
|
|
mov eax, DWORD PTR [rdi+12]
|
|
mov DWORD PTR [rsp+20h + KDT_CLR_A], eax
|
|
|
|
; Kerning = 0.0f
|
|
mov DWORD PTR [rsp+20h + KDT_KERNING], 0
|
|
|
|
; ShadowColor = {0,0,0,0}
|
|
mov DWORD PTR [rsp+20h + KDT_SHADOW_R], 0
|
|
mov DWORD PTR [rsp+20h + KDT_SHADOW_G], 0
|
|
mov DWORD PTR [rsp+20h + KDT_SHADOW_B], 0
|
|
mov DWORD PTR [rsp+20h + KDT_SHADOW_A], 0
|
|
|
|
; ShadowOffset = {posX+1.0f, posY+1.0f}
|
|
movss xmm0, DWORD PTR [rsp+20h + KDT_POS_X]
|
|
mov eax, F_1_0
|
|
movd xmm1, eax
|
|
addss xmm0, xmm1
|
|
movss DWORD PTR [rsp+20h + KDT_SOFF_X], xmm0
|
|
movss xmm0, DWORD PTR [rsp+20h + KDT_POS_Y]
|
|
addss xmm0, xmm1
|
|
movss DWORD PTR [rsp+20h + KDT_SOFF_Y], xmm0
|
|
|
|
; bCentreX, bCentreY=1, bOutlined
|
|
movzx eax, BYTE PTR [rsp+88h]
|
|
mov BYTE PTR [rsp+20h + KDT_CENTREX], al
|
|
mov BYTE PTR [rsp+20h + KDT_CENTREY], 1
|
|
movzx eax, BYTE PTR [rsp+89h]
|
|
mov BYTE PTR [rsp+20h + KDT_OUTLINED], al
|
|
mov BYTE PTR [rsp+20h + KDT_PAD], 0
|
|
|
|
; OutlineColor = {0, 0, 0, 0.30f}
|
|
mov DWORD PTR [rsp+20h + KDT_OUT_CLR_R], 0
|
|
mov DWORD PTR [rsp+20h + KDT_OUT_CLR_G], 0
|
|
mov DWORD PTR [rsp+20h + KDT_OUT_CLR_B], 0
|
|
mov eax, F_0_30
|
|
mov DWORD PTR [rsp+20h + KDT_OUT_CLR_A], eax
|
|
|
|
; ProcessEvent(canvas, K2_DrawText, ¶ms)
|
|
mov rax, QWORD PTR [rsp+80h]
|
|
test rax, rax
|
|
jz @@cleanup
|
|
mov rcx, QWORD PTR [ZG_canvas]
|
|
test rcx, rcx
|
|
jz @@cleanup
|
|
mov rdx, rax
|
|
lea r8, [rsp+20h]
|
|
call QWORD PTR [ProcessEvent]
|
|
|
|
@@cleanup:
|
|
; Free FString buffer
|
|
lea rcx, [rsp+20h + KDT_STR_DATA]
|
|
call FString_Free
|
|
|
|
add rsp, 0A8h
|
|
pop rdi
|
|
pop rsi
|
|
pop rbp
|
|
pop rbx
|
|
ret
|
|
ZeroGUI__DrawText ENDP
|
|
|
|
|
|
; ZeroGUI__CalcPos (internal helper)
|
|
; Computes element position from GUI state.
|
|
; In: EAX = padding.X bits (REAL4), ECX = padding.Y bits (REAL4)
|
|
; Out: XMM0 = posX (REAL4), XMM1 = posY (REAL4)
|
|
; Uses XMM2-XMM5 (all volatile).
|
|
; No frame allocation - leaf-like, no CALLs. RSP must be = 0 before CALL.
|
|
ZeroGUI__CalcPos PROC
|
|
; posX = menu_pos.X + padX + offset_x
|
|
movss xmm0, DWORD PTR [ZG_menu_pos_X]
|
|
movd xmm2, eax ; padX
|
|
addss xmm0, xmm2
|
|
addss xmm0, DWORD PTR [ZG_offset_x]
|
|
|
|
; posY = menu_pos.Y + padY + offset_y
|
|
movss xmm1, DWORD PTR [ZG_menu_pos_Y]
|
|
movd xmm3, ecx ; padY
|
|
addss xmm1, xmm3
|
|
addss xmm1, DWORD PTR [ZG_offset_y]
|
|
|
|
; if sameLine:
|
|
movzx eax, BYTE PTR [ZG_sameLine]
|
|
test al, al
|
|
jz @@no_sameline
|
|
movss xmm0, DWORD PTR [ZG_last_elem_X]
|
|
addss xmm0, DWORD PTR [ZG_last_size_X]
|
|
addss xmm0, xmm2 ; + padX
|
|
movss xmm1, DWORD PTR [ZG_last_elem_Y]
|
|
@@no_sameline:
|
|
|
|
; if pushY:
|
|
movzx eax, BYTE PTR [ZG_pushY]
|
|
test al, al
|
|
jz @@no_pushY
|
|
movss xmm1, DWORD PTR [ZG_pushYvalue]
|
|
mov BYTE PTR [ZG_pushY], 0
|
|
xor eax, eax
|
|
mov DWORD PTR [ZG_pushYvalue], eax
|
|
; offset_y = posY - menu_pos.Y
|
|
movss xmm4, xmm1
|
|
subss xmm4, DWORD PTR [ZG_menu_pos_Y]
|
|
movss DWORD PTR [ZG_offset_y], xmm4
|
|
@@no_pushY:
|
|
|
|
ret
|
|
ZeroGUI__CalcPos ENDP
|
|
|
|
|
|
; ZeroGUI_SetupCanvas
|
|
; In: RCX = UCanvas*
|
|
ZeroGUI_SetupCanvas PROC
|
|
mov QWORD PTR [ZG_canvas], rcx
|
|
ret
|
|
ZeroGUI_SetupCanvas ENDP
|
|
|
|
|
|
; ZeroGUI_Begin (= ZeroGUI::Window)
|
|
; In: RCX = title (wchar_t*)
|
|
; RDX = pos (FVector2D* = &{X:REAL4, Y:REAL4})
|
|
; R8D = sizeX bits (REAL4)
|
|
; R9D = sizeY bits (REAL4)
|
|
; [rsp+20h] = isOpen (BYTE)
|
|
; Out: AL = bool (true -> render children)
|
|
;
|
|
; Frame: 4 pushes (RBX=title*, RBP=pos*, RSI=sizeX, RDI=sizeY)
|
|
; + sub 48h (72) -> RSP = 8-32-72 = -96 = 0
|
|
; [rsp+0..+1F] = shadow
|
|
; [rsp+20h..+27h] = 5th/6th arg slots (for sub-calls: DrawFilledRect, DrawText)
|
|
; [rsp+28h] = isOpen (BYTE, saved)
|
|
; [rsp+29..+2Bh] = pad
|
|
; [rsp+2Ch] = isHovered (BYTE)
|
|
; [rsp+2D..+2Fh] = pad
|
|
; [rsp+30h..+37h] = scratch (hWndFortnite save slot, cursor_pos FVector2D)
|
|
; [rsp+38h..+47h] = spare
|
|
; 5th arg isOpen at entry_RSP+0x28 = current_RSP+0x90
|
|
; (prologue=104 bytes; 104+0x28=0x90)
|
|
ZeroGUI_Begin PROC
|
|
push rbx
|
|
push rbp
|
|
push rsi
|
|
push rdi
|
|
sub rsp, 48h
|
|
|
|
mov rbx, rcx ; title*
|
|
mov rbp, rdx ; pos*
|
|
mov esi, r8d ; sizeX bits
|
|
mov edi, r9d ; sizeY bits
|
|
|
|
; Reset elements_count = 0
|
|
mov DWORD PTR [ZG_elem_count], 0
|
|
|
|
; Read isOpen from 5th arg - prologue=104 bytes; at entry_RSP+0x28 = current_RSP+0x90
|
|
movzx eax, BYTE PTR [rsp+90h]
|
|
mov BYTE PTR [rsp+28h], al
|
|
|
|
; Return false if !isOpen
|
|
test al, al
|
|
jz @@return_false
|
|
|
|
; FindWindow check (lazy-init HWND cache)
|
|
mov rax, QWORD PTR [ZG_hWndFortnite]
|
|
test rax, rax
|
|
jnz @@hwnd_ready
|
|
lea rcx, [szWC_UnrealWindow]
|
|
lea rdx, [szWC_Fortnite]
|
|
call FindWindowW
|
|
mov QWORD PTR [ZG_hWndFortnite], rax
|
|
@@hwnd_ready:
|
|
|
|
; GetActiveWindow() - must match Fortnite window
|
|
mov QWORD PTR [rsp+30h], rax ; save hWndFortnite in local slot (no push tho)
|
|
call GetActiveWindow
|
|
mov rcx, QWORD PTR [rsp+30h] ; restore hWndFortnite
|
|
cmp rax, rcx
|
|
jne @@return_false ; wrong window focused
|
|
|
|
; Drop current drag element if mouse released
|
|
mov eax, DWORD PTR [ZG_curr_elem]
|
|
cmp eax, -1
|
|
je @@skip_drop
|
|
mov ecx, 1
|
|
call GetAsyncKeyState
|
|
test ax, ax
|
|
jnz @@skip_drop
|
|
mov DWORD PTR [ZG_curr_elem], -1
|
|
@@skip_drop:
|
|
|
|
; isHovered = MouseInZone(pos, size)
|
|
mov ecx, DWORD PTR [rbp+0] ; pos->X bits
|
|
mov edx, DWORD PTR [rbp+4] ; pos->Y bits
|
|
mov r8d, esi ; sizeX bits
|
|
mov r9d, edi ; sizeY bits
|
|
call ZeroGUI__MouseInZone
|
|
mov BYTE PTR [rsp+2Ch], al ; isHovered
|
|
|
|
; Drag logic
|
|
movzx eax, BYTE PTR [ZG_hover_element]
|
|
test al, al
|
|
jz @@drag_no_hover
|
|
|
|
; hover_element is set: check if mouse pressed
|
|
mov ecx, 1
|
|
call GetAsyncKeyState
|
|
test ax, ax
|
|
jnz @@drag_done ; hover element handles drag, skip
|
|
mov BYTE PTR [ZG_hover_element], 0
|
|
jmp @@drag_done
|
|
|
|
@@drag_no_hover:
|
|
; !hover_element: check if isHovered or dragPos.X != 0
|
|
movzx eax, BYTE PTR [rsp+2Ch] ; isHovered
|
|
test al, al
|
|
jnz @@check_drag
|
|
movss xmm0, DWORD PTR [ZG_dragPos_X]
|
|
xorps xmm1, xmm1
|
|
comiss xmm0, xmm1
|
|
je @@drag_done ; dragPos.X == 0 and !isHovered: skip drag
|
|
|
|
@@check_drag:
|
|
; IsMouseClicked(button=0, element_id=0, repeat=true)
|
|
xor ecx, ecx ; button = 0
|
|
xor edx, edx ; element_id = 0
|
|
mov r8b, 1 ; repeat = true
|
|
call ZeroInput_IsMouseClicked
|
|
test al, al
|
|
jz @@drag_release ; not clicked: clear dragPos
|
|
|
|
; GetCursorPos -> [rsp+38h] (FVector2D scratch)
|
|
lea rcx, [rsp+38h]
|
|
call ZeroGUI__CursorPos
|
|
|
|
movss xmm0, DWORD PTR [rsp+38h] ; curX
|
|
movss xmm1, DWORD PTR [rsp+3Ch] ; curY
|
|
|
|
; if dragPos.X == 0: init dragPos
|
|
movss xmm4, DWORD PTR [ZG_dragPos_X]
|
|
xorps xmm5, xmm5
|
|
comiss xmm4, xmm5
|
|
jne @@drag_update ; already initialized
|
|
|
|
; dragPos.X = cursorX - pos->X; dragPos.Y = cursorY - pos->Y
|
|
movss xmm5, xmm0
|
|
subss xmm5, DWORD PTR [rbp+0] ; cursorX - pos->X
|
|
movss DWORD PTR [ZG_dragPos_X], xmm5
|
|
movss xmm5, xmm1
|
|
subss xmm5, DWORD PTR [rbp+4] ; cursorY - pos->Y
|
|
movss DWORD PTR [ZG_dragPos_Y], xmm5
|
|
|
|
@@drag_update:
|
|
; pos->X = cursorX - dragPos.X; pos->Y = cursorY - dragPos.Y
|
|
movss xmm4, xmm0
|
|
subss xmm4, DWORD PTR [ZG_dragPos_X]
|
|
movss DWORD PTR [rbp+0], xmm4
|
|
movss xmm4, xmm1
|
|
subss xmm4, DWORD PTR [ZG_dragPos_Y]
|
|
movss DWORD PTR [rbp+4], xmm4
|
|
jmp @@drag_done
|
|
|
|
@@drag_release:
|
|
; Mouse not held: clear dragPos
|
|
xor eax, eax
|
|
mov DWORD PTR [ZG_dragPos_X], eax
|
|
mov DWORD PTR [ZG_dragPos_Y], eax
|
|
|
|
@@drag_done:
|
|
|
|
; Reset state
|
|
xor eax, eax
|
|
mov DWORD PTR [ZG_offset_x], eax
|
|
mov DWORD PTR [ZG_offset_y], eax
|
|
; menu_pos = *pos
|
|
mov eax, DWORD PTR [rbp+0]
|
|
mov DWORD PTR [ZG_menu_pos_X], eax
|
|
mov eax, DWORD PTR [rbp+4]
|
|
mov DWORD PTR [ZG_menu_pos_Y], eax
|
|
; first_element_pos = {0,0}
|
|
xor eax, eax
|
|
mov DWORD PTR [ZG_first_elem_X], eax
|
|
mov DWORD PTR [ZG_first_elem_Y], eax
|
|
|
|
; Draw background
|
|
mov ecx, DWORD PTR [rbp+0] ; posX bits
|
|
mov edx, DWORD PTR [rbp+4] ; posY bits
|
|
mov r8d, esi ; sizeX bits
|
|
mov r9d, edi ; sizeY bits
|
|
lea rax, [clr_Win_Bg]
|
|
mov QWORD PTR [rsp+20h], rax ; 5th arg = color*
|
|
call ZeroGUI__DrawFilledRect
|
|
|
|
; Draw header
|
|
mov ecx, DWORD PTR [rbp+0]
|
|
mov edx, DWORD PTR [rbp+4]
|
|
mov r8d, esi
|
|
mov r9d, 041C80000h ; h = 25.0f
|
|
lea rax, [clr_Win_Hdr]
|
|
mov QWORD PTR [rsp+20h], rax
|
|
call ZeroGUI__DrawFilledRect
|
|
|
|
; offset_y += 25.0f
|
|
movss xmm0, DWORD PTR [ZG_offset_y]
|
|
movd xmm1, DWORD PTR [f_25_0]
|
|
addss xmm0, xmm1
|
|
movss DWORD PTR [ZG_offset_y], xmm0
|
|
|
|
; Draw title (TextCenter)
|
|
; titlePos = { pos->X + sizeX/2, pos->Y + 12.5f }
|
|
movss xmm0, DWORD PTR [rbp+0] ; pos->X
|
|
movd xmm1, esi ; sizeX bits -> float
|
|
movss xmm2, DWORD PTR [f_0_5]
|
|
mulss xmm1, xmm2 ; sizeX * 0.5
|
|
addss xmm0, xmm1 ; pos->X + sizeX/2
|
|
movd edx, xmm0 ; posX bits -> EDX
|
|
|
|
movss xmm0, DWORD PTR [rbp+4] ; pos->Y
|
|
mov eax, F_12_5
|
|
movd xmm1, eax
|
|
addss xmm0, xmm1 ; pos->Y + 12.5f
|
|
movd r8d, xmm0 ; posY bits -> R8D
|
|
|
|
mov rcx, rbx ; title*
|
|
lea r9, [clr_White] ; color*
|
|
mov BYTE PTR [rsp+20h], 1 ; bCentreX = true
|
|
mov BYTE PTR [rsp+28h], 0 ; bOutlined = false
|
|
call ZeroGUI__DrawText
|
|
|
|
; Return true
|
|
mov al, 1
|
|
jmp @@done
|
|
|
|
@@return_false:
|
|
xor al, al
|
|
@@done:
|
|
add rsp, 48h
|
|
pop rdi
|
|
pop rsi
|
|
pop rbp
|
|
pop rbx
|
|
ret
|
|
ZeroGUI_Begin ENDP
|
|
|
|
|
|
; ZeroGUI_Button
|
|
; In: RCX = name (wchar_t*)
|
|
; EDX = sizeX bits (REAL4)
|
|
; R8D = sizeY bits (REAL4)
|
|
; Out: AL = bool (true if clicked)
|
|
;
|
|
; Frame: 4 pushes (RBX=name*, RBP=sizeX, RSI=sizeY, RDI=spare)
|
|
; + sub 48h (72) -> RSP = 8-32-72 = -96 = 0
|
|
; [rsp+0..+1F] = shadow
|
|
; [rsp+20h..+27h] = 5th/6th arg slots for sub-calls
|
|
; [rsp+28h..+2Fh] = spare
|
|
; [rsp+30h..+33h] = posX bits
|
|
; [rsp+34h..+37h] = posY bits
|
|
; [rsp+38h] = isHovered (BYTE)
|
|
; [rsp+39..+47h] = spare
|
|
ZeroGUI_Button PROC
|
|
push rbx
|
|
push rbp
|
|
push rsi
|
|
push rdi
|
|
sub rsp, 48h
|
|
|
|
mov rbx, rcx ; name*
|
|
mov ebp, edx ; sizeX bits
|
|
mov esi, r8d ; sizeY bits
|
|
|
|
; elements_count++
|
|
inc DWORD PTR [ZG_elem_count]
|
|
|
|
; Compute pos = { menu_pos.X+5+offset_x, menu_pos.Y+10+offset_y }
|
|
mov eax, F_5_0
|
|
mov ecx, F_10_0
|
|
call ZeroGUI__CalcPos ; XMM0=posX, XMM1=posY
|
|
movd DWORD PTR [rsp+30h], xmm0 ; save posX - safe above arg slots
|
|
movd DWORD PTR [rsp+34h], xmm1 ; save posY
|
|
|
|
; isHovered = MouseInZone(posX, posY, sizeX, sizeY)
|
|
movd ecx, xmm0
|
|
movd edx, xmm1
|
|
mov r8d, ebp
|
|
mov r9d, esi
|
|
call ZeroGUI__MouseInZone
|
|
mov BYTE PTR [rsp+38h], al
|
|
|
|
; Draw background - reload ecx/edx from saved slots (MouseInZone clobbered xmm0/1)
|
|
mov ecx, DWORD PTR [rsp+30h]
|
|
mov edx, DWORD PTR [rsp+34h]
|
|
mov r8d, ebp
|
|
mov r9d, esi
|
|
|
|
test BYTE PTR [rsp+38h], 1 ; isHovered?
|
|
jz @@draw_idle
|
|
lea rax, [clr_Btn_Hover]
|
|
mov QWORD PTR [rsp+20h], rax ; 5th arg - correct slot
|
|
call ZeroGUI__DrawFilledRect
|
|
mov BYTE PTR [ZG_hover_element], 1
|
|
jmp ZGB_draw_text
|
|
@@draw_idle:
|
|
lea rax, [clr_Btn_Idle]
|
|
mov QWORD PTR [rsp+20h], rax ; 5th arg - correct slot
|
|
call ZeroGUI__DrawFilledRect
|
|
|
|
ZGB_draw_text:
|
|
; if !sameLine: offset_y += sizeY + 10
|
|
movzx eax, BYTE PTR [ZG_sameLine]
|
|
test al, al
|
|
jnz @@skip_adv_y
|
|
movss xmm0, DWORD PTR [ZG_offset_y]
|
|
movd xmm1, esi ; sizeY
|
|
mov eax, F_10_0
|
|
movd xmm2, eax
|
|
addss xmm0, xmm1
|
|
addss xmm0, xmm2
|
|
movss DWORD PTR [ZG_offset_y], xmm0
|
|
@@skip_adv_y:
|
|
|
|
; TextCenter(name, {posX+sizeX/2, posY+sizeY/2}, white, center=true, outline=false)
|
|
movss xmm0, DWORD PTR [rsp+30h] ; posX
|
|
movd xmm1, ebp ; sizeX
|
|
movss xmm2, DWORD PTR [f_0_5]
|
|
mulss xmm1, xmm2
|
|
addss xmm0, xmm1
|
|
movd edx, xmm0 ; textX
|
|
|
|
movss xmm0, DWORD PTR [rsp+34h] ; posY
|
|
movd xmm1, esi ; sizeY
|
|
mulss xmm1, xmm2 ; xmm2 still = 0.5
|
|
addss xmm0, xmm1
|
|
movd r8d, xmm0 ; textY
|
|
|
|
mov rcx, rbx
|
|
lea r9, [clr_White]
|
|
mov BYTE PTR [rsp+20h], 1 ; bCentreX = true (5th arg)
|
|
mov BYTE PTR [rsp+28h], 0 ; bOutlined = false (6th arg)
|
|
call ZeroGUI__DrawText
|
|
|
|
; Update state
|
|
mov BYTE PTR [ZG_sameLine], 0
|
|
mov eax, DWORD PTR [rsp+30h]
|
|
mov DWORD PTR [ZG_last_elem_X], eax
|
|
mov eax, DWORD PTR [rsp+34h]
|
|
mov DWORD PTR [ZG_last_elem_Y], eax
|
|
mov DWORD PTR [ZG_last_size_X], ebp
|
|
mov DWORD PTR [ZG_last_size_Y], esi
|
|
|
|
; Set first_element_pos if not yet set (first_elem_X == 0.0f)
|
|
movss xmm0, DWORD PTR [ZG_first_elem_X]
|
|
xorps xmm1, xmm1
|
|
comiss xmm0, xmm1
|
|
jne @@first_done
|
|
mov eax, DWORD PTR [rsp+30h]
|
|
mov DWORD PTR [ZG_first_elem_X], eax
|
|
mov eax, DWORD PTR [rsp+34h]
|
|
mov DWORD PTR [ZG_first_elem_Y], eax
|
|
@@first_done:
|
|
|
|
; Return: isHovered && IsMouseClicked(0, elements_count, false)
|
|
movzx eax, BYTE PTR [rsp+38h]
|
|
test al, al
|
|
jz @@ret_false
|
|
|
|
xor ecx, ecx
|
|
mov edx, DWORD PTR [ZG_elem_count]
|
|
xor r8b, r8b
|
|
call ZeroInput_IsMouseClicked
|
|
jmp @@done
|
|
|
|
@@ret_false:
|
|
xor al, al
|
|
@@done:
|
|
add rsp, 48h
|
|
pop rdi
|
|
pop rsi
|
|
pop rbp
|
|
pop rbx
|
|
ret
|
|
ZeroGUI_Button ENDP
|
|
|
|
|
|
; ZeroGUI_ButtonTab
|
|
; In: RCX = name (wchar_t*)
|
|
; EDX = sizeX bits (REAL4)
|
|
; R8D = sizeY bits (REAL4)
|
|
; R9B = active (bool)
|
|
; Out: AL = bool (true if clicked)
|
|
;
|
|
; Like Button but uses clr_Btn_Active when active=true.
|
|
; Frame: 4 pushes + sub 48h -> RSP = 0 (same layout as Button)
|
|
ZeroGUI_ButtonTab PROC
|
|
push rbx
|
|
push rbp
|
|
push rsi
|
|
push rdi
|
|
sub rsp, 48h
|
|
|
|
mov rbx, rcx
|
|
mov ebp, edx
|
|
mov esi, r8d
|
|
movzx edi, r9b ; active bool
|
|
|
|
inc DWORD PTR [ZG_elem_count]
|
|
|
|
mov eax, F_5_0
|
|
mov ecx, F_10_0
|
|
call ZeroGUI__CalcPos
|
|
movd DWORD PTR [rsp+30h], xmm0
|
|
movd DWORD PTR [rsp+34h], xmm1
|
|
|
|
movd ecx, xmm0
|
|
movd edx, xmm1
|
|
mov r8d, ebp
|
|
mov r9d, esi
|
|
call ZeroGUI__MouseInZone
|
|
mov BYTE PTR [rsp+38h], al
|
|
|
|
; Choose color: active -> Active, hovered -> Hovered, else -> Idle
|
|
mov ecx, DWORD PTR [rsp+30h]
|
|
mov edx, DWORD PTR [rsp+34h]
|
|
mov r8d, ebp
|
|
mov r9d, esi
|
|
|
|
test edi, edi
|
|
jz @@tab_not_active
|
|
lea rax, [clr_Btn_Active]
|
|
mov QWORD PTR [rsp+20h], rax ; 5th arg
|
|
call ZeroGUI__DrawFilledRect
|
|
jmp @@tab_text
|
|
@@tab_not_active:
|
|
test BYTE PTR [rsp+38h], 1
|
|
jz ZGBTab_idle
|
|
lea rax, [clr_Btn_Hover]
|
|
mov QWORD PTR [rsp+20h], rax ; 5th arg
|
|
call ZeroGUI__DrawFilledRect
|
|
mov BYTE PTR [ZG_hover_element], 1
|
|
jmp @@tab_text
|
|
ZGBTab_idle:
|
|
lea rax, [clr_Btn_Idle]
|
|
mov QWORD PTR [rsp+20h], rax ; 5th arg
|
|
call ZeroGUI__DrawFilledRect
|
|
|
|
@@tab_text:
|
|
movzx eax, BYTE PTR [ZG_sameLine]
|
|
test al, al
|
|
jnz @@tab_skip_adv
|
|
movss xmm0, DWORD PTR [ZG_offset_y]
|
|
movd xmm1, esi
|
|
mov eax, F_10_0
|
|
movd xmm2, eax
|
|
addss xmm0, xmm1
|
|
addss xmm0, xmm2
|
|
movss DWORD PTR [ZG_offset_y], xmm0
|
|
@@tab_skip_adv:
|
|
|
|
movss xmm0, DWORD PTR [rsp+30h]
|
|
movd xmm1, ebp
|
|
movss xmm2, DWORD PTR [f_0_5]
|
|
mulss xmm1, xmm2
|
|
addss xmm0, xmm1
|
|
movd edx, xmm0
|
|
|
|
movss xmm0, DWORD PTR [rsp+34h]
|
|
movd xmm1, esi
|
|
mulss xmm1, xmm2
|
|
addss xmm0, xmm1
|
|
movd r8d, xmm0
|
|
|
|
mov rcx, rbx
|
|
lea r9, [clr_White]
|
|
mov BYTE PTR [rsp+20h], 1 ; bCentreX = true (5th arg)
|
|
mov BYTE PTR [rsp+28h], 0 ; bOutlined = false (6th arg)
|
|
call ZeroGUI__DrawText
|
|
|
|
mov BYTE PTR [ZG_sameLine], 0
|
|
mov eax, DWORD PTR [rsp+30h]
|
|
mov DWORD PTR [ZG_last_elem_X], eax
|
|
mov eax, DWORD PTR [rsp+34h]
|
|
mov DWORD PTR [ZG_last_elem_Y], eax
|
|
mov DWORD PTR [ZG_last_size_X], ebp
|
|
mov DWORD PTR [ZG_last_size_Y], esi
|
|
|
|
movss xmm0, DWORD PTR [ZG_first_elem_X]
|
|
xorps xmm1, xmm1
|
|
comiss xmm0, xmm1
|
|
jne @@tab_first_done
|
|
mov eax, DWORD PTR [rsp+30h]
|
|
mov DWORD PTR [ZG_first_elem_X], eax
|
|
mov eax, DWORD PTR [rsp+34h]
|
|
mov DWORD PTR [ZG_first_elem_Y], eax
|
|
@@tab_first_done:
|
|
|
|
movzx eax, BYTE PTR [rsp+38h]
|
|
test al, al
|
|
jz @@tab_ret_false
|
|
xor ecx, ecx
|
|
mov edx, DWORD PTR [ZG_elem_count]
|
|
xor r8b, r8b
|
|
call ZeroInput_IsMouseClicked
|
|
jmp @@tab_done
|
|
|
|
@@tab_ret_false:
|
|
xor al, al
|
|
@@tab_done:
|
|
add rsp, 48h
|
|
pop rdi
|
|
pop rsi
|
|
pop rbp
|
|
pop rbx
|
|
ret
|
|
ZeroGUI_ButtonTab ENDP
|
|
|
|
|
|
; ZeroGUI_Text
|
|
; In: RCX = text (wchar_t*)
|
|
; DL = center (bool)
|
|
; R8B = outline (bool)
|
|
; Out: none
|
|
;
|
|
; Frame: 4 pushes (RBX=text, RBP=center, RSI=outline, RDI=spare)
|
|
; + sub 48h -> RSP = 0 (same layout as Button)
|
|
; size implicit=25px, padding={10,10}
|
|
ZeroGUI_Text PROC
|
|
push rbx
|
|
push rbp
|
|
push rsi
|
|
push rdi
|
|
sub rsp, 48h
|
|
|
|
mov rbx, rcx
|
|
movzx ebp, dl
|
|
movzx esi, r8b
|
|
|
|
inc DWORD PTR [ZG_elem_count]
|
|
|
|
mov eax, F_10_0
|
|
mov ecx, F_10_0
|
|
call ZeroGUI__CalcPos
|
|
movd DWORD PTR [rsp+30h], xmm0 ; posX
|
|
movd DWORD PTR [rsp+34h], xmm1 ; posY
|
|
|
|
; if !sameLine: offset_y += 25 + 10 = 35
|
|
movzx eax, BYTE PTR [ZG_sameLine]
|
|
test al, al
|
|
jnz @@text_skip_adv
|
|
movss xmm0, DWORD PTR [ZG_offset_y]
|
|
mov eax, 041C80000h ; 25.0f
|
|
movd xmm1, eax
|
|
mov eax, F_10_0
|
|
movd xmm2, eax
|
|
addss xmm0, xmm1
|
|
addss xmm0, xmm2
|
|
movss DWORD PTR [ZG_offset_y], xmm0
|
|
@@text_skip_adv:
|
|
|
|
; textPos = { posX + 5, posY + 12.5 }
|
|
movss xmm0, DWORD PTR [rsp+30h]
|
|
mov eax, F_5_0
|
|
movd xmm1, eax
|
|
addss xmm0, xmm1
|
|
movd edx, xmm0
|
|
|
|
movss xmm0, DWORD PTR [rsp+34h]
|
|
mov eax, F_12_5
|
|
movd xmm1, eax
|
|
addss xmm0, xmm1
|
|
movd r8d, xmm0
|
|
|
|
mov rcx, rbx
|
|
lea r9, [clr_White]
|
|
mov BYTE PTR [rsp+20h], bpl ; bCentreX = center (5th arg)
|
|
mov BYTE PTR [rsp+28h], sil ; bOutlined (6th arg)
|
|
call ZeroGUI__DrawText
|
|
|
|
mov BYTE PTR [ZG_sameLine], 0
|
|
mov eax, DWORD PTR [rsp+30h]
|
|
mov DWORD PTR [ZG_last_elem_X], eax
|
|
mov eax, DWORD PTR [rsp+34h]
|
|
mov DWORD PTR [ZG_last_elem_Y], eax
|
|
|
|
movss xmm0, DWORD PTR [ZG_first_elem_X]
|
|
xorps xmm1, xmm1
|
|
comiss xmm0, xmm1
|
|
jne @@text_first_done
|
|
mov eax, DWORD PTR [rsp+30h]
|
|
mov DWORD PTR [ZG_first_elem_X], eax
|
|
mov eax, DWORD PTR [rsp+34h]
|
|
mov DWORD PTR [ZG_first_elem_Y], eax
|
|
@@text_first_done:
|
|
|
|
add rsp, 48h
|
|
pop rdi
|
|
pop rsi
|
|
pop rbp
|
|
pop rbx
|
|
ret
|
|
ZeroGUI_Text ENDP
|
|
|
|
|
|
; ZeroGUI_NextColumn
|
|
; In: XMM0 = x (REAL4 float)
|
|
; Out: none
|
|
;
|
|
; Sets offset_x = x
|
|
; Sets pushY = true, pushYvalue = first_elem_Y
|
|
;
|
|
; Frame: 0 pushes + sub 28h -> RSP = 8-40 = -32 = 0
|
|
ZeroGUI_NextColumn PROC
|
|
sub rsp, 28h
|
|
|
|
movss DWORD PTR [ZG_offset_x], xmm0
|
|
|
|
mov BYTE PTR [ZG_pushY], 1
|
|
mov eax, DWORD PTR [ZG_first_elem_Y]
|
|
mov DWORD PTR [ZG_pushYvalue], eax
|
|
|
|
add rsp, 28h
|
|
ret
|
|
ZeroGUI_NextColumn ENDP
|
|
|
|
|
|
; ZeroGUI_End (= ZeroGUI::Render)
|
|
; Flushes the PostRenderer drawlist.
|
|
; Each non-empty slot is dispatched to direct draw, then reset.
|
|
;
|
|
; Frame: 2 pushes (RBX=loop_idx*72, RSI=drawlist_base) + sub 58h (88)
|
|
; 2 pushes (16) + 88 = 104; RSP = 8-104 = -96 = 0
|
|
; [rsp+0..+1F] = shadow
|
|
; [rsp+20h..+43h] = K2_DrawLine params (0x24 bytes) - safe above shadow
|
|
; [rsp+44h..+57h] = spare
|
|
ZeroGUI_End PROC
|
|
push rbx
|
|
push rsi
|
|
sub rsp, 58h
|
|
|
|
lea rsi, [ZG_drawlist] ; base of drawlist
|
|
xor rbx, rbx ; entry byte offset = 0
|
|
|
|
@@render_loop:
|
|
cmp rbx, (DRAWLIST_COUNT * DL_SIZE)
|
|
jae @@render_done
|
|
|
|
; Check if entry type != -1
|
|
mov eax, DWORD PTR [rsi + rbx + DL_type]
|
|
cmp eax, -1
|
|
je @@next_entry
|
|
|
|
; Dispatch by type
|
|
cmp eax, 1
|
|
je @@type_rect
|
|
cmp eax, 2
|
|
je @@type_text_left
|
|
cmp eax, 3
|
|
je @@type_text_center
|
|
cmp eax, 4
|
|
je @@type_line
|
|
jmp @@reset_entry ; unknown type: reset
|
|
|
|
@@type_rect:
|
|
; drawFilledRect(pos.X, pos.Y, size.X, size.Y, &color)
|
|
mov ecx, DWORD PTR [rsi + rbx + DL_pos_X]
|
|
mov edx, DWORD PTR [rsi + rbx + DL_pos_Y]
|
|
mov r8d, DWORD PTR [rsi + rbx + DL_size_X]
|
|
mov r9d, DWORD PTR [rsi + rbx + DL_size_Y]
|
|
lea rax, [rsi + rbx + DL_color_R]
|
|
mov QWORD PTR [rsp+20h], rax ; 5th arg - correct slot
|
|
call ZeroGUI__DrawFilledRect
|
|
jmp @@reset_entry
|
|
|
|
@@type_text_left:
|
|
mov rcx, QWORD PTR [rsi + rbx + DL_name]
|
|
mov edx, DWORD PTR [rsi + rbx + DL_pos_X]
|
|
mov r8d, DWORD PTR [rsi + rbx + DL_pos_Y]
|
|
lea r9, [rsi + rbx + DL_color_R]
|
|
mov al, BYTE PTR [rsi + rbx + DL_outline]
|
|
mov BYTE PTR [rsp+20h], 0 ; bCentreX = false (5th arg)
|
|
mov BYTE PTR [rsp+28h], al ; bOutlined (6th arg)
|
|
call ZeroGUI__DrawText
|
|
jmp @@reset_entry
|
|
|
|
@@type_text_center:
|
|
mov rcx, QWORD PTR [rsi + rbx + DL_name]
|
|
mov edx, DWORD PTR [rsi + rbx + DL_pos_X]
|
|
mov r8d, DWORD PTR [rsi + rbx + DL_pos_Y]
|
|
lea r9, [rsi + rbx + DL_color_R]
|
|
mov al, BYTE PTR [rsi + rbx + DL_outline]
|
|
mov BYTE PTR [rsp+20h], 1 ; bCentreX = true (5th arg)
|
|
mov BYTE PTR [rsp+28h], al ; (6th arg)
|
|
call ZeroGUI__DrawText
|
|
jmp @@reset_entry
|
|
|
|
@@type_line:
|
|
; Build K2_DrawLine params at [rsp+20h..+43h] - above shadow, safe across CALL
|
|
mov eax, DWORD PTR [rsi + rbx + DL_from_X]
|
|
mov DWORD PTR [rsp+20h], eax ; params.A.X
|
|
mov eax, DWORD PTR [rsi + rbx + DL_from_Y]
|
|
mov DWORD PTR [rsp+24h], eax ; params.A.Y
|
|
mov eax, DWORD PTR [rsi + rbx + DL_to_X]
|
|
mov DWORD PTR [rsp+28h], eax ; params.B.X
|
|
mov eax, DWORD PTR [rsi + rbx + DL_to_Y]
|
|
mov DWORD PTR [rsp+2Ch], eax ; params.B.Y
|
|
cvtsi2ss xmm0, DWORD PTR [rsi + rbx + DL_thickness]
|
|
movss DWORD PTR [rsp+30h], xmm0 ; params.Thickness
|
|
mov eax, DWORD PTR [rsi + rbx + DL_color_R]
|
|
mov DWORD PTR [rsp+34h], eax ; params.Color.R
|
|
mov eax, DWORD PTR [rsi + rbx + DL_color_G]
|
|
mov DWORD PTR [rsp+38h], eax ; params.Color.G
|
|
mov eax, DWORD PTR [rsi + rbx + DL_color_B]
|
|
mov DWORD PTR [rsp+3Ch], eax ; params.Color.B
|
|
mov eax, DWORD PTR [rsi + rbx + DL_color_A]
|
|
mov DWORD PTR [rsp+40h], eax ; params.Color.A
|
|
; ProcessEvent(canvas, K2_DrawLine, ¶ms)
|
|
mov rcx, QWORD PTR [ZG_canvas]
|
|
test rcx, rcx
|
|
jz @@reset_entry
|
|
mov rdx, QWORD PTR [ZG_pFn_K2DrawLine]
|
|
test rdx, rdx
|
|
jz @@reset_entry
|
|
lea r8, [rsp+20h] ; pointer to params - above shadow
|
|
call QWORD PTR [ProcessEvent]
|
|
jmp @@reset_entry
|
|
|
|
@@reset_entry:
|
|
mov DWORD PTR [rsi + rbx + DL_type], -1
|
|
|
|
@@next_entry:
|
|
add rbx, DL_SIZE
|
|
jmp @@render_loop
|
|
|
|
@@render_done:
|
|
add rsp, 58h
|
|
pop rsi
|
|
pop rbx
|
|
ret
|
|
ZeroGUI_End ENDP
|
|
|
|
END |