Für Anstoss 2 Gold · Original, GOG & 2007er-CD

Anstoss 2 Gold,
wie es sein sollte.

Ein kleines Fenster, ein paar Haken: Die Pfeilknöpfe zählen wieder weiter, die Videos zu WM, EM und Finale lassen das Spiel nicht mehr abstürzen, nichts friert nach langer Windows-Laufzeit ein, der Ton kommt aus dem richtigen Gerät, und wer mag, hebt die Torgrenzen auf. GOG- und 2007er-Version bekommen dazu Patch 1.01, die GOG-Version ihre Dialoge zurück, und ihr Kopierschutz macht keine „Raubkopie“ mehr aus dem Spielstand. Ohne Kompatibilitätsmodus, jederzeit rückgängig zu machen.

Windows XP (SP3) bis 11 · .NET Framework 4.0 oder neuer · GPL-3.0

Das Fenster von A2G-Patch: Spielordner-Auswahl und je ein Haken pro Patch

01Die Patches

Fehlerbehebung

Pfeile zählen beim Gedrückthalten weiter

Unter aktuellem Windows zählen die Pfeilknöpfe bei Zahlenwerten nur ein, zwei Schritte und bleiben dann stehen. Bisher half nur der Kompatibilitätsmodus „Windows 98“. Mit dem Patch zählen sie einfach weiter.

Fehlerbehebung

Kein Absturz bei den Videos zu WM, EM und Finale

Nach dem WM-Titel stürzt das Spiel ab, weil Windows das Videoformat von WM.AVI, EM.AVI und FINALE.AVI nicht mehr kennt. Der Patch überspringt das Video, das Spiel läuft weiter. Mit installiertem Indeo-Codec laufen die Videos wie gewohnt.

Fehlerbehebung

Kein Einfrieren nach über 24 Tagen Windows-Laufzeit

Eine Wartepause von 3 Sekunden wird zu Wochen, sobald Windows länger als 231 ms läuft. Das kommt schneller als gedacht: Der Schnellstart von Windows setzt die Laufzeit beim Herunterfahren nicht zurück.

Fehlerbehebung

Ton über das Standard-Audiogerät von Windows

Das Spiel nimmt das zuletzt gefundene Soundgerät statt des eingestellten. Mit Monitor-Lautsprechern und Headset landet der Ton so leicht auf dem falschen. Mit dem Patch kommt er dort heraus, wo Windows ihn hinschickt.

Fehlerbehebung

Keine falsche Warnung „Festplatte fast voll“

Den freien Platz rechnet das Spiel mit 32 Bit aus. Auf großen Platten läuft die Rechnung über, und beim Speichern erscheint ab und zu grundlos die Warnung, die Festplatte sei fast voll.

Fehlerbehebung

Kader nicht über 30 Spieler wachsen lassen

Ein Verein mit ausgeliehenen Spielern kann einen 31. Spieler bekommen, der Daten hinter dem Kader überschreibt. Der Patch zählt bei der Prüfung „Kader voll?“ auch die tatsächlichen Spieler.

Fehlerbehebung

Desktop-Auflösung auch nach einem Absturz zurückholen

Das Spiel stellt den Bildschirm so auf 640×480 um, dass die Umstellung einen Absturz überdauert. Mit dem Patch stellt Windows die Auflösung selbst wieder her, sobald das Spiel endet. Die GOG-Version macht das schon richtig, dort ist der Haken ausgegraut.

Fehlerbehebung

Vereinsnamen bei der Pokalauslosung richtig darstellen

Unter aktuellem Windows und unter Wine erscheinen die Vereinsnamen im Video der Pokalauslosung doppelt so breit, halb so hoch und gepunktet, weil das Spiel ein Bild mit 16 Bit pro Pixel erwartet und 32 bekommt. Der Patch holt das Bild ausdrücklich mit 16 Bit.

Fehlerbehebung

Kein Hänger beim Öffnen der Kalkulation

Der Kalkulationsbildschirm der Vorsaison übernimmt eine seiner zwei Auswahlen aus Speicher, den er nie gelöscht hat. Steht dort ein großer Wert, bleibt er unsichtbar, und das Spiel wartet auf ihn. Unter Wine gesehen; unter Windows ist der Speicher meist 0, der Patch stellt es sicher.

Nur GOG

Keine Kopierschutz-Strafen

GOG verkauft die Fassung von 2007, aus dem Kopierschutz herausgelöst. Dessen Reste schlagen trotzdem an: Ab der zweiten Saison heißen alle Vereine „Raubkopie“, Spieler fallen auf Stärke 1, und zehn Selbstprüfungen der run.exe scheitern. Mit dem Patch bestehen alle Prüfungen.

