Example #1
0
// tilDump creates a dump directory and dumps the TIL file's squares using the
// pillars constructed based on the MIN format, once for each image config
// (pal).
func tilDump(tilName string) (err error) {
	squares, err := til.Parse(tilName)
	if err != nil {
		return err
	}
	nameWithoutExt := tilName[:len(tilName)-len(path.Ext(tilName))]
	minName := nameWithoutExt + ".min"
	pillars, err := min.Parse(minName)
	if err != nil {
		return err
	}
	imgName := nameWithoutExt + ".cel"
	relPalPaths := imgconf.GetRelPalPaths(imgName)
	for _, relPalPath := range relPalPaths {
		conf, err := cel.GetConf(imgName, relPalPath)
		if err != nil {
			return err
		}
		var palDir string
		if len(relPalPaths) > 1 {
			dbg.Println("using pal:", relPalPath)
			palDir = path.Base(relPalPath) + "/"
		}
		bar, err = barcli.New(len(squares))
		if err != nil {
			return err
		}
		levelFrames, err := cel.DecodeAll(imgName, conf)
		if err != nil {
			return err
		}
		dumpDir := path.Clean(dumpPrefix+"_squares_/"+nameWithoutExt) + "/" + palDir
		// prevent directory traversal
		if !strings.HasPrefix(dumpDir, dumpPrefix) {
			return fmt.Errorf("path (%s) contains no dump prefix (%s).", dumpDir, dumpPrefix)
		}
		err = os.MkdirAll(dumpDir, 0755)
		if err != nil {
			return err
		}
		err = dumpSquares(squares, pillars, levelFrames, dumpDir)
		if err != nil {
			return err
		}
	}
	return nil
}
Example #2
0
// Parse parses a given DUN file and stores each pillarNum at a coordinate in
// the dungeon, based on the DUN format described above.
//
// Below is a description of how the squares are positioned on the dungeon map:
//    1) Start at the coordinates colStart, rowStart.
//    2) Place a square.
//       - Each square is two cols in width and two rows in height.
//    3) Increment col with two.
//    4) goto 2) dunQWidth number of times.
//    5) Increment row with two.
//    6) goto 2) dunQHeight number of times.
//
// ref: GetPillarRect (illustration of map coordinate system)
//
// Any additional cell data is stored afterwards using row major.
func (dungeon *Dungeon) Parse(dunName string) (err error) {
	dunPath, err := mpq.GetPath(dunName)
	if err != nil {
		return err
	}
	fr, err := os.Open(dunPath)
	if err != nil {
		return err
	}
	defer fr.Close()
	var tmp [2]uint16
	err = binary.Read(fr, binary.LittleEndian, &tmp)
	if err != nil {
		return err
	}
	dunQWidth := int(tmp[0])
	dunQHeight := int(tmp[1])
	colStart, err := dunconf.GetColStart(dunName)
	if err != nil {
		return err
	}
	rowStart, err := dunconf.GetRowStart(dunName)
	if err != nil {
		return err
	}
	nameWithoutExt, err := GetLevelName(dunName)
	if err != nil {
		return err
	}

	// squareNumsPlus1.
	squares, err := til.Parse(nameWithoutExt + ".til")
	if err != nil {
		return err
	}
	row := rowStart
	for i := 0; i < dunQHeight; i++ {
		col := colStart
		for j := 0; j < dunQWidth; j++ {
			var x uint16
			err = binary.Read(fr, binary.LittleEndian, &x)
			if err != nil {
				return err
			}
			squareNumPlus1 := int(x)
			if squareNumPlus1 != 0 {
				square := squares[squareNumPlus1-1]
				dungeon[col][row]["pillarNum"] = square.PillarNumTop
				dungeon[col+1][row]["pillarNum"] = square.PillarNumRight
				dungeon[col][row+1]["pillarNum"] = square.PillarNumLeft
				dungeon[col+1][row+1]["pillarNum"] = square.PillarNumBottom
			}
			col += 2
		}
		row += 2
	}

	dunWidth := 2 * dunQWidth
	dunHeight := 2 * dunQHeight

	// TODO: Figure out what these values are used for. Items?
	row = rowStart
	for i := 0; i < dunHeight; i++ {
		col := colStart
		for j := 0; j < dunWidth; j++ {
			var x uint16
			err = binary.Read(fr, binary.LittleEndian, &x)
			if err != nil {
				// Some DUN files only contain the pillar IDs.
				if err == io.EOF && i == 0 && j == 0 {
					return nil
				}
				return err
			}
			dungeon[col][row]["unknown"] = int(x)
			col++
		}
		row++
	}

	// dunMonsterIDs.
	row = rowStart
	for i := 0; i < dunHeight; i++ {
		col := colStart
		for j := 0; j < dunWidth; j++ {
			var x uint16
			err = binary.Read(fr, binary.LittleEndian, &x)
			if err != nil {
				if err == io.EOF && i == 0 && j == 0 {
					return nil
				}
				return err
			}
			// TODO: Lookup monster idx from dunMonsterID.
			// ref: 4B6C98
			dungeon[col][row]["dunMonsterID"] = int(x)
			col++
		}
		row++
	}

	// dunObjectIDs.
	row = rowStart
	for i := 0; i < dunHeight; i++ {
		col := colStart
		for j := 0; j < dunWidth; j++ {
			var x uint16
			err = binary.Read(fr, binary.LittleEndian, &x)
			if err != nil {
				if err == io.EOF && i == 0 && j == 0 {
					return nil
				}
				return err
			}
			// TODO: Lookup object idx from dunObjectID.
			// ref: 4AAD28
			dungeon[col][row]["dunObjectID"] = int(x)
			col++
		}
		row++
	}

	// transparencies.
	row = rowStart
	for i := 0; i < dunHeight; i++ {
		col := colStart
		for j := 0; j < dunWidth; j++ {
			var x uint16
			err = binary.Read(fr, binary.LittleEndian, &x)
			if err != nil {
				if err == io.EOF && i == 0 && j == 0 {
					return nil
				}
				return err
			}
			dungeon[col][row]["transparency"] = int(x)
			col++
		}
		row++
	}

	return nil
}