Formaty plików Outpost 2 · bei.pm

Ten tekst został automatycznie przetłumaczony przez OpenAI GPT-4o Mini.

Opisywane na tej stronie formaty plików opierają się na analizie technicznej własności intelektualnej Dynamix, Inc. oraz Sierra Entertainment.
Własność intelektualna jest obecnie częścią majątku Activision Publishing, Inc. / Activision Blizzard, Inc. i jest aktualnie w posiadaniu Microsoft Corp..

Informacje zostały zebrane poprzez inżynierię odwrotną oraz analizę danych w celach archiwizacji i interoperacyjności z danymi historycznymi.
Nie wykorzystano żadnych zastrzeżonych ani poufnych specyfikacji.

Gra jest obecnie dostępna do zakupu jako pobranie na stronie gog.com.

Sztuka z gry

Następna seria artykułów dokumentuje moje odkrycia dotyczące formatów danych w grze strategicznej czasu rzeczywistego "Outpost 2: Divided Destiny", która została wydana przez Sierra w 1997 roku i opracowana przez Dynamix.

Zajmowałem się analizą danych z gry - i tym, co można z nimi zrobić - głównie od 1 do 14 listopada 2015 roku.

Z informacji, które do tej pory udało mi się zdobyć, wynika, że Dynamix - jak wiele firm komercyjnych - nie opracowało kilku formatów danych specjalnie dla Outpost 2, lecz również zastosowało je w innych projektach, takich jak seria Mechwarrior (w zmienionej formie).
Niezależnie od tego, można również stwierdzić, że innowacyjność formatów danych jest praktycznie ograniczona i często opiera się na dłużej istniejących koncepcjach z powszechnych formatów, takich jak JFIF i RIFF.

Dodatkowe informacje na temat interpretacji tabel i formatów danych można znaleźć pod Co to jest?.
Zapewnione tutaj dane są ogólnie rozumiane jako Little Endian.

Podsumowując, można powiedzieć, że inżynieria odwrotna sprawiła mi dużo frajdy, choć nie jest pełna.
Oczywiście mogę również polecić, aby zagrać w grę samodzielnie, ponieważ oferuje ciekawe mechaniki rozgrywki.

Wprowadzenie

Dane formaty używane przez Outpost 2 mają strukturę przypominającą JFIF / PNG - poszczególne bloki danych zawsze mają nagłówek o długości 8 bajtów. W związku z tym oszczędzam sobie dokumentowania poszczególnych nagłówków w odpowiednich specyficznych miejscach i dokumentuję tylko odchylenia.

Format jest zawsze następujący; właściwe dane użytkowe są w nim osadzone:

Adres x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF znak
0x0000 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- . . . . . . . . . . . . . . . .
Przesunięcie Typ danych Nazwa Wyjaśnienie
0x0000 uint(32) Bajty Magii

Zawiera informacje o tym, czego można się spodziewać w następnym bloku danych.

Znane wartości:

  • 0x204C4F56 ('VOL '):
    Objętość
  • 0x686C6F76 ('VOLH'):
    Nagłówek objętości
  • 0x736C6F76 ('VOLS'):
    Napisy objętości
  • 0x696C6F76 ('VOLI'):
    Informacje o objętości
  • 0x4B4C4256 ('BLCK'):
    Blok objętości
  • 0x504D4250 ('PBMP'):
    Dane graficzne
  • 0x4C415050 ('PPAL'):
    Paleta kolorów
  • 0x4C415043 ('CPAL'):
    Kontejner palet kolorów
  • 0x64616568 ('head'):
    Nagłówek
  • 0x61746164 ('data'):
    Dane użytkowe
0x0004 uint(24) Długość bloku

Zawiera informację o tym, jak duży (w bajtach) jest następujący blok danych.

Chodzi tutaj o czyste dane użytkownika - 8 bajtów nagłówka nie jest w to wliczonych.

0x0007 uint(8) Flagi?

Nie wiadomo, do czego dokładnie służy ten blok.

