VOGONS


Reply 20 of 34, by masterotaku

User metadata
Rank Newbie
Rank
Newbie

How about this?:

- The user runs a ".bat" script (that we could make).
- It asks the user for their desired width resolution, the user types it and presses enter.
- It asks the user for their desired height resolution, the user types it and presses enter.
- That resolution is written into the registry (https://docs.microsoft.com/en-us/windows-serv … mands/reg-query) (https://www.computing.net/answers/programming … bles/28873.html). "HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\LucasArts Entertainment Company LLC\Star Wars: Episode I Racer\v1.0", "Display Width" and "Display Height" but converted into hexadecimal.
- The aspect ratio of that resolution is saved into a variable, and then multiplied by 0.75. The resulting value is then used to patch "SWEP1RCR.EXE" (what would you use to do this?).
- If you want to go even further, the script could open my "d3dx.ini" if it exists and change the line starting by "z1=" into "z1=" plus the result of 1.333333/resolution aspect ratio. For example, for 2560x1440 it's 0.75, for 2560x720 it's 0.375, and for 2560x480 it's 0.25.

Testing those super wide resolutions made me notice two problems with the sun and lens flares:

1- My correction in the shader doesn't fix the occlusion caused by the sun being originally at a lower position at that aspect ratio. Meaning that if the sun is (wrongly) supposed to disappear because of some geometry, you may see it disappear in the sky for no reason. In triple monitor it's actually hard to see the sun at all in the first track.
2- With the fix I made to correct its Y axis position, I actually make the sun bigger than it should. Not very noticeable at 16:9, but it's very big at 48:9. If I correct the X axis instead, it has the correct size but it has a lower position as you know. Maybe I can correct its aspect ratio in the X axis (edit: I don't think so. It behaved in a weird way horizontally) and then move the effect up, but we still have problem number 1.

Other than these problems, the game looks nice at a very wide aspect ratio.

Reply 21 of 34, by CoolGamer

User metadata
Rank Member
Rank
Member
masterotaku wrote:

- The aspect ratio of that resolution is saved into a variable, and then multiplied by 0.75. The resulting value is then used to patch "SWEP1RCR.EXE" (what would you use to do this?).
- If you want to go even further, the script could open my "d3dx.ini" if it exists and change the line starting by "z1=" into "z1=" plus the result of 1.333333/resolution aspect ratio. For example, for 2560x1440 it's 0.75, for 2560x720 it's 0.375, and for 2560x480 it's 0.25.

Unfortunately I don't have the programming skills necessary to make a patcher. I can't do the steps that you outlined above. I can only make simple modifications using Ollydbg. I couldn't figure out how to do floating number division in assembly language. That's why I am not able to add assembly code to the EXE that calculates Aspect Ratio and FOV automatically.

In case somebody with good assembly skills want to pick up this issue, I summarized everything I figured out below. The modifications shown below set memory address 00DFB1F0 to 1.33333, which is 3FAAAAAB in hexadecimal representation. This is a static patch that only works for 16:9 resolutions.

Address	Original Value			            Changed Value
00483265 NOP MOV DWORD PTR DS:[ESI+44],3FAAAAAB
0048326C NOP MOV DWORD PTR DS:[ESI+48],EAX
0048326F NOP RETN
004832EE MOV DWORD PTR DS:[ESI+44],ECX CALL 00483265
004832F1 MOV DWORD PTR DS:[ESI+48],EAX (occupied as part of above instruction)
004832F3 (occupied as part of above) NOP

For a patch that calculates Aspect Ratio and FOV automatically, the following method can be used:

width = get from memory address 00EC8E10 (e.g. 1280 decimal represented in Hexadecimal)
height = get from memory address 00EC8E0C (e.g. 720 decimal represented in Hexadecimal)
AspectRatio = width/height = result will be a float represented in Hexadecimal
NewFOV = AspectRatio / 1.33333 = result will be a float represented in Hexadecimal
MOV DWORD PTR DS:[00DFB1F0],NewFOV

