Formaty plików Outpost 2 · bei.pm
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.
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:
|
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.
|
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 |
0x000c | uint(32) | Szerokość (Rozdzielczość pozioma) | Określa, jak szeroki jest plik graficzny (w pikselach). Wszystkie studnie z Outpost 2 powinny mieć tutaj wartość |
0x0010 | uint(32) | Wysokość (Rozdzielczość pionowa) | Określa, jak wysoki jest plik obrazu (w pikselach). Wszystkie studnie w Outpost 2 powinny mieć tutaj wartość |
0x0014 | uint(32) | Głębokość koloru? | Znaczenie tej wartości jest nieznane. Ponieważ we wszystkich sprawdzonych plikach zawiera wartość |
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.
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:
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ą |
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ą |
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ą |
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ę |
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 |
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.
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. |
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:
|
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.
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:
-
Animacja
Animacja to najwyższa instancja; przedstawia animację jednostki, budynku lub 'animacji cząsteczkowej' (uderzenie komety, pogoda, wybuch) w określonej sytuacji początkowej. -
Klucz
Klucz to pojedynczy obrazek w ramach animacji. Animacja może zawierać jeden lub więcej kluczy. -
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:
|
0x0001 | uint(8) | Nieznany 1 i przełącznik dla Opcjonalny 3, 4 | Ta wartość zawiera:
|
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:
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 |