Civ 1.5 Remastered

Jak to działa

Od 16-bitowego programu DOS do nowoczesnej aplikacji .NET — funkcja po funkcji.

Od CIV.EXE do C#

Każda funkcja oryginalnego pliku CIV.EXE została przetłumaczona na odpowiadającą jej metodę w C#. Początkowo translacja wiernie odtwarzała kod maszynowy: rejestry procesora, stos i adresy pamięci zachowywały pierwotną postać. Krok po kroku kod ten został przepisany na przejrzysty, idiomatyczny C#, z czytelnymi nazwami, parametrami i typami zwracanymi, podczas gdy rozbudowany zestaw testów weryfikował, czy gra zachowuje się w 100% identycznie jak pierwotna wersja.

Niektóre fragmenty nadal odczytują stan pamięci gry bezpośrednio po adresach. Pamięć ta symuluje środowisko procesora 8086: struktury danych gry, stany zapisów oraz tabele oryginału znajdują się dokładnie tam, gdzie oczekiwała ich gra w 1991 roku.

Grafika, dźwięk i dane

Grafiki, palety kolorów, czcionki oraz teksty pobierane są bezpośrednio z plików Twojej kopii gry. Dane samego programu rozpakowywane są z oryginalnego pliku CIV.EXE podczas startu aplikacji. Sterowniki dźwięku oryginału działają wewnątrz małego interpretera kodu maszynowego, który steruje emulowanym syntezatorem AdLib lub tłumaczy polecenia Roland MT-32 na standard General MIDI.

Struktura projektów

ProjektRola w architekturze
MachineEmulowany procesor, pamięć i biblioteka uruchomieniowa C oryginału
ImagingEkrany, grafiki, palety i czcionki
AcousticsSterowniki dźwiękowe i syntezatory
FoundationStrumienie, kompresja, generowanie losowości, logowanie
GameModelStan gry i zasady rozgrywki
Core.SharedInterfejsy usług, pamięć gry, tabele i teksty
Core.EngineRenderowanie, sesje gry i usługi platformowe
Core.GameGłówna logika rozgrywki
Core.UIEkrany interfejsu użytkownika gry
CoreGameEngine, spinający wszystkie podsystemy w całość
DesktopOkno aplikacji oparte na Avalonia UI
TestsZestawy testów jednostkowych i regresyjnych

Testy automatyczne

Testy symulują rozgrywanie tur z zapisanych stanów gry w trybie bezokienkowym (headless) i porównują wyniki z nagraniami wygenerowanymi przez pierwszą translację. Dziennik wywołań (call journal) precyzyjnie rejestruje, jakie funkcje zostały wywołane i z jakimi argumentami, dzięki czemu każda zmiana w zachowaniu natychmiast ujawnia się jako błąd w teście. Zegar testowy odmierza czas zgodnie z operacjami pamięciowymi gry, gwarantując pełną powtarzalność każdego uruchomienia.

Historia repozytorium

Repozytorium zachowuje każdy commit z oryginalną datą, lecz tylko najnowsze commity budują się automatycznie (pliki usunięte z projektu zostały wyczyszczone z historii). Do kompilacji i gry należy używać szczytu gałęzi main.