W woluminach ta wartość często wynosi 0x80, w innych plikach często 0x00. Sugeruje to, że jest to zestaw flag.

Woluminy

Volume to kontener danych dla gry, podobny do formatu archiwum, takiego jak Tarball. Przynajmniej w Outpost 2 format ten zna jedynie pliki - bez folderów. Prawdopodobnie jednak można by je zasymulować za pomocą odpowiednich nazw plików.

Volume składa się z nagłówka Volume oraz z kilku bloków Volume, które odpowiadają konkretnym plikom.

"Volumes" to pliki z rozszerzeniem 'vol' w katalogu gry.

Adres x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF znak
0x0000 56 4f 4c 20 -- -- -- -- -- -- -- -- -- -- -- -- V O L . . . . . . . . . . . .
Przesunięcie Typ danych Nazwa Wyjaśnienie
0x0000 uint(32) Bajty Magii
0x0004 uint(24) Długość bloku
0x0007 uint(8) Flagi

Nagłówek objętości

Adres x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF znak
0x0000 76 6f 6c 68 -- -- -- -- -- -- -- -- -- -- -- -- v o l h . . . . . . . . . . . .
Przesunięcie Typ danych Nazwa Wyjaśnienie
0x0000 uint(32) Bajty Magii
0x0004 uint(24) Długość bloku
0x0007 uint(8) Flagi

Nagłówek wolumenu sam w sobie nie zawiera żadnych danych użytkowych.
Jest jedynie kontenerem.

Pierwszymi danymi w nagłówku wolumenu powinny być ciągi wolumenu; następnie pojawiają się informacje o wolumenie.

Łańcuchy objętości

Adres x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF znak
0x0000 76 6f 6c 69 -- -- -- -- -- -- -- -- -- -- -- -- v o l i . . . . . . . . . . . .
Przesunięcie Typ danych Nazwa Wyjaśnienie
0x0000 uint(32) Bajty Magii
0x0004 uint(24) Długość bloku
0x0007 uint(8) Flagi
Adres x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF znak
0x0000 76 6f 6c 73 -- -- -- -- -- -- -- -- -- -- -- -- v o l s . . . . . . . . . . . .
Przesunięcie Typ danych Nazwa Wyjaśnienie
0x0000 uint(32) Bajty Magii
0x0004 uint(24) Długość bloku
0x0007 uint(8) Flagi
0x0008 uint(32) Długość ładunku

Wskazuje, ile bajtów z poniższych danych to faktycznie dane użytkowe.

Pozostałe dane z listy ciągów woluminu najwyraźniej należy traktować jako śmieci.

W plikach z późniejszą datą te 'pozostałe dane' to 0x00, co może wskazywać na niedociągnięcia w narzędziach podczas rozwoju gry, a konkretnie, że dopiero na późnym etapie programista zajął się poprawną inicjalizacją buforów, ponieważ nie ma to wpływu na grę, czy dane są zainicjowane, czy nie.

0x000c uint(8)[] Lista nazw plików

To jest lista nazw plików zakończona znakiem 0-Byte, która - przynajmniej w bieżącym składniku danych - spodziewa się jedynie znaków ASCII.

Nie ma potrzeby dokładniejszego analizowania tego bloku danych podczas parsowania, ponieważ w informacjach o wolumenie i tak bezpośrednio odniesione są offsety nazw plików.

Volume Strings to lista nazw plików, które znajdują się w obrębie woluminu.

Informacje o wolumenie

Adres x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF znak
0x0000 76 6f 6c 69 -- -- -- -- -- -- -- -- -- -- -- -- v o l i . . . . . . . . . . . .
Przesunięcie Typ danych Nazwa Wyjaśnienie
0x0000 uint(32) Bajty Magii
0x0004 uint(24) Długość bloku
0x0007 uint(8) Flagi

Informacje o woluminie zawierają bardziej szczegółowe dane na temat plików. W pewnym sensie jest to rodzaj wpisu w katalogu FAT (FAT = Tablica Przydziału Plików).

Liczba plików wynika z wielkości bloku podzielonej przez długość wpisów katalogowych - 14 bajtów.