Of course this is easier said than done. I looked at youtube videos but I couldn't figure out how to do floating point division using assembly code. Finding space in the executable to insert that code is another issue. I would appreciate if someone with advanced assembly skills can help.

Until we get some help in assembly coding, CheatEngine seems to be the only option that works for everybody.

Reply 22 of 34, by Falcosoft

User metadata
Rank Oldbie
Rank
Oldbie
width = get from memory address 00EC8E10 (e.g. 1280 decimal represented in Hexadecimal) height = get from memory address 00EC8E0 […]
Show full quote

width = get from memory address 00EC8E10 (e.g. 1280 decimal represented in Hexadecimal)
height = get from memory address 00EC8E0C (e.g. 720 decimal represented in Hexadecimal)
AspectRatio = width/height = result will be a float represented in Hexadecimal
NewFOV = AspectRatio / 1.33333 = result will be a float represented in Hexadecimal
MOV DWORD PTR DS:[00DFB1F0],NewFOV

Of course this is easier said than done. I looked at youtube videos but I couldn't figure out how to do floating point division using assembly code

It's not too difficult but I do not know if you can have enough space to inject the code. I have tried to write a solution with as few instructions as possible. Also you will have to find a writable place in memory where you can store your '1.3333' constant (named 'Cnst_43' in code) since you cannot load arbitrary constants into the x87 FPU stack. You have to give a memory location instead:

 
MOV Cnst_43, 0x3faaa993 //Load 1.3333 float to a 32 bit memory location;
FILD width //Load the int width value to stack register ST(0)
FIDIV height //Divide ST(0) by int height value
FDIV Cnst_43 //now ST(0) stores the AspectRatio value, divide this by 1.3333
FSTP NewFOV //now ST(0) stores the final result, save it to NewFOV and pop ST(0) register.

Website, Facebook, Youtube
Falcosoft Soundfont Midi Player + Munt VSTi + BassMidi VSTi
VST Midi Driver Midi Mapper

Reply 23 of 34, by CoolGamer

User metadata
Rank Member
Rank
Member

Falcosoft, thank you so much for providing the floating point division code. I was easily able to patch the EXE using your instructions. I would not be able to do it without your help.

The patched EXEs for US CD version and GOG version (v1.0_hotfix3_20791) of the game are attached below. Remember to run the game EXE with -v switch to change game resolution before you play.

The following addresses were changed using OllyDbg to add automatic FOV Calculation. Game will look better on Widescreen monitors. The top and bottom of the screen will not be cut off. There will be more view on the sides.

ADDRESS    ORIGINAL VALUE                    CHANGED VALUE
004832EE MOV DWORD PTR DS:[ESI+44],ECX CALL 004AB750
004832F1 MOV DWORD PTR DS:[ESI+48],EAX (occupied as part of above instruction)
004832F3 (occupied as part of above) NOP
004AB750 DB 00 MOV DWORD PTR DS:[ESI+44],3FAAAAAB
004AB757 DB 00 FILD DWORD PTR DS:[00EC8E10]
004AB75D DB 00 FIDIV DWORD PTR DS:[00EC8E0C]
004AB763 DB 00 FDIV DWORD PTR DS:[ESI+44]
004AB766 DB 00 FSTP DWORD PTR DS:[ESI+44]
004AB769 DB 00 MOV DWORD PTR DS:[ESI+48],EAX
004AB76C DB 00 RETN
004AB76D DB 00 NOP

We still have the issue where the double Suns in the sky shift down a little (and become slightly oval) since they are drawn with the HUD, but we can use masterotaku's fix for those.

Please note that the shift in double suns is actually worse on vanilla GOG version (with widescreen resolutions) without this FOV calculation fix. This FOV fix is not causing any extra problems.

Attachments