GOG & 2007er-CD

Patch 1.01

Die run.exe von GOG und die der 2007er-CD sind aus dem Stand 1.00 gebaut. Der Patch bringt Programm und Daten auf den Stand des offiziellen Patches 1.01, den die Version von 1999 schon hat: Spielerlisten, neue Spieler und Torhüter, Zähler, Ereignistexte und mehr.

Nur GOG

Dialoge wie im Original von 1999

In der RESDLL.dll von GOG fehlen 342 Dialogen die Titelleiste und 68 Feldern der eingelassene Rahmen, etwa den Auswahlen, die wie Knöpfe aussehen. Der Patch gibt ihnen die Stile von 1999 zurück.

Nur GOG

Kein schwarzer Strich an den Animationen

Der DirectDraw-Wrapper von GOG (ddraw.dll) zeigt rechts und unten an den Animationen, etwa dem Fallrückzieher im Hauptmenü, eine schwarze Linie. Der Patch füllt sie mit dem Bild. Angeboten nur, wenn die ddraw.dll von GOG im Spielordner liegt.

Optional

Torgrenzen aufheben

Das Spiel lässt eine Mannschaft nur treffen, solange sie bis zur Halbzeit unter 6 und danach unter 10 Toren liegt, und halbiert ab 7 Toren ihre Chancen. Der Patch hebt die Grenze auf 15 an und streicht die Bremse.

10→15

02So geht’s

  1. Spiel beenden.A2G-Patch ändert nichts, während Anstoss 2 läuft.
  2. A2G-Patch.exe starten.Von wo auch immer. Es schlägt den eigenen Ordner und die installierte CD- und GOG-Version vor, „Durchsuchen …“ wählt einen anderen Spielordner.
  3. Haken setzen, „Übernehmen“.Gewünschte Patches anhaken, nicht mehr gewünschte abhaken. Fertig.

Was dabei passiert

Original (1999)anstoss2.exe

Die Spieldatei wird direkt geändert. Vorher legt A2G-Patch eine Sicherung anstoss2.exe.vor-a2g-patch daneben. Sind alle Patches wieder abgehakt, ist die Datei Byte für Byte wie vorher und die Sicherung verschwindet.

GOGrun.exe

Genauso, mit run.exe.vor-a2g-patch. Die GOG-Patches ändern auch die RESDLL.dll (Sicherung daneben) und die Datendateien von Patch 1.01; abhaken stellt auch sie wieder her. Eine Dateiprüfung in GOG Galaxy stellt das Original wieder her; dann einfach noch einmal übernehmen.

2007er-CDrun.exe (gepackt)

Der Programmcode liegt nur verschlüsselt auf der Platte. A2G-Patch legt deshalb eine msvfw32.dll in den Spielordner, die bei jedem Spielstart den Code im Speicher ändert. Die Datendateien von Patch 1.01 ändert A2G-Patch direkt. Alle Patches abhaken löscht die DLL wieder.

03Gut zu wissen

Warum fragt A2G-Patch nach Administratorrechten?

Liegt das Spiel unter „Programme“, darf dort nur ein Administrator schreiben. A2G-Patch bietet dann an, sich selbst als Administrator neu zu starten.

Mein Virenscanner meldet die msvfw32.dll.

Manche Scanner schlagen bei einer unsignierten DLL im Spielordner an, die so heißt wie eine System-DLL; Schadsoftware nutzt denselben Trick. Die DLL reicht alle Aufrufe an die echte msvfw32.dll von Windows weiter und ändert nur den Code des Spiels. Der Quellcode liegt offen in dll/msvfw32.c.

Ein Haken ist ausgegraut.

Jeder Patch sucht seine Stellen anhand der Befehle drumherum. Findet er sie nicht genau einmal, im Original- oder im gepatchten Zustand, bietet A2G-Patch ihn nicht an, statt blind etwas zu überschreiben. Die Haken unter „Nur für die GOG-Version“ gibt es nur, wenn die Dateien genau die von GOG sind.

Liegt schon eine andere msvfw32.dll im Spielordner?

Eine DLL, die nicht von A2G-Patch stammt, wird nie angefasst. Eine aus einer anderen Version von A2G-Patch wird beim „Übernehmen“ ersetzt.

Verträgt sich das mit A2G-Trainer?

Ja. Der Schalter „Spielmechaniken“ im A2G-Trainer hebt die Torgrenzen auf, solange der Trainer läuft, und erkennt, wenn A2G-Patch das schon dauerhaft erledigt hat.

04Unter der Haube

