[Bug 21924] Interstate '76 Arsenal crashes (privileged instructions used in attempt to measure the CPU speed)

wine-bugs at winehq.org wine-bugs at winehq.org
Sun Oct 6 17:33:02 CDT 2013


http://bugs.winehq.org/show_bug.cgi?id=21924

Anastasius Focht <focht at gmx.net> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |focht at gmx.net
            Summary|Interstate '76 Arsenal      |Interstate '76 Arsenal
                   |crashes                     |crashes (privileged
                   |                            |instructions used in
                   |                            |attempt to measure the CPU
                   |                            |speed)

--- Comment #5 from Anastasius Focht <focht at gmx.net> 2013-10-06 17:33:02 CDT ---
Hello folks,

bought the game just for analysis ... confirming.
In short: the game contains a small code snippet that is incompatible with
modern Windows NT-based operating systems.

The game calls GetSystemInfo() to retrieve system information:

--- snip ---
...
0049995A  50             PUSH EAX            ; pSysteminfo
0049995B  FF15 24C14B00  CALL DWORD PTR DS:[<KERNEL32.GetSystemInfo>]
...
--- snip ---

Dump of returned structure:

--- snip ---
Structure SYSTEM_INFO at 0033F33C

0033F33C  .0000        DW 0  ; Architecture = PROCESSOR_ARCHITECTURE_INTEL
0033F33E  .0000        DW 0         ; Reserved = 0
0033F340  .00100000    DD 00001000  ; PageSize = 4096.
0033F344  .00000100    DD 00010000  ; MinimumAppAddress = 10000
0033F348  .FFFFFE7F    DD 7FFEFFFF  ; MaximumAppAddress = 7FFEFFFF
0033F34C  .0F000000    DD 0000000F  ; ActiveProcessorMask = 0F
0033F350  .04000000    DD 00000004  ; NumberOfProcessors = 4
0033F354  .4A020000    DD 0000024A  ; ProcessorType = PROCESSOR_INTEL_PENTIUM
0033F358  .00000100    DD 00010000  ; AllocationGranularity = 65536.
0033F35C  .0600        DW 6         ; ProcessorLevel = 6
0033F35E  .0525        DW 2505      ; ProcessorRevision = 9477.
--- snip ---

"ProcessorType" member is evaluated for i386/i486 and pentium class processors:

--- snip ---
00499961  8B45 F0        MOV EAX,DWORD PTR SS:[EBP-10h] ; ProcessorType
00499964  2D 82010000    SUB EAX,182         ; switch (cases 182..24A)
00499969  74 18          JZ SHORT 00499983
0049996B  83E8 64        SUB EAX,64
0049996E  74 0C          JZ SHORT 0049997C
00499970  83E8 64        SUB EAX,64
00499973  75 6B          JNZ SHORT 004999E0
00499975  BE 05000000    MOV ESI,5           ; case 24A of switch 00499964
0049997A  EB 0C          JMP SHORT 00499988
0049997C  BE 04000000    MOV ESI,4           ; case 1E6 of switch 00499964
00499981  EB 05          JMP SHORT 00499988
00499983  BE 03000000    MOV ESI,3           ; case 182 of switch 00499964
00499988  83FE 03        CMP ESI,3
0049998B  73 0A          JAE SHORT 00499997
0049998D  B8 66FDFFFF    MOV EAX,-29A        ; not i386/i486/i586
00499992  5E             POP ESI
00499993  8BE5           MOV ESP,EBP
00499995  5D             POP EBP
00499996  C3             RETN
--- snip ---

Upon match the following code ought to be run:

--- snip ---
00499997  FA             CLI
00499998  B0 B8          MOV AL,0B8
0049999A  E6 43          OUT 43,AL
0049999C  E4 61          IN AL,61
0049999E  0C 01          OR AL,01
004999A0  E6 61          OUT 61,AL
004999A2  32C0           XOR AL,AL
004999A4  E6 42          OUT 42,AL
004999A6  E6 42          OUT 42,AL
004999A8  B8 00000080    MOV EAX,80000000
004999AD  66:BA 5000     MOV DX,50
004999B1  0FBCC8         BSF ECX,EAX
004999B4  66:4A          DEC DX
004999B6  66:83FA 01     CMP DX,1
004999BA  7D F5          JGE SHORT 004999B1
004999BC  E4 42          IN AL,42
004999BE  8AE0           MOV AH,AL
004999C0  E4 42          IN AL,42
004999C2  86C4           XCHG AH,AL
004999C4  66:F7D8        NEG AX
004999C7  66:8945 FC     MOV WORD PTR SS:[EBP-4],AX
004999CB  FB             STI
004999CC  66:8B0475 40E2 MOV AX,WORD PTR DS:[ESI*2+4FE240]
004999D4  8B4D FC        MOV ECX,DWORD PTR SS:[EBP-4]
004999D7  66:6BC0 50     IMUL AX,AX,50
004999DB  66:85C9        TEST CX,CX
004999DE  75 08          JNZ SHORT 004999E8
004999E0  83C8 FF        OR EAX,FFFFFFFF
004999E3  5E             POP ESI
004999E4  8BE5           MOV ESP,EBP
004999E6  5D             POP EBP
004999E7  C3             RETN
...
---- snip ---

