Định dạng tệp Outpost 2 · bei.pm

Văn bản này đã được dịch tự động bởi OpenAI GPT-4o Mini.

Các định dạng tệp được mô tả trên trang này dựa trên phân tích kỹ thuật về sở hữu trí tuệ của Dynamix, Inc.Sierra Entertainment.
Sở hữu trí tuệ này hiện là một phần của tập đoàn Activision Publishing, Inc.- / Activision Blizzard, Inc. và hiện đang thuộc sở hữu của Microsoft Corp..

Các thông tin đã được thu thập thông qua Reverse Engineeringphân tích dữ liệu nhằm mục đích lưu trữ và tương tác với dữ liệu lịch sử.
Không có thông số kỹ thuật nào thuộc quyền sở hữu hoặc bí mật nào được sử dụng.

Trò chơi hiện có thể được mua dưới dạng tải về tại gog.com.

Nghệ thuật của trò chơi

Bài viết sau đây ghi lại những hiểu biết của tôi về các định dạng dữ liệu trong trò chơi chiến lược thời gian thực "Outpost 2: Divided Destiny", được phát hành bởi Sierra vào năm 1997 và được phát triển bởi Dynamix.

Tôi đã dành thời gian từ ngày 01 tháng 11 năm 2015 đến ngày 14 tháng 11 năm 2015 chủ yếu để phân tích dữ liệu của trò chơi - và những gì nó có thể làm với nó.

Các thông tin mà tôi đã thu thập được cho thấy rằng Dynamix - như nhiều công ty thương mại khác - không chỉ phát triển một số định dạng dữ liệu đặc biệt cho Outpost 2, mà còn sử dụng chúng trong các phát triển khác như series Mechwarrior (được điều chỉnh).
Bất chấp điều đó, có thể nhận thấy rằng sức sáng tạo của các định dạng tệp hầu như bị giới hạn và thường dựa trên các khái niệm đã tồn tại từ các định dạng thông thường như JFIF và RIFF.

Để giải thích các bảng và định dạng dữ liệu, có thêm thông tin tại Cái gì là cái gì?.
Các dữ liệu được chỉ định ở đây thường được hiểu là Little Endian.

Cuối cùng, có thể nói rằng việc đảo ngược kỹ thuật rất thú vị, mặc dù chưa hoàn chỉnh.
Tất nhiên, tôi cũng khuyên bạn nên chơi trò chơi này, vì nó cung cấp những cơ chế chơi thú vị.

Giới thiệu

Các định dạng dữ liệu được sử dụng bởi Outpost 2 có cấu trúc giống như JFIF / PNG - các khối dữ liệu riêng lẻ luôn có một tiêu đề 8 byte. Vì vậy, tôi sẽ không ghi chép lại từng tiêu đề ở các vị trí cụ thể tương ứng mà chỉ ghi chép các điểm khác biệt.

Định dạng luôn là như sau; các dữ liệu thực tế sau đó được nhúng vào bên trong:

Địa chỉ x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF ký tự
0x0000 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- . . . . . . . . . . . . . . . .
Địa chỉ lệch Loại dữ liệu Tên gọi Giải thích
0x0000 uint(32) Byte Ma thuật

Chứa thông tin về những gì sẽ được mong đợi trong khối dữ liệu tiếp theo.

Giá trị đã biết:

  • 0x204C4F56 ('VOL '):
    Âm lượng
  • 0x686C6F76 ('VOLH'):
    Tiêu đề âm lượng
  • 0x736C6F76 ('VOLS'):
    Dòng âm lượng
  • 0x696C6F76 ('VOLI'):
    Thông tin âm lượng
  • 0x4B4C4256 ('BLCK'):
    Khối âm lượng
  • 0x504D4250 ('PBMP'):
    Dữ liệu đồ họa
  • 0x4C415050 ('PPAL'):
    Bảng màu
  • 0x4C415043 ('CPAL'):
    Container bảng màu
  • 0x64616568 ('head'):
    Tiêu đề
  • 0x61746164 ('data'):
    Dữ liệu hữu ích
0x0004 uint(24) Chiều dài khối

Chứa thông tin về kích thước (tính bằng Byte) của khối dữ liệu tiếp theo.

Ở đây chỉ đề cập đến dữ liệu thực tế - 8 byte tiêu đề không được tính vào đó.

0x0007 uint(8) Cờ?

Không rõ khối này có chức năng gì chính xác.

