Outpost 2 Filformater · bei.pm
De filformater, der er beskrevet på denne side, er baseret på den tekniske analyse af intellektuel ejendom fra Dynamix, Inc. og Sierra Entertainment.
Den intellektuelle ejendom er i dag en del af Activision Publishing, Inc. / Activision Blizzard, Inc. og ejes i øjeblikket af Microsoft Corp..
Oplysningerne er indsamlet gennem Reverse Engineering og dataanalyse med henblik på arkivering og interoperabilitet med historiske data.
Der er ikke anvendt nogen proprietære eller fortrolige specifikationer.
Spillet kan i øjeblikket købes som download på gog.com.
Den følgende artikelserie dokumenterer mine indsigter om dataformaterne i realtidsstrategispillet "Outpost 2: Divided Destiny", som blev udgivet af Sierra i 1997 og udviklet af Dynamix.
Jeg har primært beskæftiget mig med analysen af spillets data - og hvad man kan gøre med dem - fra den 1. november 2015 til den 14. november 2015.
Ifølge de oplysninger, jeg hidtil har kunnet indsamle, har Dynamix - ligesom mange andre kommercielle virksomheder - ikke udviklet enkelte dataformater specifikt til Outpost 2, men også anvendt dem (i modificeret form) i andre projekter som for eksempel Mechwarrior-serien.
Uafhængigt af dette kan det også konstateres, at innovationskraften i dataformaterne praktisk talt er begrænset og ofte bygger på længere eksisterende koncepter fra almindelige formater som JFIF og RIFF.
For at fortolke tabellerne og dataformaterne er der yderligere oplysninger tilgængelige under Hvad er hvad?.
De angivne data skal generelt forstås som Little Endian.
Afslutningsvis kan det siges, at reverse engineering var meget sjovt, selvom det ikke er komplet.
Jeg kan naturligvis kun anbefale at spille spillet selv, da det tilbyder interessante spilmekanikker.
Introduktion
De dataformater, der bruges af Outpost 2, har en struktur, der minder om JFIF / PNG - de enkelte datablokke har altid en 8 bytes header. Derfor undlader jeg at dokumentere de enkelte headere på de relevante specifikke steder og dokumenterer kun afvigelserne der.
Formatet er altid det følgende; de egentlige nyttedata er derefter indlejret i det:
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | tegn | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Datatype | Betegnelse | Forklaring |
---|---|---|---|
0x0000 | uint(32) | Magiske Bytes | Indeholder information om, hvad der kan forventes i det næste datablok. Kendte værdier:
|
0x0004 | uint(24) | Blok-længde | Indeholder information om, hvor stor (i byte) den følgende datablok er. Her menes de rene nyttedata - de 8 header-byte er ikke inkluderet. |
0x0007 | uint(8) | Flagger? | Det er uklart, hvad denne blok præcist tjener til. I volumenerne er denne værdi ofte 0x80, mens den i andre filer ofte er 0x00. Det tyder på, at det er et flag-sæt. |
Volumener
Volumener er en databeholder til spillet, svarende til et arkivformat som f.eks. Tarball. I det mindste i Outpost 2 kender formatet kun filer - ingen mapper. Det er sandsynligt, at disse dog kan simuleres gennem passende filnavne.
Et volume består af volume-headeren samt flere volume blokke, der svarer til de konkrete filer.
"Volumes" er filerne med endelsen 'vol'
i spilmappen.
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | tegn | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 56 | 4f | 4c | 20 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | V | O | L | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Datatype | Betegnelse | Forklaring |
---|---|---|---|
0x0000 | uint(32) | Magiske Bytes | |
0x0004 | uint(24) | Bloklængde | |
0x0007 | uint(8) | Flagger |
Volume Overskrift
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | tegn | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 76 | 6f | 6c | 68 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | v | o | l | h | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Datatype | Betegnelse | Forklaring |
---|---|---|---|
0x0000 | uint(32) | Magiske Bytes | |
0x0004 | uint(24) | Bloklængde | |
0x0007 | uint(8) | Flagger |
Volume-headeret indeholder i sig selv ingen nyttedata.
Det fungerer kun som en container.
Som det første element i volume-headeret skal der findes volume-strenge; derefter følger volume-oplysningerne.
Volumen Strenge
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | tegn | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 76 | 6f | 6c | 69 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | v | o | l | i | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Datatype | Betegnelse | Forklaring |
---|---|---|---|
0x0000 | uint(32) | Magiske Bytes | |
0x0004 | uint(24) | Bloklængde | |
0x0007 | uint(8) | Flagger |
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | tegn | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 76 | 6f | 6c | 73 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | v | o | l | s | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Datatype | Betegnelse | Forklaring |
---|---|---|---|
0x0000 | uint(32) | Magiske Bytes | |
0x0004 | uint(24) | Bloklængde | |
0x0007 | uint(8) | Flagger | |
0x0008 | uint(32) | Payload-længde | Angiver, hvor mange bytes af de følgende data der faktisk er nyttige data. De resterende data fra volume-strenglisten skal åbenbart betragtes som affald. I filer med senere datoer er disse 'resterende data' 0x00, hvilket kan pege på utilstrækkeligheder med værktøjsrækken under udviklingen af spillet, med andre ord, at en udvikler først meget sent har taget sig af korrekt initialisering af buffere, da det ikke har nogen indflydelse på spillet, om dataene er initialiseret eller ej. |
0x000c | uint(8)[] | Filnavn-liste | Dette er en 0-byte-termineret liste af filnavne, der - i det mindste i den nuværende datakomponent - kun forventer ASCII-tegn. Det er ikke nødvendigt at evaluere denne datablok nærmere under parsing af dataene, da offsetene for filnavnene allerede bliver refereret direkte i volumeninformationerne. |
Volume Strings er en liste over filnavne, der er indeholdt i volumenet.
Volumeinformationer
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | tegn | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 76 | 6f | 6c | 69 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | v | o | l | i | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Datatype | Betegnelse | Forklaring |
---|---|---|---|
0x0000 | uint(32) | Magiske Bytes | |
0x0004 | uint(24) | Bloklængde | |
0x0007 | uint(8) | Flagger |
Volume-oplysningerne indeholder mere detaljerede oplysninger om filerne. Det drejer sig på en måde om en slags FAT-katalogpost (FAT = File Allocation Table)
Antallet af filer beregnes ved at dividere blokstørrelsen med længden af katalogposterne - 14 byte.
De enkelte katalogposter har følgende opbygning:
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | tegn | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Datatype | Betegnelse | Forklaring |
---|---|---|---|
0x0000 | uint(32) | Filnavn-offset | Angiver, ved hvilken offset (!) inden for filnavnelisten (volumen-strenge) filnavnet på filen findes. Dette refererer til begyndelsen af datablokken. |
0x0004 | uint(32) | Filoffset | Angiver, hvilken offset inden for hele volume-filen filen befinder sig. |
0x0008 | uint(32) | Filstørrelse | Angiver hvor stor filen er i byte. |
0x000c | uint(16) | Flagger? | Angiver åbenbart yderligere oplysninger om filkodningen.
|
Volume Blok
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | tegn | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 56 | 42 | 4c | 48 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | V | B | L | H | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Datatype | Betegnelse | Forklaring |
---|---|---|---|
0x0000 | uint(32) | Magiske Bytes | |
0x0004 | uint(24) | Bloklængde | |
0x0007 | uint(8) | Flagger |
En volume-block er en beholder, der indeholder filer. Den indeholder blot endnu en gang - på grund af blokformatet - redundant filstørrelsen, og derefter følger direkte brugerdataene.
Fliser
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | tegn | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 50 | 42 | 4d | 50 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | P | B | M | P | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Datatype | Betegnelse | Forklaring |
---|---|---|---|
0x0000 | uint(32) | Magiske Bytes | |
0x0004 | uint(24) | Bloklængde | |
0x0007 | uint(8) | Flagger |
Tiles er et Outpost-2-specifikt
Bitmap-grafikformat. De strækker sig over 13 tilesets,
"wells" kaldet (well0000.bmp
til well0012.bmp
),
som findes inden for volumen maps.vol.
De indeholder følgende i tilesets / wells:
Filnavn | Indhold |
---|---|
well0000.bmp | En 32x32px stor blå grafik - ideel til at teste, om din egen image-loader fungerer |
well0001.bmp | Indeholder lyst sten, bjergkæder på lyst sten og utallige varianter af nedslagskratre i lyst sten |
well0002.bmp | Indeholder 'Doodads' af lyst sten - elementer, der kan placeres for at bryde op (eller bevidst som struktur, som f.eks. mure) på lyst sten, herunder vegetation |
well0003.bmp | Indeholder en skorpeagtig struktur på lyst sten |
well0004.bmp | Indeholder mørkt sten, bjergkæder på mørkt sten og utallige varianter af nedslagskratre i mørkt sten |
well0005.bmp | Indeholder 'Doodads' af mørkt sten - elementer, der kan placeres for at bryde op (eller bevidst som struktur, som f.eks. mure) på mørkt sten |
well0006.bmp | Indeholder en skorpeagtig struktur på mørkt sten samt overgange mellem lyst og mørkt sten |
well0007.bmp | Indeholder lava inklusiv hver 4-5 frames animation af samme |
well0008.bmp | Indeholder sand og utallige varianter af nedslagskratre i sand |
well0009.bmp | Indeholder 'Doodads' af sand - elementer, der kan placeres for at bryde op (eller bevidst som struktur, som f.eks. mure) på sand |
well0010.bmp | Indeholder hver 48 overgange fra sand til lyst og mørkt sten |
well0011.bmp | Indeholder de polare kapper af kortet, med mørkt sten som underlag |
well0012.bmp | Indeholder de polare kapper af kortet, med lyst sten som underlag |
Det er stærkt anbefalet for en præcis implementering ikke at forudrenderere tiles for at cache dem, da dataene til dag/nat-cyklussen stadig skal behandles - og der ville opstå meget, meget store datamængder.
Tiles er 8bpp-grafik med en indekseret palette med en opløsning på 32x32 pixels, som er arrangeret i et gitter. I et sådan tileset kan der dog være langt flere
Hovedcontaineren består af 2 sektioner: head
og data
.
Fliser Overskrift
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | tegn | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 68 | 65 | 61 | 64 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | h | e | a | d | . | . | . | . | . | . | . | . | . | . | . | . |
0x0010 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Datatype | Betegnelse | Forklaring |
---|---|---|---|
0x0000 | uint(32) | Magiske Bytes | |
0x0004 | uint(24) | Bloklængde | |
0x0007 | uint(8) | Flagger | |
0x0008 | uint(32) | Version / Flag? | Dette kan være en versionsangivelse af filformatet; i alle de filer, jeg har, var værdien her |
0x000c | uint(32) | Bredde (Horisontal opløsning) | Angiver, hvor bred billedfilen er (i pixels). I alle brønde fra Outpost 2 forventes værdien |
0x0010 | uint(32) | Højde (Vertikal opløsning) | Angiver, hvor høj billedfilen er (i pixel). For alle brønde fra Outpost 2 forventes værdien her at være |
0x0014 | uint(32) | Farve dybde? | Betydningen af denne værdi er ukendt. Da den i alle kontrollerede filer indeholder værdien |
0x0018 | uint(32) | Farvedybde 2? | Betydningen af denne værdi er ukendt. Det kan muligvis være en 'mål'-farvedybde. |
Efter disse oplysninger følger der en palettedat fil i det standardiserede RIFF-format. Den præcise specifikation findes - da paletterne også optræder andre steder - under Paletter.
Tiles data
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | tegn | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 64 | 61 | 74 | 61 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | d | a | t | a | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Datatype | Betegnelse | Forklaring |
---|---|---|---|
0x0000 | uint(32) | Magiske Bytes | |
0x0004 | uint(24) | Bloklængde | |
0x0007 | uint(8) | Flagger |
Endelig følger de rå pixeldata, fra venstre-øverst række for række mod højre-nederst.
Data værdien for de grafikker, der som regel findes som 8bpp-bitmap, svarer til farveindekset i farvepaletten.
Spil-motoren tegner fliserne *sandsynligvis* on-demand.
Dette ser blandt andet ud til at skyldes dag-nat cyklussen, som har 32 nuancer af enkelte fliser. Her bliver der åbenbart trukket 'lidt' fra lysstyrken. Nøjagtige værdier er endnu ikke blevet fastslået, jeg arbejder på beregningsgrundlaget
v *= (daylight / 48) + 0.25;
med HSV-dataene fra pixel, hvor daylight er en værdi fra 0-31 og v en værdi mellem 0-1. Derudover skal det tages i betragtning, at der på kortet er en kant på 16 fliser til venstre og højre (den tjener til usynligt at spawn enheder).
Derudover ser det ud til, at dag-nat cyklussen kun opdaterer én søjle af kortet pr. spilcyklus.
En accelereret dag-nat cyklus ser derfor sådan ud:
PRT
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | tegn | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 43 | 50 | 41 | 4c | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | C | P | A | L | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Datatype | Betegnelse | Forklaring |
---|---|---|---|
0x0000 | uint(32) | Magiske bytes | |
0x0004 | uint(24) | Pallelængde | Angiver, i modsætning til det normale blokformat, antallet af paletter, der findes i denne fil - ikke længden af blokkene i byte. |
0x0007 | uint(8) | Flagger | Formodentlig, som sædvanligt, flags. Jeg kender dog ikke til nogen flags; da alle de værdier, jeg kender til, svarer til |
Hvad PRT
præcist står for, er mig ikke bekendt; det kunne for eksempel være 'Palette and Resource Table' - da denne fil - som findes som op2_art.prt i maps.vol - netop handler om dette, eller det ville i hvert fald beskrive funktionen ret godt.
Denne fil indeholder en liste over paletter, en tabel over alle anvendte bitmapper, alle animationsdefinitioner samt en række ukendte data. Den følger det hidtidige containerformat løst, idet ikke alle datasæt følger dette schema.
CPAL
-sektionen (som sandsynligvis står for palette-container) omfatter kun palettedataene, ved at angive hvor mange af de typisk 1052 byte store 8-bit paletter der er til stede.
Angivelsen af 1052 byte betragtes ikke som bindende, da paletteformatet potentielt kunne have forskellige paletstørrelser. Den gælder kun for det datasæt, som Outpost 2 leveres med.
Efter paletlisten følger straks, uden en indledende header, listen over bitmapper; ligeledes følger animationslisterne umiddelbart efter.
Disse indledes hver især med en uint(32) (eller måske uint24+uint8 flags?), som indeholder antallet af datasæt.
Paletter
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | tegn | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 50 | 50 | 41 | 4c | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | P | P | A | L | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Datatype | Betegnelse | Forklaring |
---|---|---|---|
0x0000 | uint(32) | Magiske Bytes | |
0x0004 | uint(24) | Palet-længde | Angiver, i modsætning til det normale blokformat, antallet af paletter, der findes i denne fil - ikke længden af blokken i byte. |
0x0007 | uint(8) | Flagger | Sandsynligvis, som sædvanlig, flags. Jeg kender dog ikke til nogen flags; da alle de værdier, jeg kender til, svarer til |
Paletteinformationerne er meget enkle at læse.
De består hver især af en header og et datasegment.
Palette-Header
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | tegn | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 68 | 65 | 61 | 64 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | h | e | a | d | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Datatype | Betegnelse | Forklaring |
---|---|---|---|
0x0000 | uint(32) | Magiske Bytes | |
0x0004 | uint(24) | Palet-længde | Angiver, i modsætning til det normale blokformat, antallet af paletter, der findes i denne fil - ikke længden af blokken i byte. |
0x0007 | uint(8) | Flagger | Sandsynligvis, som sædvanlig, flags. Jeg kender dog ikke til nogen flags; da alle de værdier, jeg kender til, svarer til |
0x0008 | uint(32) | Palettenformat-version? | Definerer sandsynligvis, hvilken paletformat-version paletten følger. Alle Outpost2-paletter ser ud til at have version |
Palette-data
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | tegn | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 64 | 61 | 74 | 61 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | d | a | t | a | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Datatype | Betegnelse | Forklaring |
---|---|---|---|
0x0000 | uint(32) | Magiske Bytes | |
0x0004 | uint(24) | Block-længde | |
0x0007 | uint(8) | Flagger |
Dataafsnittet indeholder de enkelte paletindgange. Antallet af paletindgange er baseret på bloklængden / 4.
De enkelte indgange har følgende enkle opbygning;
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | tegn | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | -- | -- | -- | 04 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Datatype | Betegnelse | Forklaring |
---|---|---|---|
0x0000 | uint(8) | Rød-komponent | Angiver andelen af rød i farven |
0x0001 | uint(8) | Grøn komponent | Angiver andelen af grønt i farven |
0x0002 | uint(8) | Blå komponent | Angiver andelen af blå i farven |
0x0003 | uint(8) | Ukendt - Flag? | Det er uklart, hvad denne værdi betyder, da den tilsyneladende grundlæggende er |
Om paletterne er der ellers kun at sige, at der gælder følgende regler for paletter, der bruges til animationer:
- Den første farve er ALDRIG transparent, uanset hvilken værdi der angives.
-
Paletternes indgange 1-24 betragtes som spillerfarver i paletterne 1-8.
Hvor farverne uden for spiller 1 præcist kommer fra, er mig uklart.
Jeg formoder, at de resterende farver er hardcoded.
Bitmaps
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | tegn | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
0x0010 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Datatype | Betegnelse | Forklaring |
---|---|---|---|
0x0000 | uint(32) | Justeret bredde | Angiver bredden af pixeldata-linjerne i byte - da de er justeret til 4-byte-grænser. Det gør det hurtigt muligt at springe til en bestemt billedlinje. Hvorfor denne værdi gemmes separat, selvom den kunne beregnes, er uklart. |
0x0004 | uint(32) | Offset | Angiver offset for den første linje i bitmap'en |
0x0008 | uint(32) | Højde | Angiver højden af billedet i pixel |
0x000c | uint(32) | Bredde | Angiver bredden af billedet i pixels |
0x0010 | uint(16) | Type | Angiver typen af billedet. Her ser det ud til at være en bitmaske:
|
0x0012 | uint(16) | Palette | Definerer, hvilken palette der skal bruges fra PRT-filen |
Denne datastruktur i PRT-filen angiver, hvordan de bitmaps, der bruges til sprites, er opbygget. Disse bitmaps fungerer som individuelle komponenter, hvor flere sammensættes til en animationsramme for et sprite.
De konkrete billeddata findes derimod i
op2_art.BMP i spillets mappe.
Hvorfor denne bitmapfil har en (overvejende korrekt) RIFF-bitmapheader,
er uklart. Sandsynligvis bruger Outpost 2 system-API'er til at indlæse grafikken,
ved midlertidigt at overtage denne header og overskrive de relevante, varierede felter.
Pixeldatarne findes i BMP-filen ved positionen Offset + det uint32-offset, der kan findes i BMP-filen på adresse 0x000A (RIFF-bitmap-dataoffset), og svarer igen til den linjemæssige opstilling fra øverste venstre til nederste højre.
Monokrome 1bpp-grafikker kan tegnes sådan, at farve 0 er fuldstændig gennemsigtig, mens farve 1 er et halvtransparent sort/grå, da monokrom-grafikker typisk bruges til skygger af køretøjer og bygninger i animationerne.
Derfor kan man allerede sammensætte mange grafikker.
Animationer
Nu kommer vi til kongeklassen af discipliner inden for Outpost 2 dataformater:
Animationerne.
Animationslisterne indledes med en global header, der primært tjener til dataverifikation. Herefter følger de konkrete animationsdefinitioner, der er opdelt i 3 niveauer:
-
Animation
En animation er den øverste instans; den repræsenterer en animation af en enhed, en bygning eller en 'partikel-animation' (kometnedslag, vejr, eksplosion) i en bestemt udgangssituation. -
Frame
Et frame er et enkelt billede inden for en animation. En animation kan indeholde et eller flere frames. -
Subframe
Et subframe er informationen om, at et bestemt bitmap skal tegnes på en bestemt position i et frame under bestemte kriterier. Et frame kan indeholde et eller flere subframes.
Herefter følger de enkelte animationsdefinitioner.
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | tegn | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Datatype | Betegnelse | Forklaring |
---|---|---|---|
0x0000 | uint(32) | Antal animationer | Hvor mange animationsdatasæt er der? |
0x0004 | uint(32) | Antal rammer | Hvor mange rammer burde der være i alt |
0x0008 | uint(32) | Antal underrammer | Hvor mange subframes bør der i alt være |
0x000c | uint(32) | Antal valgfri poster | Hvor mange "valgfri indlæg" er der? |
Animation
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | tegn | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
0x0010 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
0x0020 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Datatype | Betegnelse | Forklaring |
---|---|---|---|
0x0000 | uint(32) | Ukendt 1 | Ukendte oplysninger |
0x0004 | uint(32) | Bounding Box: Venstre | Angiver venstre begyndelse (i pixel) af Bounding Box. |
0x0008 | uint(32) | Afgrænsningsboks: Ovenfor | Angiver den øverste startpunkt (i pixel) af Bounding Box. |
0x000c | uint(32) | Bounding Box: Bredde | Angiver bredden (i pixel) af Bounding Box. |
0x0010 | uint(32) | Bounding Box: Højde | Angiver højden (i pixel) af Bounding Box. |
0x0014 | uint(32) | Offset: X | Angiver den horisontale midtpunkt for animationen |
0x0018 | uint(32) | Offset: Y | Angiver den vertikale midtpunkt for animationen |
0x001c | uint(32) | Ukendt 2 | Ukendt information |
0x0020 | uint(32) | Antal rammer | Angiver, hvor mange animationsrammer der er i denne animation |
0x0024 | uint(32) | Antal vinduer | Angiver hvor mange vinduer der skal bruges ved tegning |
Dataene fra det øverste lag, animationen, er primært administrationsdata - Boundingbox angiver koordinaterne for markeringen omkring køretøjet/bygningen, når det er valgt, og angiver samtidig, hvilket område der skal være klikbart.
Offsettet bestemmer primært "nulpunktet"; det punkt, der skal lægges til eller trækkes fra de interne koordinater. Man kunne også sige mere matematisk, at offsettet her angiver koordinatursprunget.
Windowsene består, ligesom offsettet, af 4 uint(32)-værdier pr. vindue, der angiver et område, der betragtes som anvendeligt for enkelte subframes. Uden for vinduerne må der, hvis det er relevant for bitmap'en, ikke tegnes.
Ramme
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | tegn | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Datatype | Betegnelse | Forklaring |
---|---|---|---|
0x0000 | uint(8) | Subframe antal og Toggle for Valgfri 1, 2 | Denne værdi indeholder:
|
0x0001 | uint(8) | Ukendt 1 og Toggle for Valgfri 3, 4 | Denne værdi indeholder:
|
0x0002 | uint(8) | Valgfri 1 | Ukendt |
0x0003 | uint(8) | Valgfri 2 | Ukendt |
0x0004 | uint(8) | Valgfri 3 | Ukendt |
0x0005 | uint(8) | Valgfri 4 | Ukendt |
Underramme
Adr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | tegn | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Datatype | Betegnelse | Forklaring |
---|---|---|---|
0x0000 | uint(16) | Bitmap-ID | Angiver hvilken bitmap der skal bruges til denne subframe |
0x0002 | uint(8) | Ukendt 1 | Er ukendt - jeg formoder dog stærkt, at det drejer sig om en render-prioritet (Z-lag). |
0x0003 | uint(8) | Subframe-id | Angiver, hvilket underframe vi befinder os i |
0x0004 | sint(16) | Offset - Vandret | Angiver, hvor inden for rammen subrammen skal placeres, eller med hvor mange pixel bitmap'en skal flyttes vandret. |
0x0006 | sint(16) | Offset - Vertikal | Angiver, hvor inden for rammen subrammen skal placeres, eller hvor mange pixel bitmap'en skal flyttes vertikalt. |
Med dette kan vi nu samle individuelle rammer såvel som komplette animationer, her vist som eksempel med en mere kompleks animation, animationen med indeks 500.
Animation 500
Animation 500 viser, hvordan en Plymouth-transportør, der er lastet med almindeligt mineral, bliver tømt. Dette er en af de få animationer, der bruger vinduesfunktionaliteten.
Og sådan kan den komplette animation samles.
Desværre er der stadig et problem med den øverste lastelem, da det relevante bit i grafiktypen-informationen ikke er sat.
Her er nogle flere, smukt animerede sprites fra spillet:
Brugergrænseflade
Nu mangler vi kun brugergrænsefladen til spillet, som har et børstet metal-look.
Men her er det også tydeligt, at Dynamix ikke behøvede at genopfinde hjulet; her bruges ikke blot de funktioner, der leveres af Windows’ User32- og GDI32-API'er - især anvendes også ressourcestyringen fra User32.
Disse kan for eksempel udtrækkes ved hjælp af programmer som den freeware, der er udviklet af Angus Johnson, Resource Hacker, eller - hvis man undgår at bruge Wine på Linux / Mac OS - ved hjælp af wrestool, som er inkluderet i icoutils.
Filnavn | Indhold |
---|---|
Outpost2.exe | Indeholder kun ikonet for spillet, som viser rumstationen foran New Terra |
op2shres.dll | Indeholder udover grafik til betjeningselementer som rammer, knapper, radioknapper og afkrydsningsfelter også dialogbaggrunde, ledsagebilleder til story-missionstekster samt baggrundsgrafikken til hovedmenuen |
out2res.dll | Indeholder ingame-vinduesdekoration, ikoner for almindeligt og specielt metal, indlæsningsskærmen, grafik til dialoger samt yderligere cursor-grafikker, ud over de animerede i spillets mappe |