Pojedyncze wpisy katalogowe mają następującą strukturę:

Adres x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF znak
0x0000 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- . . . . . . . . . . . . . . . .
Przesunięcie Typ danych Nazwa Wyjaśnienie
0x0000 uint(32) Offset nazwy pliku

Określa, na którym offsetcie (!) w liście nazw plików (Volume-Strings) znajduje się nazwa pliku.

Odnosimy się przy tym do początku bloku danych użytkownika.

0x0004 uint(32) Offset pliku

Określa, na jakim offsecie w całym pliku woluminu znajduje się plik.

0x0008 uint(32) Rozmiar pliku

Określa, jak duży jest plik w bajtach.

0x000c uint(16) Flagi?

Wygląda na to, że są dodatkowe informacje dotyczące kodowania plików.

  • 0x03 jest ustawione, gdy plik jest skompresowany. Wygląda na to, że używany jest tutaj drzewo Huffmana.
  • 0x80 wydaje się być zawsze ustawione.

Blok objętości

Adres x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF znak
0x0000 56 42 4c 48 -- -- -- -- -- -- -- -- -- -- -- -- V B L H . . . . . . . . . . . .
Przesunięcie Typ danych Nazwa Wyjaśnienie
0x0000 uint(32) Bajty Magii
0x0004 uint(24) Długość bloku
0x0007 uint(8) Flagi

Blok woluminu to kontener, który przechowuje pliki. Zawiera on jedynie - ze względu na format bloku - redundantnie rozmiar pliku, a następnie bezpośrednio następują dane użytkowe.

Płytki

Adres x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF znak
0x0000 50 42 4d 50 -- -- -- -- -- -- -- -- -- -- -- -- P B M P . . . . . . . . . . . .
Przesunięcie Typ danych Nazwa Wyjaśnienie
0x0000 uint(32) Bajty magii
0x0004 uint(24) Długość bloku
0x0007 uint(8) Flagi

Tiles to specyficzny format grafiki bitmapowej dla Outpost-2. Obejmuje 13 zestawów tiles, zwanych "studniami" (well0000.bmp do well0012.bmp), które znajdują się w woluminie maps.vol.

Zestawy tiles / studnie zawierają następujące elementy:

Nazwa pliku Treść
well0000.bmp Grafika o wymiarach 32x32px w kolorze niebieskim - idealna do testowania, czy własny loader obrazów działa
well0001.bmp Zawiera jasne skały, łańcuchy górskie na jasnych skałach oraz niezliczone warianty kraterów uderzeniowych w jasne skały
well0002.bmp Zawiera 'Doodady' z jasnych skał - elementy, które mogą być umieszczane na jasnych skałach dla urozmaicenia (lub celowo jako struktura, jak np. mury), w tym roślinność
well0003.bmp Zawiera strukturę przypominającą skorupę na jasnych skałach
well0004.bmp Zawiera ciemne skały, łańcuchy górskie na ciemnych skałach oraz niezliczone warianty kraterów uderzeniowych w ciemne skały
well0005.bmp Zawiera 'Doodady' z ciemnych skał - elementy, które mogą być umieszczane na ciemnych skałach dla urozmaicenia (lub celowo jako struktura, jak np. mury)
well0006.bmp Zawiera strukturę przypominającą skorupę na ciemnych skałach oraz przejścia między jasnymi a ciemnymi skałami
well0007.bmp Zawiera lawę, w tym po 4-5 klatek animacji dla każdej z nich
well0008.bmp Zawiera piasek oraz niezliczone warianty kraterów uderzeniowych w piasku
well0009.bmp Zawiera 'Doodady' z piasku - elementy, które mogą być umieszczane na piasku dla urozmaicenia (lub celowo jako struktura, jak np. mury)
well0010.bmp Zawiera 48 przejść z piasku do jasnych i ciemnych skał
well0011.bmp Zawiera pokrywy polarne mapy, z ciemnymi skałami jako podłożem
well0012.bmp Zawiera pokrywy polarne mapy, z jasnymi skałami jako podłożem

