Restore native inference, card-bound readings and paged dialogue. Provide manual, checksum-verified model setup instead of Git LFS so source checkouts work without uploading multi-gigabyte weights. The game stays offline; complete release archives still bundle the model.
399 lines
11 KiB
PHP
399 lines
11 KiB
PHP
; 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
|