Пример #1
0
def write_voxelskirt(archive, sized_str_entry, out_dir):
    name = sized_str_entry.name
    print(f"\nWriting {name}")

    ovl_header = pack_header(archive, b"VOXE")
    out_path = out_dir(name)
    buffers = sized_str_entry.data_entry.buffer_datas
    # write voxelskirt
    with open(out_path, 'wb') as outfile:
        # write the sized str and buffers
        # print(sized_str_entry.pointers[0].data)
        outfile.write(ovl_header)
        outfile.write(sized_str_entry.pointers[0].data)
        for buff in buffers:
            outfile.write(buff)
    return out_path,
Пример #2
0
def write_enumnamer(ovl, sized_str_entry, out_dir, show_temp_files,
                    progress_callback):
    name = sized_str_entry.name
    print(f"\nWriting {name}")

    ovl_header = pack_header(ovl, b"ENUM")
    out_path = out_dir(name)
    # buffers = sized_str_entry.data_entry.buffer_datas
    # write voxelskirt
    with open(out_path, 'wb') as outfile:
        # write the sized str and buffers
        # print(sized_str_entry.pointers[0].data)
        outfile.write(ovl_header)
        outfile.write(sized_str_entry.pointers[0].data)
        # print(sized_str_entry.pointers[0].address)
        for f in sized_str_entry.vars:
            # print(f)
            # print(f.pointers[1].data)
            outfile.write(f.pointers[1].data)
    return out_path,
Пример #3
0
def write_specdef(ovl, sized_str_entry, out_dir, show_temp_files,
                  progress_callback):
    name = sized_str_entry.name
    print(f"\nWriting {name}")

    ovl_header = pack_header(ovl, b"SPEC")
    out_path = out_dir(name)

    # save .bin data
    with open(out_path + ".bin", 'wb') as outfile:
        print("Exporting binary specdef file")
        outfile.write(ovl_header)
        outfile.write(sized_str_entry.pointers[0].data)
        for f in sized_str_entry.fragments:
            outfile.write(f.pointers[1].data)
        outfile.close()

    # save .text file
    with open(out_path, 'w') as outfile:
        print("Exporting text specdef file")
        attribcount, flags, namecount, childspeccount, managercount, scriptcount = struct.unpack(
            "<2H4B", sized_str_entry.pointers[0].data)
        outfile.write(f"Name : {name}\nFlags: {flags:x}\n")

        #debug print all fragments
        #for f in sized_str_entry.fragments:
        #	print(f.pointers[1].data)

        # skip frags here based on counts
        offset = 3 + (namecount > 0) + (childspeccount > 0) + (
            managercount > 0) + (scriptcount > 0)

        if attribcount > 0:
            outfile.write(f"Attributes:\n")
            lend = len(sized_str_entry.fragments[0].pointers[1].data)

            #this frag has padding
            dtypes = struct.unpack(
                f"<{attribcount}I",
                sized_str_entry.fragments[0].pointers[1].data[:4 *
                                                              attribcount])

            for i in range(0, attribcount):
                iname = sized_str_entry.fragments[
                    offset + i].pointers[1].data.decode().rstrip('\x00')
                dtype = dtypes[i]
                #todo: the tflags structure depends on the dtype value
                #tflags = struct.unpack(f"<{4}I", sized_str_entry.fragments[offset + attribcount + i].pointers[1].data)
                tflags = sized_str_entry.fragments[offset + attribcount +
                                                   i].pointers[1].data
                outstr = f" - Type: {dtype:02} Name: {iname}  Flags: {tflags}"
                #print(outstr)
                outfile.write(outstr + "\n")

            # skip the attrib names and data
            offset += 2 * attribcount

        if namecount > 0:
            outfile.write(f"Names:\n")
            for i in range(0, namecount):
                iname = sized_str_entry.fragments[
                    offset + i].pointers[1].data.decode().rstrip('\x00')
                outstr = f" - Name: {iname}"
                #print(outstr)
                outfile.write(outstr + "\n")

            # skip the names
            offset += namecount

        if childspeccount > 0:
            outfile.write(f"Child Specdefs:\n")
            for i in range(0, childspeccount):
                iname = sized_str_entry.fragments[
                    offset + i].pointers[1].data.decode().rstrip('\x00')
                outstr = f" - Specdef: {iname}"
                #print(outstr)
                outfile.write(outstr + "\n")

            # skip the names
            offset += childspeccount

        if managercount > 0:
            outfile.write(f"Managers:\n")
            for i in range(0, managercount):
                iname = sized_str_entry.fragments[
                    offset + i].pointers[1].data.decode().rstrip('\x00')
                outstr = f" - Manager: {iname}"
                #print(outstr)
                outfile.write(outstr + "\n")

                # skip the names
            offset += managercount

        if scriptcount > 0:
            outfile.write(f"Scripts:\n")
            for i in range(0, scriptcount):
                iname = sized_str_entry.fragments[
                    offset + i].pointers[1].data.decode().rstrip('\x00')
                outstr = f" - Script: {iname}"
                #print(outstr)
                outfile.write(outstr + "\n")

        outfile.close()

    return out_path + ".bin", out_path,
