Discover how frames are encoded, use that knowledge to (finally) get the viewport locked in
This commit is contained in:
@@ -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)
|
||||||
|
@@ -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.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -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!
|
|||||||
|
|
||||||

|
)
|
||||||
|
|
||||||
@@ -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:
|
||||||
|
@@ -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)
|
||||||
|
Reference in New Issue
Block a user