From bd362aaebb4d33da5e57c858858e0b821499e402 Mon Sep 17 00:00:00 2001 From: Bradley Bell Date: Thu, 13 Feb 2003 22:02:29 +0000 Subject: [PATCH] fix remaining polymodel alignment issues. Courtesy of Martin Schaffner --- 3d/interp.c | 130 ++++++----------------------------------------- include/interp.h | 25 ++++++++- main/polyobj.c | 87 ++++++++++++++++++++++++++++++- 3 files changed, 125 insertions(+), 117 deletions(-) diff --git a/3d/interp.c b/3d/interp.c index be948cd2..ff826dcc 100644 --- a/3d/interp.c +++ b/3d/interp.c @@ -1,4 +1,4 @@ -/* $Id: interp.c,v 1.11 2003-01-03 00:57:00 btb Exp $ */ +/* $Id: interp.c,v 1.12 2003-02-13 22:02:29 btb Exp $ */ /* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO @@ -40,7 +40,7 @@ COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. #endif #ifdef RCS -static char rcsid[] = "$Id: interp.c,v 1.11 2003-01-03 00:57:00 btb Exp $"; +static char rcsid[] = "$Id: interp.c,v 1.12 2003-02-13 22:02:29 btb Exp $"; #endif #include @@ -222,63 +222,22 @@ void swap_polygon_model_data(ubyte *data) #endif #ifdef WORDS_NEED_ALIGNMENT - -#include // for memcpy - -typedef struct chunk { // pointer-thing to next chunk of model_data - ubyte *old_base; // where the offset sets off from (relative to beginning of model_data) - ubyte *new_base; // where the base is in the aligned structure - short offset; // how much to add to base to get the address of the offset - short correction; // how much the value of the offset must be shifted for alignment -} chunk; - -ubyte * old_dest(chunk o) // return where the chunk is (in unaligned structure) -{ - return o.old_base + INTEL_SHORT(w(o.old_base + o.offset)); -} - -ubyte * new_dest(chunk o) // return where the chunk is (in aligned structure) +void add_chunk(ubyte *old_base, ubyte *new_base, int offset, + chunk *chunk_list, int *no_chunks) { - return o.new_base + INTEL_SHORT(w(o.old_base + o.offset)) + o.correction; -} - -#define MAX_CHUNKS 100 // increase if insufficent - -int no_chunks; // the number of chunks currently in array -chunk *chunk_list; - -void add_chunk(ubyte *old_base, ubyte *new_base, int offset) { - Assert(no_chunks + 1 < MAX_CHUNKS); //increase MAX_CHUNKS if you get this - chunk_list[no_chunks].old_base = old_base; - chunk_list[no_chunks].new_base = new_base; - chunk_list[no_chunks].offset = offset; - chunk_list[no_chunks].correction = 0; - no_chunks++; -} - -chunk get_first_chunk() // return chunk (from old structure) with smallest address, removing it from array -{ - int i, first_index = 0; - chunk first; - - Assert(no_chunks >= 1); - // find index of chunk with smallest address: - for (i = 1; i < no_chunks; i++) - if (old_dest(chunk_list[i]) < old_dest(chunk_list[first_index])) - first_index = i; - // assign it: - first = chunk_list[first_index]; - // remove it from array: - no_chunks--; - for (i = first_index; i < no_chunks; i++) - chunk_list[i] = chunk_list[i + 1]; - return first; + Assert(*no_chunks + 1 < MAX_CHUNKS); //increase MAX_CHUNKS if you get this + chunk_list[*no_chunks].old_base = old_base; + chunk_list[*no_chunks].new_base = new_base; + chunk_list[*no_chunks].offset = offset; + chunk_list[*no_chunks].correction = 0; + (*no_chunks)++; } /* - * find out what chunks the chunk "data" points to, return length of current chunk + * finds what chunks the data points to, adds them to the chunk_list, + * and returns the length of the current chunk */ -int get_chunks(ubyte *data, ubyte *new_data) +int get_chunks(ubyte *data, ubyte *new_data, chunk *list, int *no) { short n; ubyte *p = data; @@ -302,15 +261,15 @@ int get_chunks(ubyte *data, ubyte *new_data) p += 30 + ((n&~1)+1)*2 + n*12; break; case OP_SORTNORM: - add_chunk(p, p - data + new_data, 28); - add_chunk(p, p - data + new_data, 30); + add_chunk(p, p - data + new_data, 28, list, no); + add_chunk(p, p - data + new_data, 30, list, no); p += 32; break; case OP_RODBM: p+=36; break; case OP_SUBCALL: - add_chunk(p, p - data + new_data, 16); + add_chunk(p, p - data + new_data, 16, list, no); p+=20; break; case OP_GLOW: @@ -322,63 +281,6 @@ int get_chunks(ubyte *data, ubyte *new_data) } return p + 2 - data; } - -#define SHIFT_SPACE 500 // increase if insufficent - -void align_polygon_model_data(polymodel *pm) -{ - int i, chunk_len; - int total_correction = 0; - ubyte *cur_old, *cur_new; - chunk cur_ch; - chunk cl[MAX_CHUNKS]; // we need the chunk_list only in this function - int tmp_size = pm->model_data_size + SHIFT_SPACE; - ubyte *tmp = d_malloc(tmp_size); // where we build the aligned version of pm->model_data - - Assert(tmp != NULL); - chunk_list = cl; // so other functions can access it - no_chunks = 0; - //start with first chunk (is always aligned!) - cur_old = pm->model_data; - cur_new = tmp; - chunk_len = get_chunks(cur_old, cur_new); - memcpy(cur_new, cur_old, chunk_len); - while (no_chunks > 0) { - cur_ch = get_first_chunk(); - if ((u_int32_t)new_dest(cur_ch) % 4L != 0) { // if (new) address unaligned - short to_shift = 4 - (u_int32_t)new_dest(cur_ch) % 4L; // how much to align - - // correct chunks' addresses - cur_ch.correction += to_shift; - for (i = 0; i < no_chunks; i++) - chunk_list[i].correction += to_shift; - total_correction += to_shift; - Assert((u_int32_t)new_dest(cur_ch) % 4L == 0); - Assert(total_correction <= SHIFT_SPACE); // if you get this, increase SHIFT_SPACE - } - //write (corrected) chunk for current chunk: - w(cur_ch.new_base + cur_ch.offset) - = INTEL_SHORT(cur_ch.correction - + INTEL_SHORT(w(cur_ch.old_base + cur_ch.offset))); - //write (correctly aligned) chunk: - cur_old = old_dest(cur_ch); - cur_new = new_dest(cur_ch); - chunk_len = get_chunks(cur_old, cur_new); - memcpy(cur_new, cur_old, chunk_len); - //correct submodel_ptr's for pm, too - for (i = 0; i < MAX_SUBMODELS; i++) - if (pm->model_data + pm->submodel_ptrs[i] >= cur_old - && pm->model_data + pm->submodel_ptrs[i] < cur_old + chunk_len) - pm->submodel_ptrs[i] += (cur_new - tmp) - (cur_old - pm->model_data); - } - d_free(pm->model_data); - pm->model_data_size += total_correction; - pm->model_data = d_malloc(pm->model_data_size); - Assert(pm->model_data != NULL); - memcpy(pm->model_data, tmp, pm->model_data_size); - d_free(tmp); -} - #endif //def WORDS_NEED_ALIGNMENT void verify(ubyte *data) diff --git a/include/interp.h b/include/interp.h index 2e1f8081..f6d80074 100644 --- a/include/interp.h +++ b/include/interp.h @@ -1,4 +1,4 @@ -/* $Id: interp.h,v 1.4 2003-01-22 00:54:13 btb Exp $ */ +/* $Id: interp.h,v 1.5 2003-02-13 22:02:29 btb Exp $ */ /* * * took out functions declarations from include/3d.h @@ -42,4 +42,27 @@ void g3_remap_interp_colors(void); void swap_polygon_model_data(ubyte *data); #endif +#ifdef WORDS_NEED_ALIGNMENT +/* + * A chunk struct (as used for alignment) contains all relevant data + * concerning a piece of data that may need to be aligned. + * To align it, we need to copy it to an aligned position, + * and update all pointers to it. + * (Those pointers are actually offsets + * relative to start of model_data) to it. + */ +typedef struct chunk { + ubyte *old_base; // where the offset sets off from (relative to beginning of model_data) + ubyte *new_base; // where the base is in the aligned structure + short offset; // how much to add to base to get the address of the offset + short correction; // how much the value of the offset must be shifted for alignment +} chunk; +#define MAX_CHUNKS 100 // increase if insufficent +/* + * finds what chunks the data points to, adds them to the chunk_list, + * and returns the length of the current chunk + */ +int get_chunks(ubyte *data, ubyte *new_data, chunk *list, int *no); +#endif //def WORDS_NEED_ALIGNMENT + #endif //_INTERP_H diff --git a/main/polyobj.c b/main/polyobj.c index 31b018d6..3629edff 100644 --- a/main/polyobj.c +++ b/main/polyobj.c @@ -1,4 +1,4 @@ -/* $Id: polyobj.c,v 1.10 2003-01-03 00:56:33 btb Exp $ */ +/* $Id: polyobj.c,v 1.11 2003-02-13 22:02:29 btb Exp $ */ /* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO @@ -17,7 +17,7 @@ COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. #endif #ifdef RCS -static char rcsid[] = "$Id: polyobj.c,v 1.10 2003-01-03 00:56:33 btb Exp $"; +static char rcsid[] = "$Id: polyobj.c,v 1.11 2003-02-13 22:02:29 btb Exp $"; #endif #include @@ -226,6 +226,89 @@ void robot_set_angles(robot_info *r,polymodel *pm,vms_angvec angs[N_ANIM_STATES] #define DEBUG_LEVEL CON_NORMAL +#ifdef WORDS_NEED_ALIGNMENT +ubyte * old_dest(chunk o) // return where chunk is (in unaligned struct) +{ + return o.old_base + INTEL_SHORT(*((short *)(o.old_base + o.offset))); +} +ubyte * new_dest(chunk o) // return where chunk is (in aligned struct) +{ + return o.new_base + INTEL_SHORT(*((short *)(o.old_base + o.offset))) + o.correction; +} +/* + * find chunk with smallest address + */ +int get_first_chunks_index(chunk *chunk_list, int no_chunks) +{ + int i, first_index = 0; + Assert(no_chunks >= 1); + for (i = 1; i < no_chunks; i++) + if (old_dest(chunk_list[i]) < old_dest(chunk_list[first_index])) + first_index = i; + return first_index; +} +#define SHIFT_SPACE 500 // increase if insufficent + +void align_polygon_model_data(polymodel *pm) +{ + int i, chunk_len; + int total_correction = 0; + ubyte *cur_old, *cur_new; + chunk cur_ch; + chunk ch_list[MAX_CHUNKS]; + int no_chunks = 0; + int tmp_size = pm->model_data_size + SHIFT_SPACE; + ubyte *tmp = d_malloc(tmp_size); // where we build the aligned version of pm->model_data + + Assert(tmp != NULL); + //start with first chunk (is always aligned!) + cur_old = pm->model_data; + cur_new = tmp; + chunk_len = get_chunks(cur_old, cur_new, ch_list, &no_chunks); + memcpy(cur_new, cur_old, chunk_len); + while (no_chunks > 0) { + int first_index = get_first_chunks_index(ch_list, no_chunks); + cur_ch = ch_list[first_index]; + // remove first chunk from array: + no_chunks--; + for (i = first_index; i < no_chunks; i++) + ch_list[i] = ch_list[i + 1]; + // if (new) address unaligned: + if ((u_int32_t)new_dest(cur_ch) % 4L != 0) { + // calculate how much to move to be aligned + short to_shift = 4 - (u_int32_t)new_dest(cur_ch) % 4L; + // correct chunks' addresses + cur_ch.correction += to_shift; + for (i = 0; i < no_chunks; i++) + ch_list[i].correction += to_shift; + total_correction += to_shift; + Assert((u_int32_t)new_dest(cur_ch) % 4L == 0); + Assert(total_correction <= SHIFT_SPACE); // if you get this, increase SHIFT_SPACE + } + //write (corrected) chunk for current chunk: + *((short *)(cur_ch.new_base + cur_ch.offset)) + = INTEL_SHORT(cur_ch.correction + + INTEL_SHORT(*((short *)(cur_ch.old_base + cur_ch.offset)))); + //write (correctly aligned) chunk: + cur_old = old_dest(cur_ch); + cur_new = new_dest(cur_ch); + chunk_len = get_chunks(cur_old, cur_new, ch_list, &no_chunks); + memcpy(cur_new, cur_old, chunk_len); + //correct submodel_ptr's for pm, too + for (i = 0; i < MAX_SUBMODELS; i++) + if (pm->model_data + pm->submodel_ptrs[i] >= cur_old + && pm->model_data + pm->submodel_ptrs[i] < cur_old + chunk_len) + pm->submodel_ptrs[i] += (cur_new - tmp) - (cur_old - pm->model_data); + } + d_free(pm->model_data); + pm->model_data_size += total_correction; + pm->model_data = d_malloc(pm->model_data_size); + Assert(pm->model_data != NULL); + memcpy(pm->model_data, tmp, pm->model_data_size); + d_free(tmp); +} +#endif //def WORDS_NEED_ALIGNMENT + //reads a binary file containing a 3d model polymodel *read_model_file(polymodel *pm,char *filename,robot_info *r) { -- 2.39.2