Пример #4
0
def write_ms2(ovl, ms2_sized_str_entry, out_dir):
	name = ms2_sized_str_entry.name
	if not ms2_sized_str_entry.data_entry:
		print("No data entry for ", name)
		return
	buffers = ms2_sized_str_entry.data_entry.buffer_datas
	if len(buffers) == 3:
		bone_names, bone_matrices, verts = buffers
	elif len(buffers) == 2:
		bone_names, verts = buffers
		bone_matrices = b""
	else:
		raise BufferError(f"Wrong amount of buffers for {name}\nWanted 2 or 3 buffers, got {len(buffers)}")

	# sizedstr data has bone count
	ms2_general_info_data = ms2_sized_str_entry.pointers[0].data[:24]
	# ms2_general_info = ms2_sized_str_entry.pointers[0].load_as(Ms2SizedStrData, version_info=versions)
	# print("Ms2SizedStrData", ms2_sized_str_entry.pointers[0].address, ms2_general_info)

	ovl_header = pack_header(ovl, b"MS2 ")
	ms2_header = struct.pack("<2I", len(bone_names), len(bone_matrices))

	print("\nWriting", name)
	print("\nbuffers", len(buffers))
	# for i, buffer in enumerate(buffers):
	# 	p = out_dir(name+str(i)+".ms2")
	# 	with open(p, 'wb') as outfile:
	# 		outfile.write(buffer)

	# Planet coaster
	if is_pc(ovl.ovl) or is_ed(ovl.ovl):
		# only ss entry holds any useful stuff
		ms2_buffer_info_data = b""
		next_model_info_data = b""
	# Planet Zoo, JWE
	else:
		if len(ms2_sized_str_entry.fragments) != 3:
			print("must have 3 fragments")
			return
		f_0, f_1, f_2 = ms2_sized_str_entry.fragments

		# f0 has information on vert & tri buffer sizes
		ms2_buffer_info_data = f_0.pointers[1].data
		# this fragment informs us about the model count of the next mdl2 that is read
		# so we can use it to collect the variable mdl2 fragments describing a model each
		next_model_info_data = f_1.pointers[1].data
		# next_model_info = f_1.pointers[1].load_as(CoreModelInfo, version_info=versions)
		# print("next_model_info", f_1.pointers[1].address, next_model_info)

	# write the ms2 file
	out_path = out_dir(name)
	out_paths = [out_path, ]
	with open(out_path, 'wb') as outfile:
		outfile.write(ovl_header)
		outfile.write(ms2_header)
		outfile.write(ms2_general_info_data)
		outfile.write(ms2_buffer_info_data)
		outfile.write(bone_names)
		outfile.write(bone_matrices)
		outfile.write(verts)

	# zeros = []
	# ones = []
	bone_info_index = 0
	# export each mdl2
	for mdl2_index, mdl2_entry in enumerate(ms2_sized_str_entry.children):
		mdl2_path = out_dir(mdl2_entry.name)
		out_paths.append(mdl2_path)
		with open(mdl2_path, 'wb') as outfile:
			print("Writing", mdl2_entry.name, mdl2_index)

			mdl2_header = struct.pack("<2I", mdl2_index, bone_info_index)
			outfile.write(ovl_header)
			outfile.write(mdl2_header)
			# pack ms2 name as a sized string
			write_sized_str(outfile, ms2_sized_str_entry.name)

			if not (is_pc(ovl.ovl) or is_ed(ovl.ovl)):
				# the fixed fragments
				green_mats_0, blue_lod, orange_mats_1, yellow_lod0, pink = mdl2_entry.fragments
				print("model_count", mdl2_entry.model_count)
				# write the model info for this model, buffered from the previous model or ms2 (pink fragments)
				outfile.write(next_model_info_data)
				# print("PINK",pink.pointers[0].address,pink.pointers[0].data_size,pink.pointers[1].address, pink.pointers[1].data_size)
				if pink.pointers[0].data_size == 40:
					# 40 bytes (0,1 or 0,0,0,0)
					has_bone_info = pink.pointers[0].data
				elif (is_jwe(ovl.ovl) and pink.pointers[0].data_size == 144) \
				or   (is_pz(ovl.ovl) and pink.pointers[0].data_size == 160):
					# read model info for next model, but just the core part without the 40 bytes of 'padding' (0,1,0,0,0)
					next_model_info_data = pink.pointers[0].data[40:]
					has_bone_info = pink.pointers[0].data[:40]
					# core_model_data = pink.pointers[0].load_as(Mdl2ModelInfo, version_info=versions)
					# print(core_model_data)
				else:
					raise ValueError(f"Unexpected size {len(pink.pointers[0].data)} for pink fragment for {mdl2_entry.name}")

				core_model_data = struct.unpack("<5Q", has_bone_info)
				# print(core_model_data)
				var = core_model_data[1]
				bone_info_index += var
				# if var == 1:
				# 	ones.append((mdl2_index, mdl2_entry.name))
				# elif var == 0:
				# 	zeros.append((mdl2_index, mdl2_entry.name))

				# avoid writing bad fragments that should be empty
				if mdl2_entry.model_count:
					# need not write lod0
					for f in (green_mats_0, blue_lod, orange_mats_1):
						# print(f.pointers[0].address,f.pointers[0].data_size,f.pointers[1].address, f.pointers[1].data_size)
						other_data = f.pointers[1].data
						outfile.write(other_data)
						# data 0 must be empty
						assert(f.pointers[0].data == b'\x00\x00\x00\x00\x00\x00\x00\x00')

				# print("modeldata frags")
				for f in mdl2_entry.model_data_frags:
					# each address_0 points to ms2's f_0 address_1 (size of vert & tri buffer)
					# print(f.pointers[0].address,f.pointers[0].data_size,f.pointers[1].address, f.pointers[1].data_size)
					# model_data = f.pointers[0].load_as(ModelData, version_info=versions)
					# print(model_data)

					model_data = f.pointers[0].data
					outfile.write(model_data)
	# print("ones", len(ones), ones)
	# print("zeros", len(zeros), zeros)
	return out_paths