Trong các khối, giá trị này thường là 0x80, trong các tệp khác thì thường là 0x00. Điều này cho thấy đây có thể là một tập hợp cờ.

Khối lượng

Các Volume là một container dữ liệu cho trò chơi, tương tự như một định dạng lưu trữ như Tarball. Ít nhất trong Outpost 2, định dạng này chỉ biết đến các tệp - không có thư mục. Có lẽ chúng có thể được mô phỏng thông qua tên tệp tương ứng.

Một Volume bao gồm tiêu đề Volume và nhiều khối Volume, mà tương ứng với các tệp cụ thể.

"Volumes" là các tệp có đuôi 'vol' trong thư mục trò chơi.

Địa chỉ x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF ký tự
0x0000 56 4f 4c 20 -- -- -- -- -- -- -- -- -- -- -- -- V O L . . . . . . . . . . . .
Địa chỉ lệch Loại dữ liệu Tên gọi Giải thích
0x0000 uint(32) Magic Bytes
0x0004 uint(24) Độ dài khối
0x0007 uint(8) Cờ

Tiêu đề Âm lượng

Địa chỉ x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF ký tự
0x0000 76 6f 6c 68 -- -- -- -- -- -- -- -- -- -- -- -- v o l h . . . . . . . . . . . .
Địa chỉ lệch Loại dữ liệu Tên gọi Giải thích
0x0000 uint(32) Magic Bytes
0x0004 uint(24) Độ dài khối
0x0007 uint(8) Cờ

Header khối chứa không có dữ liệu hữu ích nào.
Nó chỉ đơn giản là một bộ chứa.

Dữ liệu đầu tiên trong Header khối nên là các chuỗi Volume; tiếp theo là thông tin về Volume.

Dây chuyền thể tích

Địa chỉ x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF ký tự
0x0000 76 6f 6c 69 -- -- -- -- -- -- -- -- -- -- -- -- v o l i . . . . . . . . . . . .
Địa chỉ lệch Loại dữ liệu Tên gọi Giải thích
0x0000 uint(32) Magic Bytes
0x0004 uint(24) Độ dài khối
0x0007 uint(8) Cờ
Địa chỉ x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF ký tự
0x0000 76 6f 6c 73 -- -- -- -- -- -- -- -- -- -- -- -- v o l s . . . . . . . . . . . .
Địa chỉ lệch Loại dữ liệu Tên gọi Giải thích
0x0000 uint(32) Magic Bytes
0x0004 uint(24) Độ dài khối
0x0007 uint(8) Cờ
0x0008 uint(32) Độ dài tải trọng

Cho biết số byte nào trong dữ liệu sau đây thực sự là dữ liệu hữu ích.

Các dữ liệu còn lại trong danh sách chuỗi Volume dường như được xem là rác.

Trong các tệp có ngày tháng muộn hơn, những 'dữ liệu còn lại' là 0x00, điều này có thể chỉ ra những thiếu sót trong công cụ phát triển trong quá trình phát triển trò chơi, tức là một nhà phát triển đã chỉ quan tâm đến việc khởi tạo đúng các bộ đệm rất muộn, vì nó không ảnh hưởng đến trò chơi nếu dữ liệu được khởi tạo hay không.

0x000c uint(8)[] Danh sách tên tệp

Đây là một danh sách tên tệp được kết thúc bằng 0 byte, mà - ít nhất trong thành phần dữ liệu hiện có - chỉ mong đợi các ký tự ASCII.

Không cần thiết phải phân tích kỹ hơn khối dữ liệu này khi phân tích dữ liệu, vì trong thông tin Volume, các offset của tên tệp đã được tham chiếu trực tiếp.

Các Volume Strings là một danh sách tên tệp nằm trong volume này.

Thông tin về khối lượng

Địa chỉ x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF ký tự
0x0000 76 6f 6c 69 -- -- -- -- -- -- -- -- -- -- -- -- v o l i . . . . . . . . . . . .
Địa chỉ lệch Loại dữ liệu Tên gọi Giải thích
0x0000 uint(32) Magic Bytes
0x0004 uint(24) Độ dài khối
0x0007 uint(8) Cờ

Thông tin Volume chứa các thông tin chi tiết về các tệp. Điều này có thể được coi là một loại mục nhập thư mục FAT (FAT = Bảng phân bổ tệp).

Số lượng tệp được tính bằng kích thước khối chia cho độ dài của mục nhập thư mục - 14 byte.

Các mục nhập thư mục riêng lẻ có cấu trúc như sau:

Địa chỉ x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF ký tự
0x0000 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- . . . . . . . . . . . . . . . .
Địa chỉ lệch Loại dữ liệu Tên gọi Giải thích
0x0000 uint(32) Độ lệch tên tệp

Chỉ rõ vị trí (Offset!) trong danh sách tên tệp (Volume-Strings) mà tên tệp của tệp đó nằm.

Điều này liên quan đến phần bắt đầu của khối dữ liệu.

0x0004 uint(32) Độ lệch tệp

Chỉ ra vị trí offset bên trong toàn bộ file volume mà file đang nằm.

0x0008 uint(32) Kích thước tệp

Cho biết kích thước của tệp tin tính bằng byte.

0x000c uint(16) Cờ?

Có vẻ như có thêm thông tin về mã hóa tệp.

  • 0x03 được đặt nếu tệp đã được nén. Có vẻ như một cây Huffman đang được sử dụng ở đây.
  • 0x80 dường như luôn được đặt.

Khối Khối Lượng

Địa chỉ x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF ký tự
0x0000 56 42 4c 48 -- -- -- -- -- -- -- -- -- -- -- -- V B L H . . . . . . . . . . . .
Địa chỉ lệch Loại dữ liệu Tên gọi Giải thích
0x0000 uint(32) Magic Bytes
0x0004 uint(24) Độ dài khối
0x0007 uint(8) Cờ

Một khối Volume là một container, có nhiệm vụ chứa các tệp tin. Nó chỉ bao gồm một lần nữa - do định dạng khối - thông tin kích thước tệp tin và sau đó là ngay lập tức dữ liệu sử dụng.

Gạch

Địa chỉ x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF ký tự
0x0000 50 42 4d 50 -- -- -- -- -- -- -- -- -- -- -- -- P B M P . . . . . . . . . . . .
Địa chỉ lệch Loại dữ liệu Tên gọi Giải thích
0x0000 uint(32) Magic Bytes
0x0004 uint(24) Độ dài khối
0x0007 uint(8) Cờ

Các Tiles là định dạng đồ họa Bitmap đặc thù của Outpost-2. Chúng trải dài qua 13 Tilesets, được gọi là "wells" (well0000.bmp đến well0012.bmp), nằm trong khối maps.vol.

Các Tilesets / Wells chứa những nội dung sau:

Tên tệp Nội dung
well0000.bmp Một đồ họa màu xanh kích thước 32x32px - lý tưởng để kiểm tra xem trình tải ảnh của bạn có hoạt động hay không
well0001.bmp Chứa đá sáng màu, dãy núi trên đá sáng màu và vô số biến thể của các hố va chạm vào đá sáng màu
well0002.bmp Chứa các 'Doodads' đá sáng màu - tức là các yếu tố có thể được đặt lên đá sáng màu để làm phong phú thêm (hoặc cố ý như cấu trúc, chẳng hạn như tường), bao gồm cả thực vật
well0003.bmp Chứa một cấu trúc dạng vỏ trên đá sáng màu
well0004.bmp Chứa đá tối màu, dãy núi trên đá tối màu và vô số biến thể của các hố va chạm vào đá tối màu
well0005.bmp Chứa các 'Doodads' đá tối màu - tức là các yếu tố có thể được đặt lên đá tối màu để làm phong phú thêm (hoặc cố ý như cấu trúc, chẳng hạn như tường)
well0006.bmp Chứa một cấu trúc dạng vỏ trên đá tối màu, cũng như các chuyển tiếp giữa đá sáng và đá tối
well0007.bmp Chứa dung nham bao gồm 4-5 khung hình animation cho mỗi loại
well0008.bmp Chứa cát và vô số biến thể của các hố va chạm vào cát
well0009.bmp Chứa các 'Doodads' cát - tức là các yếu tố có thể được đặt lên cát để làm phong phú thêm (hoặc cố ý như cấu trúc, chẳng hạn như tường)
well0010.bmp Chứa 48 chuyển tiếp từ cát sang đá sáng và đá tối
well0011.bmp Chứa các cực băng của bản đồ, với đá tối là nền
well0012.bmp Chứa các cực băng của bản đồ, với đá sáng là nền

Thật sự khuyên rằng nên thực hiện một cách chính xác, không nên render các ô (tiles) trước để lưu vào bộ nhớ cache, vì dữ liệu cho chu kỳ ngày/đêm vẫn cần phải được xử lý - và sẽ có rất nhiều dữ liệu phát sinh.

