mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2025-01-18 22:31:36 +00:00
Allow testsuite to pass on big endian
Move the progs header and body byteswapping into util functions and call those functions when either reading or writing the progs.
This commit is contained in:
parent
f7e074d88f
commit
69b89dc6ac
4 changed files with 78 additions and 48 deletions
53
code.c
53
code.c
|
@ -260,59 +260,18 @@ static void code_create_header(code_t *code, prog_header_t *code_header, const c
|
|||
}
|
||||
|
||||
/* ensure all data is in LE format */
|
||||
util_endianswap(&code_header->version, 1, sizeof(code_header->version));
|
||||
util_endianswap(&code_header->crc16, 1, sizeof(code_header->crc16));
|
||||
util_endianswap(&code_header->statements.offset, 1, sizeof(code_header->statements.offset));
|
||||
util_endianswap(&code_header->statements.length, 1, sizeof(code_header->statements.length));
|
||||
util_endianswap(&code_header->defs.offset, 1, sizeof(code_header->defs.offset));
|
||||
util_endianswap(&code_header->defs.length, 1, sizeof(code_header->defs.length));
|
||||
util_endianswap(&code_header->fields.offset, 1, sizeof(code_header->fields.offset));
|
||||
util_endianswap(&code_header->fields.length, 1, sizeof(code_header->fields.length));
|
||||
util_endianswap(&code_header->functions.offset, 1, sizeof(code_header->functions.offset));
|
||||
util_endianswap(&code_header->functions.length, 1, sizeof(code_header->functions.length));
|
||||
util_endianswap(&code_header->strings.offset, 1, sizeof(code_header->strings.offset));
|
||||
util_endianswap(&code_header->strings.length, 1, sizeof(code_header->strings.length));
|
||||
util_endianswap(&code_header->globals.offset, 1, sizeof(code_header->globals.offset));
|
||||
util_endianswap(&code_header->globals.length, 1, sizeof(code_header->globals.length));
|
||||
util_endianswap(&code_header->entfield, 1, sizeof(code_header->entfield));
|
||||
util_swap_header(code_header);
|
||||
|
||||
/*
|
||||
* These are not part of the header but we ensure LE format here to save on duplicated
|
||||
* code.
|
||||
*/
|
||||
|
||||
for (i = 0; i < vec_size(code->statements); ++i) {
|
||||
util_endianswap(&code->statements[i].opcode, 1, sizeof(code->statements[i].opcode));
|
||||
util_endianswap(&code->statements[i].o1, 1, sizeof(code->statements[i].o1));
|
||||
util_endianswap(&code->statements[i].o2, 1, sizeof(code->statements[i].o2));
|
||||
util_endianswap(&code->statements[i].o3, 1, sizeof(code->statements[i].o3));
|
||||
}
|
||||
|
||||
for (i = 0; i < vec_size(code->defs); ++i) {
|
||||
util_endianswap(&code->defs[i].type, 1, sizeof(code->defs[i].type));
|
||||
util_endianswap(&code->defs[i].offset, 1, sizeof(code->defs[i].offset));
|
||||
util_endianswap(&code->defs[i].name, 1, sizeof(code->defs[i].name));
|
||||
}
|
||||
|
||||
for (i = 0; i < vec_size(code->fields); ++i) {
|
||||
util_endianswap(&code->fields[i].type, 1, sizeof(code->fields[i].type));
|
||||
util_endianswap(&code->fields[i].offset, 1, sizeof(code->fields[i].offset));
|
||||
util_endianswap(&code->fields[i].name, 1, sizeof(code->fields[i].name));
|
||||
}
|
||||
|
||||
for (i = 0; i < vec_size(code->functions); ++i) {
|
||||
util_endianswap(&code->functions[i].entry, 1, sizeof(code->functions[i].entry));
|
||||
util_endianswap(&code->functions[i].firstlocal, 1, sizeof(code->functions[i].firstlocal));
|
||||
util_endianswap(&code->functions[i].locals, 1, sizeof(code->functions[i].locals));
|
||||
util_endianswap(&code->functions[i].profile, 1, sizeof(code->functions[i].profile));
|
||||
util_endianswap(&code->functions[i].name, 1, sizeof(code->functions[i].name));
|
||||
util_endianswap(&code->functions[i].file, 1, sizeof(code->functions[i].file));
|
||||
util_endianswap(&code->functions[i].nargs, 1, sizeof(code->functions[i].nargs));
|
||||
/* Don't swap argsize[] - it's just a byte array, which Quake uses only as such. */
|
||||
}
|
||||
|
||||
util_endianswap(code->globals, vec_size(code->globals), sizeof(int32_t));
|
||||
|
||||
util_swap_statements (code->statements);
|
||||
util_swap_defs_fields(code->defs);
|
||||
util_swap_defs_fields(code->fields);
|
||||
util_swap_functions (code->functions);
|
||||
util_swap_globals (code->globals);
|
||||
|
||||
if (!OPTS_OPTION_BOOL(OPTION_QUIET)) {
|
||||
if (lnofile)
|
||||
|
|
8
exec.c
8
exec.c
|
@ -66,6 +66,8 @@ qc_program_t* prog_load(const char *filename, bool skipversion)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
util_swap_header(&header);
|
||||
|
||||
if (!skipversion && header.version != 6) {
|
||||
loaderror("header says this is a version %i progs, we need version 6\n", header.version);
|
||||
fs_file_close(file);
|
||||
|
@ -114,6 +116,12 @@ qc_program_t* prog_load(const char *filename, bool skipversion)
|
|||
read_data1(strings);
|
||||
read_data2(globals, 2); /* reserve more in case a RETURN using with the global at "the end" exists */
|
||||
|
||||
util_swap_statements (prog->code);
|
||||
util_swap_defs_fields(prog->defs);
|
||||
util_swap_defs_fields(prog->fields);
|
||||
util_swap_functions (prog->functions);
|
||||
util_swap_globals (prog->globals);
|
||||
|
||||
fs_file_close(file);
|
||||
|
||||
/* profile counters */
|
||||
|
|
5
gmqcc.h
5
gmqcc.h
|
@ -627,6 +627,11 @@ enum {
|
|||
/* TODO: elide */
|
||||
extern const char *util_instr_str[VINSTR_END];
|
||||
|
||||
void util_swap_header (prog_header_t *code_header);
|
||||
void util_swap_statements (prog_section_statement_t *statements);
|
||||
void util_swap_defs_fields(prog_section_both_t *section);
|
||||
void util_swap_functions (prog_section_function_t *functions);
|
||||
void util_swap_globals (int32_t *globals);
|
||||
|
||||
typedef float qcfloat_t;
|
||||
typedef int32_t qcint_t;
|
||||
|
|
60
util.c
60
util.c
|
@ -85,8 +85,8 @@ const char *util_instr_str[VINSTR_END] = {
|
|||
d[l] = (v << 32) | (v >> 32);
|
||||
}
|
||||
*/
|
||||
l *= 2;
|
||||
size_t i;
|
||||
l *= 2;
|
||||
for (i = 0; i < l; i += 2) {
|
||||
uint32_t v1 = d[i];
|
||||
d[i] = d[i+1];
|
||||
|
@ -129,6 +129,64 @@ void util_endianswap(void *_data, size_t count, unsigned int typesize) {
|
|||
#endif
|
||||
}
|
||||
|
||||
void util_swap_header (prog_header_t *code_header) {
|
||||
util_endianswap(&code_header->version, 1, sizeof(code_header->version));
|
||||
util_endianswap(&code_header->crc16, 1, sizeof(code_header->crc16));
|
||||
util_endianswap(&code_header->statements.offset, 1, sizeof(code_header->statements.offset));
|
||||
util_endianswap(&code_header->statements.length, 1, sizeof(code_header->statements.length));
|
||||
util_endianswap(&code_header->defs.offset, 1, sizeof(code_header->defs.offset));
|
||||
util_endianswap(&code_header->defs.length, 1, sizeof(code_header->defs.length));
|
||||
util_endianswap(&code_header->fields.offset, 1, sizeof(code_header->fields.offset));
|
||||
util_endianswap(&code_header->fields.length, 1, sizeof(code_header->fields.length));
|
||||
util_endianswap(&code_header->functions.offset, 1, sizeof(code_header->functions.offset));
|
||||
util_endianswap(&code_header->functions.length, 1, sizeof(code_header->functions.length));
|
||||
util_endianswap(&code_header->strings.offset, 1, sizeof(code_header->strings.offset));
|
||||
util_endianswap(&code_header->strings.length, 1, sizeof(code_header->strings.length));
|
||||
util_endianswap(&code_header->globals.offset, 1, sizeof(code_header->globals.offset));
|
||||
util_endianswap(&code_header->globals.length, 1, sizeof(code_header->globals.length));
|
||||
util_endianswap(&code_header->entfield, 1, sizeof(code_header->entfield));
|
||||
}
|
||||
|
||||
void util_swap_statements (prog_section_statement_t *statements) {
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < vec_size(statements); ++i) {
|
||||
util_endianswap(&statements[i].opcode, 1, sizeof(statements[i].opcode));
|
||||
util_endianswap(&statements[i].o1, 1, sizeof(statements[i].o1));
|
||||
util_endianswap(&statements[i].o2, 1, sizeof(statements[i].o2));
|
||||
util_endianswap(&statements[i].o3, 1, sizeof(statements[i].o3));
|
||||
}
|
||||
}
|
||||
|
||||
void util_swap_defs_fields (prog_section_both_t *section) {
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < vec_size(section); ++i) {
|
||||
util_endianswap(§ion[i].type, 1, sizeof(section[i].type));
|
||||
util_endianswap(§ion[i].offset, 1, sizeof(section[i].offset));
|
||||
util_endianswap(§ion[i].name, 1, sizeof(section[i].name));
|
||||
}
|
||||
}
|
||||
|
||||
void util_swap_functions (prog_section_function_t* functions) {
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < vec_size(functions); ++i) {
|
||||
util_endianswap(&functions[i].entry, 1, sizeof(functions[i].entry));
|
||||
util_endianswap(&functions[i].firstlocal, 1, sizeof(functions[i].firstlocal));
|
||||
util_endianswap(&functions[i].locals, 1, sizeof(functions[i].locals));
|
||||
util_endianswap(&functions[i].profile, 1, sizeof(functions[i].profile));
|
||||
util_endianswap(&functions[i].name, 1, sizeof(functions[i].name));
|
||||
util_endianswap(&functions[i].file, 1, sizeof(functions[i].file));
|
||||
util_endianswap(&functions[i].nargs, 1, sizeof(functions[i].nargs));
|
||||
/* Don't swap argsize[] - it's just a byte array, which Quake uses only as such. */
|
||||
}
|
||||
}
|
||||
|
||||
void util_swap_globals (int32_t * globals) {
|
||||
util_endianswap(globals, vec_size(globals), sizeof(int32_t));
|
||||
}
|
||||
|
||||
/*
|
||||
* Based On:
|
||||
* Slicing-by-8 algorithms by Michael E.
|
||||
|
|
Loading…
Reference in a new issue