Пример #5
0
def write_ms2(ovl, ms2_sized_str_entry, out_dir, show_temp_files,
              progress_callback):
    name = ms2_sized_str_entry.name
    assert ms2_sized_str_entry.data_entry
    buffers = ms2_sized_str_entry.data_entry.stream_datas
    name_buffer = buffers[0]
    bone_infos = buffers[1]
    verts = b"".join(buffers[2:])
    for i, vbuff in enumerate(buffers[2:]):
        print(f"Vertex buffer {i}, size {len(vbuff)} bytes")
    print("\nWriting", name)
    print("buffers", len(buffers))
    print(
        f"name_buffer: {len(name_buffer)}, bone_infos: {len(bone_infos)}, verts: {len(verts)}"
    )
    # sizedstr data has bone count
    ms2_general_info_data = ms2_sized_str_entry.pointers[0].data[:24]
    # print("ms2 ss rest", ms2_sized_str_entry.pointers[0].data[24:])
    # ms2_general_info = ms2_sized_str_entry.pointers[0].load_as(Ms2SizedStrData, version_info=versions)
    # print("Ms2SizedStrData", ms2_sized_str_entry.pointers[0].address, ms2_general_info)

    ovl_header = pack_header(ovl, b"MS2 ")
    ms2_header = struct.pack("<2I", len(name_buffer), len(bone_infos))

    # for i, buffer in enumerate(buffers):
    # 	p = out_dir(name+str(i)+".ms2")
    # 	with open(p, 'wb') as outfile:
    # 		outfile.write(buffer)

    # Planet coaster
    if is_pc(ovl) or is_ztuac(ovl):
        # only ss entry holds any useful stuff
        ms2_buffer_info_data = b""
        next_model_info_data = b""
    # Planet Zoo, JWE
    else:
        if len(ms2_sized_str_entry.fragments) != 3:
            print("must have 3 fragments")
            return
        f_0, f_1, f_2 = ms2_sized_str_entry.fragments

        # f0 has information on vert & tri buffer sizes
        ms2_buffer_info_data = f_0.pointers[1].data
        # this fragment informs us about the model count of the next mdl2 that is read
        # so we can use it to collect the variable mdl2 fragments describing a model each
        next_model_info_data = f_1.pointers[1].data
    # next_model_info = f_1.pointers[1].load_as(CoreModelInfo, version_info=versions)
    # print("next_model_info", f_1.pointers[1].address, next_model_info)

    # write the ms2 file
    out_path = out_dir(name)
    out_paths = [
        out_path,
    ]
    with open(out_path, 'wb') as outfile:
        outfile.write(ovl_header)
        outfile.write(ms2_header)
        outfile.write(ms2_general_info_data)
        outfile.write(ms2_buffer_info_data)
        outfile.write(name_buffer)
        outfile.write(bone_infos)
        outfile.write(verts)

    # zeros = []
    # ones = []
    bone_info_index = 0
    # export each mdl2
    for mdl2_index, mdl2_entry in enumerate(ms2_sized_str_entry.children):
        mdl2_path = out_dir(mdl2_entry.name)
        out_paths.append(mdl2_path)
        with open(mdl2_path, 'wb') as outfile:
            print("Writing", mdl2_entry.name, mdl2_index)

            mdl2_header = struct.pack("<2I", mdl2_index, bone_info_index)
            outfile.write(ovl_header)
            outfile.write(mdl2_header)
            # pack ms2 name as a sized string
            write_sized_str(outfile, ms2_sized_str_entry.name)

            if not (is_pc(ovl) or is_ztuac(ovl)):
                # the fixed fragments
                materials, lods, objects, model_data_ptr, model_info = mdl2_entry.fragments
                print("num_models", mdl2_entry.num_models)
                # write the model info for this model, buffered from the previous model or ms2 (model_info fragments)
                outfile.write(next_model_info_data)
                # print("model_info",model_info.pointers[0].address,model_info.pointers[0].data_size,model_info.pointers[1].address, model_info.pointers[1].data_size)
                if model_info.pointers[0].data_size == 40:
                    # 40 bytes (0,1 or 0,0,0,0)
                    has_bone_info = model_info.pointers[0].data
                elif (is_jwe(ovl) and model_info.pointers[0].data_size == 144) \
                 or (is_pz(ovl) and model_info.pointers[0].data_size == 160):
                    # read model info for next model, but just the core part without the 40 bytes of 'padding' (0,1,0,0,0)
                    next_model_info_data = model_info.pointers[0].data[40:]
                    has_bone_info = model_info.pointers[0].data[:40]
                # core_model_data = model_info.pointers[0].load_as(Mdl2ModelInfo, version_info=versions)
                # print(core_model_data)
                else:
                    raise ValueError(
                        f"Unexpected size {len(model_info.pointers[0].data)} for model_info fragment for {mdl2_entry.name}"
                    )

                core_model_data = struct.unpack("<5Q", has_bone_info)
                # print(core_model_data)
                var = core_model_data[1]
                bone_info_index += var
                # if var == 1:
                # 	ones.append((mdl2_index, mdl2_entry.name))
                # elif var == 0:
                # 	zeros.append((mdl2_index, mdl2_entry.name))

                # avoid writing bad fragments that should be empty
                if mdl2_entry.num_models:
                    # need not write model_data_ptr
                    for f in (materials, lods, objects):
                        # print(f.pointers[0].address,f.pointers[0].data_size,f.pointers[1].address, f.pointers[1].data_size)
                        outfile.write(f.pointers[1].data)
                        # data 0 must be empty
                        assert f.pointers[
                            0].data == b'\x00\x00\x00\x00\x00\x00\x00\x00'

                # print("modeldata frags")
                for f in mdl2_entry.model_data_frags:
                    # each address_0 points to ms2's f_0 address_1 (size of vert & tri buffer)
                    # print(f.pointers[0].address,f.pointers[0].data_size,f.pointers[1].address, f.pointers[1].data_size)
                    # model_data = f.pointers[0].load_as(ModelData, version_info=versions)
                    # print(model_data)
                    outfile.write(f.pointers[0].data)
    # print("ones", len(ones), ones)
    # print("zeros", len(zeros), zeros)
    return out_paths