Các ô là hình ảnh 8bpp với bảng màu chỉ mục có độ phân giải 32x32 pixel, được sắp xếp theo chiều dọc. Trong một bộ ô (tileset) như vậy, có thể có nhiều hơn nữa.

Container chính bao gồm 2 phần: headdata.

Tiêu đề Gạch

Địa chỉ x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF ký tự
0x0000 68 65 61 64 -- -- -- -- -- -- -- -- -- -- -- -- h e a d . . . . . . . . . . . .
0x0010 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- . . . . . . . . . . . . . . . .
Địa chỉ lệch Loại dữ liệu Tên gọi Giải thích
0x0000 uint(32) Magic Bytes
0x0004 uint(24) Độ dài khối
0x0007 uint(8) Cờ
0x0008 uint(32) Phiên bản / Cờ hiệu?

Có thể đây là một chỉ dẫn phiên bản của định dạng tệp; trong tất cả các tệp mà tôi có, giá trị ở đây là 0x02

0x000c uint(32) Chiều rộng (Độ phân giải ngang)

Chỉ ra độ rộng của tệp hình ảnh (tính bằng pixel).

Đối với tất cả các giếng trong Outpost 2, giá trị 0x20 hoặc 32 sẽ được mong đợi ở đây.

0x0010 uint(32) Chiều cao (Độ phân giải theo chiều dọc)

Chỉ ra chiều cao của tệp hình ảnh (tính bằng pixel).

Đối với tất cả các giếng của Outpost 2, giá trị 0x20 hay 32 sẽ được mong đợi ở đây.

0x0014 uint(32) Độ sâu màu?

Ý nghĩa của giá trị này không rõ ràng.

Bởi vì nó chứa giá trị 8 trong tất cả các tệp được kiểm tra, có thể đây là một chỉ số về độ sâu màu.

0x0018 uint(32) Độ sâu màu 2?

Ý nghĩa của giá trị này không được biết đến.

Có thể đây là độ sâu màu 'mục tiêu'.

Theo những thông tin này, còn có một tệp bảng màu ở định dạng RIFF chuẩn. Thông số kỹ thuật chính xác có thể tìm thấy - vì các bảng màu cũng xuất hiện ở nơi khác - tại Bảng màu.

Dữ liệu gạch

Địa chỉ x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF ký tự
0x0000 64 61 74 61 -- -- -- -- -- -- -- -- -- -- -- -- d a t a . . . . . . . . . . . .
Địa chỉ lệch Loại dữ liệu Tên gọi Giải thích
0x0000 uint(32) Magic Bytes
0x0004 uint(24) Độ dài khối
0x0007 uint(8) Cờ

Cuối cùng, dữ liệu pixel đã được hiển thị, từ góc trên bên trái theo hàng đến góc dưới bên phải.
Giá trị dữ liệu đối với các hình ảnh thường được trình bày dưới dạng bitmap 8bpp tương ứng với chỉ số của màu trong bảng màu.

Dữ liệu pixel bắt đầu từ góc trên bên trái và kết thúc ở góc dưới bên phải.

Động cơ trò chơi vẽ các ô *có khả năng* theo yêu cầu.
Điều này dường như liên quan đến chu kỳ ngày-đêm, với 32 cấp độ của từng ô. Trong đó, có vẻ như giá trị độ sáng được trừ đi 'một chút'. Các giá trị chính xác vẫn chưa được xác định, tôi đang làm việc dựa trên cơ sở tính toán

v *= (daylight / 48) + 0.25;

với dữ liệu HSV của các pixel, trong đó daylight là một giá trị từ 0-31 và v là một giá trị từ 0-1. Hơn nữa, cần lưu ý rằng trên bản đồ vẫn còn một dải 16 ô ở bên trái và bên phải (để tạo ra các đơn vị không nhìn thấy).

Bên cạnh đó, chu kỳ ngày-đêm dường như chỉ cập nhật một cột của bản đồ cho mỗi chu kỳ trò chơi.
Một chu kỳ ngày-đêm được tăng tốc sẽ trông như sau:

Minh họa chu kỳ ngày-đêm

Bảng màu và tài nguyên

Địa chỉ x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF ký tự
0x0000 43 50 41 4c -- -- -- -- -- -- -- -- -- -- -- -- C P A L . . . . . . . . . . . .
Địa chỉ lệch Loại dữ liệu Tên gọi Giải thích
0x0000 uint(32) Bytes ma thuật
0x0004 uint(24) Chiều dài pallet

