Example #1
0
def extract_directx9_shader(file, date, shader_size, headers, section_offset,
                            section_size, shader):
    bin = file.read(shader_size)
    align(
        file, 4
    )  # Seems ok without this - looks like the shader binary is always a multiple of 4 bytes
    assert (
        bin[8:12] in (b'CTAB', b'DBUG')
    )  # XXX: May fail for shaders without embedded constant tables. Debug section seen in Salt Hidden_GlobalFog

    hash = zlib.crc32(bin)

    extract_unity_shaders._add_shader_hash_asm_crc(shader.sub_program,
                                                   zlib.crc32(bin))
    path_components = extract_unity_shaders.export_filename_combined_short(
        shader)
    dest = extract_unity_shaders.path_components_to_dest(path_components)

    dump_raw_bind_info(file, dest, section_offset, section_size)

    # Have not fully deciphered the data around this point, and depending
    # on the values the size can vary. Making a best guess based on
    # obsevations that DX9 ends in 0, 0. Values seem to be in pairs. Suspect
    # they are related to the generic "Bind" statements in previous Unity
    # versions, but can't make heads or tails of them.
    undeciphered3 = list(struct.unpack('<I', file.read(4)))
    undeciphered3.extend(consume_until_double_zero(file))
    add_header(headers, ('undeciphered3:' +
                         ' {}' * len(undeciphered3)).format(*undeciphered3))

    decode_dx9_bind_info(file, date, headers)
    assert (file.tell() - section_size - section_offset == 0)

    delay_writing_dx9_shader(hash, dest, bin, headers, shader.sub_program)
Example #2
0
def extract_directx9_shader(file, date, shader_size, headers, section_offset, section_size, shader):
    bin = file.read(shader_size)
    align(file, 4) # Seems ok without this - looks like the shader binary is always a multiple of 4 bytes
    assert(bin[8:12] in (b'CTAB', b'DBUG')) # XXX: May fail for shaders without embedded constant tables. Debug section seen in Salt Hidden_GlobalFog

    hash = zlib.crc32(bin)

    extract_unity_shaders._add_shader_hash_asm_crc(shader.sub_program, zlib.crc32(bin))
    path_components = extract_unity_shaders.export_filename_combined_short(shader)
    dest = extract_unity_shaders.path_components_to_dest(path_components)

    dump_raw_bind_info(file, dest, section_offset, section_size)

    # Have not fully deciphered the data around this point, and depending
    # on the values the size can vary. Making a best guess based on
    # obsevations that DX9 ends in 0, 0. Values seem to be in pairs. Suspect
    # they are related to the generic "Bind" statements in previous Unity
    # versions, but can't make heads or tails of them.
    undeciphered3 = list(struct.unpack('<I', file.read(4)))
    undeciphered3.extend(consume_until_double_zero(file))
    add_header(headers, ('undeciphered3:' + ' {}'*len(undeciphered3)).format(*undeciphered3))

    decode_dx9_bind_info(file, date, headers)
    assert(file.tell() - section_size - section_offset == 0)

    delay_writing_dx9_shader(hash, dest, bin, headers, shader.sub_program)
Example #3
0
def extract_opengl_shader(file, shader_size, headers, shader):
    shader.sub_program.shader_asm = file.read(shader_size).decode('utf-8')
    try:
        hash = {}
        for program_name in ('fp', 'vp'):
            shader.program.name = program_name;
            hash[program_name] = extract_unity_shaders.hash_gl_crc(shader.sub_program)
            add_header(headers, ('{} hash: {:x}'.format(program_name, hash[program_name])))
        for program_name in ('fp', 'vp'):

            # FIXME: Write out any with duplicate hashes in case we ever have
            # an autofix that needs to e.g. find all PS corresponding with a
            # given VS hash, where that hash appears in multiple distinct
            # shaders (e.g. Internal-PrePassLighting and
            # Internal-DeferredReflection share the same VS, but have differing PS)

            if hash[program_name] in processed:
                continue
            processed.add(hash[program_name])

            shader.program.name = program_name;
            extract_unity_shaders._add_shader_hash_gl_crc(shader.sub_program, hash[program_name])
            path_components = extract_unity_shaders.export_filename_combined_short(shader)
            dest = extract_unity_shaders.path_components_to_dest(path_components)

            print('Extracting %s.glsl...' % dest)
            with open('%s.glsl' % dest, 'w') as out:
                out.write(extract_unity_shaders.fixup_glsl_like_unity(shader.sub_program))
            with open('%s.info' % dest, 'w') as f:
                f.write('\n'.join(headers))
    except extract_unity_shaders.BogusShader:
        return
