Stunt GP #2: Ponadczasowe problemy

Kiedy zacząłem grać w Stunt GP na Windowsie 10 natychmiast zauważyłem denerwujące półsekundowe przycinki co 7 minut i 9.5 sekundy, problem który praktycznie nie występował na starszych komputerach. W końcu po półtora roku znalazłem powód dlaczego tak się dzieje i naprawiłem ten błąd 🙂

Problem

Gra używa funkcji QueryPerformanceFrequency() oraz QueryPer-
formanceCounter()
do pomiaru czasu. Pierwsza funkcja zwraca częstotliwość z jaką licznik czasu jest aktualizowany. Ta częstotliwość jest różna dla każdego komputera, ale o tym za chwilę. Licznik wydajności jest 64 bitowy, nawet na najszybszych komputerach jego przepełnienie i zresetowanie do 0 nastąpiło by dopiero po 24 TYSIĄCACH lat (zakładając częstotliwość 24MHz). Problem polega na tym, że gra używa tylko 32 bitów z tego licznika, co oznacza, że w najgorszym razie ten licznik przepełni się już po 3 minutach.

Na starszych komputerach częstotliwość tego licznika oscylowała wokół 2-3 MHz, więc licznik przepełnił by się po 23-36 minutach. W Windowsie 10 Microsoft zdecydował ustawić tę częstotliwość na 10MHz, niezależnie od sprzętu, więc licznik przepełnia się dokładnie co 7 minut i 9.5 sekundy. Użytkownik może wymusić używanie sprzętowego zegara przez Windowsa, ale zamiast częstotliwości rzedu 2-3 MHz, w nowszych komputerach wyposażonych w High Precision Event Timer (HPET) ten zegar może mieć częstotliwość 14 lub nawet 24MHz, przepełniając licznik w 5 lub nawet 3 minuty!

Gra źle znosi przepełnienia tego licznika, po prostu się zawieszając. Jedynie to, ze gra wykrywa gdy zacięła się na pół sekundy i resetuje wewnętrzne liczniki pozwala grze działać, ale samo przepełnienie licznika nie jest traktowane w jakiś szczególny sposób.

Rozwiązanie

Stworzyłem nowy moduł StuntKit, który podczas startu gry podmienia funkcję odpowiedzialną za pomiar czasu na taką, która wykrywa przepełnienie licznika i resetuje wewnętrzne liczniki gry, eliminując półsekundowe przycinki.

Zbudowano z Hugo
Motyw Stack zaprojektowany przez Jimmy