Chỉ ra số lượng pallet có trong tệp này - không phải độ dài của khối tính bằng byte.

0x0007 uint(8) Cờ

Có lẽ, như thường lệ, là các cờ.

Tuy nhiên, tôi không biết đến bất kỳ cờ nào; vì tất cả các giá trị tôi biết đều tương ứng với 0x00, nên cũng có khả năng số lượng bảng màu đơn giản chỉ là một uint(32).

Tôi không biết chính xác PRT đại diện cho điều gì; có thể là 'Bảng Palettes và Tài nguyên' - vì đây là một tệp - được tìm thấy với tên op2_art.prt trong maps.vol - liên quan đến điều đó, hoặc điều này sẽ mô tả chức năng khá tốt.

Tệp này chứa danh sách các palette, một bảng về tất cả các bitmap đã sử dụng, tất cả các định nghĩa animation và một loạt dữ liệu chưa biết. Nó tuân theo định dạng container trước đó một cách lỏng lẻo, vì không phải tất cả các bản ghi đều theo mô hình này.

Phần CPAL (có khả năng đại diện cho Container Palette) chỉ bao gồm dữ liệu palette, bằng cách chỉ ra số lượng palette 8-bit có kích thước 1052 byte thông thường.

Sự chỉ định 1052 byte không được coi là bắt buộc, vì định dạng palette có thể cho phép kích thước palette khác nhau. Nó chỉ áp dụng cho tập dữ liệu mà Outpost 2 được phát hành.

Sau danh sách palette ngay lập tức và không có tiêu đề mở đầu, là danh sách bitmap; ngay sau đó là danh sách animation.
Cả hai đều được bắt đầu bằng một uint(32) (hoặc lại là uint24 + uint8 flags?) chứa số lượng bản ghi.

Bảng màu

Địa chỉ x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF ký tự
0x0000 50 50 41 4c -- -- -- -- -- -- -- -- -- -- -- -- P P A L . . . . . . . . . . . .
Địa chỉ lệch Loại dữ liệu Tên gọi Giải thích
0x0000 uint(32) Bytes Ma thuật
0x0004 uint(24) Chiều dài pallet

Chỉ ra số lượng pallet có trong tệp này - không phải độ dài của khối theo byte, trái với định dạng khối thông thường.

0x0007 uint(8) Cờ

Có lẽ, như thường lệ, là các cờ.

Tuy nhiên, tôi không biết đến bất kỳ cờ nào; vì tất cả các giá trị mà tôi biết đều tương ứng với 0x00, nên cũng có thể khả thi rằng số lượng bảng màu chỉ đơn giản là một uint(32).

Thông tin về pallet rất dễ dàng để đọc.
Nó bao gồm một tiêu đề và một đoạn dữ liệu.

Tiêu đề Paletten

Địa chỉ x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF ký tự
0x0000 68 65 61 64 -- -- -- -- -- -- -- -- -- -- -- -- h e a d . . . . . . . . . . . .
Địa chỉ lệch Loại dữ liệu Tên gọi Giải thích
0x0000 uint(32) Bytes Ma thuật
0x0004 uint(24) Chiều dài pallet

Chỉ ra số lượng pallet có trong tệp này - không phải độ dài của khối theo byte, trái với định dạng khối thông thường.

0x0007 uint(8) Cờ

Có lẽ, như thường lệ, là các cờ.

Tuy nhiên, tôi không biết đến bất kỳ cờ nào; vì tất cả các giá trị mà tôi biết đều tương ứng với 0x00, nên cũng có thể khả thi rằng số lượng bảng màu chỉ đơn giản là một uint(32).

0x0008 uint(32) Phiên bản định dạng pallet?

Có thể xác định phiên bản định dạng pallet mà pallet tuân theo.

Tất cả các pallet Outpost2 dường như đều có phiên bản 0x01.

Dữ liệu pallet

Địa chỉ x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF ký tự
0x0000 64 61 74 61 -- -- -- -- -- -- -- -- -- -- -- -- d a t a . . . . . . . . . . . .
Địa chỉ lệch Loại dữ liệu Tên gọi Giải thích
0x0000 uint(32) Bytes Ma thuật
0x0004 uint(24) Độ dài khối
0x0007 uint(8) Cờ

Phần dữ liệu bao gồm các mục pallet riêng lẻ. Số lượng mục pallet được xác định bởi độ dài của khối / 4.

Các mục riêng lẻ có cấu trúc đơn giản như sau;