*Eeeekkk*

That's an ancient way to determine CPU speed using PIT (Intel 8253 programmable
interval timer, 16-Bit).
The whole sequence contains several instructions that can't be executed in user
mode on modern operating systems.

For example "cli" will always raise a "privileged instruction" exception in
user mode when executed on Windows NT based systems.

In Windows 95, executing "cli" instruction in user mode generates a general
protection fault which is transparently handled by the OS, eventually giving
the same result (IF cleared) as a regular "cli".

Interestingly the comment section for this game on GOG.com shares some opinion
(most likely related to other issues):

--- quote ---
However this game is not properly compatible with modern systems! There are
tons of bugs which the community has had to fix! This wasn't really what I
hoped from GoG and seriously damages their reputation for games that work on
modern PC's. I was considering gifting this game to my friends but I can't
really give them a game in this state. The game is easily 5 stars but minus 3
stars for the trouble trying to get the game to work properly! :P
--- quote ---

The game executable "i76.exe" is from year 2009 so it was likely recompiled.
I wonder why GOG.com or the contractor who prepared the game did not remove
this brain damaged ancient code to allow running on NT based systems.

I made a short workaround patch which allows to run the game in any WinVer mode
in Wine:

--- snip ---
$ printf '\xEB\x22' | dd of=i76.exe bs=1 seek=626025 count=2 conv=notrunc
--- snip ---

What does it do?

It changes the opcode 0x74,0x18 (jz short 00499983) at file offset 0x98D69 to
0xEB,0x22 (jmp short 0049998D), avoiding the incompatible code.

I tested this only on the executable from GOG.com:

--- snip ---
$ pwd
/home/focht/.wine/drive_c/Program Files/GOG.com/Interstate 76
Arsenal/interstate 76

$ du -sh i76.exe 
1.1M    i76.exe

$ sha1sum i76.exe 
0d21c35d6b4f81f645f14c345dcbe7f33b2cfdc5  i76.exe
--- snip ---

There is also an "Interstate 76 Nitro" pack included in the download.
The executable for this pack has the same problem, hence I present another
patch:

--- snip ---
$ printf '\xEB\x22' | dd of=nitro.exe bs=1 seek=630921 count=2 conv=notrunc
--- snip ---

--- snip ---
$ pwd
/home/focht/.wine/drive_c/Program Files/GOG.com/Interstate 76
Arsenal/Interstate 76 Nitro Pack

$ du -sh nitro.exe
1.1M    nitro.exe

$ sha1sum nitro.exe
753a73a205f7f8d973f452e5ec2c90f5f5b2c34b  nitro.exe
--- snip ---

Download from GOG.com:

$ du -sh setup_interstate76_arsenal.exe 
592M    setup_interstate76_arsenal.exe

$ sha1sum setup_interstate76_arsenal.exe 
21671fbd8dce7d573095fda2612133bb24128bd8  setup_interstate76_arsenal.exe

$ wine --version
wine-1.7.3-231-g264e27b

If you have a different version, exhibiting the same issues, it should fairly
easy to find the place where to patch the executable.

==

In general: That game will most likely only run in Win9X compat mode on Windows
NT systems.
I wonder how/if they did a full Intel 8253 emulation to allow this code to work
or if they just cheat with an application shim, having GetSystemInfo() _not_
returning i386/i486/i585 to avoid the critical code path.

Regards

-- 
Configure bugmail: http://bugs.winehq.org/userprefs.cgi?tab=email
Do not reply to this email, post in Bugzilla using the
above URL to reply.
------- You are receiving this mail because: -------
You are watching all bug changes.



More information about the wine-bugs mailing list