Jest to zalecane dla dokładnej realizacji, aby nie renderować kafli z wyprzedzeniem w celu ich buforowania, ponieważ dane dotyczące cyklu dnia/nocy muszą być jeszcze przetworzone - a danych byłoby naprawdę bardzo dużo.

Kafle to grafiki 8bpp z paletą indeksowaną o rozdzielczości 32x32 pikseli, które są ułożone w stos. W tak powstałym zestawie kafli może być jednak znacznie więcej

Główny kontener składa się z 2 sekcji: head i data.

Nagłówek Płytek

Adres x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF znak
0x0000 68 65 61 64 -- -- -- -- -- -- -- -- -- -- -- -- h e a d . . . . . . . . . . . .
0x0010 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- . . . . . . . . . . . . . . . .
Przesunięcie Typ danych Nazwa Wyjaśnienie
0x0000 uint(32) Bajty magii
0x0004 uint(24) Długość bloku
0x0007 uint(8) Flagi
0x0008 uint(32) Wersja / Flagi?

Może to być oznaczenie wersji formatu pliku; we wszystkich dostępnych mi plikach wartość ta wynosiła 0x02

0x000c uint(32) Szerokość (Rozdzielczość pozioma)

Określa, jak szeroki jest plik graficzny (w pikselach).

Wszystkie studnie z Outpost 2 powinny mieć tutaj wartość 0x20 lub 32.

0x0010 uint(32) Wysokość (Rozdzielczość pionowa)

Określa, jak wysoki jest plik obrazu (w pikselach).

Wszystkie studnie w Outpost 2 powinny mieć tutaj wartość 0x20 lub 32.

0x0014 uint(32) Głębokość koloru?

Znaczenie tej wartości jest nieznane.

Ponieważ we wszystkich sprawdzonych plikach zawiera wartość 8, może to dotyczyć głębi koloru.

0x0018 uint(32) Głębokość koloru 2?

Znaczenie tej wartości jest nieznane.

Możliwe, że jest to 'docelowa' głębia koloru.

Zgodnie z tymi danymi, następnie dostępny będzie plik palety w standardowym formacie RIFF. Dokładna specyfikacja znajduje się - ponieważ palety pojawiają się także w innych miejscach - pod Palety.

Dane Płytek

Adres x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF znak
0x0000 64 61 74 61 -- -- -- -- -- -- -- -- -- -- -- -- d a t a . . . . . . . . . . . .
Przesunięcie Typ danych Nazwa Wyjaśnienie
0x0000 uint(32) Bajty magii
0x0004 uint(24) Długość bloku
0x0007 uint(8) Flagi

W końcu następują surowe dane pikseli, od lewego górnego rogu, wierszami do prawego dolnego rogu.
Wartość danych w grafikach, które zazwyczaj występują jako bitmapy 8bpp, odpowiada indeksowi koloru w palecie kolorów.

Dane pikseli zaczynają się w lewym górnym rogu i kończą w prawym dolnym rogu.

Silnik gry prawdopodobnie rysuje kafelki *na żądanie*.
Wydaje się to być związane z cyklem dnia i nocy, który zna 32 stopnie poszczególnych kafelków. Wygląda na to, że od wartości jasności odejmowane jest 'trochę'. Dokładne wartości nie zostały jeszcze ustalone, pracuję na podstawie obliczeń

v *= (daylight / 48) + 0.25;

za pomocą danych HSV pikseli, gdzie daylight to wartość od 0 do 31, a v to wartość między 0 a 1. Należy również wziąć pod uwagę, że na mapie istnieje dodatkowo margines 16 kafelków po lewej i prawej stronie (służy to niewidzialnemu pojawianiu się jednostek).

Dodatkowo wydaje się, że cykl dnia i nocy aktualizuje tylko jedną kolumnę mapy w każdym cyklu gry.
Przyspieszony cykl dnia i nocy wygląda zatem następująco:

Wizualizacja cyklu dnia i nocy

PRT