Für Neugierige: Was genau im Maschinencode passiert. Dieselben Muster gelten auf der Platte (Patches.cs) und im Speicher (dll/msvfw32.c).

PfeileEin Wettlauf zwischen zwei Threads

Beim Gedrückthalten schickt ein Thread alle 60 ms einen Schritt ans Fenster, aber nur, solange keiner aussteht (+0xF4 == 0). Als ausstehend markiert er den Schritt erst nach PostMessageA. Unter Windows NT ist das Fenster oft schneller, findet beim Abarbeiten noch eine 0, und danach schreibt der Thread eine 1, die nie wieder abgebaut wird. Der Patch markiert den Schritt vor dem Senden, in denselben 41 Bytes:

; vorher
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
; nachher
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
VideosEin fehlender NULL-Check

Die Videos sind Indeo 3.2, das aktuelles Windows nicht mehr dekodiert. Der Videospieler des Spiels prüft das Ergebnis von AVIStreamGetFrameOpen nicht und liest dann durch einen NULL-Zeiger. Der Patch ergänzt die Prüfung und nimmt bei NULL den Weg, den das Spiel ohnehin bei einer fehlenden Datei geht. Den Platz dafür schafft eine kompaktere Kodierung der Befehle davor, in denselben 75 Bytes:

push [edi] / call AVIStreamGetFrameOpen / test eax,eax / jnz ok
mov [edi],eax / jmp release   ; Video überspringen
ok: mov [edi-8],eax
TorgrenzenZwei Bremsen in der Spiel-Engine

Die Grenze wird zu einem festen Wert, die Halbierung wird übersprungen. Mehr als 15 geht nicht: Ergebnis und Halbzeitstand speichert das Spiel als 4-Bit-Wert pro Mannschaft.

limit:  setg r8 / dec r32 / and r,-4 / add r,10  →  setg r8 / mov r32,15 / nop …
brakes: jle (7E)                                  →  jmp (EB)
EinfrierenEin Vergleich mit Vorzeichen

Eine Antwortsequenz wartet bis zu 3 Sekunden und vergleicht dazu die Differenz zweier timeGetTime-Werte mit Vorzeichen. Läuft Windows länger als 231 ms, wird die Differenz negativ, und Sleep bekommt eine riesige Wartezeit. Der Patch vergleicht ohne Vorzeichen, an beiden Stellen:

sub eax,[ebp+17C] / cmp eax,0BB8 / mov [ebp+17C],eax / jge (7D)  →  jae (73)
SoundgerätDie falsche GUID

Beim Aufzählen merkt sich das Spiel das Gerät mit den meisten 3D-Puffern. Seit Vista melden alle dort 0, bei Gleichstand gewinnt das letzte, und dessen GUID geht an DirectSoundCreate. Mit NULL nimmt DirectSound das Standardgerät von Windows:

push &guid (68 xx xx xx xx)  →  push esi / nop ×4   ; esi ist hier 0
Platz-WarnungEin 32-Bit-Überlauf

Das Spiel multipliziert die Werte von GetDiskFreeSpaceA in 32 Bit. Auf großen Platten ist das Ergebnis der freie Platz modulo 4 GB und liegt ab und zu unter der Schwelle von 1,5 MB. Der Patch überspringt die Warnung, gespeichert wird ohnehin:

cmp eax,177000 / jae (73)  →  jmp (EB)
KaderLeihen zählen als Abgang

Ob ein Kader voll ist, prüft das Spiel vielerorts nur anhand einer Prognose, in der ein ausgeliehener Spieler als Abgang zählt. So passt ein 31. Spieler hinein, der hinter die 30 Plätze geschrieben wird. Der Patch prüft zusätzlich die tatsächliche Kadergröße, in denselben 32 Bytes der Funktion:

voll = Prognose >= 30  →  voll = Prognose >= 30 oder Kader >= 30
AuflösungEin fehlendes Flag

Das Spiel ruft ChangeDisplaySettingsA mit Flag 0 auf, die Umstellung ist dann nicht an den Prozess gebunden. Mit CDS_FULLSCREEN gilt sie nur fürs Spiel, und Windows stellt die Auflösung zurück, wenn es endet, auch nach einem Absturz:

mov [esi+1C8],ebx (Feld ist schon 0)  →  mov byte [esp+4],4 / nop
Pokalauslosung32 statt 16 Bit pro Pixel

