Outpost 2 Filformat · bei.pm
De filformat som beskrivs på denna sida är baserade på teknisk analys av immateriella rättigheter från Dynamix, Inc. och Sierra Entertainment.
Det immateriella rättigheterna är idag en del av Activision Publishing, Inc.- / Activision Blizzard, Inc.-massan och ägs för närvarande av Microsoft Corp..
Informationen har sammanställts genom Reverse Engineering och dataanalys för syftet att arkivera och säkerställa interoperabilitet med historiska data.
Inga proprietära eller konfidentiella specifikationer har använts.
Spelet kan för närvarande köpas som nedladdning på gog.com.
Den följande artikelserien dokumenterar mina insikter om dataformaten i realtidsstrategispelet "Outpost 2: Divided Destiny", som släpptes av Sierra 1997 och utvecklades av Dynamix.
Jag har främst ägnat mig åt analysen av spelets data - och hur man hanterar dem - från den 1 november 2015 till den 14 november 2015.
Enligt den information jag hittills har kunnat få fram har Dynamix - liksom många kommersiella företag - inte utvecklat några dataformat specifikt för Outpost 2, utan också använt dem i andra projekt, som till exempel Mechwarrior-serien (modifierade versioner).
Oavsett detta kan man också konstatera att innovationskraften i dataformaten i praktiken är ganska begränsad och ofta bygger på längre etablerade koncept från vanliga format som JFIF och RIFF.
För att tolka tabellerna och dataformaten finns ytterligare information under Vad är vad? tillgänglig.
De angivna uppgifterna här bör generellt förstås som Little Endian.
Avslutningsvis kan man säga att reverse engineering var mycket roligt, även om det inte är fullständigt.
Självklart rekommenderar jag också att spela spelet själv, eftersom det erbjuder intressanta spelmekaniker.
Introduktion
Dataformat som används av Outpost 2 har en struktur som påminner om JFIF / PNG - de enskilda datablocken har alltid en 8-byte header. Därför hoppar jag över att dokumentera de enskilda headerna på de aktuella specifika ställena och dokumenterar endast avvikelser där.
Formatet är alltid följande; de verkliga nyttolastdata är sedan inbäddade däri:
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | tecken | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
Förskjutning | Datatyp | Beteckning | Förklaring |
---|---|---|---|
0x0000 | uint(32) | Magiska byte | Innehåller information om vad som kan förväntas i nästa datablok. Kända värden:
|
0x0004 | uint(24) | Block-längd | Innehåller information om hur stor (i byte) den följande datablocken är. Det handlar om de rena nyttodatan - de 8 header-byten ingår inte. |
0x0007 | uint(8) | Flaggor? | Det är okänt vad denna block exakt används till. I volymerna är detta värde ofta 0x80, i andra filer ofta 0x00. Detta tyder på att det handlar om en flagguppsättning. |
Volymer
Volymer är en databehållare för spelet, liknande ett arkivformat som till exempel Tarball. Åtminstone i Outpost 2 känner formatet endast till filer - inga mappar. Det är troligt att dessa ändå skulle kunna simuleras genom motsvarande filnamn.
Ett volym består av volymhuvudet samt flera volymblock som motsvarar de konkreta filerna.
"Volymer" är filerna med ändelsen 'vol'
i spelmappen.
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | tecken | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 56 | 4f | 4c | 20 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | V | O | L | . | . | . | . | . | . | . | . | . | . | . | . |
Förskjutning | Datatyp | Beteckning | Förklaring |
---|---|---|---|
0x0000 | uint(32) | Magiska byte | |
0x0004 | uint(24) | Blocklängd | |
0x0007 | uint(8) | Flaggor |
Volymhuvud
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | tecken | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 76 | 6f | 6c | 68 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | v | o | l | h | . | . | . | . | . | . | . | . | . | . | . | . |
Förskjutning | Datatyp | Beteckning | Förklaring |
---|---|---|---|
0x0000 | uint(32) | Magiska byte | |
0x0004 | uint(24) | Blocklängd | |
0x0007 | uint(8) | Flaggor |
Volymhuvudet innehåller i sin tur inga användardata.
Det fungerar bara som en behållare.
Det första datumet i volymhuvudet bör vara volymsträngarna; följt av volyminformationen.
Volymsträngar
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | tecken | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 76 | 6f | 6c | 69 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | v | o | l | i | . | . | . | . | . | . | . | . | . | . | . | . |
Förskjutning | Datatyp | Beteckning | Förklaring |
---|---|---|---|
0x0000 | uint(32) | Magiska byte | |
0x0004 | uint(24) | Blocklängd | |
0x0007 | uint(8) | Flaggor |
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | tecken | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 76 | 6f | 6c | 73 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | v | o | l | s | . | . | . | . | . | . | . | . | . | . | . | . |
Förskjutning | Datatyp | Beteckning | Förklaring |
---|---|---|---|
0x0000 | uint(32) | Magiska byte | |
0x0004 | uint(24) | Blocklängd | |
0x0007 | uint(8) | Flaggor | |
0x0008 | uint(32) | Payload-längd | Anger för hur många bytes av de följande data som faktiskt är nyttolast. De återstående, kvarvarande data i volymsträngslistan bör tydligen betraktas som skräp. I filer med senare datum är dessa 'kvarvarande data' 0x00, vilket kan tyda på brister i verktygen under utvecklingen av spelet, det vill säga att en utvecklare först mycket sent har tagit hand om korrekt initialisering av buffrarna, eftersom det inte har någon påverkan på spelet om datan är initialiserad eller inte. |
0x000c | uint(8)[] | Filnamn-lista | Detta är en 0-byte-terminerad lista över filnamn som - åtminstone i den aktuella datakomponenten - enbart verkar förvänta sig ASCII-tecken. Det är inte nödvändigt att noggrant utvärdera denna datablok vid parsning av uppgifterna, eftersom filnamnens offsetar direkt refereras i volyminformationen. |
Volume-strängarna är en lista med filnamn som ingår i volymen.
Volyminformation
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | tecken | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 76 | 6f | 6c | 69 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | v | o | l | i | . | . | . | . | . | . | . | . | . | . | . | . |
Förskjutning | Datatyp | Beteckning | Förklaring |
---|---|---|---|
0x0000 | uint(32) | Magiska byte | |
0x0004 | uint(24) | Blocklängd | |
0x0007 | uint(8) | Flaggor |
Volyminformationerna tar detaljerad information om filerna. Det handlar på ett sätt om en slags FAT-katalogpost (FAT = File Allocation Table).
Antalet filer beräknas genom blockstorleken dividerat med längden på katalogposterna - 14 byte.
De enskilda katalogposterna har följande struktur:
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | tecken | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
Förskjutning | Datatyp | Beteckning | Förklaring |
---|---|---|---|
0x0000 | uint(32) | Filnamn-offset | Anger vilken förskjutning (!) inom filnamnslistan (volymssträngar) filnamnet för filen finns. Det hänvisar till början av nyttolastblocket. |
0x0004 | uint(32) | Fil-offset | Angegerar vid vilken offset inom hela volymfilen filen befinner sig. |
0x0008 | uint(32) | Filstorlek | Anger att filens storlek i byte. |
0x000c | uint(16) | Flaggor? | Ger uppenbarligen ytterligare information om filkodningen.
|
Volymblock
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | tecken | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 56 | 42 | 4c | 48 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | V | B | L | H | . | . | . | . | . | . | . | . | . | . | . | . |
Förskjutning | Datatyp | Beteckning | Förklaring |
---|---|---|---|
0x0000 | uint(32) | Magiska byte | |
0x0004 | uint(24) | Blocklängd | |
0x0007 | uint(8) | Flaggor |
En volymblock är en behållare som tar emot filer. Den innehåller ytterligare en gång - på grund av blockformatet - redundant filstorleken och därefter följer direkt användardata.
Kakel
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | tecken | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 50 | 42 | 4d | 50 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | P | B | M | P | . | . | . | . | . | . | . | . | . | . | . | . |
Förskjutning | Datatyp | Beteckning | Förklaring |
---|---|---|---|
0x0000 | uint(32) | Magiska byte | |
0x0004 | uint(24) | Block-längd | |
0x0007 | uint(8) | Flaggor |
Tiles handlar om ett Outpost-2-specifikt
bitmap-grafikformat. De sträcker sig över 13 tilesets,
""wells" kallade (well0000.bmp
till well0012.bmp
),
som finns inom volymen maps.vol.
Tilesets / Wells innehåller följande:
Filnamn | Innehåll |
---|---|
well0000.bmp | En 32x32px stor, blå grafik - idealisk för att testa om din egen bildladdare fungerar |
well0001.bmp | Innehåller ljust berg, bergskedjor på ljust berg och otaliga varianter av nedslagskratrar i ljust berg |
well0002.bmp | Innehåller ljust berg-'Doodads' - alltså element som kan placeras för att bryta upp (eller medvetet som struktur, som till exempel murar) på ljust berg, inklusive vegetation |
well0003.bmp | Innehåller en skorpliknande struktur på ljust berg |
well0004.bmp | Innehåller mörkt berg, bergskedjor på mörkt berg och otaliga varianter av nedslagskratrar i mörkt berg |
well0005.bmp | Innehåller mörkt berg-'Doodads' - alltså element som kan placeras för att bryta upp (eller medvetet som struktur, som till exempel murar) på mörkt berg |
well0006.bmp | Innehåller en skorpliknande struktur på mörkt berg, samt övergångar mellan ljust och mörkt berg |
well0007.bmp | Innehåller lava inklusive 4-5 ramar av animation av densamma |
well0008.bmp | Innehåller sand och otaliga varianter av nedslagskratrar i sand |
well0009.bmp | Innehåller sand-'Doodads' - alltså element som kan placeras för att bryta upp (eller medvetet som struktur, som till exempel murar) på sand |
well0010.bmp | Innehåller 48 övergångar från sand till ljust och mörkt berg |
well0011.bmp | Innehåller polarområdena på kartan, med mörkt berg som underlag |
well0012.bmp | Innehåller polarområdena på kartan, med ljust berg som underlag |
Det är rekommenderat för en noggrann implementering att inte rendera tiles i förväg för att cacha dem, eftersom datan för dag/natt-cykeln fortfarande måste bearbetas - och det skulle genereras väldigt mycket data.
Tiles är 8bpp-grafik med indexerad palett på 32x32 pixlar, som är ordnade i ett rutnät. I ett så skapat tileset kan dock mycket fler
Huvudcontainern består av 2 sektioner: head
och data
.
Plattor Rubrik
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | tecken | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 68 | 65 | 61 | 64 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | h | e | a | d | . | . | . | . | . | . | . | . | . | . | . | . |
0x0010 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
Förskjutning | Datatyp | Beteckning | Förklaring |
---|---|---|---|
0x0000 | uint(32) | Magiska byte | |
0x0004 | uint(24) | Block-längd | |
0x0007 | uint(8) | Flaggor | |
0x0008 | uint(32) | Version / Flaggor? | Detta kan vara en versionsangivelse av filformatet; i alla filer jag har funnits här stod värdet |
0x000c | uint(32) | Bredd (Horisontell upplösning) | Angeger hur bred bildfilen är (i pixlar). För alla brunnar i Outpost 2 kan värdet |
0x0010 | uint(32) | Höjd (Vertikal upplösning) | Angeger hur hög bildfilen är (i pixlar). För alla brunnar i Outpost 2 förväntas här värdet |
0x0014 | uint(32) | Färgdjup? | Betydelsen av detta värde är okänd. Eftersom det i alla granskade filer innehåller värdet |
0x0018 | uint(32) | Färgdjup 2? | Betydelsen av detta värde är okänd. Det kan möjligen vara en 'mål'-färgdjup. |
En palettfil i standardiserat RIFF-format kommer att följa dessa uppgifter. Den exakta specifikationen finns - eftersom paletterna också förekommer på andra ställen - under Paletter.
Tiles Data
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | tecken | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 64 | 61 | 74 | 61 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | d | a | t | a | . | . | . | . | . | . | . | . | . | . | . | . |
Förskjutning | Datatyp | Beteckning | Förklaring |
---|---|---|---|
0x0000 | uint(32) | Magiska byte | |
0x0004 | uint(24) | Block-längd | |
0x0007 | uint(8) | Flaggor |
Till slut följer de rena pixeldatan, rad för rad från vänster-övre till höger-nedre.
Datastrukturen för de grafiker som vanligtvis presenteras som 8bpp-bitmaps motsvarar färgindexet i färgpaletten.
Spelmotorn ritar tiles *troligen* på begäran.
Detta verkar bland annat bero på dag-natt-cykeln som har 32 olika nivåer av enskilda tiles. Det verkar som om ljusstyrkevärdet minskas 'lite' varje gång. Exakta värden har ännu inte kunnat fastställas, jag arbetar utifrån beräkningsgrunden
v *= (daylight / 48) + 0.25;
med HSV-data för pixlarna, där daylight är ett värde mellan 0-31 och v är ett värde mellan 0-1. Dessutom är det viktigt att beakta att det på kartan finns en kant av 16 tiles till vänster och höger (som används för osynligt spawnande av enheter).
Det verkar också som att dag-natt-cykeln uppdaterar endast en kolumn av kartan per spelcykel.
En accelererad dag-natt-cykel ser därför ut som följande:
PRT
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | tecken | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 43 | 50 | 41 | 4c | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | C | P | A | L | . | . | . | . | . | . | . | . | . | . | . | . |
Förskjutning | Datatyp | Beteckning | Förklaring |
---|---|---|---|
0x0000 | uint(32) | Magiska byte | |
0x0004 | uint(24) | Palettens längd | Angeger istället för det normala blockformatet, anger antalet paletter som finns i den här filen - inte blockets längd i byte. |
0x0007 | uint(8) | Flaggor | Sannolikt, som vanligt, flaggor. Jag känner dock inte till några flaggor; eftersom alla värden jag känner till motsvarar |
Vad PRT
exakt står för är mig okänt; en möjlighet skulle kunna vara 'Palette and Resource Table' - eftersom denna fil - som finns som op2_art.prt i maps.vol - handlar om just detta, vilket skulle beskriva funktionen ganska bra.
Denna fil innehåller en lista över paletter, en tabell över alla använda bitmaps, alla animationsdefinitioner och en mängd okända data. Den följer det tidigare containerformatet löst, eftersom inte alla poster följer detta schema.
CPAL
-sektionen (som troligen står för Palettcontainer) omfattar endast palettdata genom att ange hur många av de vanligen 1052 byte stora 8-bitars paletterna som finns.
Angivelsen av 1052 byte ska inte ses som bindande, eftersom palettformatet potentiellt kan föreskriva olika palettstorlekar. Den gäller endast för den datamängd som Outpost 2 levereras med.
Efter palettlistorna följer omedelbart och utan inledande rubrik, redan listan över bitmaps; precis som omedelbart följer animationslistorna.
Båda inleds med en uint(32) (eller kanske igen uint24+uint8 flaggor?) som innehåller antalet poster.
Paletter
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | tecken | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 50 | 50 | 41 | 4c | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | P | P | A | L | . | . | . | . | . | . | . | . | . | . | . | . |
Förskjutning | Datatyp | Beteckning | Förklaring |
---|---|---|---|
0x0000 | uint(32) | Magiska byte | |
0x0004 | uint(24) | Palettens längd | Ange, i motsats till det vanliga blockformatet, antalet paletter som finns i denna fil - inte blockets längd i byte. |
0x0007 | uint(8) | Flaggor | Sannolikt, som vanligt, flaggor. Jag känner dock inte till några flaggor; eftersom alla värden jag känner till motsvarar |
Palettinformationerna är mycket enkla att läsa.
De består av en header och ett datasegment.
Palettens rubrik
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | tecken | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 68 | 65 | 61 | 64 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | h | e | a | d | . | . | . | . | . | . | . | . | . | . | . | . |
Förskjutning | Datatyp | Beteckning | Förklaring |
---|---|---|---|
0x0000 | uint(32) | Magiska byte | |
0x0004 | uint(24) | Palettens längd | Ange, i motsats till det vanliga blockformatet, antalet paletter som finns i denna fil - inte blockets längd i byte. |
0x0007 | uint(8) | Flaggor | Sannolikt, som vanligt, flaggor. Jag känner dock inte till några flaggor; eftersom alla värden jag känner till motsvarar |
0x0008 | uint(32) | Palettformat-version? | Definierar troligen vilken palettformat-version paletten följer. Alla Outpost2-paletter verkar ha version |
Palettdata
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | tecken | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 64 | 61 | 74 | 61 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | d | a | t | a | . | . | . | . | . | . | . | . | . | . | . | . |
Förskjutning | Datatyp | Beteckning | Förklaring |
---|---|---|---|
0x0000 | uint(32) | Magiska byte | |
0x0004 | uint(24) | Blocklängd | |
0x0007 | uint(8) | Flaggor |
Dataavsnittet tar upp de enskilda pallinläggen. Antalet pallinlägg beräknas utifrån blocklängden / 4.
De enskilda inläggen har följande, enkla struktur;
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | tecken | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | -- | -- | -- | 04 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
Förskjutning | Datatyp | Beteckning | Förklaring |
---|---|---|---|
0x0000 | uint(8) | Röd komponent | Anger den röda andelen av färgen |
0x0001 | uint(8) | Grön komponent | Anger den gröna andelen av färgen |
0x0002 | uint(8) | Blå komponent | Anger den blå andelen av färgen |
0x0003 | uint(8) | Okänt - Flaggor? | Det är oklart vad detta värde betyder, eftersom det tydligen grundläggande är |
Angående paletterna är det enda att säga att följande regler gäller för paletter som används för animationer:
- Den första färgen är ALLTID transparent, oavsett vilket värde som anges där.
-
Palettposterna 1-24 räknas som spelarfärg i paletter 1-8.
Var färgerna utöver spelare 1 kommer ifrån är oklart för mig.
Jag misstänker att de övriga färgerna är hårdkodade.
Bitmapp bilder
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | tecken | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
0x0010 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
Förskjutning | Datatyp | Beteckning | Förklaring |
---|---|---|---|
0x0000 | uint(32) | Riktad bredd | Anger att bredden på pixeldata-raderna i byte - eftersom dessa är justerade till 4-byte-gränser. Så är det snabbt möjligt att hoppa till en viss bildrad. Varför detta värde lagras separat, även om det skulle kunna beräknas, är oklart. |
0x0004 | uint(32) | Offset | Anger den första radens offset i bitmapen |
0x0008 | uint(32) | Höjd | Anger höjden på bilden i pixlar |
0x000c | uint(32) | Bredd | Anger bredden på bilden i pixlar |
0x0010 | uint(16) | Typ | Angeger bilden av typen. Det verkar handla om en bitmask:
|
0x0012 | uint(16) | Palett | Definierar vilken palett som ska användas från PRT-filen |
Datastrukturen för PRT-filen anger hur de bitmappar som används för spriter är uppbyggda. Dessa bitmappar fungerar som enskilda komponenter, varav flera sätts samman till en animationsram för en sprite.
De konkreta bilddata finns istället i op2_art.BMP i spelkatalogen.
Varför denna bitmapfil har en (övervägande korrekt) RIFF-bitmapheader är oklart. Troligtvis använder Outpost 2 system-API:er för att ladda grafik genom att temporärt ta över denna header och överskriva de motsvarande, varierande fälten.
Pixeldatan finns i BMP-filen på position Offset + uint32-offsetet, som finns i BMP-filen vid adress 0x000A (RIFF-bitmapdataoffset), och följer återigen den radvisa arrangemanget från övre vänstra till nedre högra hörnet.
Monokroma 1bpp-grafiker kan ritas på så sätt att färg 0 representerar fullständig transparens, medan färg 1 är en halvtransparent svart/grå ton, eftersom monokromgrafiker vanligtvis används för fordon och byggnadsskuggor i animationerna.
Därmed kan man redan sätta ihop många grafik.
Animationer
Nu kommer vi till kungaklassen bland disciplinerna inom Outpost 2 dataformat:
Animationerna.
Animationslistorna inleds med en global header som främst används för dataverifikation. Därefter följer de konkreta animationsdefinitionerna, som är indelade i 3 nivåer:
-
Animation
En animation är den högsta instansen; den representerar en animation av en enhet, en byggnad eller en 'partikel-animation' (kometnedslag, väder, explosion) i en viss utgångssituation. -
Frame
En frame är en enskild bild inom en animation. En animation kan innehålla en eller flera frames. -
Subframe
En subframe är informationen om att en viss bitmap under vissa kriterier ska ritas på en viss position av en frame. En frame kan innehålla en eller flera subframes.
Därefter följer direkt de enskilda animationsdefinitionerna.
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | tecken | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
Förskjutning | Datatyp | Beteckning | Förklaring |
---|---|---|---|
0x0000 | uint(32) | Antal animationer | Hur många animationsdatakällor finns det |
0x0004 | uint(32) | Antal ramar | Hur många ramar bör det finnas totalt |
0x0008 | uint(32) | Antal underfack | Hur många subramar bör det finnas totalt |
0x000c | uint(32) | Antal valfria poster | Hur många "valfria poster" finns det. |
Animering
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | tecken | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
0x0010 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
0x0020 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
Förskjutning | Datatyp | Beteckning | Förklaring |
---|---|---|---|
0x0000 | uint(32) | Okänd 1 | Okända uppgifter |
0x0004 | uint(32) | Avgränsningsruta: Länkar | Anger den vänstra början (i pixlar) av Bounding Box. |
0x0008 | uint(32) | Bounding Box: Över | Anger den övre början (i pixlar) av Bounding Box. |
0x000c | uint(32) | Bounding Box: Bredd | Anger den bredden (i pixlar) av Bounding Box. |
0x0010 | uint(32) | Avgränsningsruta: Höjd | Anger den höjd (i pixlar) på Bounding Box. |
0x0014 | uint(32) | Offset: X | Anger horisontell mittpunkt för animationen |
0x0018 | uint(32) | Offset: Y | Anger den vertikala mittpunkten för animationen |
0x001c | uint(32) | Okänd 2 | Okänd information |
0x0020 | uint(32) | Antal ramar | Anger att hur många animationsramar som ingår i denna animation |
0x0024 | uint(32) | Antal fönster | Angeger hur många fönster som ska användas vid ritning |
Datana från det översta lagret, animationen, är främst administrationsdata - Boundingbox anger koordinaterna för markeringen runt fordonet/byggnaden när det har valts och indikerar samtidigt vilket område som ska vara klickbart.
Offsetet bestämmer främst "nollpunkten"; den punkt som ska läggas till eller subtraheras från spelinternt koordinatsystem. Man kan också säga mer matematiskt: offsetet anger här koordinatursprunget.
Fönstren består, precis som offsetet, av 4 uint(32)-värden per fönster som anger ett område som är användbart för individuella subframes. Utanför fönstren får, om det är avsett för bitmapen, inte ritas.
Ram
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | tecken | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
Förskjutning | Datatyp | Beteckning | Förklaring |
---|---|---|---|
0x0000 | uint(8) | Subframe-antal och växlingsknapp för valfri 1, 2 | Detta värde innehåller:
|
0x0001 | uint(8) | Okänd 1 och växla för valfri 3, 4 | Detta värde innehåller:
|
0x0002 | uint(8) | Valfritt 1 | Okänd |
0x0003 | uint(8) | Valfri 2 | Okänd |
0x0004 | uint(8) | Valfritt 3 | Okänd |
0x0005 | uint(8) | Valfritt 4 | Okänd |
Underkonstruktion
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | tecken | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
Förskjutning | Datatyp | Beteckning | Förklaring |
---|---|---|---|
0x0000 | uint(16) | Bitmap-ID | Angeger vilken bitmap som ska användas för denna subram |
0x0002 | uint(8) | Okänd 1 | Är okänt - jag misstänker dock stark att det handlar om en renderingsprioritet (Z-lager). |
0x0003 | uint(8) | Subframe-ID | Anger på vilket underfönster vi befinner oss i |
0x0004 | sint(16) | Offset - Horisontell | Anger vilken plats inom ramen som subramen ska placeras, eller hur många pixlar bitmapen ska flyttas horisontellt |
0x0006 | sint(16) | Offset - Vertikal | Angeger var inom ramen subramen ska placeras, eller med hur många pixlar bitmapen ska flyttas vertikalt |
Med detta kan vi nu sätta ihop enskilda ramar såväl som kompletta animationer, här demonstrerat med en mer komplex animation, animationen med index 500.
Animation 500
Animation 500 visar hur en Plymouth-transportör, som är lastad med vanligt malm, lastas ur. Detta är en av de få animationerna som utnyttjar fönsterfunktionaliteten.
Och så kan hela animationen sättas ihop.
Tyvärr finns det fortfarande ett problem med den övre lastluckan, eftersom det aktuella biten i grafiktyp-informationen inte är inställt.
Här är några fler vackert animerade sprites från spelet:
Användargränssnitt
Nu saknas användargränssnittet för spelet, som har en borstad metall-look.
Men här är det också tydligt att Dynamix inte behövde uppfinna hjulet på nytt; här används inte bara enkelt de User32- och GDI32-API:er som tillhandahålls av Windows - särskilt används också resursförvaltningen från User32.
Dessa kan exempelvis extraheras med program som Angus Johnson utvecklat som freeware, Resource Hacker, eller - om man avstår från att använda Wine på Linux / Mac OS - med hjälp av wrestool som ingår i icoutils.
Filnamn | Innehåll |
---|---|
Outpost2.exe | Innehåller endast spelets ikon, som visar rymdstationen framför New Terra |
op2shres.dll | Innehåller förutom grafik för kontroller som kanter, knappar, radioknappar och kryssrutor även dialogbakgrunder, illustrativa bilder för berättelseuppdrags texter och huvudmeny bakgrundsgrafik |
out2res.dll | Innehåller in-game fönsterdekoration, ikoner för vanligt och speciellt metall, laddningsskärmen, grafik för dialoger samt ytterligare muspekargrafik, utöver de animerade i spelmappen |