Example #4
0
def extract_unknown_shader(file, shader_size, headers, shader):
    raw = file.read(shader_size)
    hash = zlib.crc32(raw)

    extract_unity_shaders._add_shader_hash_unknown(shader.sub_program, hash)
    path_components = extract_unity_shaders.export_filename_combined_short(shader)
    dest = extract_unity_shaders.path_components_to_dest(path_components)

    print('Extracting %s.raw...' % dest)
    with open('%s.raw' % dest, 'wb') as out:
        out.write(raw)
    with open('%s.headers' % dest, 'w') as f:
        f.write('\n'.join(headers))
Example #5
0
def extract_directx11_shader(file, shader_size, headers, section_offset,
                             section_size, shader, date):
    # Is this the correct way to detect this? Could be a file version, but it
    # looks suspiciously like a date (but 2015? Last year for an update
    # released this year?), so I'm not certain this is correct. If not this,
    # maybe just check the Unity version for 5.4?
    if date == 201509030:  # Unity 5.3
        u8len = 5
    elif date >= 201510240:  # Unity 5.4+
        u8len = 6
    else:
        assert (False)
    u8 = struct.unpack('<%ib' % u8len, file.read(u8len))
    add_header(headers, 'undeciphered2: {}'.format(' '.join(map(
        str, u8))))  # Think this is related to the bindings

    bin = file.read(shader_size - u8len)
    align(file, 4)
    assert (bin[:4] == b'DXBC')

    hash = extract_unity_shaders.fnv_3Dmigoto_shader(bin)

    extract_unity_shaders._add_shader_hash_fnv(shader.sub_program, hash)
    path_components = extract_unity_shaders.export_filename_combined_short(
        shader)
    dest = extract_unity_shaders.path_components_to_dest(path_components)

    # print('Extracting %s.bin...' % dest)
    # with open('%s.bin' % dest, 'wb') as out:
    #     out.write(bin)

    dump_raw_bind_info(file, dest, section_offset, section_size)

    # Have not fully deciphered the data around this point, and depending
    # on the values the size can vary. Making a best guess based on
    # obsevations that DX11 ends in num_sections, 0, 0, 0. If first value != 0
    # it is followed by two 0s. Values seem to be in pairs. Suspect they are
    # related to the generic "Bind" statements in previous Unity versions, but
    # can't make heads or tails of them.
    undeciphered3 = list(struct.unpack('<2I', file.read(8)))
    if undeciphered3[1]:
        undeciphered3.extend(struct.unpack('<2I', file.read(8)))

    num_sections = consume_until_dx11_num_sections(file, undeciphered3)
    add_header(headers, ('undeciphered3:' +
                         ' {}' * len(undeciphered3)).format(*undeciphered3))

    decode_dx11_bind_info(file, date, num_sections, headers)
    assert (file.tell() - section_size - section_offset == 0)

    delay_writing_dx11_shader(hash, dest, bin, headers, shader.sub_program)
Example #6
0
def extract_unknown_shader(file, shader_size, headers, shader):
    raw = file.read(shader_size)
    hash = zlib.crc32(raw)

    extract_unity_shaders._add_shader_hash_unknown(shader.sub_program, hash)
    path_components = extract_unity_shaders.export_filename_combined_short(
        shader)
    dest = extract_unity_shaders.path_components_to_dest(path_components)

    print('Extracting %s.raw...' % dest)
    with open('%s.raw' % dest, 'wb') as out:
        out.write(raw)
    with open('%s.headers' % dest, 'w') as f:
        f.write('\n'.join(headers))
