From: Henri Verbeet hverbeet@codeweavers.com
--- programs/vkd3d-dxbc/main.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-)
diff --git a/programs/vkd3d-dxbc/main.c b/programs/vkd3d-dxbc/main.c index efe0a8fd1..6d065f3bb 100644 --- a/programs/vkd3d-dxbc/main.c +++ b/programs/vkd3d-dxbc/main.c @@ -514,6 +514,7 @@ int main(int argc, char **argv) FILE *input, *output; char *messages; uint32_t flags; + bool success; int fail = 1; size_t i; int ret; @@ -583,18 +584,15 @@ int main(int argc, char **argv) goto done; }
- if (!write_output(output, &serialized)) - { + if (!(success = write_output(output, &serialized))) fprintf(stderr, "Failed to write output blob.\n"); - vkd3d_shader_free_shader_code(&serialized); - goto done; - }
+ if (close_output) + fclose(output); vkd3d_shader_free_shader_code(&serialized); + if (!success) + goto done; break; - - default: - vkd3d_unreachable(); } }
@@ -605,7 +603,5 @@ done: free(options.actions); if (close_input) fclose(input); - if (close_output) - fclose(output); return fail; }
From: Henri Verbeet hverbeet@codeweavers.com
--- programs/vkd3d-dxbc/main.c | 66 +++++++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 26 deletions(-)
diff --git a/programs/vkd3d-dxbc/main.c b/programs/vkd3d-dxbc/main.c index 6d065f3bb..c23cfa81b 100644 --- a/programs/vkd3d-dxbc/main.c +++ b/programs/vkd3d-dxbc/main.c @@ -82,7 +82,10 @@ struct action } type; union { - const char *output_filename; + struct emit + { + const char *output_filename; + } emit; } u; };
@@ -206,7 +209,7 @@ static bool parse_command_line(int argc, char **argv, struct options *options) "If this is really what you intended, specify the output explicitly.\n"); return false; } - action->u.output_filename = options->output_filename; + action->u.emit.output_filename = options->output_filename; break;
case 'h': @@ -505,17 +508,47 @@ static void dump_dxbc(const struct vkd3d_shader_code *dxbc, const struct vkd3d_s } }
+static bool emit_dxbc(const struct vkd3d_shader_dxbc_desc *dxbc_desc, const struct emit *emit) +{ + struct vkd3d_shader_code dxbc; + bool close_output; + char *messages; + FILE *output; + bool success; + int ret; + + ret = vkd3d_shader_serialize_dxbc(dxbc_desc->section_count, dxbc_desc->sections, &dxbc, &messages); + if (messages) + fputs(messages, stderr); + vkd3d_shader_free_messages(messages); + if (ret < 0) + return false; + + if (!(output = open_output(emit->output_filename, &close_output))) + { + vkd3d_shader_free_shader_code(&dxbc); + return false; + } + + if (!(success = write_output(output, &dxbc))) + fprintf(stderr, "Failed to write output blob.\n"); + + if (close_output) + fclose(output); + vkd3d_shader_free_shader_code(&dxbc); + return success; +} + int main(int argc, char **argv) { - bool close_input = false, close_output = false; - struct vkd3d_shader_code dxbc, serialized; struct vkd3d_shader_dxbc_desc dxbc_desc; + struct vkd3d_shader_code dxbc; + bool close_input = false; struct options options; - FILE *input, *output; char *messages; uint32_t flags; - bool success; int fail = 1; + FILE *input; size_t i; int ret;
@@ -571,26 +604,7 @@ int main(int argc, char **argv) switch (action->type) { case ACTION_TYPE_EMIT: - ret = vkd3d_shader_serialize_dxbc(dxbc_desc.section_count, dxbc_desc.sections, &serialized, &messages); - if (messages) - fputs(messages, stderr); - vkd3d_shader_free_messages(messages); - if (ret < 0) - goto done; - - if (!(output = open_output(action->u.output_filename, &close_output))) - { - vkd3d_shader_free_shader_code(&serialized); - goto done; - } - - if (!(success = write_output(output, &serialized))) - fprintf(stderr, "Failed to write output blob.\n"); - - if (close_output) - fclose(output); - vkd3d_shader_free_shader_code(&serialized); - if (!success) + if (!emit_dxbc(&dxbc_desc, &action->u.emit)) goto done; break; }
From: Henri Verbeet hverbeet@codeweavers.com
--- programs/vkd3d-dxbc/main.c | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-)
diff --git a/programs/vkd3d-dxbc/main.c b/programs/vkd3d-dxbc/main.c index c23cfa81b..0fb99bc02 100644 --- a/programs/vkd3d-dxbc/main.c +++ b/programs/vkd3d-dxbc/main.c @@ -539,6 +539,25 @@ static bool emit_dxbc(const struct vkd3d_shader_dxbc_desc *dxbc_desc, const stru return success; }
+static bool apply_actions(struct vkd3d_shader_dxbc_desc *dxbc_desc, + size_t action_count, const struct action *actions) +{ + for (size_t i = 0; i < action_count; ++i) + { + const struct action *action = &actions[i]; + + switch (action->type) + { + case ACTION_TYPE_EMIT: + if (!emit_dxbc(dxbc_desc, &action->u.emit)) + return false; + break; + } + } + + return true; +} + int main(int argc, char **argv) { struct vkd3d_shader_dxbc_desc dxbc_desc; @@ -549,7 +568,6 @@ int main(int argc, char **argv) uint32_t flags; int fail = 1; FILE *input; - size_t i; int ret;
if (!parse_command_line(argc, argv, &options)) @@ -597,22 +615,10 @@ int main(int argc, char **argv) if (options.list || options.list_data) dump_dxbc(&dxbc, &dxbc_desc, &options);
- for (i = 0; i < options.action_count; ++i) - { - struct action *action = &options.actions[i]; - - switch (action->type) - { - case ACTION_TYPE_EMIT: - if (!emit_dxbc(&dxbc_desc, &action->u.emit)) - goto done; - break; - } - } + fail = !apply_actions(&dxbc_desc, options.action_count, options.actions);
vkd3d_shader_free_dxbc(&dxbc_desc); vkd3d_shader_free_shader_code(&dxbc); - fail = 0; done: free(options.actions); if (close_input)
From: Henri Verbeet hverbeet@codeweavers.com
--- programs/vkd3d-dxbc/main.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/programs/vkd3d-dxbc/main.c b/programs/vkd3d-dxbc/main.c index 0fb99bc02..aaccffadd 100644 --- a/programs/vkd3d-dxbc/main.c +++ b/programs/vkd3d-dxbc/main.c @@ -610,7 +610,10 @@ int main(int argc, char **argv) fputs(messages, stderr); vkd3d_shader_free_messages(messages); if (ret < 0) + { + vkd3d_shader_free_shader_code(&dxbc); goto done; + }
if (options.list || options.list_data) dump_dxbc(&dxbc, &dxbc_desc, &options);
From: Henri Verbeet hverbeet@codeweavers.com
--- programs/vkd3d-dxbc/main.c | 91 +++++++++++++++++++++++++++++++++----- 1 file changed, 81 insertions(+), 10 deletions(-)
diff --git a/programs/vkd3d-dxbc/main.c b/programs/vkd3d-dxbc/main.c index aaccffadd..ff4635847 100644 --- a/programs/vkd3d-dxbc/main.c +++ b/programs/vkd3d-dxbc/main.c @@ -65,6 +65,7 @@ enum { OPTION_COLOUR = CHAR_MAX + 1, OPTION_EMIT, + OPTION_EXTRACT, OPTION_HELP, OPTION_IGNORE_CHECKSUM, OPTION_LIST, @@ -79,6 +80,7 @@ struct action enum action_type { ACTION_TYPE_EMIT, + ACTION_TYPE_EXTRACT, } type; union { @@ -86,6 +88,11 @@ struct action { const char *output_filename; } emit; + struct extract + { + const char *section; + const char *output_filename; + } extract; } u; };
@@ -157,6 +164,7 @@ static bool parse_command_line(int argc, char **argv, struct options *options) { {"colour", no_argument, NULL, OPTION_COLOUR}, {"emit", no_argument, NULL, OPTION_EMIT}, + {"extract", required_argument, NULL, OPTION_EXTRACT}, {"help", no_argument, NULL, OPTION_HELP}, {"ignore-checksum", no_argument, NULL, OPTION_IGNORE_CHECKSUM}, {"list", no_argument, NULL, OPTION_LIST}, @@ -191,7 +199,7 @@ static bool parse_command_line(int argc, char **argv, struct options *options)
for (;;) { - if ((option = getopt_long(argc, argv, "ehtVo:", long_options, NULL)) == -1) + if ((option = getopt_long(argc, argv, "ex:hto:V", long_options, NULL)) == -1) break;
switch (option) @@ -212,6 +220,14 @@ static bool parse_command_line(int argc, char **argv, struct options *options) action->u.emit.output_filename = options->output_filename; break;
+ case 'x': + case OPTION_EXTRACT: + if (!(action = action_push(options, ACTION_TYPE_EXTRACT))) + return false; + action->u.extract.section = optarg; + action->u.extract.output_filename = options->output_filename; + break; + case 'h': case OPTION_HELP: options->print_help = true; @@ -234,8 +250,8 @@ static bool parse_command_line(int argc, char **argv, struct options *options) options->colours = no_colours; break;
- case OPTION_OUTPUT: case 'o': + case OPTION_OUTPUT: options->output_filename = optarg; break;
@@ -262,27 +278,30 @@ static void print_usage(const char *program_name) "Options:\n" " --colour Enable colour, even when not supported by the output.\n" " -e, --emit Emit the content of the DXBC blob.\n" + " -x, --extract=<section> Extract the data contained in <section>.\n" + " <section> must be of the form 'i:<index>'.\n" " -h, --help Display this information and exit.\n" + " --ignore-checksum Do not validate the checksum when parsing the DXBC\n" + " blob.\n" " -t, --list List the contents of the DXBC blob.\n" " --list-data List the data contained in the DXBC sections.\n" " --no-colour Disable colour, even when supported by the output.\n" + " -o, --output=<file> Set the output filename for --emit or --extract.\n" " -V, --version Display version information and exit.\n" - " --ignore-checksum Do not validate the checksum when parsing the DXBC blob.\n" - " -o, --output=<file> Set the output filename for --emit.\n" " -- Stop option processing. Any subsequent argument is\n" " interpreted as a filename.\n" "\n" "If the input file is '-' or not specified, input will be read from standard\n" "input. Similarly, if the output file is '-' or not specified at the point\n" - "--emit is found, output will be written to the standard output.\n" + "--emit or --extract is found, output will be written to the standard output.\n" "\n" "Currently this tool can only re-emit the same DXBC blob it loaded. However, it\n" - "will recompute the checksum while doing so, so --emit can be useful\n" - "together with --ignore-checksum to fix the checksum for a blob.\n" + "will recompute the checksum while doing so, so --emit can be useful together\n" + "with --ignore-checksum to fix the checksum for a blob.\n" "\n" - "Options --emit and --output can be specified more than once. The DXBC blob\n" - "will be emitted once for each --emit occurrence, each time using the closest\n" - "previous --output occurrence as output filename.\n"; + "Options --emit, --extract, and --output can be specified more than once. The\n" + "DXBC blob will be emitted once for each --emit occurrence, each time using the\n" + "closest previous --output occurrence as output filename.\n";
fprintf(stderr, "Usage: %s %s", program_name, usage); } @@ -539,6 +558,53 @@ static bool emit_dxbc(const struct vkd3d_shader_dxbc_desc *dxbc_desc, const stru return success; }
+static struct vkd3d_shader_dxbc_section_desc *get_section(size_t section_count, + struct vkd3d_shader_dxbc_section_desc *sections, const char *s) +{ + size_t idx; + char *end; + + if (!strncmp("i:", s, 2)) + { + s += 2; + idx = strtoul(s, &end, 10); + if (*end || idx >= section_count) + { + fprintf(stderr, "Invalid section index '%s' specified.\n", s); + return NULL; + } + return §ions[idx]; + } + + fprintf(stderr, "Invalid section specifier '%s' specified.\n", s); + return NULL; +} + +static bool extract_section(struct vkd3d_shader_dxbc_desc *dxbc_desc, const struct extract *extract) +{ + const struct vkd3d_shader_dxbc_section_desc *section; + bool close_output, success = true; + FILE *output; + + if (!(section = get_section(dxbc_desc->section_count, dxbc_desc->sections, extract->section))) + return false; + + if (!(output = open_output(extract->output_filename, &close_output))) + return false; + + if (!extract->output_filename && isatty(fileno(output))) + fprintf(stderr, "Output is a tty, skipping section '%s'.\n" + "If this is really what you intended, specify the output explicitly.\n", + extract->section); + else if (!(success = write_output(output, §ion->data))) + fprintf(stderr, "Failed to write output.\n"); + + if (close_output) + fclose(output); + + return success; +} + static bool apply_actions(struct vkd3d_shader_dxbc_desc *dxbc_desc, size_t action_count, const struct action *actions) { @@ -552,6 +618,11 @@ static bool apply_actions(struct vkd3d_shader_dxbc_desc *dxbc_desc, if (!emit_dxbc(dxbc_desc, &action->u.emit)) return false; break; + + case ACTION_TYPE_EXTRACT: + if (!extract_section(dxbc_desc, &action->u.extract)) + return false; + break; } }
From: Henri Verbeet hverbeet@codeweavers.com
--- programs/vkd3d-dxbc/main.c | 46 +++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-)
diff --git a/programs/vkd3d-dxbc/main.c b/programs/vkd3d-dxbc/main.c index ff4635847..c08e50afe 100644 --- a/programs/vkd3d-dxbc/main.c +++ b/programs/vkd3d-dxbc/main.c @@ -279,7 +279,13 @@ static void print_usage(const char *program_name) " --colour Enable colour, even when not supported by the output.\n" " -e, --emit Emit the content of the DXBC blob.\n" " -x, --extract=<section> Extract the data contained in <section>.\n" - " <section> must be of the form 'i:<index>'.\n" + " <section> may either be of the form 'i:<index>' in\n" + " order to specify a section by its index or of the\n" + " form 't:<tag>' in order to specify a section by its\n" + " tag. <tag> may be either a four-character string or a\n" + " 32-bit hexadecimal integer. For example: 'i:2',\n" + " 't:SHDR', 't:52444853'. If multiple sections match\n" + " the same tag, the first matching section is used.\n" " -h, --help Display this information and exit.\n" " --ignore-checksum Do not validate the checksum when parsing the DXBC\n" " blob.\n" @@ -428,6 +434,26 @@ static const char *dump_tag(char *out, uint32_t tag) return out; }
+static bool parse_tag(uint32_t *t, const char *s) +{ + char *end; + + if (strlen(s) == 4) + { + *t = VKD3D_MAKE_TAG(s[0], s[1], s[2], s[3]); + return true; + } + + if (strlen(s) == 8) + { + *t = strtoul(s, &end, 16); + if (!*end) + return true; + } + + return false; +} + static void dump_line(const struct colours *colours, const char *prefix, const uint8_t *data, size_t offset, size_t count) { @@ -561,6 +587,7 @@ static bool emit_dxbc(const struct vkd3d_shader_dxbc_desc *dxbc_desc, const stru static struct vkd3d_shader_dxbc_section_desc *get_section(size_t section_count, struct vkd3d_shader_dxbc_section_desc *sections, const char *s) { + uint32_t tag; size_t idx; char *end;
@@ -576,6 +603,23 @@ static struct vkd3d_shader_dxbc_section_desc *get_section(size_t section_count, return §ions[idx]; }
+ if (!strncmp("t:", s, 2)) + { + s += 2; + if (!parse_tag(&tag, s)) + { + fprintf(stderr, "Invalid section tag '%s' specified.\n", s); + return NULL; + } + for (idx = 0; idx < section_count; ++idx) + { + if (sections[idx].tag == tag) + return §ions[idx]; + } + fprintf(stderr, "Section '%s' not found.\n", s); + return NULL; + } + fprintf(stderr, "Invalid section specifier '%s' specified.\n", s); return NULL; }
This merge request was approved by Henri Verbeet.