For Anstoss 2 Gold · Original, GOG & 2007 CD

Anstoss 2 Gold,
the way it should be.

One small window, a few ticks: the arrow buttons keep counting, the World Cup, European Championship and final videos no longer crash the game, nothing freezes after Windows has run for weeks, the sound comes out of the right device, and if you like, the goal limits are lifted. The GOG and 2007 releases also get patch 1.01, the GOG release gets its dialogs back, and its copy protection no longer turns your save into a “Raubkopie” (pirated copy). No compatibility mode needed, and every change can be taken back.

Windows XP (SP3) to 11 · .NET Framework 4.0 or later · GPL-3.0 · user interface in German, like the game

The A2G-Patch window: game folder selection and one tick box per patch

01The patches

Bug fix

Arrows keep counting while held down

On current Windows, the arrow buttons for numeric values count one or two steps and then stop. Until now the only cure was the “Windows 98” compatibility mode. With the patch they simply keep counting.

Bug fix

No crash on the World Cup, European Championship and final videos

After winning the World Cup the game crashes, because Windows no longer knows the video format of WM.AVI, EM.AVI and FINALE.AVI. The patch skips the video and the game goes on. With an Indeo codec installed, the videos play as before.

Bug fix

No freeze after more than 24 days of Windows uptime

A 3-second pause turns into weeks once Windows has been running for more than 231 ms. That comes sooner than you think: Windows Fast Startup keeps the uptime across a shutdown.

Bug fix

Sound on the Windows default audio device

The game takes the last sound device it finds instead of the one set in Windows. With monitor speakers and a headset, the sound easily ends up on the wrong one. With the patch it comes out where Windows sends it.

Bug fix

No false “disk almost full” warning

The game computes the free space in 32 bits. On large disks the calculation overflows, and now and then saving brings up the warning that the disk is almost full, for no reason.

Bug fix

Squads no longer grow beyond 30 players

A club with players on loan can get a 31st player, who overwrites the data behind the squad. The patch also counts the actual players when checking “squad full?”.

Bug fix

Desktop resolution restored, even after a crash

The game switches the screen to 640×480 in a way that outlives a crash. With the patch, Windows restores the resolution itself as soon as the game ends. The GOG release already gets this right; there the tick box is greyed out.

Bug fix

Readable club names in the cup draw

On current Windows and under Wine, the club names in the cup draw video come out twice as wide, half as high and dotted, because the game expects a picture with 16 bits per pixel and gets 32. The patch asks for the picture in 16 bits explicitly.

Bug fix

No hang when opening the calculation screen

The preseason calculation screen takes one of its two selections from memory it never cleared. If a large value is there, the screen stays invisible and the game waits for it. Seen under Wine; on Windows that memory is usually 0, the patch makes sure.

GOG only

No copy protection penalties

GOG sells the 2007 release, taken out of its copy protection. What is left of it still strikes: from the second season all clubs are called “Raubkopie” (pirated copy), players drop to strength 1, and ten self-checks of run.exe fail. With the patch all checks pass.

GOG & 2007 CD

Patch 1.01

The run.exe of GOG and that of the 2007 CD are built from version 1.00. The patch brings program and data up to the official patch 1.01, which the 1999 release already has: player lists, new players and goalkeepers, counters, event texts and more.

GOG only

Dialogs as in the 1999 original

In GOG’s RESDLL.dll, 342 dialogs lack their title bar and 68 controls their sunken frame, such as the choices that look like buttons. The patch gives them back the styles of 1999.

GOG only

No black line on the animations

GOG’s DirectDraw wrapper (ddraw.dll) shows a black line along the right and bottom edge of the animations, such as the overhead kick in the main menu. The patch fills it with the picture. Offered only with GOG’s ddraw.dll in the game folder.

Optional

Lift the goal limits

The game lets a team score only while it has fewer than 6 goals up to half-time and fewer than 10 after, and halves its chances from 7 goals on. The patch raises the limit to 15 and drops the brake.

10→15

02How to

  1. Close the game.A2G-Patch changes nothing while Anstoss 2 is running.
  2. Start A2G-Patch.exe.From anywhere. It offers its own folder and the installed CD and GOG releases; Durchsuchen … (Browse) picks another game folder.
  3. Tick, then Übernehmen (Apply).Tick the patches you want, untick the ones you no longer want. Done.

What happens

Original (1999)anstoss2.exe