Reply 24 of 34, by Falcosoft

User metadata
Rank Oldbie
Rank
Oldbie

Just a non-essential remark: a little more optimized code would be if instead of dividing by 1.33333 you would multiply by 0.75. I do not think performance is relevant here (multiplication is much faster than division) but it could give a little more precise result since contrary to 1.33333... 0.75 is not a repeating decimal. so:

 
MOV Cnst_34, 0x3f400000 //Load 0.75 float to a 32 bit memory location;
FILD width //Load the int width value to stack register ST(0)
FIDIV height //Divide ST(0) by int height value
FMUL Cnst_34 //now ST(0) stores the AspectRatio value, multiply this by 0.75
FSTP NewFOV //now ST(0) stores the final result, save it to NewFOV and pop ST(0) register.

Website, Facebook, Youtube
Falcosoft Soundfont Midi Player + Munt VSTi + BassMidi VSTi
VST Midi Driver Midi Mapper

Reply 25 of 34, by CoolGamer

User metadata
Rank Member
Rank
Member

I tested and compared both methods using cheat engine. It seems like we got lucky 😀. I agree that the multiplication method is more precise in theory but it does not make a difference in this case. The hexadecimal constant 3FAAAAAB that I used is 1.3333333 (7 decimal places), so in theory a division error might be 0.0000001 in some cases but that does not produce any visual difference in the game. In fact, we don't even see that error in most cases due to truncation. All 4:3 resolutions give a perfect 1.0 decimal FOV since truncation errors cancel out (1.3333333/1.3333333=1.0). Furthermore, many other widescreen resolutions that I tested produced identical FOVs up to 7 decimal places under both methods (due to truncation of the numbers after 7 decimal places). I actually could not find a resolution that produced 0.0000001 error in calculated FOV.

I will keep the same EXEs for now in order not to confuse people with a new revision. It does not make any visual difference. In the future if I make other modifications to the EXE, I might switch to multiplication method.

I think the best way to absolutely minimize any error (due to repeating numbers and truncations) should be doing two integer multiplications and only one integer division:
FOV = (width/height) / (640/480)= (width/height) / (4/3) = (width X 3) / (height x4)

numerator = width x 3          ;we are multiplying two integers here and the result is an integer.  No truncation or rounding errors.
denominator = height x 4 ;we are multiplying two integers here and the result is an integer. No truncation or rounding errors.
FOV = numerator/denominator ;we are dividing two integers here and the result is a float.

How can we implement this method in assembly?

Reply 26 of 34, by Falcosoft

User metadata
Rank Oldbie
Rank
Oldbie

How can we implement this method in assembly?

It can be something like this:

 
PUSH EAX // Save EAX to stack
MOV EAX, Width // Move Width to EAX
IMUL EAX, 3 // Multiply Width by 3 (use the sign extended byte opcode '6BC003' here, it's only 3 bytes)
MOV NewFOV, EAX // Move Width * 3 to NewFOV
FILD NewFOV // Load Width * 3 to ST(0)
MOV EAX, Height // Move Height to EAX
IMUL EAX, 4 // Multiply Height by 4 (use the sign extended byte opcode '6BC004' here, it's only 3 bytes)
MOV NewFOV, EAX // Move Height * 4 to NewFOV
FIDIV NewFOV // Divide Width * 3 in ST(0) by Height * 4 in NewFOV
FSTP NewFOV // Now ST(0) contains the final result, save it to NewFOV and pop ST(0)
POP EAX // Load EAX from stack

Since MUL (unsigned integer multiplication) has no 2/3 operand form where you can use a constant, IMUL (signed integer multiplication) is used instead. The PUSH EAX/POP EAX instructions at the begin/end are only necessary if EAX register contains useful data here, so the content should be preserved. You can also use another general purpose register (ECX, EDX, etc.) instead of EAX if it does not contain relevant data here. The memory location 'NewFov' is also used as a temporary place storing immediate results.

