2022-10-06 20:31:43 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2022-10-06 21:24:10 +00:00
|
|
|
#define VERSION_MAX_LEN (size_t)(35)
|
2022-10-06 20:31:43 +00:00
|
|
|
#define METROID_BUILD_INFO_TAG "!#$MetroidBuildInfo!#$"
|
|
|
|
|
|
|
|
void* memmem(const void* l, size_t l_len, const void* s, size_t s_len) {
|
|
|
|
register char *cur, *last;
|
|
|
|
const char* cl = (const char*)l;
|
|
|
|
const char* cs = (const char*)s;
|
|
|
|
|
|
|
|
/* we need something to compare */
|
|
|
|
if (l_len == 0 || s_len == 0)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
/* "s" must be smaller or equal to "l" */
|
|
|
|
if (l_len < s_len)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
/* special case where s_len == 1 */
|
|
|
|
if (s_len == 1)
|
|
|
|
return memchr(l, (int)*cs, l_len);
|
|
|
|
|
|
|
|
/* the last position where its possible to find "s" in "l" */
|
|
|
|
last = (char*)cl + l_len - s_len;
|
|
|
|
|
|
|
|
for (cur = (char*)cl; cur <= last; cur++)
|
|
|
|
if (cur[0] == cs[0] && memcmp(cur, cs, s_len) == 0)
|
|
|
|
return cur;
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
int main(int argc, const char* argv[]) {
|
|
|
|
if (argc < 3) {
|
|
|
|
fprintf(stdout, "\t--- METROID BUILD INFO ---\n"
|
|
|
|
"\tWritten by Phillip \"Antidote\" Stephens\n"
|
|
|
|
"\tReleased under the MIT License\n\n"
|
|
|
|
"\tSets the MetroidBuildInfo tag value in a given binary\n"
|
|
|
|
"\tThe version string can be a maximum of 35 characters,\n"
|
|
|
|
"\texcluding null terminator\n"
|
|
|
|
"\t--------------------------\n"
|
|
|
|
|
|
|
|
);
|
|
|
|
fprintf(stdout, "Usage:\n"
|
2022-10-06 21:24:10 +00:00
|
|
|
"\tmetroidbuildinfo <binary> <build_file>\n");
|
2022-10-06 20:31:43 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Let's try to get the source binary */
|
|
|
|
FILE* source = fopen(argv[1], "rb");
|
|
|
|
if (!source) {
|
|
|
|
fprintf(stderr, "Unable to open '%s'\nPlease ensure the file exists!\n", argv[1]);
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
|
2022-10-06 21:24:10 +00:00
|
|
|
char build_string[36] = {0};
|
|
|
|
FILE* build = fopen(argv[2], "rb");
|
|
|
|
|
|
|
|
if (!build) {
|
|
|
|
fprintf(stderr, "Unable to open '%s'\nPlease ensure the file exists!\n", argv[2]);
|
2022-10-06 20:31:43 +00:00
|
|
|
return -3;
|
|
|
|
}
|
2022-10-06 21:24:10 +00:00
|
|
|
size_t read_len = fread(build_string, 1, 35, build);
|
|
|
|
fclose(build);
|
|
|
|
|
|
|
|
if (read_len <= 0) {
|
|
|
|
fprintf(stderr, "Empty file %s specified for build version!\n", argv[2]);
|
|
|
|
return -4;
|
|
|
|
}
|
|
|
|
|
2022-10-06 21:40:29 +00:00
|
|
|
build_string[strcspn(build_string, "\r\n")] = '\0';
|
2022-10-06 20:31:43 +00:00
|
|
|
|
|
|
|
/* Get source length */
|
|
|
|
fseek(source, 0, SEEK_END);
|
|
|
|
size_t source_len = ftell(source);
|
|
|
|
rewind(source);
|
|
|
|
void* source_buf = malloc(source_len);
|
|
|
|
if (source_buf == NULL) {
|
|
|
|
fprintf(stderr, "Unable to allocate buffer of size %zubytes!\n", source_len);
|
2022-10-06 21:24:10 +00:00
|
|
|
return -5;
|
2022-10-06 20:31:43 +00:00
|
|
|
}
|
|
|
|
fread(source_buf, 1, source_len, source);
|
|
|
|
fclose(source);
|
|
|
|
|
|
|
|
/* Find the build info tag so we can stuff our version info in the binary */
|
|
|
|
void* ptr =
|
|
|
|
memmem(source_buf, source_len, METROID_BUILD_INFO_TAG, strlen(METROID_BUILD_INFO_TAG));
|
|
|
|
if (ptr == NULL) {
|
|
|
|
fprintf(stderr, "Unable to find build info tag in source!\n");
|
2022-10-06 21:27:43 +00:00
|
|
|
return -6;
|
2022-10-06 20:31:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Lets actually copy over the build string */
|
2022-10-06 21:24:10 +00:00
|
|
|
strcpy(ptr + strlen(METROID_BUILD_INFO_TAG), build_string);
|
2022-10-06 20:31:43 +00:00
|
|
|
|
|
|
|
/* Now attempt to open the target file */
|
|
|
|
FILE* target = fopen(argv[1], "wb");
|
|
|
|
|
|
|
|
if (!target) {
|
|
|
|
fprintf(stderr, "Unable to open '%s'\nPlease ensure you have write permissions!\n", argv[1]);
|
2022-10-06 21:27:43 +00:00
|
|
|
return -7;
|
2022-10-06 20:31:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Finally write the buffer to the target file */
|
|
|
|
fwrite(source_buf, 1, source_len, target);
|
|
|
|
fclose(target);
|
|
|
|
|
|
|
|
/* Don't leak */
|
|
|
|
free(source_buf);
|
|
|
|
|
2022-10-06 21:24:10 +00:00
|
|
|
return 0;
|
2022-10-06 20:31:43 +00:00
|
|
|
}
|