diff --git a/src/object.c b/src/object.c index 369ce6b8cf..98cd3b104c 100644 --- a/src/object.c +++ b/src/object.c @@ -1764,12 +1764,12 @@ void object_free_scenario_text() } } -int object_get_length(rct_object_entry *entry) +uintptr_t object_get_length(const rct_object_entry *entry) { - return (int)object_get_next(entry) - (int)entry; + return (uintptr_t)object_get_next(entry) - (uintptr_t)entry; } -rct_object_entry *object_get_next(rct_object_entry *entry) +rct_object_entry *object_get_next(const rct_object_entry *entry) { uint8 *pos = (uint8*)entry; diff --git a/src/object.h b/src/object.h index f19c70f7df..eebef4e10f 100644 --- a/src/object.h +++ b/src/object.h @@ -115,10 +115,10 @@ int object_load_chunk(int groupIndex, rct_object_entry *entry, int* chunk_size); void object_unload_chunk(rct_object_entry *entry); int object_get_scenario_text(rct_object_entry *entry); void object_free_scenario_text(); -int object_get_length(rct_object_entry *entry); +uintptr_t object_get_length(const rct_object_entry *entry); int object_entry_compare(const rct_object_entry *a, const rct_object_entry *b); int object_calculate_checksum(const rct_object_entry *entry, const uint8 *data, int dataLength); -rct_object_entry *object_get_next(rct_object_entry *entry); +rct_object_entry *object_get_next(const rct_object_entry *entry); int write_object_file(SDL_RWops* rw, rct_object_entry* entry); void reset_loaded_objects(); int find_object_in_entry_group(rct_object_entry* entry, uint8* entry_type, uint8* entry_index); diff --git a/src/object_list.c b/src/object_list.c index 2e464f7258..e5706ef093 100644 --- a/src/object_list.c +++ b/src/object_list.c @@ -108,6 +108,11 @@ static void get_plugin_path(utf8 *outPath) strcat(outPath, "plugin.dat"); } +static uintptr_t object_get_length_cached(const rct_object_entry **entryCache, const size_t index) +{ + return (uintptr_t)entryCache[index + 1] - (uintptr_t)entryCache[index]; +} + static rct_object_entry **_entryCache = NULL; static int object_comparator(const void *left, const void *right) @@ -123,14 +128,15 @@ static void object_list_sort() { rct_object_entry **objectBuffer, *newBuffer, *entry, *destEntry; rct_object_filters *newFilters = NULL, *destFilter = NULL; - int numObjects, bufferSize, entrySize; + int numObjects, bufferSize; + size_t entrySize; objectBuffer = &gInstalledObjects; numObjects = gInstalledObjectsCount; - _entryCache = malloc(numObjects * sizeof(rct_object_entry*)); - size_t *sortLUT = malloc(numObjects * sizeof(size_t)); + _entryCache = malloc((numObjects + 1)* sizeof(rct_object_entry*)); + size_t *sortLUT = malloc((numObjects + 1) * sizeof(size_t)); entry = *objectBuffer; // This loop initialises entry cache, so it doesn't have to be called 17M // times, but only a few thousand. @@ -138,10 +144,8 @@ static void object_list_sort() do { _entryCache[i] = entry; sortLUT[i] = i; - } while (++i < numObjects && (entry = object_get_next(entry))); + } while (i++ < numObjects && (entry = object_get_next(entry))); qsort(sortLUT, numObjects, sizeof(size_t), object_comparator); - // Get size of last entry so buffer is allocated properly. - entry = object_get_next(entry); // Get buffer size bufferSize = (uintptr_t)entry - (uintptr_t)*objectBuffer; @@ -156,7 +160,7 @@ static void object_list_sort() // Copy over sorted objects for (int i = 0; i < numObjects; i++) { - entrySize = object_get_length(_entryCache[sortLUT[i]]); + entrySize = object_get_length_cached((const rct_object_entry **)_entryCache, sortLUT[i]); memcpy(destEntry, _entryCache[sortLUT[i]], entrySize); destEntry = (rct_object_entry*)((uintptr_t)destEntry + entrySize); if (_installedObjectFilters)