Adres x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF znak
0x0000 43 50 41 4c -- -- -- -- -- -- -- -- -- -- -- -- C P A L . . . . . . . . . . . .
Przesunięcie Typ danych Nazwa Wyjaśnienie
0x0000 uint(32) Bajty Magii
0x0004 uint(24) Długość palety

Wskazuje, w przeciwieństwie do normalnego formatu blokowego, liczbę palet znajdujących się w tym pliku - a nie długość bloku w bajtach.

0x0007 uint(8) Flagi

Prawdopodobnie, jak zwykle, flagi.

Nie znam jednak żadnych flag; ponieważ wszystkie znane mi wartości odpowiadają 0x00, możliwe, że liczba palet to po prostu uint(32).

Za co dokładnie odpowiada PRT, nie jest mi znane; możliwe, że chodzi o 'Tabela Palet i Zasobów' - ponieważ ten plik - znajdowany jako op2_art.prt w maps.vol - jest takim plikiem, a ta nazwa dobrze opisuje jego funkcję.

Ten plik zawiera listę palet, tabelę wszystkich używanych bitmap, wszystkie definicje animacji oraz szereg nieznanych danych. Luźno podąża za dotychczasowym formatem kontenera, ponieważ nie wszystkie rekordy są zgodne z tym schematem.

Sekcja CPAL (prawdopodobnie oznaczająca kontener palet) obejmuje jedynie dane palet, wskazując, ile z typowo 1052-bajtowych 8-bitowych palet jest dostępnych.

Podana wartość 1052 bajtów nie jest wiążąca, ponieważ format palet potencjalnie przewiduje różne rozmiary palet. Dotyczy to jedynie zbioru danych, z którym dostarczany jest Outpost 2.

Bezpośrednio po liście palet, i to bez wstępnego nagłówka, następuje lista bitmap; natychmiast po niej pojawiają się listy animacji.
Obie zaczynają się odpowiednio od uint(32) (lub znowu uint24+uint8 flagi?), które zawierają liczbę rekordów.

Palety

Adres x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF znak
0x0000 50 50 41 4c -- -- -- -- -- -- -- -- -- -- -- -- P P A L . . . . . . . . . . . .
Przesunięcie Typ danych Nazwa Wyjaśnienie
0x0000 uint(32) Bajty Magii
0x0004 uint(24) Długość palety

W przeciwieństwie do normalnego formatu bloku, podaje liczbę palet znajdujących się w tym pliku - nie długość bloku w bajtach.

0x0007 uint(8) Flagi

Prawdopodobnie, jak zwykle, flagi.

Nie znam jednak żadnych flag; ponieważ wszystkie znane mi wartości odpowiadają 0x00, mogłoby być również potencjalnie możliwe, że liczba palet to po prostu uint(32).

Informacje o paletach są bardzo łatwe do odczytania.
Składają się z nagłówka i segmentu danych.

Nagłówek palet

Adres x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF znak
0x0000 68 65 61 64 -- -- -- -- -- -- -- -- -- -- -- -- h e a d . . . . . . . . . . . .
Przesunięcie Typ danych Nazwa Wyjaśnienie
0x0000 uint(32) Bajty Magii
0x0004 uint(24) Długość palety

W przeciwieństwie do normalnego formatu bloku, podaje liczbę palet znajdujących się w tym pliku - nie długość bloku w bajtach.

0x0007 uint(8) Flagi

Prawdopodobnie, jak zwykle, flagi.

Nie znam jednak żadnych flag; ponieważ wszystkie znane mi wartości odpowiadają 0x00, mogłoby być również potencjalnie możliwe, że liczba palet to po prostu uint(32).

0x0008 uint(32) Wersja formatu palet?

Prawdopodobnie definiuje, która wersja formatu palet w danej palecie jest stosowana.

Wszystkie palety Outpost2 wydają się mieć wersję 0x01.

Dane palet

Adres x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF znak
0x0000 64 61 74 61 -- -- -- -- -- -- -- -- -- -- -- -- d a t a . . . . . . . . . . . .
Przesunięcie Typ danych Nazwa Wyjaśnienie
0x0000 uint(32) Bajty Magii
0x0004 uint(24) Długość bloku
0x0007 uint(8) Flagi

