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
| Projekt | Rola w architekturze |
|---|---|
Machine | Emulowany procesor, pamięć i biblioteka uruchomieniowa C oryginału |
Imaging | Ekrany, grafiki, palety i czcionki |
Acoustics | Sterowniki dźwiękowe i syntezatory |
Foundation | Strumienie, kompresja, generowanie losowości, logowanie |
GameModel | Stan gry i zasady rozgrywki |
Core.Shared | Interfejsy usług, pamięć gry, tabele i teksty |
Core.Engine | Renderowanie, sesje gry i usługi platformowe |
Core.Game | Główna logika rozgrywki |
Core.UI | Ekrany interfejsu użytkownika gry |
Core | GameEngine, spinający wszystkie podsystemy w całość |
Desktop | Okno aplikacji oparte na Avalonia UI |
Tests | Zestawy 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.