Compare commits
3 Commits
48d098134e
...
14fdab72a0
Author | SHA1 | Date | |
---|---|---|---|
14fdab72a0 | |||
c7a2fa80e7 | |||
def40a1ee2 |
@@ -517,3 +517,86 @@ Around 001841A0: mission objectives!
|
||||
|
||||
Since all the files are exactly the same length uncompressed, I'm going to
|
||||
assume these are all a fixed number of fixed-size records when looking into it.
|
||||
|
||||
|
||||
|
||||
|
||||
## Soldiers At War
|
||||
|
||||
All the above applies to Chaos Gate maps. Maps for Soldiers At War seem to have
|
||||
a lot of similarities, but also some differences. For a start, the maps are a
|
||||
variable size!
|
||||
|
||||
Starting with the header, given a tiny 26x20 generated map, the first 256 bytes
|
||||
look like this:
|
||||
|
||||
```
|
||||
00000000: 1500414d 425f4d41 50005041 52495300 ..AMB_MAP.PARIS.
|
||||
00000010: 00000000 00000000 00000000 00000000 ................
|
||||
00000020: 00000000 00000000 00000000 00000000 ................
|
||||
00000030: 00000000 00000000 00000000 00000000 ................
|
||||
00000040: 00000000 00000000 00000000 00000000 ................
|
||||
00000050: 00000000 00000000 00000000 00000000 ................
|
||||
00000060: 00000000 00000000 00000000 00000000 ................
|
||||
00000070: 00000000 00000000 00000000 00000000 ................
|
||||
00000080: 00000000 00000000 00001e00 45000100 ............E...
|
||||
00000090: 1f004600 10010000 52000000 00001b00 ..F.....R.......
|
||||
000000a0: 38000100 00000500 0a000001 00f0f9ff 8...............
|
||||
000000b0: ffb60500 00000100 ff370a00 64006400 .........7..d.d.
|
||||
000000c0: 08008501 00000000 00ff0000 1f008082 ................
|
||||
000000d0: 01000000 0000ff00 001f0080 84010000 ................
|
||||
000000e0: 000000ff 00001f00 00810100 00000000 ................
|
||||
000000f0: ff00001f 00808301 00000000 00ff0000 ................
|
||||
```
|
||||
|
||||
Almost everything we knew is out of the window, but a few things look familiar.
|
||||
First, the header seems simplified down to just two recognisable-at-first-glance
|
||||
fields: Magic bytes (now `\x15\x00AMV_MAP\x00`) and the set name, coming
|
||||
immediately after.
|
||||
|
||||
Like Chaos Gate, all map files are the same size once uncompressed, but they are
|
||||
smaller - at 1,214,559 bytes, they are 76% the size. This is quite significant.
|
||||
We now have 13.3 bytes per voxel, rather than the 17.5 bytes per voxel that was
|
||||
available to Chaos Gate. This means that the number of bytes *per cell* must be
|
||||
reduced, in addition to the header (and trailer?) values.
|
||||
|
||||
Looking at data from 0x110, it seems to group naturally into 13-byte records:
|
||||
|
||||
```
|
||||
$ xxd -s 0x110 -c 13 -l 65 -g 1 TINYMAP.MAP
|
||||
00000110: 80 01 00 00 00 00 00 ff 00 00 1f 00 00 .............
|
||||
0000011d: 85 01 00 00 00 00 00 ff 00 00 1f 00 00 .............
|
||||
0000012a: 82 01 00 00 00 00 00 ff 00 00 1f 00 80 .............
|
||||
00000137: 82 01 00 00 00 00 00 ff 00 00 1f 00 00 .............
|
||||
00000144: 82 01 00 00 00 00 00 ff 00 00 1f 00 80 .............
|
||||
```
|
||||
|
||||
It's a strange number. Chaos Gate cells group nicely on 16 bytes:
|
||||
|
||||
```
|
||||
$ xxd -s 0x110 -c 16 -l 64 -g 1 Chapter01.MAP
|
||||
00000110: 3f 00 00 00 83 01 00 00 00 00 00 ff 00 00 00 00 ?...............
|
||||
00000120: 38 00 00 00 85 01 00 00 00 00 00 ff 00 00 00 00 8...............
|
||||
00000130: 38 00 00 00 84 01 00 00 00 00 00 ff 00 00 00 00 8...............
|
||||
00000140: 38 00 00 00 8a 01 00 00 00 00 00 ff 00 00 00 00 8...............
|
||||
00000150: 38 00 00 00 83 01 00 00 00 00 00 ff 00 00 00 00 8...............
|
||||
```
|
||||
|
||||
That grouping is very enticing, though. I feel strongly that it's the right
|
||||
number.
|
||||
|
||||
Now we need to ask about start offset. Where is byte 0 of the per-cell data, and
|
||||
do the 13 bytes it has line up neatly to the functions of some of the 16 bytes
|
||||
seen in Chaos Gate?
|
||||
|
||||
I generated a `BIGGESTMAP` (130x100) to investigate. It's just grass, nothing
|
||||
but grass, and 0xC0 is the first offset where it starts to look nicely grouped:
|
||||
|
||||
```
|
||||
xxd -s 0xc0 -c 13 -l 260 -g 13 BIGGESTMAP.MAP
|
||||
000000c0: 08 80 81 01 00 00 00 00 00 ff 00 00 1f .............
|
||||
000000cd: 00 80 81 01 00 00 00 00 00 ff 00 00 1f .............
|
||||
000000da: 00 00 81 01 00 00 00 00 00 ff 00 00 1f .............
|
||||
000000e7: 00 00 85 01 00 00 00 00 00 ff 00 00 1f .............
|
||||
# ...
|
||||
```
|
||||
|
4
go.mod
4
go.mod
@@ -1,11 +1,11 @@
|
||||
module code.ur.gs/lupine/ordoor
|
||||
|
||||
go 1.12
|
||||
go 1.14
|
||||
|
||||
require (
|
||||
github.com/BurntSushi/toml v0.3.1
|
||||
github.com/emef/bitfield v0.0.0-20170503144143-7d3f8f823065
|
||||
github.com/hajimehoshi/ebiten v1.11.0
|
||||
github.com/hajimehoshi/ebiten v1.11.1
|
||||
github.com/jfreymuth/oggvorbis v1.0.1 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
|
||||
|
2
go.sum
2
go.sum
@@ -19,6 +19,8 @@ github.com/hajimehoshi/ebiten v1.11.0-alpha.2.0.20200101150127-38815ba801a5 h1:h
|
||||
github.com/hajimehoshi/ebiten v1.11.0-alpha.2.0.20200101150127-38815ba801a5/go.mod h1:0SLvfr8iI2NxzpNB/olBM+dLN9Ur5a9szG13wOgQ0nQ=
|
||||
github.com/hajimehoshi/ebiten v1.11.0 h1:+pIxfzfVgRbHGM7wBAJtgzPiWiZopA7lyIKNQqc9amk=
|
||||
github.com/hajimehoshi/ebiten v1.11.0/go.mod h1:aDEhx0K9gSpXw3Cxf2hCXDxPSoF8vgjNqKxrZa/B4Dg=
|
||||
github.com/hajimehoshi/ebiten v1.11.1 h1:7gy2bHBDNtfTh3GlcUAilk3lNWW9fTLaP7iZAodS9F8=
|
||||
github.com/hajimehoshi/ebiten v1.11.1/go.mod h1:aDEhx0K9gSpXw3Cxf2hCXDxPSoF8vgjNqKxrZa/B4Dg=
|
||||
github.com/hajimehoshi/go-mp3 v0.2.1 h1:DH4ns3cPv39n3cs8MPcAlWqPeAwLCK8iNgqvg0QBWI8=
|
||||
github.com/hajimehoshi/go-mp3 v0.2.1/go.mod h1:Rr+2P46iH6PwTPVgSsEwBkon0CK5DxCAeX/Rp65DCTE=
|
||||
github.com/hajimehoshi/oto v0.3.4/go.mod h1:PgjqsBJff0efqL2nlMJidJgVJywLn6M4y8PI4TfeWfA=
|
||||
|
@@ -47,12 +47,7 @@ func (a *AssetStore) Map(name string) (*Map, error) {
|
||||
}
|
||||
|
||||
m := &Map{
|
||||
Rect: image.Rect(
|
||||
int(raw.MinWidth),
|
||||
int(raw.MinLength),
|
||||
int(raw.MaxWidth),
|
||||
int(raw.MaxLength),
|
||||
),
|
||||
Rect: raw.Rect(),
|
||||
assets: a,
|
||||
raw: raw,
|
||||
set: set,
|
||||
@@ -65,8 +60,8 @@ func (a *AssetStore) Map(name string) (*Map, error) {
|
||||
|
||||
func (m *Map) LoadSprites() error {
|
||||
// Eager load the sprites we use
|
||||
for x := m.Rect.Min.X; x <= m.Rect.Max.X; x++ {
|
||||
for y := m.Rect.Min.Y; y <= m.Rect.Max.Y; y++ {
|
||||
for x := m.Rect.Min.X; x < m.Rect.Max.X; x++ {
|
||||
for y := m.Rect.Min.Y; y < m.Rect.Max.Y; y++ {
|
||||
for z := 0; z < maps.MaxHeight; z++ {
|
||||
if _, err := m.SpritesForCell(x, y, z); err != nil {
|
||||
return err
|
||||
|
@@ -5,6 +5,7 @@ import (
|
||||
"compress/gzip"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"image"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
@@ -173,6 +174,15 @@ type GameMap struct {
|
||||
Text string
|
||||
}
|
||||
|
||||
func (m *GameMap) Rect() image.Rectangle {
|
||||
return image.Rect(
|
||||
int(m.Header.MinWidth),
|
||||
int(m.Header.MinLength),
|
||||
int(m.Header.MaxWidth),
|
||||
int(m.Header.MaxLength),
|
||||
)
|
||||
}
|
||||
|
||||
// A game map contains a .txt and a .map. If they're in the same directory,
|
||||
// just pass the directory + basename to load both
|
||||
func LoadGameMap(prefix string) (*GameMap, error) {
|
||||
|
Reference in New Issue
Block a user