@Edit:
You can also use the 3 operand version of IMUL. This way you can save a few bytes:

 
PUSH EAX // Save EAX to stack
IMUL EAX, Width, 3 // Multiply Width by 3 and store result in EAX
MOV NewFOV, EAX // Move Width * 3 to NewFOV
FILD NewFOV // Load Width * 3 to ST(0)
IMUL EAX, Height, 4 // Multiply Height by 4 and store result in EAX
MOV NewFOV, EAX // Move Height * 4 to NewFOV
FIDIV NewFOV // Divide Width * 3 in ST(0) by Height * 4 in NewFOV
FSTP NewFOV // Now ST(0) contains the final result, save it to NewFOV and pop ST(0)
POP EAX // Load EAX from stack

Website, Facebook, Youtube
Falcosoft Soundfont Midi Player + Munt VSTi + BassMidi VSTi
VST Midi Driver Midi Mapper

Reply 27 of 34, by CoolGamer

User metadata
Rank Member
Rank
Member

Falcosoft, thanks for the code. In the future if I make other modifications to the EXE or get complaints about FOV precision, I can use this code.

I also added assembly integer multiplication to my skill set by looking at this example. Thanks again.

I have a general question. Do we have any risk of overwriting/loosing valuable data that is already in the stack when we use "PUSH EAX" and "POP EAX" commands? For example, if an earlier code pushed EAX or another general purpose register (ECX, EDX, etc.) to the stack.

ST(0) does not contain any data in the place where I injected the code. I verified that with OllyDbg debugger before I made the FOV patch. So the floating division did not have any adverse effects on ST(0). EAX does contain a saved value but I can check what it is and I can manually reset it to its original value after the FOV calculation is done, if necessary. If there is no risk of messing up the stack, POP/PUSH EAX is of course the most convenient option for me.

Reply 28 of 34, by Falcosoft

User metadata
Rank Oldbie
Rank
Oldbie
CoolGamer wrote:

I have a general question. Do we have any risk of overwriting/loosing valuable data that is already in the stack when we use "PUSH EAX" and "POP EAX" commands? For example, if an earlier code pushed EAX or another general purpose register (ECX, EDX, etc.) to the stack.

Generally no, since the x86 stack always 'grows' while there is enough memory. Then you will get a stack overflow that is basically a crash. In case of Win32 applications the typical stack size is at least 256K-1M so unless you use very deep call chains (recursion) or you use very big local variables stack size is not a problem. While you have enough memory you cannot 'overwrite data that is already in the stack' by using PUSH. x86 stack does not work this way, since it's a 'stack'. 😀 You can only write to the 'top of the stack' where the stack pointer points to by using PUSH (and it never overwrites the top element but adds another one to the top). And POP also always loads the data from the top of the stack.
https://en.wikipedia.org/wiki/Stack_(ab ... data_type)
https://eli.thegreenplace.net/2011/02/04/wher … stack-is-on-x86
https://en.wikipedia.org/wiki/Stack_overflow

I think your confusion partly can be attributed to the fact that the x87 also has a 'stack like' finite register set (that is there are only 8 x87 registers). So in the case of x87 stack registers pushing too many data can cause errors. But contrary to your intuition in case of an FLD x instruction (that loads data always to ST(0)) not ST(0) value would be lost but ST(7) value. It's because an FLD instruction moves the whole stack by 1, so the earlier ST(0) value will be in ST(1), ST(1) value will be in ST(2) and so on. Since there is no ST(8), in case ST(7) contains valid data you will get an error.
It's not a coincidence that you do not find a valid value in ST(0). Usually subroutines always clear the x87 register stack after floating point calculations (that's why we also use FSTP as the last instruction).

Contrary the x86 stack is not a finite register set but a continuous memory region. The rule you should follow is to use as many POP x in your routine as many PUSH x you have used so the stack pointer points to the same place as before your calculations.