Das Video zeichnet die Vereinsnamen per GDI in eine CreateCompatibleBitmap von 128×32 und liest sie mit GetBitmapBits als 16-Bit-Bild aus. Unter aktuellem Windows und unter Wine hat diese Bitmap auch im 16-Bit-Modus des Spiels 32 Bit pro Pixel, das Spiel bekommt die obere Hälfte mit jedem Pixel in zwei geteilt. Der Patch leitet den Aufruf in eingefügten Code um, der das Bild per GetDIBits ausdrücklich mit 16 Bit holt und bei Bedarf von 5-5-5 nach 5-6-5 umrechnet:

call [GetBitmapBits]  →  call helper / nop
helper: GetDC / GetDIBits(…, 128×-32, 16 Bit) / ReleaseDC / ggf. 5-5-5 → 5-6-5 / ret C
KalkulationEin nicht gelöschtes Feld

Der Konstruktor des Kalkulationsbildschirms setzt die Auswahl „Ermittlung der Zahlen“ auf 0, die von „Darstellung“ direkt daneben aber nicht. Mit einem großen Wert liest das Zeichnen der Liste über ihr Ende hinaus, der Fehler verschwindet im Fensteraufruf, und der Bildschirm bleibt halb aufgebaut und unsichtbar. Der Patch löscht beide, in denselben 11 Bytes:

mov word [esi+10D48],0 / mov eax,esi  →  mov eax,esi / and dword [esi+10D46],0 / nop / nop
Kopierschutz (GOG)Elf CD-Abfragen, zehn Prüfsummen

Elf Stellen rufen eine Signaturroutine auf und ziehen den erwarteten Wert ab; 0 heißt „Original-CD“. GOG hat das Abziehen durch NOPs ersetzt, also scheitert jede Abfrage. Der Patch setzt das Ergebnis einer bestandenen Abfrage ein. Dazu prüfen fünf Stellen eine CRC32 der run.exe auf der Platte und fünf eine CRC32 ihres eigenen Codes; A2G-Patch speichert nach jeder Änderung die passenden Werte.

call check / add esp,4 / nop ×5  →  call check / add esp,4 / xor eax,eax / nop ×3
Patch 1.01 (GOG, 2007er-CD)Ein neuer Abschnitt in der run.exe

Die Änderungen von 1.01 wurden durch Vergleich mit dem Programm von 1.01 und der Version von 1999 gefunden und in Assembler neu geschrieben (gog/a2v101.S). Der Code kommt in einen neuen Abschnitt .a2v101 am Ende der run.exe, dreizehn Stellen springen hinein oder ändern sich, etwa lädt die Pokalauslosung ihre MoveList.dat aus dem Spielordner statt von der CD. Bei der 2007er-CD legt die msvfw32.dll denselben Code in einen eigenen Speicherblock und passt seine Sprünge an. Die drei Datendateien von 1.01 entstehen aus denen von GOG und eigenem Code, ohne Dateien des Patches.

Dialoge (GOG)Fehlende Fensterstile

Alle Dialoge sind Vorlagen in der RESDLL.dll. Im Vergleich mit der Datei von 1999 fehlen bei GOG WS_CAPTION, DS_MODALFRAME, WS_EX_CLIENTEDGE und ein paar weitere Stile. Der Patch setzt sie an Ort und Stelle wieder ein; die Datei behält ihre Größe, Ausgang und Ergebnis werden per SHA-256 geprüft.

Animationen (GOG)Ein Pixel zu viel

Die Animationen laufen in einem Unterfenster genau so groß wie das Bild; ein Thread blittet sie in dessen Client-Rechteck auf die Primärfläche. Der Wrapper von GOG zeigt dieses Rechteck plus eine Spalte und eine Zeile der Primärfläche, auf die nie etwas gezeichnet wurde. Der Patch macht das Fenster in jede Richtung ein Pixel kleiner und blittet das ganze Bild hinein, sodass die zusätzliche Spalte und Zeile die letzten des Bildes zeigen. Mit einem korrekten DirectDraw schnitte der Clipper sie ab, daher nur mit dem Wrapper von GOG.

Fenster: add ecx,edx / add eax,edi           →  add ecx,edx / dec ecx / add eax,edi / dec eax
Blit:    call GetClientRect(Fenster, Ziel)   →  call CopyRect(Ziel, Quelle)
msvfw32.dllEin Proxy für die 2007er-CD

msvfw32 ist keine KnownDLL, also gewinnt die Kopie im Spielordner. Alle 47 Exporte springen an die echte DLL weiter, die erst beim ersten Aufruf geladen wird. Ein Thread wartet, bis der entpackte Code im Speicher liegt, und schreibt dann nur die aktivierten Patches. Ohne C-Laufzeit gebaut, damit sie auch unter Windows XP lädt.

Ganze Beschreibung im README →