Outpost 2 Bestandsformaten · bei.pm
De op deze pagina beschreven bestandsformaten zijn gebaseerd op de technische analyse van intellectueel eigendom van Dynamix, Inc. en Sierra Entertainment.
Het intellectueel eigendom maakt vandaag de dag deel uit van de massa van Activision Publishing, Inc. / Activision Blizzard, Inc. en is momenteel in bezit van Microsoft Corp..
De informatie is verzameld door middel van Reverse Engineering en data-analyse met als doel archivering en interoperabiliteit met historische gegevens.
Er zijn geen eigendomsrechtelijke of vertrouwelijke specificaties gebruikt.
Het spel is momenteel verkrijgbaar als download op gog.com.
De volgende artikelenreeks documenteert mijn bevindingen over de gegevensformaten in de real-time strategiespel "Outpost 2: Divided Destiny", dat in 1997 werd uitgebracht door Sierra en ontwikkeld door Dynamix.
Ik heb me van ongeveer 1 november 2015 tot 14 november 2015 voornamelijk beziggehouden met de analyse van de gegevens van het spel - en wat ermee gedaan kan worden.
Volgens de informatie die ik tot nu toe heb kunnen verzamelen, heeft Dynamix - zoals veel commerciële bedrijven - enkele gegevensformaten niet specifiek voor Outpost 2 ontwikkeld, maar ook in andere ontwikkelingen, zoals de Mechwarrior-serie (aangepast), gebruikt.
Ongeacht dat kan ook worden vastgesteld dat de innovatiekracht van de gegevensformaten praktisch beperkt is en vaak is gebaseerd op langer bestaande concepten van gebruikelijke formaten zoals JFIF en RIFF.
Voor de interpretatie van de tabellen en gegevensformaten zijn verdere informatie beschikbaar onder Wat is wat?.
De hier opgegeven gegevens zijn in het algemeen te begrijpen als Little Endian.
Ten slotte kan worden gezegd dat het reverse engineering zeer veel plezier bracht, ook al is het niet volledig.
Natuurlijk kan ik ook alleen maar aanraden het spel zelf te spelen, aangezien het interessante spelmechanismen biedt.
Inleiding
De door Outpost 2 gebruikte gegevensformaten hebben een structuur die doet denken aan JFIF / PNG - de afzonderlijke datablokken hebben altijd een header van 8 bytes. Daarom laat ik het achterwege om de afzonderlijke headers op de bijbehorende specifieke plaatsen te documenteren en documenteer ik daar alleen afwijkingen.
Het formaat is altijd het volgende; de eigenlijke nuttige gegevens zijn daar dan in ingebed:
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | teken | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Gegevenstype | Benaming | Uitleg |
---|---|---|---|
0x0000 | uint(32) | Magische Bytes | Bevat informatie over wat te verwachten valt in het volgende datablok. Bekende waarden:
|
0x0004 | uint(24) | Bloklengte | Bevat de informatie over hoe groot (in bytes) de volgende gegevensblok is. Hierbij zijn de pure nuttige gegevens bedoeld - de 8 headerbytes zijn hierin niet inbegrepen. |
0x0007 | uint(8) | Vlaggen? | Het is onbekend waarvoor deze blok precies dient. In de volumes is deze waarde vaak 0x80, in andere bestanden vaak 0x00. Dit suggereert dat het om een vlaggenstel gaat. |
Volumes
Volumes zijn een gegevenscontainer voor het spel, vergelijkbaar met een archiefformaat zoals bijvoorbeeld Tarball. In ieder geval kent het formaat in Outpost 2 alleen bestanden - geen mappen. Waarschijnlijk kunnen deze echter worden gesimuleerd door middel van de juiste bestandsnamen.
Een Volume bestaat uit de Volume-header en uit meerdere Volume-blokken die overeenkomen met de specifieke bestanden.
"Volumes" zijn de bestanden met de extensie 'vol'
in de spelmap.
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | teken | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 56 | 4f | 4c | 20 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | V | O | L | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Gegevenstype | Benaming | Uitleg |
---|---|---|---|
0x0000 | uint(32) | Magische Bytes | |
0x0004 | uint(24) | Bloklengte | |
0x0007 | uint(8) | Vlaggen |
Volume Header
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | teken | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 76 | 6f | 6c | 68 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | v | o | l | h | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Gegevenstype | Benaming | Uitleg |
---|---|---|---|
0x0000 | uint(32) | Magische Bytes | |
0x0004 | uint(24) | Bloklengte | |
0x0007 | uint(8) | Vlaggen |
De Volume Header bevat op zijn beurt geen nuttige gegevens.
Hij dient alleen als container.
Als eerste gegevens in de Volume Header zouden de Volume Strings moeten staan; daarop volgen vervolgens de Volume-informatie.
Volume Strings
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | teken | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 76 | 6f | 6c | 69 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | v | o | l | i | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Gegevenstype | Benaming | Uitleg |
---|---|---|---|
0x0000 | uint(32) | Magische Bytes | |
0x0004 | uint(24) | Bloklengte | |
0x0007 | uint(8) | Vlaggen |
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | teken | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 76 | 6f | 6c | 73 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | v | o | l | s | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Gegevenstype | Benaming | Uitleg |
---|---|---|---|
0x0000 | uint(32) | Magische Bytes | |
0x0004 | uint(24) | Bloklengte | |
0x0007 | uint(8) | Vlaggen | |
0x0008 | uint(32) | Payload-lengte | Geeft aan hoeveel bytes van de volgende gegevens daadwerkelijk nuttige gegevens zijn. De resterende gegevens van de volume-strings-lijst kunnen blijkbaar als garbage worden beschouwd. In bestanden met een latere datum zijn deze 'resterende gegevens' 0x00, wat op tekortkomingen in de toolchain tijdens de ontwikkeling van het spel kan wijzen, dat wil zeggen dat een ontwikkelaar zich pas laat heeft beziggehouden met de juiste initialisatie van de buffers, aangezien het geen invloed heeft op het spel of de gegevens zijn geïnitialiseerd of niet. |
0x000c | uint(8)[] | Bestandsnaam-lijst | Dit betreft een nul-byte-terminerende lijst van bestandsnamen, die - althans in de huidige gegevenscomponent - alleen ASCII-tekens verwacht. Het is niet nodig om bij het parseren van de gegevens deze gegevensblok uitgebreider te evalueren, aangezien in de volume-informatie de offsets van de bestandsnamen direct worden gerefereerd. |
De Volume Strings zijn een lijst van bestandsnamen die binnen het volume bevat zijn.
Volume-informatie
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | teken | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 76 | 6f | 6c | 69 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | v | o | l | i | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Gegevenstype | Benaming | Uitleg |
---|---|---|---|
0x0000 | uint(32) | Magische Bytes | |
0x0004 | uint(24) | Bloklengte | |
0x0007 | uint(8) | Vlaggen |
De volume-informatie bevat gedetailleerdere informatie over de bestanden. Het is in zekere zin een soort FAT-directory-invoer (FAT = File Allocation Table)
Het aantal bestanden wordt berekend door de blokgrootte te delen door de lengte van de directory-invoeren - 14 byte.
De individuele directory-invoeren hebben elk de volgende structuur:
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | teken | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Gegevenstype | Benaming | Uitleg |
---|---|---|---|
0x0000 | uint(32) | Bestandsnaam-offset | Geeft aan op welke offset (!) binnen de bestandsnamenlijst (volume-strings) de bestandsnaam van het bestand zich bevindt. Verwijst hierbij naar het begin van het datablok. |
0x0004 | uint(32) | Bestandsoffset | Geeft aan op welke offset binnen het gehele volume-bestand het bestand zich bevindt. |
0x0008 | uint(32) | Bestandsgrootte | Geeft aan hoe groot het bestand in bytes is. |
0x000c | uint(16) | Vlaggen? | Blijkbaar worden er extra informatie over de bestandscodering gegeven.
|
Volume Blok
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | teken | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 56 | 42 | 4c | 48 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | V | B | L | H | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Gegevenstype | Benaming | Uitleg |
---|---|---|---|
0x0000 | uint(32) | Magische Bytes | |
0x0004 | uint(24) | Bloklengte | |
0x0007 | uint(8) | Vlaggen |
Een volume-blok is een container die bestanden opslaat. Het bevat alleen nogmaals - vanwege het blokformaat - redundante informatie over de bestandsgrootte, en daarachter volgen direct de bruikbare gegevens.
Tegels
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | teken | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 50 | 42 | 4d | 50 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | P | B | M | P | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Gegevenstype | Benaming | Uitleg |
---|---|---|---|
0x0000 | uint(32) | Magische Bytes | |
0x0004 | uint(24) | Bloklengte | |
0x0007 | uint(8) | Vlaggen |
De tiles zijn een specifiek Bitmap-grafiekformaat voor Outpost-2. Ze bestaan uit 13 tilesets,
"wells" genoemd (well0000.bmp
tot well0012.bmp
),
die zich binnen de volume maps.vol bevinden.
De tilesets / wells bevatten het volgende:
Bestandsnaam | Inhoud |
---|---|
well0000.bmp | Een 32x32px grote, blauwe afbeelding - ideaal als test om te zien of je eigen afbeeldingslader werkt |
well0001.bmp | Bevat licht gesteente, bergketens op licht gesteente en talloze varianten van inslagkraters in licht gesteente |
well0002.bmp | Bevat licht-gesteente 'Doodads' - dus elementen die voor verfraaiing (of bewust als structuur, zoals muren) op licht gesteente geplaatst kunnen worden, waaronder ook vegetatie |
well0003.bmp | Bevat een korstachtige structuur op licht gesteente |
well0004.bmp | Bevat donker gesteente, bergketens op donker gesteente en talloze varianten van inslagkraters in donker gesteente |
well0005.bmp | Bevat donker-gesteente 'Doodads' - dus elementen die voor verfraaiing (of bewust als structuur, zoals muren) op donker gesteente geplaatst kunnen worden |
well0006.bmp | Bevat een korstachtige structuur op donker gesteente, evenals overgangen tussen licht en donker gesteente |
well0007.bmp | Bevat lava inclusief 4-5 frames animatie ervan |
well0008.bmp | Bevat zand en talloze varianten van inslagkraters in zand |
well0009.bmp | Bevat zand-'Doodads' - dus elementen die voor verfraaiing (of bewust als structuur, zoals muren) op zand geplaatst kunnen worden |
well0010.bmp | Bevat elk 48 overgangen van zand naar licht en donker gesteente |
well0011.bmp | Bevat de poolkappen van de map, met donker gesteente als ondergrond |
well0012.bmp | Bevat de poolkappen van de map, met licht gesteente als ondergrond |
Het is raadzaam voor een accurate uitvoering om de tiles niet van tevoren te renderen om deze te cachen, omdat de gegevens voor de dag/nacht-cyclus nog verwerkt moeten worden - en er zouden zeer veel gegevens ontstaan.
De tiles zijn 8bpp-afbeeldingen met een geïndexeerde palet van elk 32x32 pixels resolutie, die onder elkaar zijn gerangschikt. In een dergelijk ontstaan tileset kunnen echter veel meer
De hoofdcontainer bestaat uit 2 secties: head
en data
.
Vloertegels Koptekst
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | teken | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 68 | 65 | 61 | 64 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | h | e | a | d | . | . | . | . | . | . | . | . | . | . | . | . |
0x0010 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Gegevenstype | Benaming | Uitleg |
---|---|---|---|
0x0000 | uint(32) | Magische Bytes | |
0x0004 | uint(24) | Bloklengte | |
0x0007 | uint(8) | Vlaggen | |
0x0008 | uint(32) | Versie / Vlaggen? | Dit zou een versienummer van het bestandstype kunnen zijn; in alle bestanden die ik heb, stond hier de waarde |
0x000c | uint(32) | Breedte (Horizontale Resolutie) | Geeft aan hoe breed het afbeeldingsbestand is (in pixels). Bij alle wells van Outpost 2 zal hier de waarde |
0x0010 | uint(32) | Hoogte (Verticale resolutie) | Geeft aan hoe hoog het afbeeldingsbestand is (in pixels). Bij alle wells van Outpost 2 zal hier de waarde |
0x0014 | uint(32) | Kleurdiepte? | De betekenis van deze waarde is onbekend. Aangezien hij in alle gecontroleerde bestanden de waarde |
0x0018 | uint(32) | Kleurdiepte 2? | De betekenis van deze waarde is onbekend. Het kan een 'doel'-kleurdiepte zijn. |
Na deze gegevens volgt er nog een palettend bestand in het gestandaardiseerde RIFF-formaat. De exacte specificatie is te vinden - aangezien de paletten ook op andere plaatsen voorkomen - onder Paletten.
Tiles Gegevens
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | teken | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 64 | 61 | 74 | 61 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | d | a | t | a | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Gegevenstype | Benaming | Uitleg |
---|---|---|---|
0x0000 | uint(32) | Magische Bytes | |
0x0004 | uint(24) | Bloklengte | |
0x0007 | uint(8) | Vlaggen |
Eindelijk volgen hier de ruwe pixeld gegevens, van linksboven regel voor regel naar rechtsonder.
De dataverdienste van de in de regel als 8bpp-bitmaps weergegeven afbeeldingen komt overeen met de index van de kleur in de kleurenpalet.
De spel-engine tekent de tegels *waarschijnlijk* on-demand.
Dit lijkt onder andere te maken te hebben met de dag-nachtcyclus, die 32 gradaties van individuele tegels kent. Daarbij wordt blijkbaar van de helderheidswaarde telkens 'een beetje' afgetrokken. Nauwkeurige waarden zijn nog niet vastgesteld, ik werk op basis van de berekening
v *= (daylight / 48) + 0.25;
met de HSV-gegevens van de pixels, waarbij daylight een waarde van 0-31 is en v een waarde tussen 0-1. Bovendien moet in overweging worden genomen dat er op de kaart aan beide zijden nog een rand van 16 tegels bestaat (die dient voor het onzichtbaar spawnen van eenheden).
Aanvullend lijkt de dag-nachtcyclus per spelcyclus telkens slechts één kolom van de kaart bij te werken.
Een versnelde dag-nachtcyclus ziet er daarom als volgt uit:
PRT
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | teken | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 43 | 50 | 41 | 4c | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | C | P | A | L | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Gegevenstype | Benaming | Uitleg |
---|---|---|---|
0x0000 | uint(32) | Magische Bytes | |
0x0004 | uint(24) | Palletlengte | Geeft, in tegenstelling tot het normale blokformaat, het aantal paletten aan dat in dit bestand te vinden is - niet de lengte van het blok in bytes. |
0x0007 | uint(8) | Vlaggen | Waarschijnlijk, zoals gebruikelijk, vlaggen. Ik ken echter geen vlaggen; aangezien alle waarden die ik ken overeenkomen met |
Waarvoor PRT
precies staat, is mij onbekend; het zou bijvoorbeeld 'Palette and Resource Table' kunnen zijn - aangezien dit bestand, te vinden als op2_art.prt in de maps.vol, zo'n tabel betreft, of dit zou de functie goed beschrijven.
Dit bestand bevat een lijst van paletten, een tabel van alle gebruikte bitmaps, alle animatiedefinities en nog een aantal onbekende gegevens. Het volgt de bestaande containerstructuur losjes, aangezien niet alle gegevens zich aan dit schema houden.
De CPAL
-sectie (waarschijnlijk staat het voor Paletten-Container) omvat alleen de palettendata, door aan te geven hoeveel van de gebruikelijke 1052 byte grote 8-bits paletten aanwezig zijn.
De vermelding van 1052 bytes geldt niet als bindend, aangezien het palettenformaat potentieel verschillende paletgroottes zou kunnen bevatten. Het geldt alleen voor de dataset die met Outpost 2 wordt meegeleverd.
Na de palettenlijsten volgt direct en zonder inleidende kop, al de lijst van bitmaps; net zo direct volgen daarop de animatielijsten.
Beiden worden elk ingeleid met een uint(32) (of weer uint24+uint8 vlaggen?) die het aantal records bevat.
Paletten
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | teken | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 50 | 50 | 41 | 4c | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | P | P | A | L | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Gegevenstype | Benaming | Uitleg |
---|---|---|---|
0x0000 | uint(32) | Magische Bytes | |
0x0004 | uint(24) | Paletlengte | Geeft, in tegenstelling tot het normale blokformaat, het aantal paletten aan dat in dit bestand te vinden is - niet de lengte van het blok in bytes. |
0x0007 | uint(8) | Vlaggen | Waarschijnlijk, zoals gebruikelijk, vlaggen. Ik ken echter geen vlaggen; aangezien alle waarden die ik ken overeenkomen met |
De palletinformatie is zeer eenvoudig te lezen.
Deze bestaat uit een header en een datasegment.
Palettenkop
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | teken | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 68 | 65 | 61 | 64 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | h | e | a | d | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Gegevenstype | Benaming | Uitleg |
---|---|---|---|
0x0000 | uint(32) | Magische Bytes | |
0x0004 | uint(24) | Paletlengte | Geeft, in tegenstelling tot het normale blokformaat, het aantal paletten aan dat in dit bestand te vinden is - niet de lengte van het blok in bytes. |
0x0007 | uint(8) | Vlaggen | Waarschijnlijk, zoals gebruikelijk, vlaggen. Ik ken echter geen vlaggen; aangezien alle waarden die ik ken overeenkomen met |
0x0008 | uint(32) | Palettenformaat-versie? | Definieert waarschijnlijk welke paletformat-versie het palet volgt. Alle Outpost2-paletten lijken versie |
Palletgegevens
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | teken | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 64 | 61 | 74 | 61 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | d | a | t | a | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Gegevenstype | Benaming | Uitleg |
---|---|---|---|
0x0000 | uint(32) | Magische Bytes | |
0x0004 | uint(24) | Bloklengte | |
0x0007 | uint(8) | Vlaggen |
De datasectie bevat de afzonderlijke palletinvoer. Het aantal palletinvoer wordt berekend als de bloklengte / 4.
De afzonderlijke invoeren hebben de volgende eenvoudige structuur;
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | teken | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | -- | -- | -- | 04 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Gegevenstype | Benaming | Uitleg |
---|---|---|---|
0x0000 | uint(8) | Rode component | Geeft het roodpercentage van de kleur aan |
0x0001 | uint(8) | Groene component | Geeft het groenpercentage van de kleur aan |
0x0002 | uint(8) | Blauw-component | Geeft het blauwpercentage van de kleur aan |
0x0003 | uint(8) | Onbekend - Vlaggen? | Het is onduidelijk wat deze waarde betekent, aangezien deze blijkbaar in principe |
Wat de paletten betreft, is verder alleen nog te zeggen dat de volgende regels gelden voor paletten die voor animaties worden gebruikt:
- De eerste kleur is ALTIJD transparant, ongeacht welke waarde daar is opgegeven.
-
De paletten-items 1-24 worden in de paletten 1-8 als spelerskleur beschouwd.
Waar de kleuren buiten speler 1 precies vandaan komen, is mij onduidelijk.
Ik vermoed dat de overige kleuren hardcoded zijn.
Bitmaps
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | teken | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
0x0010 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Gegevenstype | Benaming | Uitleg |
---|---|---|---|
0x0000 | uint(32) | Uitgelijnde breedte | Geeft de breedte van de pixelgegevensrijen in bytes aan - omdat deze zijn uitgelijnd op de 4-byte grenzen. Hierdoor is het snel mogelijk om een bepaalde beeldrij te bereiken. Waarom deze waarde apart wordt opgeslagen, hoewel deze berekend zou kunnen worden, is onduidelijk. |
0x0004 | uint(32) | Offset | Geeft de offset van de eerste regel in de bitmap aan |
0x0008 | uint(32) | Hoogte | Geeft de hoogte van de afbeelding in pixels aan |
0x000c | uint(32) | Breedte | Geeft de breedte van de afbeelding in pixels aan |
0x0010 | uint(16) | Typ | Geeft het type afbeelding aan. Het lijkt hier te gaan om een bitmasker:
|
0x0012 | uint(16) | Palet | Definieert welke palette uit het PRT-bestand gebruikt moet worden |
Deze datastructuur van het PRT-bestand geeft aan hoe de bitmapafbeeldingen die voor de sprites worden gebruikt zijn opgebouwd. Deze bitmaps dienen als afzonderlijke onderdelen, waarvan er meerdere worden samengevoegd tot een animatieframe van een sprite.
De specifieke afbeeldingsgegevens bevinden zich daarentegen in de
op2_art.BMP in de spelmap.
Waarom dit bitmapbestand beschikt over een (overwegend correcte) RIFF-bitmapheader, is onduidelijk. Waarschijnlijk gebruikt Outpost 2 systeem-API's om de graphics te laden, door deze header tijdelijk over te nemen en de bijbehorende, variërende velden te overschrijven.
De pixelgegevens zijn in het BMP-bestand te vinden op de positie Offset + de uint32-offset, die in het BMP-bestand op adres 0x000A te vinden is (RIFF-bitmapgegevensoffset), en komen overeen met de regelmatige indeling van linksboven naar rechtsonder.
Monochrome 1bpp-graphics kunnen zo worden getekend, dat kleur 0 volledige transparantie heeft, terwijl kleur 1 een semi-transparant zwart/grijs is, aangezien de monochrome graphics doorgaans worden gebruikt voor voertuig- en gebouwschaduwen in de animaties.
Dit stelt je in staat om al veel graphics samen te stellen.
Animaties
Nu komen we bij de koningsklasse van de disciplines binnen de Outpost 2 dataformaten:
De animaties.
De animatielijsten worden ingeleid met een globale header, die primair dient voor dataverificatie. Vervolgens volgen de specifieke animatiedefinities, die zijn onderverdeeld in 3 niveaus:
-
Animatie
Een animatie is de hoogste instantie; het stelt een animatie van een eenheid, een gebouw of een 'deeltjesanimatie' (kometinslag, weer, explosie) in een bepaalde beginpositie voor. -
Frame
Een frame is een enkel beeld binnen een animatie. Een animatie kan één of meerdere frames bevatten. -
Subframe
Een subframe is de informatie dat een bepaalde bitmap onder bepaalde criteria op een specifieke positie van een frame moet worden getekend. Een frame kan één of meerdere subframes bevatten.
Vervolgens volgen direct de afzonderlijke animatiedefinities.
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | teken | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Gegevenstype | Benaming | Uitleg |
---|---|---|---|
0x0000 | uint(32) | Aantal animaties | Hoeveel animatiedatasets zijn er beschikbaar |
0x0004 | uint(32) | Aantal frames | Hoeveel frames zouden er in totaal aanwezig moeten zijn |
0x0008 | uint(32) | Aantal subframes | Hoeveel subframes zouden er in totaal aanwezig moeten zijn |
0x000c | uint(32) | Aantal optionele invoeren | Hoeveel "optionele invoer" zijn er aanwezig. |
Animatie
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | teken | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
0x0010 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
0x0020 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Gegevenstype | Benaming | Uitleg |
---|---|---|---|
0x0000 | uint(32) | Onbekend 1 | Onbekende informatie |
0x0004 | uint(32) | Bounding Box: Links | Geeft de linkerpositie (in pixels) van de Bounding Box aan. |
0x0008 | uint(32) | Bounding Box: Boven | Geeft de bovenste start (in pixels) van de Bounding Box aan. |
0x000c | uint(32) | Bounding Box: Breedte | Geeft de breedte (in pixels) van de Bounding Box aan. |
0x0010 | uint(32) | Bounding Box: Hoogte | Geeft de hoogte (in pixels) van de Bounding Box aan. |
0x0014 | uint(32) | Offset: X | Geeft het horizontale middenpunt van de animatie aan |
0x0018 | uint(32) | Offset: Y | Geeft het verticale middenpunt van de animatie aan |
0x001c | uint(32) | Onbekend 2 | Onbekende informatie |
0x0020 | uint(32) | Aantal frames | Geeft aan hoeveel animatieframes in deze animatie zijn opgenomen |
0x0024 | uint(32) | Aantal vensters | Geeft aan hoeveel vensters er bij het tekenen moeten worden toegepast |
De gegevens van de bovenste laag, de animatie, zijn voornamelijk beheergegevens - de Boundingbox geeft de coördinaten van de markering rondom het voertuig/gebouw aan, wanneer deze is geselecteerd en geeft tegelijkertijd aan welk gebied aanklikbaar moet zijn.
De offset bepaalt voornamelijk het "nulpunt"; het punt dat op de interne spelcoördinaten moet worden opgeteld of afgetrokken. Men zou ook wiskundig kunnen zeggen: de offset verwijst hier naar de coördinaten oorsprong.
De vensters bevatten, net als de offset, elk (per venster) 4 uint(32)-waarden, die een gebied aangeven dat voor individuele subframes als bruikbaar geldt. Buiten de vensters mag, voor zover dit voor de bitmap is voorzien, niet worden getekend.
Frame
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | teken | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Gegevenstype | Benaming | Uitleg |
---|---|---|---|
0x0000 | uint(8) | Subframe-aantal en Toggle voor Optioneel 1, 2 | Deze waarde bevat:
|
0x0001 | uint(8) | Onbekend 1 en Toggle voor Optioneel 3, 4 | Deze waarde bevat:
|
0x0002 | uint(8) | Optioneel 1 | Onbekend |
0x0003 | uint(8) | Optioneel 2 | Onbekend |
0x0004 | uint(8) | Optioneel 3 | Onbekend |
0x0005 | uint(8) | Optioneel 4 | Onbekend |
Subframe
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | teken | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Gegevenstype | Benaming | Uitleg |
---|---|---|---|
0x0000 | uint(16) | Bitmap-ID | Geeft aan welke bitmap voor dit subframe gebruikt moet worden |
0x0002 | uint(8) | Onbekend 1 | Het is onbekend - ik vermoed echter sterk dat dit te maken heeft met een renderprioriteit (Z-laag). |
0x0003 | uint(8) | Subframe-ID | Geeft aan in welk subframe we ons bevinden |
0x0004 | sint(16) | Verspringing - Horizontaal | Geeft aan waar binnen het frame het subframe geplaatst moet worden, of met hoeveel pixels de bitmap horizontaal verschoven moet worden |
0x0006 | sint(16) | Offset - Verticaal | Geeft aan waar binnen het frame het subframe geplaatst moet worden, of met hoeveel pixels de bitmap verticaal verschoven moet worden. |
Zo kunnen we nu individuele frames evenals complete animaties samenstellen, hier exemplaarmatig gedemonstreerd aan een complexere animatie, de animatie met index 500.
Animatie 500
Animatie 500 laat zien hoe een Plymouth-vrachtwagen, die geladen is met gewone ertsen, wordt gelost. Dit is een van de weinige animaties die de vensterfunctionaliteit benut.
En zo kan de complete animatie worden samengevoegd.
Helaas is er nog een probleem met het bovenste laadluik, omdat hier de bijbehorende bit in de grafiektype-informatie niet is ingesteld.
Hier zijn nog een paar andere prachtig geanimeerde sprites uit het spel:
Gebruikersinterface
Nu ontbreekt alleen nog de gebruikersinterface van het spel, die in een geborsteld metaal uiterlijk is uitgevoerd.
Maar ook hier is te zien dat Dynamix het wiel niet opnieuw hoefde uit te vinden; hier worden niet alleen eenvoudig de door Windows geleverde User32- en GDI32-API's gebruikt - vooral wordt ook het resourcebeheer van User32 toegepast.
Dit kan bijvoorbeeld worden geëxtraheerd met programma's zoals de door Angus Johnson als freeware ontwikkelde Resource Hacker, of - als je onder Linux / Mac OS het gebruik van Wine vermijdt - met behulp van de in icoutils opgenomen wrestool.
Bestandsnaam | Inhoud |
---|---|
Outpost2.exe | Bevat enkel het pictogram van de game, dat het ruimtestation voor New Terra toont |
op2shres.dll | Bevat naast afbeeldingen voor bedieningscomponenten zoals randen, knoppen, radio-knoppen en selectievakjes ook dialoog-achtergronden, begeleidende afbeeldingen voor de verhaal-missie teksten en de achtergrondafbeelding van het hoofdmenu |
out2res.dll | Bevat de in-game vensterdecoratie, pictogrammen voor gewoon en speciaal metaal, het laadscherm, afbeeldingen voor dialogen en verdere cursorafbeeldingen, naast de geanimeerde in de spelmap |