Website, Facebook, Youtube
Falcosoft Soundfont Midi Player + Munt VSTi + BassMidi VSTi
VST Midi Driver Midi Mapper

Reply 30 of 34, by Manu270891

User metadata
Rank Newbie
Rank
Newbie
CoolGamer wrote:
Falcosoft, thank you so much for providing the floating point division code. I was easily able to patch the EXE using your inst […]
Show full quote

Falcosoft, thank you so much for providing the floating point division code. I was easily able to patch the EXE using your instructions. I would not be able to do it without your help.

The patched EXEs for US CD version and GOG version (v1.0_hotfix3_20791) of the game are attached below. Remember to run the game EXE with -v switch to change game resolution before you play.

The following addresses were changed using OllyDbg to add automatic FOV Calculation. Game will look better on Widescreen monitors. The top and bottom of the screen will not be cut off. There will be more view on the sides.

ADDRESS    ORIGINAL VALUE                    CHANGED VALUE
004832EE MOV DWORD PTR DS:[ESI+44],ECX CALL 004AB750
004832F1 MOV DWORD PTR DS:[ESI+48],EAX (occupied as part of above instruction)
004832F3 (occupied as part of above) NOP
004AB750 DB 00 MOV DWORD PTR DS:[ESI+44],3FAAAAAB
004AB757 DB 00 FILD DWORD PTR DS:[00EC8E10]
004AB75D DB 00 FIDIV DWORD PTR DS:[00EC8E0C]
004AB763 DB 00 FDIV DWORD PTR DS:[ESI+44]
004AB766 DB 00 FSTP DWORD PTR DS:[ESI+44]
004AB769 DB 00 MOV DWORD PTR DS:[ESI+48],EAX
004AB76C DB 00 RETN
004AB76D DB 00 NOP

We still have the issue where the double Suns in the sky shift down a little (and become slightly oval) since they are drawn with the HUD, but we can use masterotaku's fix for those.

Please note that the shift in double suns is actually worse on vanilla GOG version (with widescreen resolutions) without this FOV calculation fix. This FOV fix is not causing any extra problems.

This patch works perfectly on the GOG version! Unfortunately, it doesn't work on the spanish retail version because it uses a different .exe. I don't know how OllyDbg works, but could you patch the spanish exe the same way you did with the US/GOG exe? I can provide you the Spanish .exe.

Thank you so much!

Reply 31 of 34, by CoolGamer

User metadata
Rank Member
Rank
Member

Manu270891,

I apologize for the late reply. I recently saw your post and it took me a while to patch the international version because it uses different exe and memory addresses.

The patched EXE (resolution check removed, automatic FOV calculation added) for International CD versions of the Star Wars Racer game is attached below. I used the Official patched version from Lucas Arts FTP as the base. Remember to run the game EXE with -v switch to change the game resolution before you play.

This version should work with all International Retail CD versions such as Spanish, French, Italian, etc.

Attachments

Reply 32 of 34, by Manu270891

User metadata
Rank Newbie
Rank
Newbie
CoolGamer wrote on 2020-02-02, 18:48:
Manu270891, […]
Show full quote

Manu270891,

I apologize for the late reply. I recently saw your post and it took me a while to patch the international version because it uses different exe and memory addresses.

The patched EXE (resolution check removed, automatic FOV calculation added) for International CD versions of the Star Wars Racer game is attached below. I used the Official patched version from Lucas Arts FTP as the base. Remember to run the game EXE with -v switch to change the game resolution before you play.

This version should work with all International Retail CD versions such as Spanish, French, Italian, etc.

This fix works perfectly on the spanish retail version. Thank you so much!

Reply 33 of 34, by davidmorom

User metadata
Rank Newbie
Rank
Newbie

Hello everyone!

