Compare commits
2 Commits
main
...
soldiers-a
Author | SHA1 | Date | |
---|---|---|---|
494fe4eb02 | |||
30d1786e64 |
@@ -15,8 +15,8 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
expectedMagic = []byte("\x08\x00WHMAP\x00")
|
||||
expectedSetNameOffset = uint32(0x34)
|
||||
expectedMagic = []byte("\x15\x00AMB_MAP\x00")
|
||||
expectedSetNameOffset = uint32(0x10)
|
||||
notImplemented = fmt.Errorf("Not implemented")
|
||||
)
|
||||
|
||||
@@ -25,27 +25,17 @@ const (
|
||||
MaxLength = 100 // Y coordinate
|
||||
MaxWidth = 130 // X coordinate
|
||||
|
||||
CellSize = 16 // seems to be
|
||||
CellSize = 13 // seems to be
|
||||
|
||||
cellDataOffset = 0x110 // definitely
|
||||
cellDataOffset = 0xc0
|
||||
cellCount = MaxHeight * MaxLength * MaxWidth
|
||||
)
|
||||
|
||||
type Header struct {
|
||||
IsCampaignMap uint32 // Tentatively: 0 = no, 1 = yes
|
||||
MinWidth uint32
|
||||
MinLength uint32
|
||||
MaxWidth uint32
|
||||
MaxLength uint32
|
||||
Unknown1 uint32
|
||||
Unknown2 uint32
|
||||
Unknown3 uint32
|
||||
Unknown4 uint32
|
||||
Magic [8]byte // "\x08\x00WHMAP\x00"
|
||||
Unknown5 uint32
|
||||
Unknown6 uint32
|
||||
SetName [8]byte // Links to a filename in `/Sets/*.set`
|
||||
Magic [10]byte // "\x15\x00AMB_MAP\x00"
|
||||
SetName [8]byte // Links to a filename in `/Sets/*.set`
|
||||
// Need to investigate the rest of the header too
|
||||
IsCampaignMap byte
|
||||
}
|
||||
|
||||
type TrailerHeader struct {
|
||||
@@ -82,18 +72,6 @@ type Thingy struct {}
|
||||
|
||||
type Thingies []Thingy
|
||||
|
||||
func (h Header) Width() int {
|
||||
return int(h.MaxWidth - h.MinWidth)
|
||||
}
|
||||
|
||||
func (h Header) Length() int {
|
||||
return int(h.MaxLength - h.MinLength)
|
||||
}
|
||||
|
||||
func (h Header) Height() int {
|
||||
return MaxHeight
|
||||
}
|
||||
|
||||
func (h Header) MapSetName() string {
|
||||
idx := bytes.IndexByte(h.SetName[:], 0)
|
||||
if idx < 0 {
|
||||
@@ -114,7 +92,7 @@ type ObjRef struct {
|
||||
|
||||
// The index into a set palette to retrieve the object
|
||||
func (o ObjRef) Index() int {
|
||||
return int(o.AreaByte)
|
||||
return int(o.AreaByte & 0x7f)
|
||||
}
|
||||
|
||||
func (o ObjRef) Sprite() int {
|
||||
@@ -125,12 +103,13 @@ func (o ObjRef) Sprite() int {
|
||||
// The top bit seems to say whether we should draw or not.
|
||||
func (o ObjRef) IsActive() bool {
|
||||
return (o.SpriteAndFlagByte & 0x80) == 0x80
|
||||
}
|
||||
|
||||
} // PARIS is 78 x 60 x 7
|
||||
// 4E 3C 7
|
||||
/*
|
||||
type Cell struct {
|
||||
DoorAndCanisterRelated byte
|
||||
DoorLockAndReactorRelated byte
|
||||
Unknown2 byte
|
||||
// DoorLockAndReactorRelated byte
|
||||
// Unknown2 byte
|
||||
Surface ObjRef
|
||||
Left ObjRef
|
||||
Right ObjRef
|
||||
@@ -139,43 +118,60 @@ type Cell struct {
|
||||
Unknown12 byte
|
||||
Unknown13 byte
|
||||
Unknown14 byte
|
||||
SquadRelated byte
|
||||
// SquadRelated byte
|
||||
}*/
|
||||
|
||||
type Cell struct {
|
||||
Unknown1 byte
|
||||
Surface ObjRef
|
||||
Left ObjRef
|
||||
Right ObjRef
|
||||
Center ObjRef
|
||||
Unknown2 [4]byte
|
||||
|
||||
/*
|
||||
DoorAndCanisterRelated byte
|
||||
// DoorLockAndReactorRelated byte
|
||||
// Unknown2 byte
|
||||
Surface ObjRef
|
||||
Left ObjRef
|
||||
Right ObjRef
|
||||
Center ObjRef
|
||||
Unknown11 byte
|
||||
Unknown12 byte
|
||||
Unknown13 byte
|
||||
Unknown14 byte
|
||||
SquadRelated byte*/
|
||||
}
|
||||
|
||||
func (c *Cell) At(n int) byte {
|
||||
switch n {
|
||||
case 0:
|
||||
return c.DoorAndCanisterRelated
|
||||
return c.Unknown1
|
||||
case 1:
|
||||
return c.DoorLockAndReactorRelated
|
||||
case 2:
|
||||
return c.Unknown2
|
||||
case 3:
|
||||
return c.Surface.AreaByte
|
||||
case 4:
|
||||
case 2:
|
||||
return c.Surface.SpriteAndFlagByte
|
||||
case 5:
|
||||
case 3:
|
||||
return c.Left.AreaByte
|
||||
case 6:
|
||||
case 4:
|
||||
return c.Left.SpriteAndFlagByte
|
||||
case 7:
|
||||
case 5:
|
||||
return c.Right.AreaByte
|
||||
case 8:
|
||||
case 6:
|
||||
return c.Right.SpriteAndFlagByte
|
||||
case 9:
|
||||
case 7:
|
||||
return c.Center.AreaByte
|
||||
case 10:
|
||||
case 8:
|
||||
return c.Center.SpriteAndFlagByte
|
||||
case 9:
|
||||
return c.Unknown2[0]
|
||||
case 10:
|
||||
return c.Unknown2[1]
|
||||
case 11:
|
||||
return c.Unknown11
|
||||
return c.Unknown2[2]
|
||||
case 12:
|
||||
return c.Unknown12
|
||||
case 13:
|
||||
return c.Unknown13
|
||||
case 14:
|
||||
return c.Unknown14
|
||||
case 15:
|
||||
return c.SquadRelated
|
||||
return c.Unknown2[3]
|
||||
}
|
||||
|
||||
return 0
|
||||
@@ -184,15 +180,23 @@ func (c *Cell) At(n int) byte {
|
||||
// Cells is always a fixed size; use At to get a cell according to x,y,z
|
||||
type Cells []Cell
|
||||
|
||||
// 6 Possibilities for being laid out in memory. Most likely:
|
||||
// XXYYZZ
|
||||
// OR
|
||||
// XYZXYZ
|
||||
|
||||
func (c Cells) At(x, y, z int) Cell {
|
||||
return c[(z*MaxLength*MaxWidth)+(y*MaxWidth)+x]
|
||||
// log.Printf("At (%v,%v,%v)=%v", x, y, z, x*y*z)
|
||||
return c[(z*MaxLength*MaxWidth)+
|
||||
(y*MaxWidth)+
|
||||
x]
|
||||
}
|
||||
|
||||
func (h Header) Check() []error {
|
||||
var out []error
|
||||
if h.IsCampaignMap > 1 {
|
||||
out = append(out, fmt.Errorf("Expected 0 or 1 for IsCampaignMap, got %v", h.IsCampaignMap))
|
||||
}
|
||||
// if h.IsCampaignMap > 1 {
|
||||
// out = append(out, fmt.Errorf("Expected 0 or 1 for IsCampaignMap, got %v", h.IsCampaignMap))
|
||||
// }
|
||||
|
||||
if bytes.Compare(expectedMagic, h.Magic[:]) != 0 {
|
||||
out = append(out, fmt.Errorf("Unexpected magic value: %v", h.Magic))
|
||||
@@ -217,10 +221,10 @@ type GameMap struct {
|
||||
|
||||
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),
|
||||
int(m.TrailerHeader.MinWidth),
|
||||
int(m.TrailerHeader.MinLength),
|
||||
int(m.TrailerHeader.MaxWidth-1),
|
||||
int(m.TrailerHeader.MaxLength-1),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -327,6 +331,11 @@ func loadMapFile(filename string) (*GameMap, error) {
|
||||
return nil, fmt.Errorf("Error parsing cells for %s: %v", filename, err)
|
||||
}
|
||||
|
||||
// no gzip.SeekReader, so discard unread trailer bytes for now
|
||||
if _, err := io.CopyN(ioutil.Discard, zr, int64(3320-2)); err != nil { // observed
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := binary.Read(zr, binary.LittleEndian, &out.TrailerHeader); err != nil {
|
||||
return nil, fmt.Errorf("Error parsing trailer header for %s: %v", filename, err)
|
||||
}
|
||||
|
Reference in New Issue
Block a user