; Native-pixel, CP1251 bitmap text. Count includes newlines for typewriter timing. ; Unlike DrawString8x8's 320x240 coordinates, this uses the full 640x480 frame. PresentationText3D PROC uses esi edi ebx x:DWORD,y:DWORD,text:DWORD,ink:DWORD,scale:DWORD,limit:DWORD local px:DWORD,py:DWORD,row:DWORD,col:DWORD,bits:DWORD,repeatY:DWORD,repeatX:DWORD mov esi,text mov eax,x mov px,eax mov eax,y mov py,eax pres_text_char: cmp limit,0 je pres_text_done movzx eax,BYTE PTR [esi] test eax,eax jz pres_text_done inc esi dec limit cmp eax,10 jne pres_text_glyph mov eax,x mov px,eax mov eax,scale imul eax,11 add py,eax jmp pres_text_char pres_text_glyph: lea edi,font8x8[eax*8] mov row,0 pres_text_row: mov eax,row movzx ebx,BYTE PTR [edi+eax] mov bits,ebx mov col,0 pres_text_col: test bits,80h jz pres_text_next_col mov repeatY,0 pres_text_repeat_y: mov eax,row imul eax,scale add eax,py add eax,repeatY cmp eax,SCREEN_H jae pres_text_next_y imul eax,SCREEN_W mov ebx,eax mov repeatX,0 pres_text_repeat_x: mov eax,col imul eax,scale add eax,px add eax,repeatX cmp eax,SCREEN_W jae pres_text_next_x add eax,ebx mov edx,ink mov screenBuffer[eax*4],edx pres_text_next_x: inc repeatX mov eax,repeatX cmp eax,scale jb pres_text_repeat_x pres_text_next_y: inc repeatY mov eax,repeatY cmp eax,scale jb pres_text_repeat_y pres_text_next_col: shl bits,1 inc col cmp col,8 jb pres_text_col inc row cmp row,8 jb pres_text_row mov eax,scale shl eax,3 add px,eax jmp pres_text_char pres_text_done: ret PresentationText3D ENDP RenderStartupNotice3D PROC uses ebx esi edi local lineY:DWORD,ink:DWORD invoke DrawBox,0,0,320,240,00060912h ; Quiet terminal grid, fixed geometry: never consumes gameplay RNG. mov ebx,12 pres_notice_grid: invoke DrawBox,0,ebx,320,1,000C1722h add ebx,16 cmp ebx,240 jb pres_notice_grid invoke DrawBox,20,26,3,22,00FFCE54h invoke DrawBox,26,26,274,1,002C6875h invoke DrawBox,20,212,280,1,002C6875h cmp startupPage3D,STARTUP_AI jne pres_notice_code invoke PresentationText3D,56,60,OFFSET presAITag,004FE5E2h,1,-1 invoke PresentationText3D,56,88,OFFSET presAIHeader,00FFDF82h,2,-1 invoke PresentationText3D,40,156,OFFSET presAIBody,00CFDCE4h,2,-1 invoke PresentationText3D,56,378,OFFSET presAIFooter,004FE5E2h,1,-1 jmp pres_notice_footer pres_notice_code: invoke PresentationText3D,56,64,OFFSET presCodeHeader,00FFDF82h,2,-1 invoke PresentationText3D,40,112,OFFSET presCodeSub,00CFDCE4h,2,-1 invoke DrawBoxBorder,12,80,144,90,00080F1Bh,002D7C92h,1 invoke DrawBoxBorder,164,80,144,90,00080F1Bh,003BE8CAh,1 invoke DrawBox,13,81,142,14,0017283Ch invoke DrawBox,165,81,142,14,00143435h invoke PresentationText3D,36,170,OFFSET presCodeLeft,00D0DDEBh,1,-1 invoke PresentationText3D,340,170,OFFSET presCodeRight,0062F3D3h,1,-1 mov esi,0 mov lineY,204 pres_code_line: mov ink,00C9D9E8h cmp esi,0 jne @F mov ink,00657D92h @@: invoke PresentationText3D,36,lineY,presCppLines[esi*4],ink,1,-1 invoke PresentationText3D,340,lineY,presAsmLines[esi*4],ink,1,-1 add lineY,17 inc esi cmp esi,7 jb pres_code_line invoke PresentationText3D,24,356,OFFSET presCodeCaption,00FFDF82h,2,-1 invoke PresentationText3D,40,386,OFFSET presCodeNote,009FB8C8h,1,-1 pres_notice_footer: invoke PresentationText3D,40,448,OFFSET presNext,006F939Fh,1,-1 ; Fade the notice in, then out at its own page boundary. mov eax,startupElapsed3D cmp eax,300 jae pres_notice_fade_out shl eax,8 xor edx,edx mov ecx,300 div ecx invoke FadeCityFrame3D,eax ret pres_notice_fade_out: mov ecx,startupPage3D mov ebx,startupDurations3D[ecx*4] sub ebx,400 cmp eax,ebx jb pres_notice_done sub eax,ebx cmp eax,400 jbe @F mov eax,400 @@: shl eax,8 xor edx,edx mov ecx,400 div ecx neg eax add eax,256 invoke FadeCityFrame3D,eax pres_notice_done: ret RenderStartupNotice3D ENDP BeginWelcome3D PROC mov welcomeActive3D,1 mov welcomeElapsed3D,0 mov welcomeChars3D,0 mov paused3D,0 mov interactTargetId,0 mov interactPromptPtr,0 call ClearKeys3D call UnlockMouse3D ret BeginWelcome3D ENDP CloseWelcome3D PROC mov welcomeActive3D,0 mov paused3D,0 call ClearKeys3D ret CloseWelcome3D ENDP HandleWelcome3D PROC cmp welcomeActive3D,0 je welcome_handle_done mov eax,deltaTime3D add welcomeElapsed3D,eax cmp welcomeElapsed3D,WELCOME_OPEN_MS jb welcome_handle_done ; Once manually completed, do not rewind the typewriter on the next frame. cmp welcomeChars3D,welcomeTextLength3D jae welcome_input mov eax,welcomeElapsed3D sub eax,WELCOME_OPEN_MS xor edx,edx mov ecx,WELCOME_CHAR_MS div ecx cmp eax,welcomeTextLength3D jbe @F mov eax,welcomeTextLength3D @@: mov welcomeChars3D,eax welcome_input: invoke Pressed3D,0Dh test eax,eax jnz welcome_confirm invoke Pressed3D,20h test eax,eax jnz welcome_confirm cmp mouseClick3D,0 je welcome_handle_done cmp mouseX3D,212 jb welcome_handle_done cmp mouseX3D,292 jae welcome_handle_done cmp mouseY3D,184 jb welcome_handle_done cmp mouseY3D,198 jae welcome_handle_done welcome_confirm: cmp welcomeChars3D,welcomeTextLength3D jae welcome_close mov welcomeChars3D,welcomeTextLength3D call ClearKeys3D ret welcome_close: call CloseWelcome3D welcome_handle_done: ret HandleWelcome3D ENDP RenderWelcomeScene3D PROC ; Frozen playable hall, not a replacement screenshot or second game runtime. call UpdateCamera3D call RenderCeilingAndFloor call RenderWalls call PrepareCityDepth3D call RenderSprites call RenderHall3D call RenderHUD call RenderWelcome3D ret RenderWelcomeScene3D ENDP RenderWelcome3D PROC uses ebx esi edi local halfW:DWORD,halfH:DWORD,left:DWORD,top:DWORD,wide:DWORD,panelH:DWORD local cursorX:DWORD,cursorY:DWORD cmp welcomeActive3D,0 je welcome_render_done invoke FadeCityFrame3D,90 ; Two-stage deployment: point -> horizontal line -> centred panel. mov eax,welcomeElapsed3D cmp eax,200 jae welcome_open_vertical imul eax,140 xor edx,edx mov ecx,200 div ecx inc eax mov halfW,eax mov halfH,1 jmp welcome_panel_bounds welcome_open_vertical: mov halfW,140 sub eax,200 cmp eax,400 jbe @F mov eax,400 @@: ; Ease-out quadratic: 1 - (1-t)^2, with bounded integer operands. neg eax add eax,400 imul eax,eax imul eax,81 xor edx,edx mov ecx,160000 div ecx neg eax add eax,82 mov halfH,eax welcome_panel_bounds: mov eax,160 sub eax,halfW mov left,eax mov eax,120 sub eax,halfH mov top,eax mov eax,halfW shl eax,1 mov wide,eax mov eax,halfH shl eax,1 mov panelH,eax invoke DrawBoxBorder,left,top,wide,panelH,0008101Bh,003EE7D8h,1 mov eax,left add eax,wide sub eax,2 invoke DrawBox,eax,top,2,panelH,00DC4B9Bh cmp welcomeElapsed3D,WELCOME_OPEN_MS jb welcome_render_done ; Chamfered corners, offset signal rails and a narrow animated scan line. invoke DrawBox,20,38,4,4,0008101Bh invoke DrawBox,296,198,4,4,0008101Bh invoke DrawBox,24,34,46,2,003EE7D8h invoke DrawBox,250,205,46,2,00DC4B9Bh invoke DrawBox,30,70,260,1,00284E62h invoke DrawBox,30,180,260,1,00284E62h mov eax,welcomeElapsed3D shr eax,5 xor edx,edx mov ecx,100 div ecx add edx,76 invoke DrawBox,22,edx,1,2,0058FFF0h invoke PresentationText3D,60,90,OFFSET welcomeHeader,00FFE29Ah,2,-1 invoke PresentationText3D,60,120,OFFSET welcomeTag,006C9EB0h,1,-1 invoke PresentationText3D,60,154,OFFSET welcomeBody,00CDE9E8h,1,welcomeChars3D cmp welcomeChars3D,welcomeTextLength3D jae welcome_cursor_done test welcomeElapsed3D,100h jnz welcome_cursor_done mov cursorX,60 mov cursorY,154 mov esi,OFFSET welcomeBody mov edi,welcomeChars3D welcome_cursor_scan: test edi,edi jz welcome_cursor_draw cmp BYTE PTR [esi],10 jne welcome_cursor_column mov cursorX,60 add cursorY,11 jmp welcome_cursor_next welcome_cursor_column: add cursorX,8 welcome_cursor_next: inc esi dec edi jmp welcome_cursor_scan welcome_cursor_draw: invoke PresentationText3D,cursorX,cursorY,OFFSET welcomeCursor3D,0058FFF0h,1,1 welcome_cursor_done: ; Blinking activity indicator; no random flicker and no gameplay RNG changes. mov eax,welcomeElapsed3D test eax,200h jnz @F invoke DrawBox,280,49,7,2,0058FFF0h @@: invoke DrawBoxBorder,212,184,80,14,00172A38h,003EE7D8h,1 invoke PresentationText3D,436,376,OFFSET welcomeButton,006EF4DEh,1,-1 mov eax,OFFSET welcomeTypeHint cmp welcomeChars3D,welcomeTextLength3D jb @F mov eax,OFFSET welcomeDoneHint @@: invoke PresentationText3D,60,380,eax,008EAFBEh,1,-1 welcome_render_done: ret RenderWelcome3D ENDP