Example #7
0
def extract_directx11_shader(file, shader_size, headers, section_offset, section_size, shader, date):
    # Is this the correct way to detect this? Could be a file version, but it
    # looks suspiciously like a date (but 2015? Last year for an update
    # released this year?), so I'm not certain this is correct. If not this,
    # maybe just check the Unity version for 5.4?
    if date == 201509030: # Unity 5.3
        u8len = 5
    elif date >= 201510240: # Unity 5.4+
        u8len = 6
    else:
        assert(False)
    u8 = struct.unpack('<%ib' % u8len, file.read(u8len))
    add_header(headers, 'undeciphered2: {}'.format(' '.join(map(str, u8)))) # Think this is related to the bindings

    bin = file.read(shader_size - u8len)
    align(file, 4)
    assert(bin[:4] == b'DXBC')

    hash = extract_unity_shaders.fnv_3Dmigoto_shader(bin)

    extract_unity_shaders._add_shader_hash_fnv(shader.sub_program, hash)
    path_components = extract_unity_shaders.export_filename_combined_short(shader)
    dest = extract_unity_shaders.path_components_to_dest(path_components)

    # print('Extracting %s.bin...' % dest)
    # with open('%s.bin' % dest, 'wb') as out:
    #     out.write(bin)

    dump_raw_bind_info(file, dest, section_offset, section_size)

    # Have not fully deciphered the data around this point, and depending
    # on the values the size can vary. Making a best guess based on
    # obsevations that DX11 ends in num_sections, 0, 0, 0. If first value != 0
    # it is followed by two 0s. Values seem to be in pairs. Suspect they are
    # related to the generic "Bind" statements in previous Unity versions, but
    # can't make heads or tails of them.
    undeciphered3 = list(struct.unpack('<2I', file.read(8)))
    if undeciphered3[1]:
        undeciphered3.extend(struct.unpack('<2I', file.read(8)))

    num_sections = consume_until_dx11_num_sections(file, undeciphered3)
    add_header(headers, ('undeciphered3:' + ' {}'*len(undeciphered3)).format(*undeciphered3))

    decode_dx11_bind_info(file, date, num_sections, headers)
    assert(file.tell() - section_size - section_offset == 0)

    delay_writing_dx11_shader(hash, dest, bin, headers, shader.sub_program)
Example #8
0
def extract_opengl_shader(file, shader_size, headers, shader):
    shader.sub_program.shader_asm = file.read(shader_size).decode('utf-8')
    try:
        hash = {}
        for program_name in ('fp', 'vp'):
            shader.program.name = program_name
            hash[program_name] = extract_unity_shaders.hash_gl_crc(
                shader.sub_program)
            add_header(
                headers,
                ('{} hash: {:x}'.format(program_name, hash[program_name])))
        for program_name in ('fp', 'vp'):

            # FIXME: Write out any with duplicate hashes in case we ever have
            # an autofix that needs to e.g. find all PS corresponding with a
            # given VS hash, where that hash appears in multiple distinct
            # shaders (e.g. Internal-PrePassLighting and
            # Internal-DeferredReflection share the same VS, but have differing PS)

            if hash[program_name] in processed:
                continue
            processed.add(hash[program_name])

            shader.program.name = program_name
            extract_unity_shaders._add_shader_hash_gl_crc(
                shader.sub_program, hash[program_name])
            path_components = extract_unity_shaders.export_filename_combined_short(
                shader)
            dest = extract_unity_shaders.path_components_to_dest(
                path_components)

            print('Extracting %s.glsl...' % dest)
            with open('%s.glsl' % dest, 'w') as out:
                out.write(
                    extract_unity_shaders.fixup_glsl_like_unity(
                        shader.sub_program))
            with open('%s.info' % dest, 'w') as f:
                f.write('\n'.join(headers))
    except extract_unity_shaders.BogusShader:
        return