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); }
static void align_polygon_model_data(polymodel *pm) { int chunk_len; int total_correction = 0; chunk cur_ch; chunk ch_list[MAX_CHUNKS]; int no_chunks = 0; int tmp_size = pm->model_data_size + SHIFT_SPACE; RAIIdmem<uint8_t[]> tmp; MALLOC(tmp, uint8_t[], tmp_size); // where we build the aligned version of pm->model_data Assert(tmp != NULL); //start with first chunk (is always aligned!) const uint8_t *cur_old = pm->model_data.get(); auto cur_new = tmp.get(); 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 (int i = first_index; i < no_chunks; i++) ch_list[i] = ch_list[i + 1]; // if (new) address unaligned: const uintptr_t u = reinterpret_cast<uintptr_t>(new_dest(cur_ch)); if (u % 4L != 0) { // calculate how much to move to be aligned short to_shift = 4 - u % 4L; // correct chunks' addresses cur_ch.correction += to_shift; for (int i = 0; i < no_chunks; i++) ch_list[i].correction += to_shift; total_correction += to_shift; Assert(reinterpret_cast<uintptr_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: *(reinterpret_cast<short *>(cur_ch.new_base + cur_ch.offset)) = INTEL_SHORT(static_cast<short>(cur_ch.correction + GET_INTEL_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 (int 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.get()) - (cur_old - pm->model_data.get()); } pm->model_data_size += total_correction; pm->model_data = make_unique<ubyte[]>(pm->model_data_size); Assert(pm->model_data != NULL); memcpy(pm->model_data.get(), tmp.get(), pm->model_data_size); }