Sekcja danych zawiera poszczególne wpisy palet. Liczba wpisów palet wynika z długości bloku / 4.

Pojedyncze wpisy mają następującą, prostą strukturę;

Adres x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF znak
0x0000 -- -- -- 04 -- -- -- -- -- -- -- -- -- -- -- -- . . . . . . . . . . . . . . . .
Przesunięcie Typ danych Nazwa Wyjaśnienie
0x0000 uint(8) Komponent czerwony

Określa udział koloru czerwonego

0x0001 uint(8) Komponent zielony

Określa udział koloru zielonego

0x0002 uint(8) Komponent niebieski

Określa udział koloru niebieskiego w barwie

0x0003 uint(8) Nieznane - Flagi?

Nie jest jasne, co oznacza ta wartość, ponieważ wydaje się, że zasadniczo jest 0x04.

O paletach można dodać tylko tyle, że dla palet używanych w animacjach obowiązują następujące zasady:

  • Pierwszy kolor jest ZAWSZE przezroczysty, niezależnie od podanej wartości.
  • Pozycje palet 1-24 są traktowane jako kolory graczy w paletach 1-8.
    Gdzie dokładnie pochodzą kolory poza kolorem gracza 1, nie jest dla mnie jasne.
    Podejrzewam, że pozostałe kolory są zakodowane na stałe.

Referencja palet

Obrazy rastrowe

Adres x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF znak
0x0000 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- . . . . . . . . . . . . . . . .
0x0010 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- . . . . . . . . . . . . . . . .
Przesunięcie Typ danych Nazwa Wyjaśnienie
0x0000 uint(32) Szerokość wyrównana

Podaje szerokość linii danych pikseli w bajtach - ponieważ są one wyrównane do granic 4 bajtów.

Dzięki temu szybko można przejść do konkretnej linii obrazu.

Dlaczego ta wartość jest przechowywana oddzielnie, mimo że mogłaby być obliczona, nie jest jasne.
Możliwe, że jest to optymalizacja dla kodu renderującego.

0x0004 uint(32) Przesunięcie

Określa przesunięcie pierwszej linii w bitmapie

0x0008 uint(32) Wysokość

Podaje wysokość obrazu w pikselach

0x000c uint(32) Szerokość

Podaje szerokość obrazu w pikselach

0x0010 uint(16) Typ

Określa rodzaj obrazu. Wydaje się, że jest to maska bitowa:

  • 0x04 jest ustawione, jeśli jest to grafika 1bpp.
  • 0x40 jest ustawione, jeśli jest to grafika, która musi realizować okna.
0x0012 uint(16) Paleta

Określa, która paleta z pliku PRT ma być używana

Struktura danych pliku PRT określa, jak są zbudowane bitmapy używane dla sprite'ów. Bitmapy te służą jako pojedynczy element, z którego wiele łączy się w klatkę animacji sprite'a.

Konkretnych danych obrazowych można znaleźć w op2_art.BMP w katalogu gry.
Jest niejasne, dlaczego ten plik bitmapowy posiada (przeważnie poprawny) nagłówek RIFF-Bitmap, ale prawdopodobnie Outpost 2 wykorzystuje systemowe API do ładowania grafik, tymczasowo przejmując ten nagłówek i nadpisując odpowiednie, zmienne pola.

Dane pikseli znajdują się w pliku BMP na pozycji Offset + uint32-Offset, który znajduje się w pliku BMP pod adresem 0x000A (offset danych RIFF-Bitmap) i odpowiada ponownie liniowemu układowi od góry do dołu, z lewej do prawej.

Grafiki monochromatyczne 1bpp mogą być rysowane w sposób, że kolor 0 oznacza pełną przezroczystość, a kolor 1 to półprzezroczysty czarny/szary, ponieważ monochromatyczne grafiki są zwykle używane do cieni pojazdów i budynków w animacjach.

Dzięki temu można już złożyć wiele grafik.

