; Seated fortune session. All timing, input, dealing and rendering are native MASM. BeginFortuneDialog3D PROC uses ebx esi edi call StopFortuneWorker3D lea esi,screenBuffer lea edi,fortuneBackground3D mov ecx,SCREEN_SIZE rep movsd xor ebx,ebx lea esi,fortuneSessionPacks3D fortune_session_load: invoke LoadAnimPack3D,esi,fortuneSessionPaths3D[ebx*4] add esi,SIZEOF AnimPack3D inc ebx cmp ebx,7 jb fortune_session_load mov engineMode,MODE_FORTUNE mov paused3D,0 mov fortuneSubMode3D,0 mov fortunePhase3D,0 mov fortunePhaseTime3D,0 mov fortuneDealt3D,0 mov fortuneRevealed3D,0 mov fortuneCardsDrawn3D,0 mov fortuneQuestionLength3D,0 mov fortuneQuestion3D,0 mov fortuneWorkerState3D,0 mov eax,animationClock3D mov fortuneSessionClock3D,eax invoke SetFortuneSpeech3D,OFFSET fortuneWelcome3D call ClearKeys3D mov mouseClick3D,0 ret BeginFortuneDialog3D ENDP ; Kept as the public exit/shutdown hook. No inference process is launched. StopFortuneWorker3D PROC uses ebx esi lea esi,fortuneSessionPacks3D mov ebx,7 fortune_session_free: invoke FreeAnimPack3D,esi add esi,SIZEOF AnimPack3D dec ebx jnz fortune_session_free mov fortuneWorkerState3D,0 ret StopFortuneWorker3D ENDP PollFortuneWorker3D PROC ret PollFortuneWorker3D ENDP SetFortuneSpeech3D PROC uses esi edi text:DWORD mov esi,text lea edi,fortuneSpeech3D xor ecx,ecx fortune_speech_copy: mov al,[esi+ecx] mov [edi+ecx],al test al,al jz fortune_speech_copied inc ecx cmp ecx,255 jb fortune_speech_copy mov BYTE PTR [edi+255],0 fortune_speech_copied: mov fortuneSpeechLength3D,ecx mov fortuneSpeechTime3D,0 mov fortuneSpeechVisible3D,0 ret SetFortuneSpeech3D ENDP FortuneCardSpeech3D PROC uses ebx esi edi cardSlot:DWORD mov eax,cardSlot mov ebx,fortuneDrawCards3D[eax*4] mov eax,ebx xor edx,edx mov ecx,22 div ecx mov esi,fortuneCardNames3D[edx*4] lea edi,fortuneSpeech3D fortune_card_name_copy: lodsb test al,al jz fortune_card_position stosb jmp fortune_card_name_copy fortune_card_position: mov al,10 stosb mov esi,OFFSET fortuneUpright3D cmp ebx,22 jb @F mov esi,OFFSET fortuneReversed3D @@: lodsb test al,al jz fortune_card_placeholder stosb jmp @B fortune_card_placeholder: mov al,10 stosb mov esi,OFFSET fortuneUnavailable3D fortune_card_placeholder_copy: lodsb stosb test al,al jnz fortune_card_placeholder_copy sub edi,OFFSET fortuneSpeech3D+1 mov fortuneSpeechLength3D,edi mov fortuneSpeechTime3D,0 mov fortuneSpeechVisible3D,0 ret FortuneCardSpeech3D ENDP FortuneChar3D PROC character:DWORD cmp engineMode,MODE_FORTUNE jne fortune_char_done cmp fortuneSubMode3D,FORTUNE_SUBMODE_MENU jne fortune_char_question cmp character,'1' je fortune_char_tarot cmp character,'2' je fortune_char_orb ret fortune_char_tarot: mov fortuneSubMode3D,FORTUNE_SUBMODE_TAROT invoke SetFortuneSpeech3D,OFFSET fortuneReady3D ret fortune_char_orb: mov fortuneSubMode3D,FORTUNE_SUBMODE_ORB mov fortunePhase3D,1 mov fortunePhaseTime3D,0 invoke SetFortuneSpeech3D,OFFSET fortuneOrbStatus3D ret fortune_char_question: cmp fortuneSubMode3D,FORTUNE_SUBMODE_TAROT jne fortune_char_done cmp fortunePhase3D,0 jne fortune_char_done mov eax,character cmp eax,8 je fortune_char_backspace cmp eax,32 jb fortune_char_done cmp eax,255 ja fortune_char_done cmp eax,127 je fortune_char_done mov ecx,fortuneQuestionLength3D cmp ecx,240 jae fortune_char_done mov fortuneQuestion3D[ecx],al inc ecx mov fortuneQuestionLength3D,ecx mov fortuneQuestion3D[ecx],0 ret fortune_char_backspace: mov ecx,fortuneQuestionLength3D test ecx,ecx jz fortune_char_done dec ecx mov fortuneQuestionLength3D,ecx mov fortuneQuestion3D[ecx],0 fortune_char_done: ret FortuneChar3D ENDP SubmitFortuneQuestion3D PROC uses ebx esi cmp fortuneSubMode3D,FORTUNE_SUBMODE_TAROT jne fortune_submit_done cmp fortunePhase3D,0 jne fortune_submit_done cmp fortuneQuestionLength3D,0 je fortune_submit_done xor esi,esi fortune_draw_loop: invoke RandomRange3D,22 mov ebx,eax xor ecx,ecx fortune_check_unique: cmp ecx,esi jae fortune_apply_orientation mov eax,fortuneDrawCards3D[ecx*4] xor edx,edx push ecx mov ecx,22 div ecx pop ecx cmp ebx,edx je fortune_draw_loop inc ecx jmp fortune_check_unique fortune_apply_orientation: invoke RandomRange3D,2 imul eax,22 add eax,ebx mov fortuneDrawCards3D[esi*4],eax inc esi cmp esi,3 jb fortune_draw_loop mov fortunePhase3D,1 mov fortunePhaseTime3D,0 mov fortuneDealt3D,0 mov fortuneRevealed3D,0 mov fortuneCardsDrawn3D,1 mov eax,animationClock3D mov fortuneSessionClock3D,eax invoke SetFortuneSpeech3D,OFFSET fortuneShuffle3D fortune_submit_done: ret SubmitFortuneQuestion3D ENDP ; Elapsed clock, not render count: repeated renders cannot accelerate a session. UpdateFortuneSession3D PROC uses ebx mov eax,animationClock3D mov edx,eax sub eax,fortuneSessionClock3D mov fortuneSessionClock3D,edx cmp eax,100 jbe @F mov eax,100 @@: add fortuneSpeechTime3D,eax add fortunePhaseTime3D,eax cmp fortuneSubMode3D,FORTUNE_SUBMODE_TAROT jne fortune_update_orb mov ebx,fortunePhase3D test ebx,ebx jz fortune_update_done cmp ebx,12 jae fortune_update_done mov eax,fortuneDurations3D[ebx*4] cmp fortunePhaseTime3D,eax jb fortune_update_done inc ebx mov fortunePhase3D,ebx mov fortunePhaseTime3D,0 cmp ebx,2 jb fortune_update_done cmp ebx,5 ja fortune_update_reveal mov eax,ebx sub eax,2 mov fortuneDealt3D,eax invoke SetFortuneSpeech3D,OFFSET fortuneDeal3D jmp fortune_update_done fortune_update_reveal: cmp ebx,6 je fortune_explain_one cmp ebx,8 je fortune_explain_two cmp ebx,10 je fortune_explain_three cmp ebx,11 jne fortune_update_done invoke SetFortuneSpeech3D,OFFSET fortuneSummary3D jmp fortune_update_done fortune_explain_one: mov fortuneRevealed3D,1 invoke FortuneCardSpeech3D,0 jmp fortune_update_done fortune_explain_two: mov fortuneRevealed3D,2 invoke FortuneCardSpeech3D,1 jmp fortune_update_done fortune_explain_three: mov fortuneRevealed3D,3 invoke FortuneCardSpeech3D,2 jmp fortune_update_done fortune_update_orb: cmp fortuneSubMode3D,FORTUNE_SUBMODE_ORB jne fortune_update_done cmp fortunePhase3D,1 jne fortune_orb_swirl cmp fortunePhaseTime3D,1400 jb fortune_update_done mov fortunePhase3D,2 mov fortunePhaseTime3D,0 jmp fortune_update_done fortune_orb_swirl: cmp fortunePhase3D,2 jne fortune_update_done cmp fortunePhaseTime3D,5000 jb fortune_update_done mov fortunePhase3D,3 mov fortunePhaseTime3D,0 invoke SetFortuneSpeech3D,OFFSET fortuneOrbText3D fortune_update_done: ret UpdateFortuneSession3D ENDP HandleFortuneDialog3D PROC call UpdateFortuneSession3D invoke Pressed3D,1Bh test eax,eax jnz fortune_handle_exit invoke Pressed3D,0Dh test eax,eax jnz fortune_handle_action cmp mouseClick3D,0 je fortune_handle_done mov mouseClick3D,0 cmp mouseY3D,227 jb fortune_handle_menu_click cmp mouseY3D,239 ja fortune_handle_done cmp mouseX3D,240 jae fortune_handle_exit cmp fortuneSubMode3D,FORTUNE_SUBMODE_MENU je fortune_handle_done cmp mouseX3D,172 jae fortune_handle_menu cmp mouseX3D,88 jae fortune_handle_reset jmp fortune_handle_action fortune_handle_menu_click: cmp fortuneSubMode3D,FORTUNE_SUBMODE_MENU jne fortune_handle_done cmp mouseY3D,196 jb fortune_handle_done cmp mouseY3D,214 ja fortune_handle_done cmp mouseX3D,160 jae fortune_handle_orb fortune_handle_tarot: invoke FortuneChar3D,'1' ret fortune_handle_orb: invoke FortuneChar3D,'2' ret fortune_handle_action: cmp fortuneSubMode3D,FORTUNE_SUBMODE_MENU je fortune_handle_tarot cmp fortuneSubMode3D,FORTUNE_SUBMODE_TAROT jne fortune_handle_done cmp fortunePhase3D,0 je fortune_handle_submit ; Continue only after this speech is fully visible. Never skip dealing/flips. mov eax,fortuneSpeechLength3D imul eax,28 cmp fortuneSpeechTime3D,eax jb fortune_handle_done mov eax,fortunePhase3D cmp eax,6 je fortune_handle_advance cmp eax,8 je fortune_handle_advance cmp eax,10 je fortune_handle_advance cmp eax,11 jne fortune_handle_done fortune_handle_advance: mov eax,fortuneDurations3D[eax*4] mov fortunePhaseTime3D,eax ret fortune_handle_submit: call SubmitFortuneQuestion3D ret fortune_handle_menu: mov fortuneSubMode3D,FORTUNE_SUBMODE_MENU mov fortunePhase3D,0 mov fortuneDealt3D,0 mov fortuneRevealed3D,0 invoke SetFortuneSpeech3D,OFFSET fortuneWelcome3D ret fortune_handle_reset: cmp fortuneSubMode3D,FORTUNE_SUBMODE_ORB jne @F mov fortunePhase3D,1 mov fortunePhaseTime3D,0 invoke SetFortuneSpeech3D,OFFSET fortuneOrbStatus3D ret @@: cmp fortunePhase3D,12 jne fortune_handle_done mov fortunePhase3D,0 mov fortuneDealt3D,0 mov fortuneRevealed3D,0 mov fortuneQuestionLength3D,0 mov fortuneQuestion3D,0 invoke SetFortuneSpeech3D,OFFSET fortuneReady3D ret fortune_handle_exit: call StopFortuneWorker3D mov engineMode,MODE_WALK call ClearKeys3D fortune_handle_done: ret HandleFortuneDialog3D ENDP FortuneWrap3D PROC uses ebx esi edi source:DWORD,top:DWORD,lines:DWORD,skip:DWORD,ink:DWORD local count:DWORD,lastSpace:DWORD,lineNumber:DWORD mov esi,source mov lineNumber,0 fortune_wrap_line: cmp BYTE PTR [esi],0 je fortune_wrap_end xor ebx,ebx mov lastSpace,0 fortune_wrap_measure: mov al,[esi+ebx] test al,al jz fortune_wrap_measured cmp al,10 je fortune_wrap_measured cmp al,32 jne @F mov lastSpace,ebx @@: inc ebx cmp ebx,72 jb fortune_wrap_measure cmp BYTE PTR [esi+ebx],0 je fortune_wrap_measured cmp lastSpace,0 je fortune_wrap_measured mov ebx,lastSpace fortune_wrap_measured: mov count,ebx mov eax,lineNumber cmp eax,skip jb fortune_wrap_advance sub eax,skip cmp eax,lines jae fortune_wrap_more imul eax,11 add eax,top push eax lea edi,fortuneLine3D mov ecx,ebx push esi rep movsb mov BYTE PTR [edi],0 pop esi pop eax mov fortuneCaretY3D,eax mov edx,count imul edx,8 add edx,24 mov fortuneCaretX3D,edx invoke DrawBuckshotText3D,24,eax,OFFSET fortuneLine3D,ink fortune_wrap_advance: add esi,count cmp BYTE PTR [esi],10 je fortune_wrap_skip_separator cmp BYTE PTR [esi],32 jne fortune_wrap_next fortune_wrap_skip_separator: inc esi fortune_wrap_next: inc lineNumber jmp fortune_wrap_line fortune_wrap_more: mov eax,1 ret fortune_wrap_end: xor eax,eax ret FortuneWrap3D ENDP ; The bubble grows with visible glyphs, rather than allocating a full-screen panel. DrawFortuneSpeech3D PROC uses ebx esi edi local column:DWORD,row:DWORD,maxColumn:DWORD,visible:DWORD,glyphX:DWORD,glyphY:DWORD mov eax,fortuneSpeechTime3D xor edx,edx mov ecx,28 div ecx cmp eax,fortuneSpeechLength3D jbe @F mov eax,fortuneSpeechLength3D @@: mov visible,eax mov fortuneSpeechVisible3D,eax test eax,eax jz fortune_bubble_done mov column,0 mov row,0 mov maxColumn,0 xor esi,esi fortune_bubble_measure: cmp esi,visible jae fortune_bubble_box cmp fortuneSpeech3D[esi],10 je fortune_bubble_newline inc column mov eax,column cmp eax,maxColumn jbe @F mov maxColumn,eax @@: cmp column,23 jb fortune_bubble_measure_next fortune_bubble_newline: mov column,0 inc row fortune_bubble_measure_next: inc esi jmp fortune_bubble_measure fortune_bubble_box: mov eax,maxColumn imul eax,8 add eax,20 mov fortuneSpeechWidth3D,eax shr eax,1 mov ebx,eax mov eax,row inc eax imul eax,12 add eax,20 mov fortuneSpeechHeight3D,eax shr eax,1 invoke DrawBoxBorder,208,30,ebx,eax,000A1829h,006E9DB8h,1 mov column,0 mov row,0 xor esi,esi fortune_bubble_glyph: cmp esi,visible jae fortune_bubble_done mov al,fortuneSpeech3D[esi] cmp al,10 je fortune_bubble_glyph_newline mov fortuneGlyph3D,al mov eax,column imul eax,8 add eax,426 mov glyphX,eax mov ebx,row imul ebx,12 add ebx,70 mov eax,esi inc eax imul eax,28 mov edx,fortuneSpeechTime3D sub edx,eax cmp edx,84 jae @F mov eax,84 sub eax,edx shr eax,5 sub ebx,eax @@: mov glyphY,ebx invoke DrawBuckshotText3D,glyphX,ebx,OFFSET fortuneGlyph3D,00D2E8F2h inc column cmp column,23 jb fortune_bubble_glyph_next fortune_bubble_glyph_newline: mov column,0 inc row fortune_bubble_glyph_next: inc esi jmp fortune_bubble_glyph fortune_bubble_done: ret DrawFortuneSpeech3D ENDP DrawFortuneSessionCard3D PROC uses ebx esi edi slot:DWORD local px:DWORD,py:DWORD,cw:DWORD,cardHeight:DWORD,face:DWORD,amount:DWORD mov esi,slot mov eax,esi imul eax,100 add eax,198 mov px,eax mov py,302 mov cw,72 mov cardHeight,96 mov face,44 cmp esi,fortuneRevealed3D jae @F mov eax,fortuneDrawCards3D[esi*4] mov face,eax @@: cmp esi,fortuneDealt3D jb fortune_card_flip_check mov eax,fortunePhase3D sub eax,2 cmp eax,esi jne fortune_card_done ; Release at 40%, then carry the card from the hand to its table slot. mov ebx,fortunePhaseTime3D sub ebx,400 js fortune_card_done cmp ebx,600 jbe @F mov ebx,600 @@: mov eax,px sub eax,220 imul eax,ebx cdq mov ecx,600 idiv ecx add eax,220 mov px,eax mov eax,ebx imul eax,40 xor edx,edx div ecx add eax,262 mov py,eax jmp fortune_card_draw fortune_card_flip_check: mov eax,fortunePhase3D sub eax,5 js fortune_card_draw test eax,1 jnz fortune_card_draw shr eax,1 cmp eax,esi jne fortune_card_draw cmp fortunePhase3D,9 ja fortune_card_draw mov ebx,fortunePhaseTime3D cmp ebx,400 jb fortune_card_flip_back mov eax,fortuneDrawCards3D[esi*4] mov face,eax sub ebx,400 jmp fortune_card_flip_width fortune_card_flip_back: mov eax,400 sub eax,ebx mov ebx,eax fortune_card_flip_width: imul ebx,72 mov eax,ebx xor edx,edx mov ecx,400 div ecx cmp eax,2 jae @F mov eax,2 @@: mov cw,eax mov ebx,72 sub ebx,eax shr ebx,1 add px,ebx fortune_card_draw: invoke DrawAnimSprite3D,OFFSET fortuneSessionCards3D,face,px,py,cw,cardHeight fortune_card_done: ret DrawFortuneSessionCard3D ENDP RenderFortuneDialog3D PROC uses ebx esi edi lea esi,fortuneBackground3D lea edi,screenBuffer mov ecx,SCREEN_SIZE rep movsd invoke DrawAnimSprite3D,OFFSET fortuneSessionRoom3D,0,0,0,640,480 cmp fortuneSessionRoom3D.pixels,0 jne @F invoke DrawBoxBorder,4,4,312,36,000A1829h,006E9DB8h,1 invoke DrawBuckshotText3D,24,24,OFFSET fortuneMissing3D,00FFFFFFh @@: mov ebx,OFFSET fortuneSessionShuffle3D xor esi,esi cmp fortuneSubMode3D,FORTUNE_SUBMODE_ORB je fortune_render_orb_hands mov eax,fortunePhase3D cmp eax,1 jne fortune_render_hand_deal mov eax,fortunePhaseTime3D xor edx,edx mov ecx,25 div ecx and eax,63 mov esi,eax jmp fortune_render_hands fortune_render_hand_deal: cmp eax,2 jb fortune_render_hands cmp eax,4 ja fortune_render_hand_gesture mov ebx,OFFSET fortuneSessionDeal3D mov eax,fortunePhaseTime3D xor edx,edx mov ecx,32 div ecx cmp eax,31 jbe @F mov eax,31 @@: mov esi,eax jmp fortune_render_hands fortune_render_hand_gesture: mov ebx,OFFSET fortuneSessionGesture3D mov eax,fortunePhaseTime3D shr eax,5 and eax,31 mov esi,eax jmp fortune_render_hands fortune_render_orb_hands: mov ebx,OFFSET fortuneSessionOrbHands3D mov eax,fortunePhaseTime3D shr eax,5 and eax,31 mov esi,eax fortune_render_hands: invoke DrawAnimSprite3D,ebx,esi,134,32,280,250 cmp fortuneSubMode3D,FORTUNE_SUBMODE_MENU je fortune_render_menu cmp fortuneSubMode3D,FORTUNE_SUBMODE_ORB je fortune_render_orb cmp fortunePhase3D,0 je fortune_render_input invoke DrawAnimSprite3D,OFFSET fortuneSessionCards3D,44,142,300,30,40 xor esi,esi fortune_render_cards: invoke DrawFortuneSessionCard3D,esi cmp esi,fortuneRevealed3D jae @F mov eax,esi imul eax,100 add eax,198 invoke DrawBuckshotText3D,eax,288,fortuneRoleTexts3D[esi*4],00B9D4E7h @@: inc esi cmp esi,3 jb fortune_render_cards fortune_render_input: invoke DrawBoxBorder,8,199,304,24,00081322h,0046637Fh,1 mov fortuneCaretX3D,24 mov fortuneCaretY3D,402 invoke FortuneWrap3D,OFFSET fortuneQuestion3D,402,4,0,00E8EFF4h cmp fortunePhase3D,0 jne fortune_render_footer test animationClock3D,200h jnz fortune_render_footer invoke DrawBuckshotText3D,fortuneCaretX3D,fortuneCaretY3D,OFFSET fortuneCaret3D,00FFFFFFh jmp fortune_render_footer fortune_render_menu: invoke DrawBoxBorder,8,196,148,18,000D2136h,005D86A0h,1 invoke DrawBuckshotText3D,100,404,OFFSET fortuneTarot3D,00D2E8F2h invoke DrawBoxBorder,164,196,148,18,000D2136h,005D86A0h,1 invoke DrawBuckshotText3D,364,404,OFFSET fortuneFate3D,00D2E8F2h jmp fortune_render_footer fortune_render_orb: mov eax,fortunePhaseTime3D shr eax,6 and eax,15 mov esi,eax mov ebx,195 cmp fortunePhase3D,1 jne @F mov eax,fortunePhaseTime3D imul eax,135 xor edx,edx mov ecx,1400 div ecx mov ebx,330 sub ebx,eax @@: invoke DrawAnimSprite3D,OFFSET fortuneSessionMist3D,esi,214,ebx,128,128 fortune_render_footer: call DrawFortuneSpeech3D cmp fortuneSubMode3D,FORTUNE_SUBMODE_MENU je fortune_render_exit_button cmp fortuneSubMode3D,FORTUNE_SUBMODE_TAROT jne fortune_render_again_button invoke DrawBoxBorder,8,227,76,12,000B1E30h,00445F75h,1 mov esi,OFFSET fortuneAsk3D cmp fortunePhase3D,0 je @F mov esi,OFFSET fortuneContinue3D @@: invoke DrawBuckshotText3D,24,458,esi,00CCE4F4h fortune_render_again_button: invoke DrawBoxBorder,88,227,76,12,000B1E30h,00445F75h,1 invoke DrawBuckshotText3D,192,458,OFFSET fortuneAgain3D,0091A8BCh invoke DrawBoxBorder,172,227,64,12,000B1E30h,00445F75h,1 invoke DrawBuckshotText3D,368,458,OFFSET fortuneMenu3D,00CCE4F4h fortune_render_exit_button: invoke DrawBoxBorder,240,227,72,12,000B1E30h,00445F75h,1 invoke DrawBuckshotText3D,516,458,OFFSET fortuneExit3D,00CCE4F4h ret RenderFortuneDialog3D ENDP