Địa chỉ x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF ký tự
0x0000 -- -- -- 04 -- -- -- -- -- -- -- -- -- -- -- -- . . . . . . . . . . . . . . . .
Địa chỉ lệch Loại dữ liệu Tên gọi Giải thích
0x0000 uint(8) Thành phần đỏ

Cho biết tỷ lệ màu đỏ của màu sắc

0x0001 uint(8) Thành phần màu xanh lá cây

Chỉ ra tỷ lệ màu xanh của màu sắc

0x0002 uint(8) Thành phần màu xanh

Chỉ số phần màu xanh của màu sắc

0x0003 uint(8) Không xác định - Cờ?

Không rõ giá trị này có nghĩa là gì, vì nó dường như về cơ bản là 0x04.

Về các bảng màu, chỉ có thể nói rằng, các quy tắc sau áp dụng cho các bảng màu được sử dụng cho hoạt hình:

  • Màu đầu tiên LUÔN LUÔN là trong suốt, bất kể giá trị nào được chỉ định ở đó.
  • Các mục bảng màu 1-24 được coi là màu của người chơi trong các bảng màu 1-8.
    Tôi không rõ màu sắc từ người chơi 1 và các màu sắc khác đến từ đâu.
    Tôi nghi ngờ rằng các màu còn lại được mã hóa cứng.

Tài liệu tham khảo bảng màu

Bitmap

Địa chỉ x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF ký tự
0x0000 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- . . . . . . . . . . . . . . . .
0x0010 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- . . . . . . . . . . . . . . . .
Địa chỉ lệch Loại dữ liệu Tên gọi Giải thích
0x0000 uint(32) Chiều rộng căn chỉnh

Chỉ ra độ rộng của các dòng dữ liệu pixel tính bằng Byte - vì chúng được căn chỉnh theo các ranh giới 4 Byte.

Vì vậy, rất dễ dàng để nhảy đến một dòng hình ảnh cụ thể.

Tại sao giá trị này lại được lưu trữ riêng, mặc dù có thể tính toán, thì không rõ.
Có thể đây là một tối ưu hóa cho mã render.

0x0004 uint(32) Bù đắp

Chỉ định độ lệch của dòng đầu tiên trong bitmap

0x0008 uint(32) Chiều cao

Cho biết chiều cao của hình ảnh bằng pixel

0x000c uint(32) Chiều rộng

Chỉ định độ rộng của hình ảnh bằng pixel

0x0010 uint(16) Loại

Chỉ ra loại hình ảnh. Dường như đây là một mặt nạ bit:

  • 0x04 được đặt nếu đây là một đồ họa 1bpp.
  • 0x40 được đặt nếu đây là một đồ họa cần thực hiện Windowing.
0x0012 uint(16) Bảng màu

Định nghĩa bảng màu nào sẽ được sử dụng từ tệp PRT

Cấu trúc dữ liệu của tệp PRT này chỉ ra cách mà các bitmap được sử dụng cho các sprite được xây dựng. Những bitmap này đóng vai trò là thành phần riêng lẻ, từ đó nhiều cái được ghép lại thành một khung hình hoạt hình của một sprite.

Dữ liệu hình ảnh cụ thể thì ẩn chứa trong op2_art.BMP trong thư mục trò chơi.
Nguyên nhân tại sao tệp bitmap này có một tiêu đề RIFF bitmap (chủ yếu là chính xác) vẫn chưa rõ. Có thể Outpost 2 sử dụng các API hệ thống để tải đồ họa, bằng cách tạm thời sử dụng tiêu đề này và ghi đè lên các trường tương ứng, có sự thay đổi.

Dữ liệu pixel được tìm thấy trong tệp BMP tại vị trí Offset + uint32-Offset, mà có thể tìm thấy ở địa chỉ 0x000A trong tệp BMP (điểm dữ liệu RIFF-Bitmap), và lại tương ứng với cách sắp xếp theo dòng từ trên xuống dưới bên trái sang phải.

Đồ họa đơn sắc 1bpp có thể được vẽ sao cho màu 0 hoàn toàn trong suốt, trong khi màu 1 là một màu đen/xám bán trong suốt, vì đồ họa đơn sắc thường được sử dụng cho bóng của phương tiện và tòa nhà trong các hoạt hình.

Với điều này, người ta có thể ghép nhiều đồ họa lại với nhau.

Mô-đun nhà ở bảo vệ (Plymouth)

Hoạt hình