The game file is changed directly. First, A2G-Patch puts a backup anstoss2.exe.vor-a2g-patch next to it. Once all patches are unticked again, the file is byte for byte as before and the backup goes.

GOGrun.exe

The same, with run.exe.vor-a2g-patch. The GOG patches also change RESDLL.dll (backup next to it) and the data files of patch 1.01; unticking restores them too. A file check in GOG Galaxy restores the original; then simply apply again.

2007 CDrun.exe (packed)

The program code is only stored encrypted on disk. So A2G-Patch puts an msvfw32.dll into the game folder, which changes the code in memory at every game start. A2G-Patch changes the data files of patch 1.01 directly. Unticking all patches deletes the DLL again.

03Good to know

Why does A2G-Patch ask for administrator rights?

If the game is installed under “Program Files”, only an administrator may write there. A2G-Patch then offers to restart itself as administrator.

My virus scanner flags msvfw32.dll.

Some scanners react to an unsigned DLL in a game folder that has the name of a system DLL; malware uses the same trick. The DLL passes every call on to the real msvfw32.dll of Windows and only changes the game’s code. The source code is open in dll/msvfw32.c.

A tick box is greyed out.

Each patch finds its places by the instructions around them. If it doesn’t find them exactly once, in the original or the patched state, A2G-Patch doesn’t offer it instead of blindly overwriting something. The tick boxes under “Nur für die GOG-Version” (GOG release only) are only there if the files are exactly GOG’s.

There is already another msvfw32.dll in the game folder?

A DLL that doesn’t come from A2G-Patch is never touched. One from another version of A2G-Patch is replaced on Übernehmen (Apply).

Does it work with A2G-Trainer?

Yes. The Spielmechaniken switch in A2G-Trainer lifts the goal limits while the trainer runs, and recognizes when A2G-Patch has already done so for good.

04Under the hood

For the curious: what exactly happens in the machine code. The same patterns apply on disk (Patches.cs) and in memory (dll/msvfw32.c).

ArrowsA race between two threads

While a button is held, a thread posts one step to the window every 60 ms, but only while none is pending (+0xF4 == 0). It marks the step pending only after PostMessageA. On Windows NT the window is often faster, still finds a 0 while handling the step, and then the thread writes a 1 that is never taken down again. The patch marks the step pending before posting, in the same 41 bytes:

; before
mov eax,[msg] / mov ecx,[esi+1C] / push 0 / push 0 / push eax / push ecx / call ebx
mov eax,[esi+F4] / mov [esi+F0],60 / inc eax / mov [esi+F4],eax
; after
mov [esi+F4],1 / mov [esi+F0],60
mov eax,[msg] / mov ecx,[esi+1C] / push 0 / push 0 / push eax / push ecx / call ebx
nop / nop / nop / jmp next
VideosA missing NULL check

The videos are Indeo 3.2, which current Windows no longer decodes. The game’s video player doesn’t check the result of AVIStreamGetFrameOpen and then reads through a NULL pointer. The patch adds the check and on NULL takes the path the game takes anyway for a missing file. The room for it comes from a more compact encoding of the instructions before, in the same 75 bytes:

push [edi] / call AVIStreamGetFrameOpen / test eax,eax / jnz ok
mov [edi],eax / jmp release   ; skip the video
ok: mov [edi-8],eax
Goal limitsTwo brakes in the match engine

The limit becomes a fixed value, the halving is skipped. More than 15 isn’t possible: the game stores results and half-time scores as a 4-bit value per team.

limit:  setg r8 / dec r32 / and r,-4 / add r,10  →  setg r8 / mov r32,15 / nop …
brakes: jle (7E)                                  →  jmp (EB)
FreezeA signed comparison

A reply sequence waits up to 3 seconds and compares the difference of two timeGetTime values with sign. Once Windows has run for more than 231 ms, the difference turns negative and Sleep gets a huge wait time. The patch compares without sign, at both places:

sub eax,[ebp+17C] / cmp eax,0BB8 / mov [ebp+17C],eax / jge (7D)  →  jae (73)
Sound deviceThe wrong GUID

While enumerating, the game remembers the device with the most 3D buffers. Since Vista all report 0 there, on a tie the last one wins, and its GUID goes to DirectSoundCreate. With NULL, DirectSound takes the Windows default device:

push &guid (68 xx xx xx xx)  →  push esi / nop ×4   ; esi is 0 here
Disk warningA 32-bit overflow

