2018-02-24 13:50:35 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"flag"
|
2018-03-17 04:15:40 +00:00
|
|
|
"fmt"
|
2018-02-24 13:50:35 +00:00
|
|
|
"log"
|
|
|
|
"path/filepath"
|
2018-12-30 23:23:08 +00:00
|
|
|
"strings"
|
2018-02-24 13:50:35 +00:00
|
|
|
|
2019-12-31 01:55:58 +00:00
|
|
|
"code.ur.gs/lupine/ordoor/internal/data"
|
|
|
|
"code.ur.gs/lupine/ordoor/internal/fonts"
|
|
|
|
"code.ur.gs/lupine/ordoor/internal/maps"
|
|
|
|
"code.ur.gs/lupine/ordoor/internal/menus"
|
|
|
|
"code.ur.gs/lupine/ordoor/internal/sets"
|
2018-02-24 13:50:35 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
gamePath = flag.String("game-path", "./orig", "Path to a WH40K: Chaos Gate installation")
|
2018-12-30 23:23:08 +00:00
|
|
|
skipObj = flag.Bool("skip-obj", true, "Skip loading .obj files")
|
2018-02-24 13:50:35 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
flag.Parse()
|
|
|
|
|
2018-03-17 04:15:40 +00:00
|
|
|
loadData()
|
2018-12-30 23:23:08 +00:00
|
|
|
|
|
|
|
if !*skipObj {
|
|
|
|
loadObj()
|
|
|
|
}
|
2018-03-17 04:15:40 +00:00
|
|
|
|
|
|
|
loadMapsFrom("Maps")
|
|
|
|
loadMapsFrom("MultiMaps")
|
2018-03-18 05:34:14 +00:00
|
|
|
loadSets()
|
2018-12-30 23:23:08 +00:00
|
|
|
loadMenus()
|
2019-01-02 06:16:15 +00:00
|
|
|
loadFonts()
|
2018-03-17 04:15:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func loadData() {
|
2018-02-24 13:50:35 +00:00
|
|
|
dataPath := filepath.Join(*gamePath, "Data")
|
|
|
|
accountingPath := filepath.Join(dataPath, "Accounting.dat")
|
|
|
|
genericDataPath := filepath.Join(dataPath, "GenericData.dat")
|
|
|
|
aniObDefPath := filepath.Join(dataPath, "AniObDef.dat")
|
2019-01-02 06:16:15 +00:00
|
|
|
i18nPath := filepath.Join(dataPath, data.I18nFile)
|
2018-02-24 13:50:35 +00:00
|
|
|
|
|
|
|
log.Printf("Loading %s...", accountingPath)
|
|
|
|
accounting, err := data.LoadAccounting(accountingPath)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatalf("Failed to parse %s: %s", accountingPath, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Printf("%s: %+v", accountingPath, accounting)
|
|
|
|
|
|
|
|
log.Printf("Loading %s...", aniObDefPath)
|
|
|
|
animated, err := data.LoadAnimatedObjectDefinitions(aniObDefPath)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatalf("Failed to parse %s: %s", genericDataPath, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Printf("%s: %+v", aniObDefPath, animated)
|
|
|
|
|
|
|
|
log.Printf("Loading %s...", genericDataPath)
|
|
|
|
genericData, err := data.LoadGeneric(genericDataPath)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatalf("Failed to parse %s: %s", genericDataPath, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Printf("%s: %+v", genericDataPath, genericData)
|
2019-01-02 06:16:15 +00:00
|
|
|
|
|
|
|
log.Printf("Loading %s...", i18nPath)
|
|
|
|
i18n, err := data.LoadI18n(i18nPath)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatalf("Failed to parse %s: %s", i18nPath, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Printf("%s: len=%v", i18nPath, i18n.Len())
|
2018-03-17 04:15:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func loadObj() {
|
|
|
|
objDataPath := filepath.Join(*gamePath, "Obj")
|
2018-02-24 13:50:35 +00:00
|
|
|
|
|
|
|
// TODO: Obj/cpiece.rec isn't loaded by this. Do we need it? How do we know?
|
|
|
|
log.Printf("Loading %s...", objDataPath)
|
|
|
|
objects, err := data.LoadObjects(objDataPath)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatalf("Failed to parse %s: %s", objDataPath, err)
|
|
|
|
}
|
|
|
|
|
2018-03-17 04:15:40 +00:00
|
|
|
inspect := "c_webs"
|
|
|
|
inspect_obj := inspect + ".obj"
|
|
|
|
|
2018-02-24 13:50:35 +00:00
|
|
|
log.Printf("Objects in %s:", objDataPath)
|
|
|
|
for key, obj := range objects {
|
2018-03-17 04:15:40 +00:00
|
|
|
if key != inspect_obj {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
log.Printf(
|
2018-03-21 18:56:30 +00:00
|
|
|
"\t%s\t%d sprites\t%d bytes",
|
|
|
|
key, obj.ObjectHeader.NumSprites, obj.ObjectHeader.DataSize,
|
2018-03-17 04:15:40 +00:00
|
|
|
)
|
2018-02-24 13:50:35 +00:00
|
|
|
}
|
|
|
|
|
2018-03-17 04:15:40 +00:00
|
|
|
log.Printf("%s: %#v", inspect, objects[inspect_obj])
|
|
|
|
|
2018-03-21 18:56:30 +00:00
|
|
|
for i, sprite := range objects[inspect_obj].Sprites {
|
|
|
|
numPixels := sprite.Width * sprite.Height
|
|
|
|
log.Printf("sprite %d: w=%d h=%d sz=%d w*h=%d bits/pixel=%v", i, sprite.Width, sprite.Height, sprite.PixelSize, numPixels, float64(sprite.PixelSize*8)/float64(numPixels))
|
2018-03-17 04:15:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func loadMapsFrom(part string) {
|
|
|
|
mapsPath := filepath.Join(*gamePath, part)
|
|
|
|
log.Printf("Loading maps from %s", mapsPath)
|
|
|
|
|
|
|
|
gameMaps, err := maps.LoadGameMaps(mapsPath)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatalf("Failed to parse %s/*.{MAP,txt} as game maps: %v", mapsPath, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Printf("Maps in %s:", mapsPath)
|
|
|
|
for key, gameMap := range gameMaps {
|
|
|
|
hdr := gameMap.Header
|
|
|
|
fmt.Printf(
|
|
|
|
" * `%s`: IsCampaignMap=%v W=%v:%v L=%v:%v SetName=%s\n",
|
|
|
|
key,
|
|
|
|
hdr.IsCampaignMap,
|
|
|
|
hdr.MinWidth, hdr.MaxWidth,
|
|
|
|
hdr.MinLength, hdr.MaxLength,
|
|
|
|
string(hdr.SetName[:]),
|
|
|
|
)
|
|
|
|
}
|
2018-02-24 13:50:35 +00:00
|
|
|
}
|
2018-03-18 05:34:14 +00:00
|
|
|
|
|
|
|
func loadSets() {
|
|
|
|
setsPath := filepath.Join(*gamePath, "Sets")
|
|
|
|
log.Printf("Loading sets from %s", setsPath)
|
|
|
|
|
|
|
|
mapSets, err := sets.LoadSets(setsPath)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatalf("Failed to parse %s/*.set as map sets: %v", setsPath, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
for key, mapSet := range mapSets {
|
2018-03-18 17:27:32 +00:00
|
|
|
fmt.Printf(" * `%s`: surface expected=%d actual=%d\n", key, mapSet.SurfaceCount, len(mapSet.SurfacePalette))
|
|
|
|
fmt.Printf(" * `%s`: left expected=%d actual=%d\n", key, mapSet.LeftCount, len(mapSet.LeftPalette))
|
|
|
|
fmt.Printf(" * `%s`: right expected=%d actual=%d\n", key, mapSet.RightCount, len(mapSet.RightPalette))
|
|
|
|
fmt.Printf(" * `%s`: center expected=%d actual=%d\n", key, mapSet.CenterCount, len(mapSet.CenterPalette))
|
2018-03-18 05:34:14 +00:00
|
|
|
}
|
|
|
|
}
|
2018-12-30 23:23:08 +00:00
|
|
|
|
|
|
|
func loadMenus() {
|
|
|
|
menusPath := filepath.Join(*gamePath, "Menu")
|
|
|
|
|
|
|
|
menus, err := menus.LoadMenus(menusPath)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatalf("Failed to parse %s/*.mnu as menus: %v", menusPath, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, menu := range menus {
|
|
|
|
fmt.Printf(" * `%s`: objects=%v fonts=%v\n", menu.Name, menu.ObjectFiles, menu.FontNames)
|
2020-04-14 03:14:49 +01:00
|
|
|
|
|
|
|
for _, group := range menu.Groups {
|
|
|
|
// TODO: display group
|
|
|
|
for _, record := range group.Records {
|
|
|
|
displayRecord(record, 2)
|
|
|
|
}
|
2018-12-30 23:23:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func displayRecord(record *menus.Record, depth int) {
|
2020-04-14 03:14:49 +01:00
|
|
|
content := fmt.Sprintf("id=%v type=%v sprite=%v", record.ID, record.Type, record.SpriteId)
|
2018-12-30 23:23:08 +00:00
|
|
|
|
|
|
|
if !record.Active {
|
|
|
|
content = "(" + content + ")"
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Printf("%s* %s\n", strings.Repeat(" ", depth), content)
|
|
|
|
}
|
2019-01-02 06:16:15 +00:00
|
|
|
|
|
|
|
func loadFonts() {
|
|
|
|
fontsPath := filepath.Join(*gamePath, "Fonts")
|
|
|
|
|
|
|
|
fonts, err := fonts.LoadFonts(fontsPath)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatalf("Failed to parse %s/*.fnt as fonts: %v", fontsPath, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, font := range fonts {
|
|
|
|
fmt.Printf(" * `%s`: obj=%v entries=%v\n", font.Name, font.ObjectFile, font.Entries())
|
|
|
|
}
|
|
|
|
}
|