Discover how frames are encoded, use that knowledge to (finally) get the viewport locked in

This commit is contained in:
2018-03-18 15:39:50 +00:00
parent 2f02c7bbf3
commit 961a213752
4 changed files with 53 additions and 49 deletions

View File

@@ -28,7 +28,7 @@ var (
type env struct {
gameMap *maps.GameMap
set sets.MapSet
set *sets.MapSet
}
type runState struct {
@@ -159,8 +159,8 @@ func present(win *pixelgl.Window, state *runState) {
// Draw the boundary
rect := pixel.R(
float64(gameMap.MinWidth)-1, float64(gameMap.MinLength)-1,
float64(gameMap.MaxWidth)+1, float64(gameMap.MaxLength)+1,
float64(gameMap.MinWidth)-0.5, float64(gameMap.MinLength)-0.5,
float64(gameMap.MaxWidth)+0.5, float64(gameMap.MaxLength)+0.5,
)
imd.Color = pixel.RGB(255, 0, 0)
@@ -210,9 +210,10 @@ func makeColour(cell *maps.Cell, colIdx int) pixel.RGBA {
scale = mult(0.004)
case 14:
scale = mult(0.004)
case 15:
scale = mult(1.0)
default:
scale = mult(0.01) // close to maximum resolution, low-value fields will be lost
}
col := scale(float64(cell.At(colIdx)))
@@ -290,9 +291,9 @@ func runStep(win *pixelgl.Window, state *runState) *runState {
log.Printf("%#v -> %d,%d", vec, x, y)
cell := state.env.gameMap.Cells.At(x, y, state.zIdx)
log.Printf(
"x=%d y=%d z=%d Object0SurfaceArea=%d Object3CenterArea=%d (%s) SquadRelated=%d",
"x=%d y=%d z=%d SurfaceTile=%d (%s) SurfaceFrame=%d SquadRelated=%d",
x, y, state.zIdx,
cell.Object0SurfaceArea, cell.Object3CenterArea, state.env.set.Palette[int(cell.Object3CenterArea)],
cell.Surface.Index(), state.env.set.Palette[int(cell.Surface.Index())], cell.Surface.Frame(),
cell.SquadRelated,
)
log.Printf("CellIdx%d=%d. Full cell data: %#v", state.cellIdx, cell.At(state.cellIdx), cell)

View File

@@ -287,7 +287,7 @@ Skipping the header we know about, we have data like this:
It would be very neat if the per-cell data started at 0x100 and took 16 bytes
per coordinate, but to get objects in my map to line up properly with cells in
WH40K_TD.exe, I've had to start parsing these rows at `0x0120` instead. Still
WH40K_TD.exe, I've had to start parsing these rows at `0x0110` instead. Still
tentative!
Total number of possible coordinates is 100x130x7 = 91,000 = 1,456,000 bytes.
@@ -379,8 +379,8 @@ I've added a `view-map` command to explore the data graphically. Each of the 16
bytes in a cell row must have a function; comparing a known map to how it looks
in WH40K_TD.exe can help me to unravel that function.
Here's a side-by-side comparison of Chapter3.MAP, investigating CellIndex=3 and
Z index = 0
Here's an (out-of-date) side-by-side comparison of Chapter3.MAP, investigating
CellIndex=3 and Z index = 0.
![Map comparison](img/chapter_01_cell_index_3.png)
@@ -400,17 +400,15 @@ Investigation has so far suggested the following:
* 0x40: Animated object
* `Cell[2]` hasn't been seen with a value > 0 yet
* `Cell[3]` Object 0 (Surface) Area (Sets/*.set lookup)
* `Cell[4]` Unsure at present, but it varies between a narrow range of values.
I've seen 128 - 147. Broadly matches the terrain layout.
* `Cell[5]` Object 1 (Left) Area (Sets/*.set lookup) **ASSUMED**.
* It's in the right place, and there seems to be correspondence, but not as
neatly as the other 3 columns. Often off-by-1
* `Cell[6]` Wide range of values, 0 - 161 observed. Seems to have identity with
some blood splatters, etc
* `Cell[4]` Object 0 (Surface) Sprite + ???
* Bottom bits encode the sprite (frame number in the .obj file)
* 0x80 is set too. A flag?
* `Cell[5]` Object 1 (Left) Area (Sets/*.set lookup)
* `Cell[6]` Object 1 (Surface) Sprite + ???
* `Cell[7]` Object 2 (Right) Area (Sets/*.set lookup)
* `Cell[8]` Wide range of values, 0 - 159 observed.
* `Cell[6]` Object 2 (Right) Sprite + ???
* `Cell[9]` Object 3 (Center) Area (Sets/*.set lookup)
* `Cell[10]` Varies from 0 - 248. Unclear what for, broadly follows terrain
* `Cell[10]` Object 3 (Right) Sprite + ???
* `Cell[11]` all 255?
* `Cell[12]` all 0?
* `Cell[13]` all 0?
@@ -435,10 +433,6 @@ So `CellIdx == 9` points to the center object's Area, looked up in the set file!
![Pinning down cell index 9](img/chapter01_cell_index_9.png
I still see weird artifacts on middle Z-layers making me think I'm off the
stride or perhaps there's a data block partway through or something. Or maybe
the data's just born that way.
## Trailer
Assuming the theory above is correct, we have trailer data starting at

View File

@@ -26,7 +26,7 @@ const (
CellSize = 16 // seems to be
cellDataOffset = 0x120 // tentatively
cellDataOffset = 0x110 // tentatively
cellCount = MaxHeight * MaxLength * MaxWidth
)
@@ -68,18 +68,28 @@ func (h Header) MapSetFilename() string {
return string(h.SetName[0:idx:idx]) + ".set"
}
type ObjRef struct {
AreaByte byte
FrameAndUnknownByte byte
}
// The index into a set palette to retrieve the object
func (o ObjRef) Index() int {
return int(o.AreaByte)
}
func (o ObjRef) Frame() int {
return int(o.FrameAndUnknownByte - 0x80)
}
type Cell struct {
DoorAndCanisterRelated byte
DoorLockAndReactorRelated byte
Unknown2 byte
Object0SurfaceArea byte
Unknown4 byte
Object1LeftArea byte
Unknown6 byte
Object2RightArea byte
Unknown8 byte
Object3CenterArea byte
Unknown10 byte
Surface ObjRef
Left ObjRef
Right ObjRef
Center ObjRef
Unknown11 byte
Unknown12 byte
Unknown13 byte
@@ -96,21 +106,21 @@ func (c *Cell) At(n int) byte {
case 2:
return c.Unknown2
case 3:
return c.Object0SurfaceArea
return c.Surface.AreaByte
case 4:
return c.Unknown4
return c.Surface.FrameAndUnknownByte
case 5:
return c.Object1LeftArea
return c.Left.AreaByte
case 6:
return c.Unknown6
return c.Left.FrameAndUnknownByte
case 7:
return c.Object2RightArea
return c.Right.AreaByte
case 8:
return c.Unknown8
return c.Right.FrameAndUnknownByte
case 9:
return c.Object3CenterArea
return c.Center.AreaByte
case 10:
return c.Unknown10
return c.Center.FrameAndUnknownByte
case 11:
return c.Unknown11
case 12:

View File

@@ -19,13 +19,13 @@ type MapSet struct {
Palette []string
}
func LoadSets(dir string) (map[string]MapSet, error) {
func LoadSets(dir string) (map[string]*MapSet, error) {
fis, err := ioutil.ReadDir(dir)
if err != nil {
return nil, err
}
out := make(map[string]MapSet, len(fis))
out := make(map[string]*MapSet, len(fis))
for _, fi := range fis {
filename := filepath.Join(dir, fi.Name())
@@ -48,35 +48,34 @@ func LoadSets(dir string) (map[string]MapSet, error) {
return out, nil
}
func LoadSet(filename string) (MapSet, error) {
var out MapSet
var err error
func LoadSet(filename string) (*MapSet, error) {
out := &MapSet{}
s, err := asciiscan.New(filename)
if err != nil {
return out, err
return nil, err
}
defer s.Close()
out.Description, err = s.ConsumeString()
if err != nil {
return out, err
return nil, err
}
out.Defs, err = consumeDefs(s)
if err != nil {
return out, err
return nil, err
}
for {
str, err := s.ConsumeString()
if err != nil {
if err == io.EOF {
err = nil
return out, nil
}
return out, err
return nil, err
}
out.Palette = append(out.Palette, str)