The game multiplies the values from GetDiskFreeSpaceA in 32 bits. On large disks the result is the free space modulo 4 GB and now and then falls below the threshold of 1.5 MB. The patch skips the warning; the game saves anyway:

cmp eax,177000 / jae (73)  →  jmp (EB)
SquadLoans count as departures

In many places the game checks whether a squad is full only by a forecast in which a player on loan counts as gone. So a 31st player fits in and is written behind the 30 slots. The patch also checks the actual squad size, in the same 32 bytes of the function:

full = forecast >= 30  →  full = forecast >= 30 or squad >= 30
ResolutionA missing flag

The game calls ChangeDisplaySettingsA with flag 0, so the change isn’t tied to the process. With CDS_FULLSCREEN it applies to the game only, and Windows restores the resolution when the game ends, even after a crash:

mov [esi+1C8],ebx (field is 0 already)  →  mov byte [esp+4],4 / nop
Cup draw32 instead of 16 bits per pixel

The video draws the club names with GDI into a 128×32 CreateCompatibleBitmap and reads them out with GetBitmapBits as a 16-bit picture. On current Windows and under Wine that bitmap has 32 bits per pixel even in the game’s 16-bit mode, so the game gets the upper half with each pixel split in two. The patch sends the call to added code that fetches the picture with GetDIBits explicitly in 16 bits and converts 5-5-5 to 5-6-5 where needed:

call [GetBitmapBits]  →  call helper / nop
helper: GetDC / GetDIBits(…, 128×-32, 16 bit) / ReleaseDC / 5-5-5 → 5-6-5 if needed / ret C
CalculationA field never cleared

The constructor of the calculation screen sets the selection “Ermittlung der Zahlen” (how the figures are computed) to 0, but not the “Darstellung” (display) one right next to it. With a large value, drawing the list reads past its end, the error vanishes inside the window call, and the screen stays half built and invisible. The patch clears both, in the same 11 bytes:

mov word [esi+10D48],0 / mov eax,esi  →  mov eax,esi / and dword [esi+10D46],0 / nop / nop
Copy protection (GOG)Eleven CD checks, ten checksums

Eleven places call a signature routine and subtract the expected value; 0 means “original CD”. GOG replaced the subtraction with NOPs, so every check fails. The patch puts in the result of a passed check. In addition, five places check a CRC32 of run.exe on disk and five a CRC32 of their own code; A2G-Patch stores the matching values after every change.

call check / add esp,4 / nop ×5  →  call check / add esp,4 / xor eax,eax / nop ×3
Patch 1.01 (GOG, 2007 CD)A new section in run.exe

The changes of 1.01 were found by comparing with the 1.01 program and the 1999 release, and rewritten in assembler (gog/a2v101.S). The code goes into a new section .a2v101 at the end of run.exe; thirteen places jump into it or change, for example the cup draw loads its MoveList.dat from the game folder instead of the CD. For the 2007 CD, msvfw32.dll puts the same code into a memory block of its own and adjusts its jumps. The three data files of 1.01 are made from GOG’s and code of our own, without any files of the patch.

Dialogs (GOG)Missing window styles

All dialogs are templates in RESDLL.dll. Compared with the 1999 file, GOG’s lacks WS_CAPTION, DS_MODALFRAME, WS_EX_CLIENTEDGE and a few more styles. The patch puts them back in place; the file keeps its size, and input and result are checked by SHA-256.

Animations (GOG)One pixel too many

The animations play in a child window exactly as large as the picture; a thread blits them into its client rect on the primary surface. GOG’s wrapper shows that rect plus one column and one row of the primary surface, where nothing was ever drawn. The patch makes the window one pixel smaller each way and blits the whole picture into it, so the extra column and row show the picture’s last ones. With a correct DirectDraw the clipper would cut them off, hence only with GOG’s wrapper.

window: add ecx,edx / add eax,edi            →  add ecx,edx / dec ecx / add eax,edi / dec eax
blit:   call GetClientRect(window, dest)     →  call CopyRect(dest, source)
msvfw32.dllA proxy for the 2007 CD

msvfw32 isn’t a KnownDLL, so the copy in the game folder wins. All 47 exports jump on to the real DLL, which is loaded only on the first call. A thread waits until the unpacked code is in memory and then writes only the enabled patches. Built without the C runtime so that it loads on Windows XP too.

Full description in the README →