Пример #6
0
def write_fgm(ovl, sized_str_entry, out_dir, show_temp_files,
              progress_callback):
    name = sized_str_entry.name
    print("\nWriting", name)
    try:
        buffer_data = sized_str_entry.data_entry.buffer_datas[0]
        print("buffer size", len(buffer_data))
    except:
        print("Found no buffer data for", name)
        buffer_data = b""
    # basic fgms
    if len(sized_str_entry.fragments) == 4:
        tex_info, attr_info, zeros, data_lib = sized_str_entry.fragments
        len_tex_info = tex_info.pointers[1].data_size
        len_zeros = zeros.pointers[1].data_size
    # no zeros, otherwise same as basic
    elif len(sized_str_entry.fragments) == 3:
        tex_info, attr_info, data_lib = sized_str_entry.fragments
        len_tex_info = tex_info.pointers[1].data_size
        len_zeros = 0
    # fgms for variants
    elif len(sized_str_entry.fragments) == 2:
        attr_info, data_lib = sized_str_entry.fragments
        len_tex_info = 0
        len_zeros = 0
    else:
        raise AttributeError("Fgm length is wrong")

    # grab the texture names that are linked to this fgm
    fgm_file_entry = get_file_entry(ovl, sized_str_entry)

    # write fgm
    fgm_header = struct.pack(
        "<6I",
        len(sized_str_entry.fragments),
        len(fgm_file_entry.dependencies),
        len_tex_info,
        attr_info.pointers[1].data_size,
        len_zeros,
        data_lib.pointers[1].data_size,
    )

    # print(file_entry.textures)
    out_path = out_dir(name)
    # for i, f in enumerate(sized_str_entry.fragments):
    # 	with open(out_path+str(i), 'wb') as outfile:
    # 		outfile.write( f.pointers[1].data )
    with open(out_path, 'wb') as outfile:
        # write custom FGM header
        outfile.write(pack_header(ovl, b"FGM "))
        outfile.write(fgm_header)
        for tex in fgm_file_entry.dependencies:
            outfile.write(tex.basename.encode())
            outfile.write(b"\x00")
        outfile.write(sized_str_entry.pointers[0].data)
        # write each of the fragments
        for frag in sized_str_entry.fragments:
            outfile.write(frag.pointers[1].data)
        # write the buffer
        outfile.write(buffer_data)
    return out_path,