Ochroniony moduł mieszkalny (Plymouth)

Animacje

Teraz przechodzimy do królewskiej klasy dyscyplin w formatach danych Outpost 2:
Do animacji.

Listy animacji rozpoczynają się od globalnego nagłówka, który służy głównie do weryfikacji danych. Następnie pojawiają się konkretne definicje animacji, które dzielą się na 3 poziomy:

  1. Animacja
    Animacja to najwyższa instancja; przedstawia animację jednostki, budynku lub 'animacji cząsteczkowej' (uderzenie komety, pogoda, wybuch) w określonej sytuacji początkowej.
  2. Klucz
    Klucz to pojedynczy obrazek w ramach animacji. Animacja może zawierać jeden lub więcej kluczy.
  3. Podklucz
    Podklucz to informacja o tym, że określona bitmapa ma być rysowana w określonej pozycji klucza według określonych kryteriów. Klucz może zawierać jeden lub więcej podkluczy.

Następnie pojawiają się już bezpośrednio poszczególne definicje animacji.

Adres x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF znak
0x0000 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- . . . . . . . . . . . . . . . .
Przesunięcie Typ danych Nazwa Wyjaśnienie
0x0000 uint(32) Liczba animacji

Ile jest dostępnych zbiorów danych animacji

0x0004 uint(32) Liczba klatek

Ile ramek powinno być łącznie dostępnych

0x0008 uint(32) Liczba subramków

Ile subram dla wszystkich powinno być dostępnych

0x000c uint(32) Liczba opcjonalnych wpisów

Ile "opcjonalnych wpisów" jest dostępnych.

Animacja

Adres x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF znak
0x0000 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- . . . . . . . . . . . . . . . .
0x0010 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- . . . . . . . . . . . . . . . .
0x0020 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- . . . . . . . . . . . . . . . .
Przesunięcie Typ danych Nazwa Wyjaśnienie
0x0000 uint(32) Nieznany 1

Nieznane informacje

0x0004 uint(32) Ramka ograniczająca: Lewo

Podaje lewy początek (w pikselach) Bounding Box.

0x0008 uint(32) Bounding Box: Górny

Określa górny początek (w pikselach) Bounding Box.

0x000c uint(32) Bounding Box: Szerokość

Określa szerokość (w pikselach) Bounding Box.

0x0010 uint(32) Ramka ograniczająca: Wysokość

Podaje wysokość (w pikselach) Bounding Box.

0x0014 uint(32) Przesunięcie: X

Określa poziomy środek animacji

0x0018 uint(32) Offset: Y

Określa pionowy środek animacji

0x001c uint(32) Nieznany 2

Nieznana informacja

0x0020 uint(32) Liczba klatek

Określa, ile klatek animacji znajduje się w tej animacji

0x0024 uint(32) Liczba okien

Określa, ile okien należy zastosować podczas rysowania

Dane najwyższej warstwy animacji to przede wszystkim dane administracyjne - Boundingbox oznacza współrzędne oznaczenia wokół pojazdu/budynku, kiedy jest on wybrany, i jednocześnie wskazuje, który obszar powinien być klikalny.

Offset przede wszystkim określa "punkt zerowy"; punkt, który należy dodać lub odjąć od współrzędnych wewnętrznych gry. Można to również ująć matematycznie: offset tutaj oznacza oryginał współrzędnych.

W przypadku okien, podobnie jak w przypadku offsetu, mamy do czynienia z 4 wartościami uint(32) dla każdego okna, które określają obszar uznawany za użyteczny dla poszczególnych subframe'ów. Poza oknami nie wolno rysować, o ile nie jest to odpowiednio przewidziane dla bitmapy.

Ramka

Adres x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF znak
0x0000 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- . . . . . . . . . . . . . . . .
Przesunięcie Typ danych Nazwa Wyjaśnienie
0x0000 uint(8) Liczba subframe'ów i przełącznik dla Opcjonalny 1, 2

Ta wartość zawiera:

  • 0x7F (Maska bitowa): Liczba subframe'ów używanych w tym ramce
  • 0x80: Informacja o tym, czy Opcjonalne 1 i 2 są obecne
