From 30d1786e64c579c75381c04325e1bbb39737683a Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Wed, 20 May 2020 01:47:04 +0100 Subject: [PATCH] Get SaW maps displaying --- internal/maps/maps.go | 122 ++++++++++++++++++++++++------------------ 1 file changed, 69 insertions(+), 53 deletions(-) diff --git a/internal/maps/maps.go b/internal/maps/maps.go index 253b321..ac53311 100644 --- a/internal/maps/maps.go +++ b/internal/maps/maps.go @@ -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 { @@ -83,11 +73,11 @@ type Thingy struct {} type Thingies []Thingy func (h Header) Width() int { - return int(h.MaxWidth - h.MinWidth) + return MaxWidth } func (h Header) Length() int { - return int(h.MaxLength - h.MinLength) + return MaxLength } func (h Header) Height() int { @@ -114,7 +104,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 +115,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 +130,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 +192,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 +233,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(0), + int(0), + int(m.Width()-1), + int(m.Length()-1), ) }