Is anyone still interested in this game? It's one of my favorite games from my childhood. I remember, like it was yesterday, playing with a 4MB S3 Virge/DX, at 512x384, glitched textures and about 5 fps. It was a pain, but I liked the game so much that I completed it this way. One year later I switched to a Voodoo 3 and it was like day and night.

Stories apart, some time ago I realised that on dgVoodoo 2.74.1 and later, the double cursor problem arises again, even with the SDB compatibility patch installed. I debugged it and discovered that, only when using dgVoodoo, the location where is the call to ShowCursor(0) function is never reached. Instead of trying to find the reason why (my debug capabilities are very limited), I remembered the CoolGamer FOV calculation patch, and reused the code injection method to make an unconditional call to ShowCursor(0). As this code is always executed, the cursor is always hidden, without needing any SDB patch.

The patch code for the international version of SWEP1RCR.EXE is the following:

ADDRESS    ORIGINAL VALUE                    CHANGED VALUE
004878DE MOV DWORD PTR DS:[ESI+44],ECX CALL 004AFD70
004878E1 MOV DWORD PTR DS:[ESI+48],EAX (occupied as part of above instruction)
004878E3 (occupied as part of above) NOP

004AFD70 DB 00 MOV DWORD PTR DS:[ESI+44],3FAAAAAB
004AFD77 DB 00 FILD DWORD PTR DS:[00ED2B10]
004AFD7D DB 00 FIDIV DWORD PTR DS:[00ED2B0C]
004AFD83 DB 00 FDIV DWORD PTR DS:[ESI+44]
004AFD86 DB 00 FSTP DWORD PTR DS:[ESI+44]
004AFD89 DB 00 MOV DWORD PTR DS:[ESI+48],EAX
004AFD8C DB 00 PUSHAD
004AFD8D DB 00 PUSH 0
004AFD8F DB 00 CALL DWORD PTR DS:[004B0228] -> &USER32.ShowCursor
004AFD95 DB 00 POPAD
004AFD96 DB 00 RET

After calculating the FOV, a call to USER32.ShowCursor is made, passing 0 as argument. The contents of the CPU registers are saved to the stack and restored with the PUSHAD/POPAD instructions, just in case they contain useful data. This patch can be ported easily to the original english version, and GOG version, just the pointer to the IAT entry of the function USER32.ShowCursor has to be resolved.

I attach the patched EXE for the international version. It has the resolution check, fov calculation, no-cd and cursor hide patches. I hope someone finds it useful.

Attachments

  • Filename
    SWEP1RCR.rar
    File size
    366.93 KiB
    Downloads
    180 downloads
    File license
    Fair use/fair dealing exception

Reply 34 of 34, by Famicom

User metadata
Rank Newbie
Rank
Newbie
CoolGamer wrote on 2018-06-12, 01:42:
Falcosoft, thank you so much for providing the floating point division code. I was easily able to patch the EXE using your inst […]
Show full quote

Falcosoft, thank you so much for providing the floating point division code. I was easily able to patch the EXE using your instructions. I would not be able to do it without your help.

The patched EXEs for US CD version and GOG version (v1.0_hotfix3_20791) of the game are attached below. Remember to run the game EXE with -v switch to change game resolution before you play.

The following addresses were changed using OllyDbg to add automatic FOV Calculation. Game will look better on Widescreen monitors. The top and bottom of the screen will not be cut off. There will be more view on the sides.

ADDRESS    ORIGINAL VALUE                    CHANGED VALUE
004832EE MOV DWORD PTR DS:[ESI+44],ECX CALL 004AB750
004832F1 MOV DWORD PTR DS:[ESI+48],EAX (occupied as part of above instruction)
004832F3 (occupied as part of above) NOP
004AB750 DB 00 MOV DWORD PTR DS:[ESI+44],3FAAAAAB
004AB757 DB 00 FILD DWORD PTR DS:[00EC8E10]
004AB75D DB 00 FIDIV DWORD PTR DS:[00EC8E0C]
004AB763 DB 00 FDIV DWORD PTR DS:[ESI+44]
004AB766 DB 00 FSTP DWORD PTR DS:[ESI+44]
004AB769 DB 00 MOV DWORD PTR DS:[ESI+48],EAX
004AB76C DB 00 RETN
004AB76D DB 00 NOP