Bây giờ chúng ta đến với lớp cao nhất của các chuyên ngành trong định dạng dữ liệu Outpost 2:
Các hình ảnh động.

Các danh sách hình ảnh động được bắt đầu bằng một tiêu đề toàn cầu, chủ yếu phục vụ cho việc xác minh dữ liệu. Sau đó là các định nghĩa hình ảnh động cụ thể, được chia thành 3 cấp độ:

  1. Hình ảnh động
    Một hình ảnh động là thực thể cao nhất; nó đại diện cho một hình ảnh động của một đơn vị, một tòa nhà hoặc một 'hình ảnh động hạt' (va chạm sao chổi, thời tiết, nổ) trong một tình huống nhất định.
  2. Khung hình
    Một khung hình là một hình ảnh đơn lẻ trong một hình ảnh động. Một hình ảnh động có thể chứa một hoặc nhiều khung hình.
  3. Khung phụ
    Một khung phụ là thông tin về việc một bitmap nhất định sẽ được vẽ ở một vị trí nhất định của một khung hình dưới các tiêu chí nhất định. Một khung hình có thể chứa một hoặc nhiều khung phụ.

Sau đó sẽ là các định nghĩa hình ảnh động cụ thể.

Địa chỉ x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF ký tự
0x0000 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- . . . . . . . . . . . . . . . .
Địa chỉ lệch Loại dữ liệu Tên gọi Giải thích
0x0000 uint(32) Số lượng hoạt hình

Có bao nhiêu bộ dữ liệu hoạt hình có sẵn

0x0004 uint(32) Số lượng khung

Có bao nhiêu khung hình tổng cộng nên có

0x0008 uint(32) Số lượng Subframe

Có bao nhiêu subframe tổng cộng nên có

0x000c uint(32) Số lượng mục tùy chọn

Có bao nhiêu "mục tùy chọn" tồn tại.

Hoạt hình

Địa chỉ x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF ký tự
0x0000 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- . . . . . . . . . . . . . . . .
0x0010 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- . . . . . . . . . . . . . . . .
0x0020 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- . . . . . . . . . . . . . . . .
Địa chỉ lệch Loại dữ liệu Tên gọi Giải thích
0x0000 uint(32) Không xác định 1

Thông tin không xác định

0x0004 uint(32) Hộp giới hạn: Bên trái

Cho biết vị trí bắt đầu bên trái (tính bằng pixel) của Bounding Box.

0x0008 uint(32) Hộp giới hạn: Trên

Chỉ định độ cao phía trên (tính bằng pixel) của Bounding Box.

0x000c uint(32) Hộp giới hạn: Chiều rộng

Chỉ định chiều rộng (tính bằng pixel) của Bounding Box.

0x0010 uint(32) Bounding Box: Chiều cao

Chỉ định chiều cao (tính bằng Pixel) của Bounding Box.

0x0014 uint(32) Offset: X

Chỉ định điểm giữa theo chiều ngang của hoạt ảnh

0x0018 uint(32) Bù: Y

Xác định điểm giữa theo chiều dọc của hoạt ảnh

0x001c uint(32) Không xác định 2

Thông tin không xác định

0x0020 uint(32) Số lượng khung

Cho biết có bao nhiêu khung hình hoạt hình trong hoạt ảnh này

0x0024 uint(32) Số lượng cửa sổ

Xác định số lượng cửa sổ cần sử dụng khi vẽ

Dữ liệu của lớp trên cùng, của hoạt ảnh, chủ yếu là dữ liệu quản lý - Boundingbox chỉ định tọa độ của điểm đánh dấu quanh phương tiện/công trình, khi nó được chọn và cũng đồng thời xác định khu vực nào có thể nhấp vào.

Offset chủ yếu xác định "điểm gốc"; điểm mà cần phải tính toán hoặc trừ trên tọa độ trong trò chơi. Có thể nói một cách toán học: offset ở đây chỉ định gốc tọa độ.

Các cửa sổ cũng giống như offset, bao gồm (cho mỗi cửa sổ) 4 giá trị uint(32), chỉ định một khu vực có thể sử dụng cho các khung con riêng lẻ. Bên ngoài các cửa sổ, nếu không được chỉ định cho bitmap, không được phép vẽ.

Khung

Địa chỉ x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF ký tự
0x0000 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- . . . . . . . . . . . . . . . .
Địa chỉ lệch Loại dữ liệu Tên gọi Giải thích
0x0000 uint(8) Số lượng khung phụ và công tắc cho Tùy chọn 1, 2