0x0001 uint(8) Nieznany 1 i przełącznik dla Opcjonalny 3, 4

Ta wartość zawiera:

  • 0x7F (Maska bitowa): Nieznane - Mocno podejrzewam, że chodzi o liczbę gameticków, które upłyną, zanim zostanie wyświetlona następna klatka
  • 0x80: Informacja o tym, czy Opcjonalne 3 i 4 są obecne
0x0002 uint(8) Opcjonalny 1

Nieznany

0x0003 uint(8) Opcjonalny 2

Nieznany

0x0004 uint(8) Opcjonalny 3

Nieznany

0x0005 uint(8) Opcjonalny 4

Nieznany

Podramka

Adres x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF znak
0x0000 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- . . . . . . . . . . . . . . . .
Przesunięcie Typ danych Nazwa Wyjaśnienie
0x0000 uint(16) Bitmap-Id

Określa, która bitmapa ma być użyta dla tego podramki

0x0002 uint(8) Nieznany 1

Jest to nieznane - jednak mocno przypuszczam, że chodzi tutaj o priorytet renderowania (Z-warstwa).

0x0003 uint(8) Id podramy

Wskazuje, w którym subramce się znajdujemy

0x0004 sint(16) Offset - Poziomy

Określa, gdzie w obrębie ramki powinno zostać umieszczone subramka, lub o ile pikseli bitmapa powinna być przesunięta w poziomie

0x0006 sint(16) Offset - Wertykalny

Określa, gdzie wewnątrz ramki powinno być umieszczone podramka, lub o ile pikseli bitmapa ma być przesunięta w pionie

Dzięki temu możemy teraz łączyć pojedyncze klatki oraz całe animacje, co zostało zaprezentowane na przykładzie bardziej złożonej animacji o indeksie 500.

Animacja 500

Animacja 500 pokazuje, jak transportowiec Plymouth, załadowany standardowym rudzikiem, jest rozładowywany. Jest to jedna z niewielu animacji, która wykorzystuje funkcjonalność okienkową.

I tak można połączyć całą animację.
Niestety, wciąż istnieje problem z górnym włazem ładunkowym, ponieważ odpowiedni bit w informacji o typie grafiki nie jest ustawiony.

Oto jeszcze kilka innych, pięknie animowanych sprite'ów z gry:

Renderowanie animacji 500 ilustrowane

Animacja 500 gotowa do połączenia

Fabryka budynków Plymouth

Port kosmiczny Eden

Centrum medyczne Eden

SCAT

Port kosmiczny Plymouth

Easteregg:
Mikołaj

Easteregg:
Piesek Dans

Interfejs użytkownika

Teraz brakuje jeszcze interfejsu użytkownika gry, który utrzymany jest w stylu szczotkowanego metalu.

Ale także tutaj widać, że Dynamix nie musiało wynajdywać koła na nowo; nie tylko prosto korzystają z API User32 i GDI32 dostarczonych przez Windows - szczególnie wykorzystywane jest także zarządzanie zasobami z User32.

Można je na przykład wyodrębnić za pomocą programów takich jak Resource Hacker, opracowanego przez Angusa Johnsona jako oprogramowanie freeware, lub - jeśli ktoś unika używania Wine na Linuxie / Mac OS - przy pomocy wrestool, które jest częścią icoutils.

Nazwa pliku Zawartość
Outpost2.exe Zawiera jedynie ikonę gry, przedstawiającą stację kosmiczną przed New Terra
op2shres.dll Zawiera grafiki dla elementów sterujących, takich jak ramki, przyciski, przyciski radiowe i pola wyboru, a także tła dialogów, obrazki towarzyszące tekstom misji fabularnych oraz grafikę tła głównego menu
out2res.dll Zawiera dekoracje okien in-game, ikony dla zwykłego i specjalnego metalu, ekran ładowania, grafiki dla dialogów oraz dodatkowe grafiki kursora, oprócz animowanych w katalogu gry