We still have the issue where the double Suns in the sky shift down a little (and become slightly oval) since they are drawn with the HUD, but we can use masterotaku's fix for those.

Please note that the shift in double suns is actually worse on vanilla GOG version (with widescreen resolutions) without this FOV calculation fix. This FOV fix is not causing any extra problems.

davidmorom wrote on 2023-04-12, 20:35:
Hello everyone! […]
Show full quote

Hello everyone!

Is anyone still interested in this game? It's one of my favorite games from my childhood. I remember, like it was yesterday, playing with a 4MB S3 Virge/DX, at 512x384, glitched textures and about 5 fps. It was a pain, but I liked the game so much that I completed it this way. One year later I switched to a Voodoo 3 and it was like day and night.

Stories apart, some time ago I realised that on dgVoodoo 2.74.1 and later, the double cursor problem arises again, even with the SDB compatibility patch installed. I debugged it and discovered that, only when using dgVoodoo, the location where is the call to ShowCursor(0) function is never reached. Instead of trying to find the reason why (my debug capabilities are very limited), I remembered the CoolGamer FOV calculation patch, and reused the code injection method to make an unconditional call to ShowCursor(0). As this code is always executed, the cursor is always hidden, without needing any SDB patch.

The patch code for the international version of SWEP1RCR.EXE is the following:

ADDRESS    ORIGINAL VALUE                    CHANGED VALUE
004878DE MOV DWORD PTR DS:[ESI+44],ECX CALL 004AFD70
004878E1 MOV DWORD PTR DS:[ESI+48],EAX (occupied as part of above instruction)
004878E3 (occupied as part of above) NOP

004AFD70 DB 00 MOV DWORD PTR DS:[ESI+44],3FAAAAAB
004AFD77 DB 00 FILD DWORD PTR DS:[00ED2B10]
004AFD7D DB 00 FIDIV DWORD PTR DS:[00ED2B0C]
004AFD83 DB 00 FDIV DWORD PTR DS:[ESI+44]
004AFD86 DB 00 FSTP DWORD PTR DS:[ESI+44]
004AFD89 DB 00 MOV DWORD PTR DS:[ESI+48],EAX
004AFD8C DB 00 PUSHAD
004AFD8D DB 00 PUSH 0
004AFD8F DB 00 CALL DWORD PTR DS:[004B0228] -> &USER32.ShowCursor
004AFD95 DB 00 POPAD
004AFD96 DB 00 RET

After calculating the FOV, a call to USER32.ShowCursor is made, passing 0 as argument. The contents of the CPU registers are saved to the stack and restored with the PUSHAD/POPAD instructions, just in case they contain useful data. This patch can be ported easily to the original english version, and GOG version, just the pointer to the IAT entry of the function USER32.ShowCursor has to be resolved.

I attach the patched EXE for the international version. It has the resolution check, fov calculation, no-cd and cursor hide patches. I hope someone finds it useful.

Thank you all so much for this.

I'm using GOG's patched exe by Coolgamer. He says HUD and the sun is not corrected but "we can use masterotaku's fix for those". I have absolutely no technical knowledge whatsoever. I'm at a loss. I wish someone could tell me how to apply masterotaku's fix, particularly this part

press "8" (not numpad) to enable the HUD/sun fix after you've used CheatEngine for 16:9 mode (I've included a cheat table in the fix file

I have CheatEngine installed, followed the tutorial that comes with it, and then loaded masterotaku's cheat file. It shows a memory address (00DFB1F0) and a description (FOV), but I don't have a clue what to do with any of those. If someone could lend me a hand if would make me a happy man.