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 { type env struct {
gameMap *maps.GameMap gameMap *maps.GameMap
set sets.MapSet set *sets.MapSet
} }
type runState struct { type runState struct {
@@ -159,8 +159,8 @@ func present(win *pixelgl.Window, state *runState) {
// Draw the boundary // Draw the boundary
rect := pixel.R( rect := pixel.R(
float64(gameMap.MinWidth)-1, float64(gameMap.MinLength)-1, float64(gameMap.MinWidth)-0.5, float64(gameMap.MinLength)-0.5,
float64(gameMap.MaxWidth)+1, float64(gameMap.MaxLength)+1, float64(gameMap.MaxWidth)+0.5, float64(gameMap.MaxLength)+0.5,
) )
imd.Color = pixel.RGB(255, 0, 0) imd.Color = pixel.RGB(255, 0, 0)
@@ -210,9 +210,10 @@ func makeColour(cell *maps.Cell, colIdx int) pixel.RGBA {
scale = mult(0.004) scale = mult(0.004)
case 14: case 14:
scale = mult(0.004) scale = mult(0.004)
case 15:
scale = mult(1.0)
default: default:
scale = mult(0.01) // close to maximum resolution, low-value fields will be lost scale = mult(0.01) // close to maximum resolution, low-value fields will be lost
} }
col := scale(float64(cell.At(colIdx))) 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) log.Printf("%#v -> %d,%d", vec, x, y)
cell := state.env.gameMap.Cells.At(x, y, state.zIdx) cell := state.env.gameMap.Cells.At(x, y, state.zIdx)
log.Printf( 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, 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, cell.SquadRelated,
) )
log.Printf("CellIdx%d=%d. Full cell data: %#v", state.cellIdx, cell.At(state.cellIdx), cell) 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 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 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! tentative!
Total number of possible coordinates is 100x130x7 = 91,000 = 1,456,000 bytes. 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 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. 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 Here's an (out-of-date) side-by-side comparison of Chapter3.MAP, investigating
Z index = 0 CellIndex=3 and Z index = 0.
![Map comparison](img/chapter_01_cell_index_3.png) ![Map comparison](img/chapter_01_cell_index_3.png)
@@ -400,17 +400,15 @@ Investigation has so far suggested the following:
* 0x40: Animated object * 0x40: Animated object
* `Cell[2]` hasn't been seen with a value > 0 yet * `Cell[2]` hasn't been seen with a value > 0 yet
* `Cell[3]` Object 0 (Surface) Area (Sets/*.set lookup) * `Cell[3]` Object 0 (Surface) Area (Sets/*.set lookup)
* `Cell[4]` Unsure at present, but it varies between a narrow range of values. * `Cell[4]` Object 0 (Surface) Sprite + ???
I've seen 128 - 147. Broadly matches the terrain layout. * Bottom bits encode the sprite (frame number in the .obj file)
* `Cell[5]` Object 1 (Left) Area (Sets/*.set lookup) **ASSUMED**. * 0x80 is set too. A flag?
* It's in the right place, and there seems to be correspondence, but not as * `Cell[5]` Object 1 (Left) Area (Sets/*.set lookup)
neatly as the other 3 columns. Often off-by-1 * `Cell[6]` Object 1 (Surface) Sprite + ???
* `Cell[6]` Wide range of values, 0 - 161 observed. Seems to have identity with
some blood splatters, etc
* `Cell[7]` Object 2 (Right) Area (Sets/*.set lookup) * `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[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[11]` all 255?
* `Cell[12]` all 0? * `Cell[12]` all 0?
* `Cell[13]` 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 ![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 ## Trailer
Assuming the theory above is correct, we have trailer data starting at Assuming the theory above is correct, we have trailer data starting at

View File

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

View File

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