Định dạng tệp Outpost 2 · bei.pm
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. và 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 Engineering và phâ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.
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:
|
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.
|
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: head
và data
.
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à |
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ị |
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ị |
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ị |
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.
Độ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:
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 |
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 |
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 |
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 |
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à |
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.
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õ. |
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:
|
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.
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 độ:
-
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. -
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. -
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:
|
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:
|
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:
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 |