; Anonymous pipes only. Polling never waits for model inference or partial frames. CloseFortuneInference3D PROC uses esi cmp fortuneProcess3D,0 je @F invoke TerminateProcess,fortuneProcess3D,0 invoke CloseHandle,fortuneProcess3D @@: mov fortuneProcess3D,0 cmp fortuneProcess3D[4],0 je @F invoke CloseHandle,fortuneProcess3D[4] @@: mov fortuneProcess3D[4],0 mov fortuneProcess3D[8],0 mov fortuneProcess3D[12],0 cmp fortuneRead3D,0 je @F invoke CloseHandle,fortuneRead3D @@: mov fortuneRead3D,0 cmp fortuneWrite3D,0 je @F invoke CloseHandle,fortuneWrite3D @@: mov fortuneWrite3D,0 lea esi,fortuneChildRead3D mov ecx,3 fortune_ai_close_child: push ecx cmp DWORD PTR [esi],0 je @F invoke CloseHandle,DWORD PTR [esi] @@: mov DWORD PTR [esi],0 add esi,4 pop ecx loop fortune_ai_close_child mov fortuneReceiveLength3D,-1 mov fortunePending3D,0 mov fortuneWorkerState3D,0 mov fortuneReadingShown3D,0 mov fortuneReadingOffset3D,0 mov fortuneReadingNext3D,0 mov fortuneAnswerLength3D,0 mov fortuneAnswer3D,0 mov fortuneSections3D,0 mov fortuneSections3D[4],0 mov fortuneSections3D[8],0 mov fortuneSections3D[12],0 ret CloseFortuneInference3D ENDP FailFortuneInference3D PROC call CloseFortuneInference3D mov fortuneWorkerState3D,4 mov fortuneErrorText3D,OFFSET fortuneAiError3D mov fortuneAnswerLength3D,0 mov fortuneAnswer3D,0 invoke SetFortuneSpeech3D,OFFSET fortuneAiError3D ret FailFortuneInference3D ENDP StartFortuneWorker3D PROC uses edi call CloseFortuneInference3D mov fortuneAnswerLength3D,0 mov fortuneAnswer3D,0 mov fortuneReadingShown3D,0 ; Fail immediately and visibly when a source checkout lacks bundled weights. invoke CreateFileA,OFFSET fortuneModelPath3D,80000000h,1,0,3,80h,0 cmp eax,-1 jne @F mov fortuneWorkerState3D,4 mov fortuneErrorText3D,OFFSET fortuneAiMissing3D invoke SetFortuneSpeech3D,OFFSET fortuneAiMissing3D ret @@: invoke CloseHandle,eax invoke CreatePipe,OFFSET fortuneChildRead3D,OFFSET fortuneWrite3D,OFFSET fortunePipeSecurity3D,16384 test eax,eax jz fortune_ai_start_fail invoke SetHandleInformation,fortuneWrite3D,1,0 test eax,eax jz fortune_ai_start_fail invoke CreatePipe,OFFSET fortuneRead3D,OFFSET fortuneChildWrite3D,OFFSET fortunePipeSecurity3D,16384 test eax,eax jz fortune_ai_start_fail invoke SetHandleInformation,fortuneRead3D,1,0 test eax,eax jz fortune_ai_start_fail invoke CreateFileA,OFFSET fortuneNullName3D,40000000h,3,OFFSET fortunePipeSecurity3D,3,80h,0 cmp eax,-1 je fortune_ai_start_fail mov fortuneNull3D,eax lea edi,fortuneStartup3D xor eax,eax mov ecx,17 rep stosd mov fortuneStartup3D,68 mov fortuneStartup3D[44],100h mov eax,fortuneChildRead3D mov fortuneStartup3D[56],eax mov eax,fortuneChildWrite3D mov fortuneStartup3D[60],eax mov eax,fortuneNull3D mov fortuneStartup3D[64],eax invoke CreateProcessA,OFFSET fortuneWorkerPath3D,OFFSET fortuneWorkerCommand3D,0,0,1,08000000h,0,0,OFFSET fortuneStartup3D,OFFSET fortuneProcess3D test eax,eax jz fortune_ai_start_fail invoke CloseHandle,fortuneProcess3D[4] mov fortuneProcess3D[4],0 invoke CloseHandle,fortuneChildRead3D mov fortuneChildRead3D,0 invoke CloseHandle,fortuneChildWrite3D mov fortuneChildWrite3D,0 invoke CloseHandle,fortuneNull3D mov fortuneNull3D,0 mov fortuneWorkerState3D,1 mov fortunePending3D,1 invoke GetTickCount mov fortuneWorkerTick3D,eax ret fortune_ai_start_fail: call FailFortuneInference3D ret StartFortuneWorker3D ENDP SendFortuneRequest3D PROC uses esi mov fortuneRequest3D,31514346h mov eax,fortuneQuestionLength3D mov fortuneRequest3D[4],eax xor esi,esi fortune_ai_request_cards: mov eax,fortuneDrawCards3D[esi*4] mov fortuneRequest3D[esi*4+8],eax inc esi cmp esi,3 jb fortune_ai_request_cards invoke WriteFile,fortuneWrite3D,OFFSET fortuneRequest3D,20,OFFSET fortuneIo3D,0 test eax,eax jz fortune_ai_send_fail cmp fortuneIo3D,20 jne fortune_ai_send_fail invoke WriteFile,fortuneWrite3D,OFFSET fortuneQuestion3D,fortuneQuestionLength3D,OFFSET fortuneIo3D,0 test eax,eax jz fortune_ai_send_fail mov eax,fortuneQuestionLength3D cmp fortuneIo3D,eax jne fortune_ai_send_fail mov fortuneWorkerState3D,3 mov fortunePending3D,0 invoke GetTickCount mov fortuneWorkerTick3D,eax ret fortune_ai_send_fail: call FailFortuneInference3D ret SendFortuneRequest3D ENDP PollFortuneWorker3D PROC cmp fortuneWorkerState3D,1 je fortune_ai_poll cmp fortuneWorkerState3D,3 jne fortune_ai_poll_done fortune_ai_poll: invoke PeekNamedPipe,fortuneRead3D,0,0,0,OFFSET fortuneAvailable3D,0 test eax,eax jz fortune_ai_poll_fail cmp fortuneReceiveLength3D,-1 jne fortune_ai_poll_body cmp fortuneAvailable3D,12 jb fortune_ai_poll_timeout invoke ReadFile,fortuneRead3D,OFFSET fortuneReceiveHeader3D,12,OFFSET fortuneIo3D,0 test eax,eax jz fortune_ai_poll_fail cmp fortuneIo3D,12 jne fortune_ai_poll_fail cmp fortuneReceiveHeader3D,31524346h jne fortune_ai_poll_fail mov eax,fortuneReceiveHeader3D[8] cmp eax,8192 ja fortune_ai_poll_fail mov fortuneReceiveLength3D,eax sub fortuneAvailable3D,12 fortune_ai_poll_body: mov eax,fortuneReceiveLength3D cmp fortuneAvailable3D,eax jb fortune_ai_poll_timeout test eax,eax jz fortune_ai_poll_status invoke ReadFile,fortuneRead3D,OFFSET fortuneAnswer3D,eax,OFFSET fortuneIo3D,0 test eax,eax jz fortune_ai_poll_fail mov eax,fortuneReceiveLength3D cmp fortuneIo3D,eax jne fortune_ai_poll_fail fortune_ai_poll_status: mov eax,fortuneReceiveLength3D mov fortuneAnswer3D[eax],0 mov fortuneAnswerLength3D,eax mov fortuneReceiveLength3D,-1 cmp fortuneWorkerState3D,1 jne fortune_ai_poll_answer cmp fortuneReceiveHeader3D[4],0 jne fortune_ai_poll_fail test eax,eax jnz fortune_ai_poll_fail cmp fortunePending3D,1 jne fortune_ai_poll_fail call SendFortuneRequest3D ret fortune_ai_poll_answer: ; Truncated output is an error, never a successful complete reading. cmp fortuneReceiveHeader3D[4],1 jne fortune_ai_poll_fail call ParseFortuneAnswer3D test eax,eax jz fortune_ai_poll_fail mov fortuneWorkerState3D,5 ret fortune_ai_poll_timeout: invoke GetTickCount sub eax,fortuneWorkerTick3D cmp eax,180000 jae fortune_ai_poll_fail ret fortune_ai_poll_fail: call FailFortuneInference3D fortune_ai_poll_done: ret PollFortuneWorker3D ENDP ; Four bounded, nonempty lines: one interpretation per card, then synthesis. ParseFortuneAnswer3D PROC uses ebx esi edi mov eax,fortuneAnswerLength3D test eax,eax jz fortune_ai_parse_fail cmp eax,8192 ja fortune_ai_parse_fail mov fortuneAnswer3D[eax],0 lea esi,fortuneAnswer3D lea edi,fortuneSections3D mov [edi],esi mov ebx,1 xor ecx,ecx fortune_ai_parse_byte: cmp ecx,fortuneAnswerLength3D jae fortune_ai_parse_end mov al,[esi+ecx] test al,al jz fortune_ai_parse_fail cmp al,10 jne fortune_ai_parse_next cmp ebx,4 jae fortune_ai_parse_fail test ecx,ecx jz fortune_ai_parse_fail cmp BYTE PTR [esi+ecx-1],0 je fortune_ai_parse_fail mov BYTE PTR [esi+ecx],0 lea eax,[esi+ecx+1] mov [edi+ebx*4],eax inc ebx fortune_ai_parse_next: inc ecx jmp fortune_ai_parse_byte fortune_ai_parse_end: cmp ebx,4 jne fortune_ai_parse_fail mov eax,[edi+12] cmp BYTE PTR [eax],0 je fortune_ai_parse_fail mov eax,1 ret fortune_ai_parse_fail: xor eax,eax ret ParseFortuneAnswer3D ENDP ; Pages stay inside the existing 23-column, ten-row speech bubble. ShowFortuneReading3D PROC uses ebx esi edi section:DWORD local column:DWORD,row:DWORD,wordLength:DWORD mov eax,section cmp eax,3 ja fortune_ai_show_done mov fortuneSection3D,eax mov esi,fortuneSections3D[eax*4] test esi,esi jz fortune_ai_show_done add esi,fortuneReadingOffset3D lea edi,fortuneSpeech3D xor ecx,ecx mov column,0 mov row,0 fortune_ai_page_word: mov al,[esi] test al,al jz fortune_ai_page_end cmp al,32 jne fortune_ai_word_measure inc esi jmp fortune_ai_page_word fortune_ai_word_measure: xor ebx,ebx fortune_ai_word_scan: mov al,[esi+ebx] test al,al jz fortune_ai_word_measured cmp al,32 je fortune_ai_word_measured inc ebx jmp fortune_ai_word_scan fortune_ai_word_measured: mov wordLength,ebx cmp column,23 jne @F cmp row,8 jae fortune_ai_page_split inc row mov column,0 @@: cmp column,0 je fortune_ai_word_copy mov eax,column add eax,ebx inc eax cmp eax,23 jbe fortune_ai_word_space cmp row,8 jae fortune_ai_page_split mov BYTE PTR [edi+ecx],10 inc ecx inc row mov column,0 jmp fortune_ai_word_copy fortune_ai_word_space: mov BYTE PTR [edi+ecx],32 inc ecx inc column fortune_ai_word_copy: cmp wordLength,0 je fortune_ai_page_word cmp column,23 jb fortune_ai_word_character ; The renderer already wraps a full 23-column line. No extra newline. cmp row,8 jae fortune_ai_page_split inc row mov column,0 fortune_ai_word_character: mov al,[esi] mov [edi+ecx],al inc esi inc ecx inc column dec wordLength jmp fortune_ai_word_copy fortune_ai_page_split: mov eax,section mov eax,fortuneSections3D[eax*4] neg eax add eax,esi mov fortuneReadingNext3D,eax jmp fortune_ai_page_ready fortune_ai_page_end: mov fortuneReadingNext3D,0 fortune_ai_page_ready: mov BYTE PTR [edi+ecx],0 mov fortuneSpeechLength3D,ecx mov fortuneSpeechTime3D,0 mov fortuneSpeechVisible3D,0 mov fortunePhaseTime3D,0 mov fortuneReadingShown3D,1 fortune_ai_show_done: ret ShowFortuneReading3D ENDP ShowFortuneStatus3D PROC cmp fortuneWorkerState3D,4 jne fortune_ai_status_wait invoke SetFortuneSpeech3D,fortuneErrorText3D ret fortune_ai_status_wait: invoke SetFortuneSpeech3D,OFFSET fortuneAiThinking3D ret ShowFortuneStatus3D ENDP AdvanceFortuneReading3D PROC cmp fortuneReadingNext3D,0 je fortune_ai_advance_phase mov eax,fortuneReadingNext3D mov fortuneReadingOffset3D,eax invoke ShowFortuneReading3D,fortuneSection3D ret fortune_ai_advance_phase: mov fortuneReadingShown3D,2 mov fortuneReadingOffset3D,0 mov fortunePhaseTime3D,7FFFFFFFh ret AdvanceFortuneReading3D ENDP