EBLAN_ENGINE/include/engine_textures.inc
Artvasil09 a1d1baa869 feat: complete engine and editor subsystems (Stages 1-5 from TODO_ARTEM)
- Stage 1: Eliminate fish-eye distortion with precomputed tangential ray offset table and fractional DDA depth
- Stage 2: Full asset management in EblanStudio (stb_image/stb_image_write, 128x128 BGRA texture packaging, WAV sound manager)
- Stage 3: Multi-level room streaming, LevelTransition/CELL_PORTAL trigger system, 16-frame screen fade to black
- Stage 4: 60Hz cutscene engine in pure x86 ASM (v4 binary track, waypoint camera motion, shortest-arc pan, CP1251 Russian subtitles, letterbox overlay, audio)
- Stage 5: EblanStudio cutscene timeline (F6) and windowless Live ASM Viewport over shared-memory IPC directly rendered into DX11
- Tooling & Tests: comprehensive regression test suite (94 editor + 107 engine tests), IPC tests, and cutscene demo
2026-10-22 16:24:22 +03:00

750 lines
16 KiB
PHP

; ==============================================================================
; EBLAN ENGINE - Texture Management & Procedural Texture Generator
; ==============================================================================
.code
GenerateDefaultSpriteTextures PROTO
; ------------------------------------------------------------------------------
; GenerateDefaultTextures: Procedurally creates 128x128 32-bit BGRA textures
; Zero external asset dependency - works out of the box on any machine!
; ------------------------------------------------------------------------------
GenerateDefaultTextures PROC uses ebx ecx edx esi edi
LOCAL texBase:DWORD, px:DWORD, py:DWORD, color:DWORD
mov edi, OFFSET textureBuffer
mov ecx, MAX_TEXTURES * TEX_SIZE_BYTES / 4
xor eax, eax
rep stosd
call GenerateDefaultSpriteTextures
; --------------------------------------------------------------------------
; Texture 1: Red Brick Wall
; --------------------------------------------------------------------------
mov eax, OFFSET textureBuffer
add eax, 1 * TEX_SIZE_BYTES
mov texBase, eax
mov py, 0
brick_y_loop:
mov px, 0
brick_x_loop:
; Base brick color (Dark red/brown)
mov color, 00852215h
; Mortar lines horizontally every 16 pixels
mov eax, py
and eax, 15
cmp eax, 0
je set_mortar
cmp eax, 1
je set_mortar
; Vertical mortar stagger: alternate every 16 rows
mov edx, px
mov eax, py
and eax, 16
jz @F
add edx, 16 ; shift vertical joint by 16 px on odd rows
@@:
and edx, 31
cmp edx, 0
je set_mortar
cmp edx, 1
je set_mortar
jmp apply_brick_noise
set_mortar:
mov color, 00555555h ; Gray mortar
jmp write_brick_pixel
apply_brick_noise:
; Add subtle shade variation
mov eax, px
xor eax, py
and eax, 7
shl eax, 2
add color, eax
write_brick_pixel:
; Write BGRA pixel to texture
mov eax, py
shl eax, 7 ; py * 128
add eax, px
shl eax, 2 ; * 4 bytes
mov edi, texBase
add edi, eax
mov edx, color
mov [edi], edx
inc px
cmp px, TEX_W
jl brick_x_loop
inc py
cmp py, TEX_H
jl brick_y_loop
; --------------------------------------------------------------------------
; Texture 2: Wood Planks
; --------------------------------------------------------------------------
mov eax, OFFSET textureBuffer
add eax, 2 * TEX_SIZE_BYTES
mov texBase, eax
mov py, 0
wood_y_loop:
mov px, 0
wood_x_loop:
; Base wood color (Warm brown)
mov color, 00683A12h
; Plank seams every 32 horizontal pixels
mov eax, px
and eax, 31
cmp eax, 0
jne @F
mov color, 00201005h ; Dark seam
jmp write_wood_pixel
@@:
; Subtle wood grain variation based on py
mov eax, py
and eax, 3
shl eax, 3
add color, eax
write_wood_pixel:
mov eax, py
shl eax, 7
add eax, px
shl eax, 2
mov edi, texBase
add edi, eax
mov edx, color
mov [edi], edx
inc px
cmp px, TEX_W
jl wood_x_loop
inc py
cmp py, TEX_H
jl wood_y_loop
; --------------------------------------------------------------------------
; Texture 3: Stone / Cobblestone
; --------------------------------------------------------------------------
mov eax, OFFSET textureBuffer
add eax, 3 * TEX_SIZE_BYTES
mov texBase, eax
mov py, 0
stone_y_loop:
mov px, 0
stone_x_loop:
; Base gray
mov color, 00555555h
; Stone border grid (32x32 blocks)
mov eax, px
and eax, 31
test eax, eax
jz set_stone_border
mov eax, py
and eax, 31
test eax, eax
jz set_stone_border
; Noise
mov eax, px
imul eax, 3
add eax, py
and eax, 15
shl eax, 2
add color, eax
jmp write_stone_pixel
set_stone_border:
mov color, 00222222h
write_stone_pixel:
mov eax, py
shl eax, 7
add eax, px
shl eax, 2
mov edi, texBase
add edi, eax
mov edx, color
mov [edi], edx
inc px
cmp px, TEX_W
jl stone_x_loop
inc py
cmp py, TEX_H
jl stone_y_loop
; --------------------------------------------------------------------------
; Texture 4: Metal Tech / Rivets
; --------------------------------------------------------------------------
mov eax, OFFSET textureBuffer
add eax, 4 * TEX_SIZE_BYTES
mov texBase, eax
mov py, 0
metal_y_loop:
mov px, 0
metal_x_loop:
; Base metal slate (blue-gray)
mov color, 00606570h
; Rivets near corners (10, 10) and (118, 118)
; Check if within 4 pixels of a rivet center
mov eax, px
sub eax, 10
imul eax, eax
mov edx, py
sub edx, 10
imul edx, edx
add eax, edx
cmp eax, 16
jle set_rivet
mov eax, px
sub eax, 118
imul eax, eax
mov edx, py
sub edx, 118
imul edx, edx
add eax, edx
cmp eax, 16
jle set_rivet
jmp write_metal_pixel
set_rivet:
mov color, 00A0B0C0h ; Shiny rivet highlight
write_metal_pixel:
mov eax, py
shl eax, 7
add eax, px
shl eax, 2
mov edi, texBase
add edi, eax
mov edx, color
mov [edi], edx
inc px
cmp px, TEX_W
jl metal_x_loop
inc py
cmp py, TEX_H
jl metal_y_loop
; --------------------------------------------------------------------------
; Texture 5: Door
; --------------------------------------------------------------------------
mov eax, OFFSET textureBuffer
add eax, 5 * TEX_SIZE_BYTES
mov texBase, eax
mov py, 0
door_y_loop:
mov px, 0
door_x_loop:
; Door frame (outer 8 pixels)
mov eax, px
cmp eax, 8
jl set_door_frame
cmp eax, 120
jge set_door_frame
mov eax, py
cmp eax, 8
jl set_door_frame
; Door body (Deep wood)
mov color, 00502D15h
; Brass door knob at (px=100, py=64)
mov eax, px
sub eax, 100
imul eax, eax
mov edx, py
sub edx, 64
imul edx, edx
add eax, edx
cmp eax, 36
jle set_brass_knob
jmp write_door_pixel
set_door_frame:
mov color, 00333333h
jmp write_door_pixel
set_brass_knob:
mov color, 00FFD000h ; Gold / Brass
write_door_pixel:
mov eax, py
shl eax, 7
add eax, px
shl eax, 2
mov edi, texBase
add edi, eax
mov edx, color
mov [edi], edx
inc px
cmp px, TEX_W
jl door_x_loop
inc py
cmp py, TEX_H
jl door_y_loop
; --------------------------------------------------------------------------
; Texture 7: Pillar / Marble Mosaic
; --------------------------------------------------------------------------
mov eax, OFFSET textureBuffer
add eax, 7 * TEX_SIZE_BYTES
mov texBase, eax
mov py, 0
pillar_y_loop:
mov px, 0
pillar_x_loop:
; Vertical fluted pillar pattern
mov eax, px
and eax, 15
cmp eax, 8
jl set_pillar_light
mov color, 00408090h ; Dark turquoise
jmp write_pillar_pixel
set_pillar_light:
mov color, 0070B0C0h ; Light turquoise
write_pillar_pixel:
mov eax, py
shl eax, 7
add eax, px
shl eax, 2
mov edi, texBase
add edi, eax
mov edx, color
mov [edi], edx
inc px
cmp px, TEX_W
jl pillar_x_loop
inc py
cmp py, TEX_H
jl pillar_y_loop
; --------------------------------------------------------------------------
; Texture 8: Glass (framed pane with diagonal shine)
; --------------------------------------------------------------------------
mov eax, OFFSET textureBuffer
add eax, 8 * TEX_SIZE_BYTES
mov texBase, eax
mov py, 0
glass_y_loop:
mov px, 0
glass_x_loop:
; Base: dark blue-green tinted glass
mov color, 00403020h
; Metal frame (outer 6 pixels)
mov eax, px
cmp eax, 6
jl set_glass_frame
cmp eax, 122
jge set_glass_frame
mov eax, py
cmp eax, 6
jl set_glass_frame
cmp eax, 122
jge set_glass_frame
; Diagonal shine streaks: (px + py) mod 64 in [0..3] or [24..27]
mov eax, px
add eax, py
and eax, 63
cmp eax, 4
jl set_glass_shine
cmp eax, 24
jl write_glass_pixel
cmp eax, 28
jl set_glass_shine
jmp write_glass_pixel
set_glass_frame:
mov color, 00606060h ; Steel frame
jmp write_glass_pixel
set_glass_shine:
mov color, 00907050h ; Bright reflection streak
write_glass_pixel:
mov eax, py
shl eax, 7
add eax, px
shl eax, 2
mov edi, texBase
add edi, eax
mov edx, color
mov [edi], edx
inc px
cmp px, TEX_W
jl glass_x_loop
inc py
cmp py, TEX_H
jl glass_y_loop
; --------------------------------------------------------------------------
; Texture 9: Marble (cream slab with dark veins)
; --------------------------------------------------------------------------
mov eax, OFFSET textureBuffer
add eax, 9 * TEX_SIZE_BYTES
mov texBase, eax
mov py, 0
marble_y_loop:
mov px, 0
marble_x_loop:
; Base: cream marble
mov color, 00D8D0C0h
; Veins: wandering pseudo-noise lines
mov eax, px
imul eax, 7
mov edx, py
imul edx, 13
add eax, edx
mov edx, eax
shr edx, 3
add eax, edx
and eax, 63
cmp eax, 2
jbe set_marble_vein
cmp eax, 40
jne marble_polish
; Single-pixel hairline vein
jmp set_marble_vein
marble_polish:
; Subtle polish variation
mov eax, px
xor eax, py
and eax, 3
add color, eax
jmp write_marble_pixel
set_marble_vein:
mov color, 00555555h ; Dark gray vein
write_marble_pixel:
mov eax, py
shl eax, 7
add eax, px
shl eax, 2
mov edi, texBase
add edi, eax
mov edx, color
mov [edi], edx
inc px
cmp px, TEX_W
jl marble_x_loop
inc py
cmp py, TEX_H
jl marble_y_loop
; --------------------------------------------------------------------------
; Texture 10: Portal / Dimensional Vortex (Swirling purple / cyan stargate)
; --------------------------------------------------------------------------
mov texBase, OFFSET portalTextureBuffer
mov py, 0
portal_y_loop:
mov px, 0
portal_x_loop:
; Base: deep cosmic dark purple
mov color, 002A0835h
; Stone arch frame on outer 8 pixels
mov eax, px
cmp eax, 8
jl set_portal_arch
cmp eax, 120
jge set_portal_arch
mov eax, py
cmp eax, 8
jl set_portal_arch
; Calculate distance from center (64, 64)
mov eax, px
sub eax, 64
imul eax, eax
mov edx, py
sub edx, 64
imul edx, edx
add eax, edx ; r^2 = dx^2 + dy^2
; Concentric glowing energy rings
cmp eax, 2500 ; r ~ 50
jg write_portal_pixel
and eax, 15
cmp eax, 3
jg @F
mov color, 00D030F0h ; Bright violet energy ring
jmp write_portal_pixel
@@:
cmp eax, 8
jg write_portal_pixel
mov color, 00E0E040h ; Cyan shimmer
jmp write_portal_pixel
set_portal_arch:
mov color, 00484852h ; Carved rune stone arch
write_portal_pixel:
mov eax, py
shl eax, 7
add eax, px
shl eax, 2
mov edi, texBase
add edi, eax
mov edx, color
mov [edi], edx
inc px
cmp px, TEX_W
jl portal_x_loop
inc py
cmp py, TEX_H
jl portal_y_loop
ret
GenerateDefaultTextures ENDP
; ------------------------------------------------------------------------------
; LoadTexturePack: Optionally overrides procedural textures with
; assets/textures/texturepack.bin (see tools/make_texturepack.py).
; Layout: dd magic 'EBTX', dw version (1), dw slotCount,
; then slotCount * 65536 bytes (128x128 BGRA per slot, slot 0 first).
; Returns: eax = 1 if pack loaded, 0 if procedural textures stay active.
; ------------------------------------------------------------------------------
LoadTexturePack PROC uses ebx ecx edx esi edi
LOCAL hFile:DWORD, bytesRead:DWORD
LOCAL magic:DWORD, pkVersion:WORD, slotCount:WORD
LOCAL payloadBytes:DWORD
mov texPackLoaded, 0
invoke CreateFileA, OFFSET szTexPackPath, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0
mov hFile, eax
cmp eax, INVALID_HANDLE_VALUE
je pack_fail
invoke ReadFile, hFile, ADDR magic, 4, ADDR bytesRead, 0
test eax, eax
jz pack_close_fail
cmp bytesRead, 4
jne pack_close_fail
cmp magic, TEXPACK_MAGIC
jne pack_close_fail
invoke ReadFile, hFile, ADDR pkVersion, 2, ADDR bytesRead, 0
test eax, eax
jz pack_close_fail
cmp bytesRead, 2
jne pack_close_fail
cmp pkVersion, 1
jne pack_close_fail
invoke ReadFile, hFile, ADDR slotCount, 2, ADDR bytesRead, 0
test eax, eax
jz pack_close_fail
cmp bytesRead, 2
jne pack_close_fail
movzx eax, slotCount
test eax, eax
jz pack_close_fail
cmp eax, MAX_TEXTURES
ja pack_close_fail
shl eax, 16
mov payloadBytes, eax
add eax, 8
mov ebx, eax
invoke GetFileSize, hFile, 0
cmp eax, ebx
jne pack_close_fail
; Commit only after the complete payload has been read successfully.
invoke ReadFile, hFile, OFFSET texturePackStaging, payloadBytes, ADDR bytesRead, 0
test eax, eax
jz pack_close_fail
mov eax, payloadBytes
cmp bytesRead, eax
jne pack_close_fail
mov esi, OFFSET texturePackStaging
mov edi, OFFSET textureBuffer
mov ecx, payloadBytes
shr ecx, 2
rep movsd
invoke CloseHandle, hFile
mov texPackLoaded, 1
mov eax, 1
ret
pack_close_fail:
invoke CloseHandle, hFile
pack_fail:
xor eax, eax
ret
LoadTexturePack ENDP
; Slots 10..15 remain sprite slots even when the map contains portals.
GenerateDefaultSpriteTextures PROC uses eax ebx ecx edx esi edi
LOCAL px:DWORD, py:DWORD, slot:DWORD, color:DWORD
mov edi, OFFSET textureBuffer + 10 * TEX_SIZE_BYTES
mov ecx, 6 * TEX_SIZE_BYTES / 4
mov eax, COLOR_CHROMA_KEY
rep stosd
mov slot, 10
sprite_default_slot:
mov py, 0
sprite_default_y:
mov px, 0
sprite_default_x:
mov color, COLOR_CHROMA_KEY
cmp slot, 10
jne default_barrel
cmp px, 60
jl lamp_shade
cmp px, 68
jge lamp_shade
cmp py, 40
jl lamp_shade
cmp py, 120
jge lamp_shade
mov color, 00404040h
lamp_shade:
cmp px, 48
jl lamp_foot
cmp px, 80
jge lamp_foot
cmp py, 16
jl lamp_foot
cmp py, 44
jge lamp_foot
mov color, 00FFC030h
lamp_foot:
cmp px, 52
jl default_sprite_write
cmp px, 76
jge default_sprite_write
cmp py, 120
jl default_sprite_write
cmp py, 126
jge default_sprite_write
mov color, 00303030h
jmp default_sprite_write
default_barrel:
cmp slot, 11
jne default_statue
mov eax, px
sub eax, 64
imul eax, eax
imul eax, 2704
mov ebx, py
sub ebx, 70
imul ebx, ebx
imul ebx, 1156
add eax, ebx
cmp eax, 3125824
jg default_sprite_write
mov color, 006A401Eh
mov eax, py
sub eax, 70
cdq
xor eax, edx
sub eax, edx
cmp eax, 29
jl barrel_highlight
cmp eax, 35
jg barrel_highlight
mov color, 00555555h
jmp default_sprite_write
barrel_highlight:
cmp px, 53
jge default_sprite_write
cmp eax, 26
jge default_sprite_write
mov color, 008A5A2Eh
jmp default_sprite_write
default_statue:
cmp px, 44
jl statue_body
cmp px, 84
jge statue_body
cmp py, 112
jl statue_body
cmp py, 126
jge statue_body
mov color, 00606060h
statue_body:
cmp px, 54
jl statue_head
cmp px, 74
jge statue_head
cmp py, 40
jl statue_head
cmp py, 112
jge statue_head
mov eax, px
xor eax, py
and eax, 7
add eax, 08Ah
imul eax, 010101h
mov color, eax
statue_head:
mov eax, px
sub eax, 64
imul eax, eax
mov ebx, py
sub ebx, 28
imul ebx, ebx
add eax, ebx
cmp eax, 100
jg default_sprite_write
mov color, 009A9A9Ah
default_sprite_write:
mov edi, slot
shl edi, 16
mov eax, py
shl eax, 7
add eax, px
shl eax, 2
add edi, eax
mov eax, color
mov DWORD PTR [textureBuffer + edi], eax
inc px
cmp px, TEX_W
jl sprite_default_x
inc py
cmp py, TEX_H
jl sprite_default_y
inc slot
cmp slot, 13
jl sprite_default_slot
ret
GenerateDefaultSpriteTextures ENDP