; Existing signed saves are imported read-only. New writes stay in runtime/profiles. BuildNativeProfileDir3D PROC invoke CopyCString, OFFSET saveDirPath, nativeProfilesDirPtr3D ret BuildNativeProfileDir3D ENDP ValidateGraphicProfile3D PROC uses ebx esi edi path:DWORD local io:DWORD,fileBytes:DWORD,signature:DWORD invoke CreateFileA, path, 80000000h, 1, 0, 3, 80h, 0 cmp eax, -1 je profile_invalid mov ebx, eax invoke GetFileSize, ebx, 0 mov fileBytes, eax cmp eax, 32 jb profile_close_invalid cmp eax, SAVE_FILE_SIZE ja profile_close_invalid invoke ReadFile, ebx, OFFSET entrySaveData3D, SAVE_FILE_SIZE, ADDR io, 0 test eax, eax jz profile_close_invalid invoke CloseHandle, ebx mov eax, fileBytes cmp eax, io jne profile_invalid cmp DWORD PTR entrySaveData3D, SAVE_MAGIC jne profile_invalid cmp DWORD PTR entrySaveData3D[4], 1000000000 ja profile_invalid cmp fileBytes, SAVE_FILE_SIZE jb profile_valid mov esi, OFFSET entrySaveData3D mov ecx, SAVE_SIGN_SIZE/4 mov eax, SAVE_SALT profile_signature: rol eax, 5 xor eax, [esi] mov edx, eax shr edx, 16 xor eax, edx add eax, 9E3779B9h add esi, 4 loop profile_signature cmp eax, DWORD PTR entrySaveData3D[SAVE_SIGN_SIZE] jne profile_invalid profile_valid: mov eax, 1 ret profile_close_invalid: invoke CloseHandle, ebx profile_invalid: xor eax, eax ret ValidateGraphicProfile3D ENDP ScanGraphicProfiles3D PROC uses ebx esi edi local index:DWORD invoke CopyCString, OFFSET entryPattern3D, OFFSET entryScanDir3D invoke AppendCString, OFFSET entryPattern3D, OFFSET entryWildcard3D invoke FindFirstFileA, OFFSET entryPattern3D, OFFSET entryFindData3D cmp eax, -1 je profile_scan_done mov ebx, eax profile_scan_next: cmp entryAccountCount3D, 20 jae profile_scan_close test DWORD PTR entryFindData3D, 10h jnz profile_scan_advance ; Restrict account stems to the same safe alphabet as account creation. mov esi, OFFSET entryFindData3D+44 xor ecx, ecx profile_scan_name: mov al, [esi+ecx] cmp al, '.' je profile_scan_extension cmp ecx, 50 jae profile_scan_advance cmp al, '0' jb profile_scan_letter cmp al, '9' jbe profile_scan_char_ok profile_scan_letter: or al, 20h cmp al, 'a' jb profile_scan_symbol cmp al, 'z' jbe profile_scan_char_ok profile_scan_symbol: mov al, [esi+ecx] cmp al, '_' je profile_scan_char_ok cmp al, '-' jne profile_scan_advance profile_scan_char_ok: inc ecx jmp profile_scan_name profile_scan_extension: test ecx, ecx jz profile_scan_advance lea eax, [esi+ecx] invoke lstrcmpiA, eax, OFFSET entryDat3D test eax, eax jnz profile_scan_advance mov index, 0 profile_scan_duplicate: mov eax, index cmp eax, entryAccountCount3D jae profile_scan_validate shl eax, 6 add eax, OFFSET entryAccountNames3D invoke lstrcmpiA, eax, esi test eax, eax jz profile_scan_advance inc index jmp profile_scan_duplicate profile_scan_validate: invoke CopyCString, OFFSET entryScanPath3D, OFFSET entryScanDir3D invoke AppendCString, OFFSET entryScanPath3D, OFFSET pathSlashText invoke AppendCString, OFFSET entryScanPath3D, esi invoke ValidateGraphicProfile3D, OFFSET entryScanPath3D test eax, eax jz profile_scan_advance mov eax, entryAccountCount3D mov edx, DWORD PTR entrySaveData3D[4] mov entryAccountBanks3D[eax*4], edx shl eax, 6 add eax, OFFSET entryAccountNames3D invoke CopyCString, eax, esi mov eax, entryAccountCount3D imul eax, 260 add eax, OFFSET entryAccountPaths3D invoke CopyCString, eax, OFFSET entryScanPath3D inc entryAccountCount3D profile_scan_advance: invoke FindNextFileA, ebx, OFFSET entryFindData3D test eax, eax jnz profile_scan_next profile_scan_close: invoke FindClose, ebx profile_scan_done: ret ScanGraphicProfiles3D ENDP CollectGraphicProfiles3D PROC mov entryAccountCount3D, 0 invoke CopyCString, OFFSET entryScanDir3D, nativeProfilesDirPtr3D call ScanGraphicProfiles3D ; Do not call BuildAppDataDir here: discovery must not create outside folders. invoke GetEnvironmentVariableA, OFFSET appDataEnvName, OFFSET entryScanDir3D, 220 test eax, eax jz profiles_workspace cmp eax, 220 jae profiles_workspace invoke AppendCString, OFFSET entryScanDir3D, OFFSET appDataSubDir call ScanGraphicProfiles3D profiles_workspace: invoke CopyCString, OFFSET entryScanDir3D, OFFSET entryLocalRoot3D call ScanGraphicProfiles3D ret CollectGraphicProfiles3D ENDP SyncGraphicBack3D PROC mov eax, shopBackOwned and eax, 1FFFh or eax, 1 mov ownedBacks3D, eax mov ecx, shopBackStyle cmp ecx, 12 ja graphic_back_default bt eax, ecx jnc graphic_back_default mov selectedBack3D, ecx ret graphic_back_default: mov selectedBack3D, 0 ret SyncGraphicBack3D ENDP SelectGraphicProfile3D PROC uses ebx esi index:DWORD mov eax, index cmp eax, entryAccountCount3D jae graphic_select_fail mov ebx, eax imul eax, 260 add eax, OFFSET entryAccountPaths3D mov esi, eax invoke ValidateGraphicProfile3D, esi test eax, eax jz graphic_select_fail shl ebx, 6 add ebx, OFFSET entryAccountNames3D invoke CopyCString, OFFSET entryFindPath3D, nativeProfilesDirPtr3D invoke AppendCString, OFFSET entryFindPath3D, OFFSET pathSlashText invoke AppendCString, OFFSET entryFindPath3D, ebx invoke lstrcmpiA, esi, OFFSET entryFindPath3D test eax, eax jz graphic_select_load invoke CreateDirectoryA, OFFSET runtime3D, 0 invoke CreateDirectoryA, nativeProfilesDirPtr3D, 0 invoke CopyFileA, esi, OFFSET entryFindPath3D, 1 test eax, eax jz graphic_select_fail graphic_select_load: invoke ValidateGraphicProfile3D, OFFSET entryFindPath3D test eax, eax jz graphic_select_fail call ResetProfileDefaults invoke CopyCString, OFFSET saveFileName, ebx mov nativeProfileActive3D, 1 call LoadSave call SyncGraphicBack3D call ApplySoundVolume mov eax, 1 ret graphic_select_fail: xor eax, eax ret SelectGraphicProfile3D ENDP CreateGraphicProfile3D PROC uses ebx local previousBank:DWORD,previousOwned:DWORD,previousBack:DWORD cmp arrivalNameLength3D, 0 je graphic_create_fail invoke CopyCString, OFFSET entryFindPath3D, nativeProfilesDirPtr3D invoke AppendCString, OFFSET entryFindPath3D, OFFSET pathSlashText invoke AppendCString, OFFSET entryFindPath3D, OFFSET arrivalName3D invoke AppendCString, OFFSET entryFindPath3D, OFFSET entryDat3D invoke GetFileAttributesA, OFFSET entryFindPath3D cmp eax, -1 jne graphic_create_fail ; Also reject a name present in the imported guest list. invoke CopyCString, OFFSET entryDisplayName3D, OFFSET arrivalName3D invoke AppendCString, OFFSET entryDisplayName3D, OFFSET entryDat3D xor ebx, ebx graphic_create_duplicate: cmp ebx, entryAccountCount3D jae graphic_create_store mov eax, ebx shl eax, 6 add eax, OFFSET entryAccountNames3D invoke lstrcmpiA, eax, OFFSET entryDisplayName3D test eax, eax jz graphic_create_fail inc ebx jmp graphic_create_duplicate graphic_create_store: mov eax, bankroll mov previousBank, eax mov eax, ownedBacks3D mov previousOwned, eax mov eax, selectedBack3D mov previousBack, eax invoke CreateDirectoryA, OFFSET runtime3D, 0 invoke CreateDirectoryA, nativeProfilesDirPtr3D, 0 call ResetProfileDefaults invoke CopyCString, OFFSET saveFileName, OFFSET entryDisplayName3D mov nativeProfileActive3D, 1 call SyncGraphicBack3D call SaveGame call ApplySoundVolume invoke ValidateGraphicProfile3D, OFFSET entryFindPath3D test eax, eax jnz @F mov nativeProfileActive3D, 0 mov eax, previousBank mov bankroll, eax mov eax, previousOwned mov ownedBacks3D, eax mov eax, previousBack mov selectedBack3D, eax ret @@: mov eax, 1 ret graphic_create_fail: xor eax, eax ret CreateGraphicProfile3D ENDP SaveGraphicProfile3D PROC mov eax, ownedBacks3D mov shopBackOwned, eax mov eax, selectedBack3D mov shopBackStyle, eax call SaveGame ret SaveGraphicProfile3D ENDP