Giá trị này bao gồm:

  • 0x7F (Bitmask): Số lượng các subframe được sử dụng trong frame này
  • 0x80: Thông tin về việc Optional 1 và 2 có sẵn hay không
0x0001 uint(8) Không xác định 1 và Chuyển đổi cho Tùy chọn 3, 4

Giá trị này bao gồm:

  • 0x7F (Bitmask): Không xác định - Tôi rất nghi ngờ rằng đây là số lượng Gameticks sẽ trôi qua trước khi khung hình tiếp theo được hiển thị
  • 0x80: Thông tin về việc liệu Tùy chọn 3 và 4 có tồn tại hay không
0x0002 uint(8) Tùy chọn 1

Không xác định

0x0003 uint(8) Tùy chọn 2

Không xác định

0x0004 uint(8) Tùy chọn 3

Không xác định

0x0005 uint(8) Tùy chọn 4

Không xác định

Khung phụ

Địa chỉ x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF ký tự
0x0000 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- . . . . . . . . . . . . . . . .
Địa chỉ lệch Loại dữ liệu Tên gọi Giải thích
0x0000 uint(16) Bitmap-Id

Chỉ định bitmap nào sẽ được sử dụng cho khung con này

0x0002 uint(8) Không xác định 1

Không rõ - tuy nhiên, tôi nghi ngờ mạnh mẽ rằng đây là một ưu tiên render (Z-Layer).

0x0003 uint(8) Id khung phụ

Chỉ ra chúng ta đang ở trong khung con nào

0x0004 sint(16) Offset - Ngang

Chỉ định vị trí bên trong khung nơi mà khung con sẽ được đặt, hoặc số pixel mà bitmap sẽ được di chuyển theo chiều ngang

0x0006 sint(16) Offset - Dọc

Chỉ định vị trí bên trong khung mà khung con sẽ được đặt, hoặc số pixel mà bitmap sẽ được dịch chuyển theo chiều dọc.

Với điều này, chúng ta có thể ghép nối các khung hình riêng lẻ cũng như các hoạt ảnh hoàn chỉnh, ở đây sẽ được minh họa bằng một hoạt ảnh phức tạp hơn, hoạt ảnh có chỉ số 500.

Hoạt hình 500

Animation 500 cho thấy cách một chiếc xe tải Plymouth, được chở đầy quặng thông thường, được dỡ hàng. Đây là một trong số ít các animation sử dụng chức năng Windowing.

Và đây là cách ghép nối toàn bộ animation lại với nhau.
Thật không may, vẫn còn một vấn đề với cửa tải phía trên, vì bit tương ứng trong thông tin loại đồ họa chưa được thiết lập.

Dưới đây là một số sprite được hoạt hình rất đẹp khác từ trò chơi:

Hình minh họa từ Animation 500

Animation 500 đã hoàn thành

Công trình Plymouth

Cảng không gian Eden

Trung tâm y tế Eden

SCAT

Cảng không gian Plymouth

Easteregg:
Ông già Noel

Easteregg:
Dans Dog

Giao diện người dùng

Bây giờ còn thiếu giao diện người dùng của trò chơi, được thiết kế với phong cách kim loại chải.

Nhưng ở đây cũng có thể thấy rằng Dynamix không cần phải phát minh lại bánh xe; ở đây không chỉ đơn giản là sử dụng các API User32 và GDI32 mà Windows cung cấp - đặc biệt là quản lý tài nguyên từ User32 cũng được sử dụng.

Các tài nguyên này có thể được trích xuất bằng các chương trình như Resource Hacker, được phát triển như phần mềm miễn phí bởi Angus Johnson, hoặc - nếu bạn ngại sử dụng Wine trên Linux / Mac OS - bằng cách sử dụng wrestool có trong icoutils.

Tên tệp Nội dung
Outpost2.exe Chỉ chứa biểu tượng của trò chơi, hiển thị trạm không gian trước New Terra
op2shres.dll Chứa các hình ảnh cho các điều khiển như viền, nút, nút radio và hộp kiểm, cũng như nền hội thoại, hình ảnh đi kèm cho các văn bản nhiệm vụ trong cốt truyện và hình nền của menu chính
out2res.dll Chứa trang trí cửa sổ trong game, biểu tượng cho kim loại thông thường và đặc biệt, màn hình tải, đồ họa cho các cuộc hội thoại cũng như các đồ họa con trỏ khác, ngoài những đồ họa hoạt hình trong thư mục trò chơi