; ============================================================================== ; 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