/** * * rct2: 0x006A93CD */ static void object_list_examine() { int i; rct_object_entry *object; object = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, rct_object_entry*); for (i = 0; i < RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, sint32); i++) { if (object->flags & 0xF0) RCT2_GLOBAL(0x00F42BDA, uint8) |= 1; object = object_get_next(object); } }
STATUS test_init(void) { OBJECT *obj; output_verbose("initializing objects..."); for (obj=object_get_first(); obj!=NULL; obj=object_get_next(obj)) { if (object_init(obj)==FAILED) { output_error("object %s initialization failed", object_name(obj)); return FAILED; } } return SUCCESS; }
/** * Takes the y coordinate of the clicked on scroll list * and converts this into an object selection. * Returns the position in the list. * Object_selection_flags, installed_entry also populated * * rct2: 0x006AA703 */ static int get_object_from_object_selection(uint8 object_type, int y, uint8 *object_selection_flags, rct_object_entry **installed_entry) { rct_object_filters *filter; *installed_entry = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, rct_object_entry*); uint8* selection_flags = RCT2_GLOBAL(RCT2_ADDRESS_EDITOR_OBJECT_FLAGS_LIST, uint8*); uint8 source; int object_count = 0; for (int i = RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32); i > 0; --i){ filter = get_object_filter(RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32) - i); source = ((*installed_entry)->flags & 0xF0) >> 4; if (((*installed_entry)->flags & 0xF) == object_type && filter_source(*installed_entry) && filter_string(*installed_entry) && filter_chunks(*installed_entry, filter)){ if (!(*selection_flags & 0x20)){ y -= 12; *object_selection_flags = *selection_flags; if (y < 0)return object_count; object_count++; } } *installed_entry = object_get_next(*installed_entry); selection_flags++; } return -1; }
/** sanitize Sanitizes a gridlabd model by clear names and position from object headers @returns 0 on success, -2 on error **/ extern "C" int sanitize(int argc, char *argv[]) { OBJECT *obj; FILE *fp; double delta_latitude, delta_longitude; // lat/lon change if ( strcmp(global_sanitizeoffset,"")==0 ) { delta_latitude = random_uniform(NULL,-5,+5); delta_longitude = random_uniform(NULL,-180,+180); } else if ( global_sanitizeoffset=="destroy" ) delta_latitude = delta_longitude = QNAN; else if ( sscanf(global_sanitizeoffset.get_string(),"%lf%*[,/]%lf",&delta_latitude,&delta_longitude)!=2 ) { output_error("sanitize_offset lat/lon '%s' is not valid", global_sanitizeoffset.get_string()); return -2; } // sanitize object names for ( obj=object_get_first() ; obj!=NULL ; obj=object_get_next(obj) ) { if ( obj->name!=NULL && (global_sanitizeoptions&SO_NAMES)==SO_NAMES ) sanitize_name(obj); if ( isfinite(obj->latitude) && (global_sanitizeoptions&SO_GEOCOORDS)==SO_GEOCOORDS ) { obj->latitude += delta_latitude; if ( obj->latitude<-90 ) obj->latitude = -90; if ( obj->latitude>+90 ) obj->latitude = +90; } if ( isfinite(obj->longitude) && (global_sanitizeoptions&SO_GEOCOORDS)==SO_GEOCOORDS ) obj->longitude = fmod(obj->longitude+delta_longitude,360); } // dump object name index if ( strcmp(global_sanitizeindex,".xml")==0 ) { strcpy(global_sanitizeindex,global_modelname); char *ext = strrchr(global_sanitizeindex,'.'); if ( ext && strcmp(ext,".glm")==0 ) strcpy(ext,"-index.xml"); else strcat(global_sanitizeindex,"-index.xml"); } else if ( strcmp(global_sanitizeindex,".txt")==0 ) { strcpy(global_sanitizeindex,global_modelname); char *ext = strrchr(global_sanitizeindex,'.'); if ( ext && strcmp(ext,".glm")==0 ) strcpy(ext,"-index.txt"); else strcat(global_sanitizeindex,"-index.txt"); } else if ( global_sanitizeindex[0]=='.' ) { output_error("sanitization index file spec '%s' is not recognized", global_sanitizeindex.get_string()); return -2; } if ( strcmp(global_sanitizeindex,"")!=0 ) { char *ext = strrchr(global_sanitizeindex,'.'); bool use_xml = (ext && strcmp(ext,".xml")==0) ; fp = fopen(global_sanitizeindex,"w"); if ( fp ) { SAFENAME *item; if ( use_xml ) { fprintf(fp,"<data>\n"); fprintf(fp,"\t<modelname>%s</modelname>\n",global_modelname); fprintf(fp,"\t<geographic_offsets>\n"); fprintf(fp,"\t\t<latitude>%.6f</latitude>\n",delta_latitude); fprintf(fp,"\t\t<longitude>%.6f</longitude>\n",delta_longitude); fprintf(fp,"\t</geographic_offsets>\n"); fprintf(fp,"\t<safename_list>\n"); for ( item=safename_list ; item!=NULL ; item=item->next ) fprintf(fp,"\t\t<name>\n\t\t\t<safe>%s</safe>\n\t\t\t<unsafe>%s</unsafe>\n\t\t</name>\n", item->name, item->old); fprintf(fp,"\t</safename_list>\n"); fprintf(fp,"</data>\n"); } else { fprintf(fp,"modelname\t= %s\n", global_modelname); fprintf(fp,"\n[POSITIONS]\n"); fprintf(fp,"latitude\t= %.6f\n",delta_latitude); fprintf(fp,"longitude\t= %.6f\n",delta_longitude); fprintf(fp,"\n[NAMES]\n"); for ( item=safename_list ; item!=NULL ; item=item->next ) fprintf(fp,"%s\t= %s\n", item->name, item->old); } fclose(fp); } } return 0; }
/** * * rct2: 0x006A8B40 */ void object_list_load() { HANDLE hFindFile; WIN32_FIND_DATAA findFileData; int totalFiles = 0, totalFileSize = 0, fileDateModifiedChecksum = 0; char pluginPath[MAX_PATH]; get_plugin_path(pluginPath); // Enumerate through each object in the directory hFindFile = FindFirstFile(RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char), &findFileData); if (hFindFile != INVALID_HANDLE_VALUE) { do { totalFiles++; totalFileSize += findFileData.nFileSizeLow; fileDateModifiedChecksum ^= findFileData.ftLastWriteTime.dwLowDateTime ^ findFileData.ftLastWriteTime.dwHighDateTime; fileDateModifiedChecksum = ror32(fileDateModifiedChecksum, 5); } while (FindNextFile(hFindFile, &findFileData)); FindClose(hFindFile); } totalFiles = ror32(totalFiles, 24); totalFiles = (totalFiles & ~0xFF) | 1; totalFiles = rol32(totalFiles, 24); // Read plugin header rct_plugin_header pluginHeader; FILE *file = fopen(pluginPath, "rb"); if (file != NULL) { if (fread(&pluginHeader, sizeof(pluginHeader), 1, file) == 1) { // Check if object repository has changed in anyway if ( totalFiles == pluginHeader.total_files && totalFileSize == pluginHeader.total_file_size && fileDateModifiedChecksum == pluginHeader.date_modified_checksum ) { // Dispose installed object list if (RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, sint32) != -1) { rct2_free(RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, void*)); RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, sint32) = -1; } // Read installed object list RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, void*) = rct2_malloc(pluginHeader.object_list_size); if (fread(RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, void*), pluginHeader.object_list_size, 1, file) == 1) { RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32) = pluginHeader.object_list_no_items; fclose(file); sub_6A9FC0(); object_list_examine(); return; } } } fclose(file); } // Reload object list RCT2_GLOBAL(0x00F42B94, uint32) = totalFiles; RCT2_GLOBAL(0x00F42B98, uint32) = totalFileSize; RCT2_GLOBAL(0x00F42B9C, uint32) = fileDateModifiedChecksum; //RCT2_CALLPROC_EBPSAFE(0x006A8D8F); int eax = 3161; if (RCT2_GLOBAL(0x9AA00D, uint8) != 0){ eax = 3160; RCT2_GLOBAL(0x9AA00D, uint8) = 0; } // File count removed and replaced by variable // RCT2_GLOBAL(0xF42BA8, uint32) = 0; uint32 file_count = 0; // Progress bar related. RCT2_GLOBAL(0xF42BD8, uint8) = 0; sub_6A9FC0(); // Dispose installed object list if (RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, sint32) != -1) { rct2_free(RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, void*)); RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, sint32) = -1; } RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32) = 0; RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, void*) = rct2_malloc(4096); if (RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, int) == -1){ RCT2_CALLPROC_X(0x006E3838, 0x343, 0xC5A, 0, 0, 0, 0, 0); return; } uint32 installed_buffer_size = 0x1000; uint32 current_item_offset = 0; hFindFile = FindFirstFile(RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char), &findFileData); if (hFindFile == INVALID_HANDLE_VALUE){ //6a92ea This hasn't been implemented but there isn't much point. // It would make a empty object file if no files found. return; } for (uint8 first_time = 1; first_time || FindNextFile(hFindFile, &findFileData);){ first_time = 0; RCT2_GLOBAL(0x9ABD98, HANDLE) = hFindFile; file_count++; // update progress bar. eax = (file_count << 8) / ((RCT2_GLOBAL(0xF42B94, uint32) & 0xFFFFFF) + 1); if ((eax & 0xFF) != RCT2_GLOBAL(0xF42BD8, uint8)){ RCT2_GLOBAL(0xF42BD8, uint8) = eax & 0xFF; // update progress bar } if ((installed_buffer_size - current_item_offset) <= 2842){ installed_buffer_size += 0x1000; RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, void*) = rct2_realloc(RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, void*), installed_buffer_size); if (RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, int) == -1){ RCT2_CALLPROC_X(0x006E3838, 0x343, 0xC5A, 0, 0, 0, 0, 0); return; } } char path[260]; subsitute_path(path, RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char), findFileData.cFileName); FILE *obj_file = fopen(path, "rb"); if (obj_file == NULL){ continue; } rct_object_entry* entry = RCT2_ADDRESS(0xF42B74, rct_object_entry); if (fread(entry, sizeof(rct_object_entry), 1, obj_file) != 1){ fclose(obj_file); continue; } fclose(obj_file); RCT2_GLOBAL(0xF42BC4, uint32) = current_item_offset; uint8* installed_entry_pointer = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, uint8*) + current_item_offset; memcpy(installed_entry_pointer, entry, sizeof(rct_object_entry)); installed_entry_pointer += sizeof(rct_object_entry); strcpy(installed_entry_pointer, findFileData.cFileName); while (*installed_entry_pointer++); *((sint32*)installed_entry_pointer) = -1; *(installed_entry_pointer + 4) = 0; *((sint32*)(installed_entry_pointer + 5)) = 0; *((uint16*)(installed_entry_pointer + 9)) = 0; *((uint32*)(installed_entry_pointer + 11)) = 0; RCT2_GLOBAL(0x9ADAF0, uint32) = 0xF26E; RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32)++; // This is a variable used by object_load to decide if it should // use object_paint on the entry. RCT2_GLOBAL(0x9ADAFD, uint8) = 1; // Probably used by object paint. RCT2_GLOBAL(0x9ADAF4, uint32) = 0xF42BDB; int chunk_size; if (!object_load(-1, entry, &chunk_size)){ RCT2_GLOBAL(0x9ADAF4, sint32) = -1; RCT2_GLOBAL(0x9ADAFD, uint8) = 0; RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32)--; continue; } // See above note RCT2_GLOBAL(0x9ADAF4, sint32) = -1; RCT2_GLOBAL(0x9ADAFD, uint8) = 0; if ((entry->flags & 0xF0) == 0x80){ RCT2_GLOBAL(0xF42B70, uint32)++; if (RCT2_GLOBAL(0xF42B70, uint32) > 772){ RCT2_GLOBAL(0xF42B70, uint32)--; RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32)--; continue; } } *((sint32*)installed_entry_pointer) = chunk_size; installed_entry_pointer += 4; uint8* chunk = RCT2_GLOBAL(RCT2_ADDRESS_CURR_OBJECT_CHUNK_POINTER, uint8*); // Loaded in object_load // When made of two parts i.e Wooden Roller Coaster (Dream Woodie Cars); if ((entry->flags & 0xF) == 0 && !(*((uint32*)(chunk + 8)) & 0x1000)){ rct_string_id obj_string = chunk[12]; if (obj_string == 0xFF){ obj_string = chunk[13]; if (obj_string == 0xFF){ obj_string = chunk[14]; } } obj_string += 2; format_string(installed_entry_pointer, obj_string, 0); strcat(installed_entry_pointer, "\t ("); strcat(installed_entry_pointer, language_get_string(RCT2_GLOBAL(0xF42BBC, uint32))); strcat(installed_entry_pointer, ")"); while (*installed_entry_pointer++); } else{ strcpy(installed_entry_pointer, language_get_string(RCT2_GLOBAL(0xF42BBC, uint32))); while (*installed_entry_pointer++); } *((uint32*)installed_entry_pointer) = RCT2_GLOBAL(0x9ADAF0, uint32) - 0xF26E; installed_entry_pointer += 4; uint8* esi = RCT2_ADDRESS(0xF42BDB, uint8); int cl = *esi++; *installed_entry_pointer++ = cl; if (cl){ memcpy(installed_entry_pointer, esi, cl*sizeof(rct_object_entry)); installed_entry_pointer += cl*sizeof(rct_object_entry); } cl = *esi++; *installed_entry_pointer++ = cl; if (cl){ memcpy(installed_entry_pointer, esi, cl*sizeof(rct_object_entry)); installed_entry_pointer += cl*sizeof(rct_object_entry); } *((uint32*)installed_entry_pointer) = RCT2_GLOBAL(0xF433DD, uint32); installed_entry_pointer += 4; int size_of_object = installed_entry_pointer - RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, uint8*) - current_item_offset; object_unload(entry->flags & 0xF, (rct_object_entry_extended*)entry); // Return pointer to start of entry installed_entry_pointer -= size_of_object; uint8* copied_entry = RCT2_ADDRESS(0x140E9AC, uint8); size_of_object = object_copy(copied_entry, installed_entry_pointer); RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32)--; copied_entry += sizeof(rct_object_entry); // Skip filename while (*copied_entry++); // Skip copied_entry += 4; installed_entry_pointer = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, uint8*); for (uint32 i = 0; i < RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32); ++i){ uint8* temp_installed_entry = installed_entry_pointer; temp_installed_entry += sizeof(rct_object_entry); // Skip filename while (*temp_installed_entry++); // Skip temp_installed_entry += 4; if (strcmp(temp_installed_entry, copied_entry) <= 0)break; installed_entry_pointer = (uint8*)(object_get_next((rct_object_entry*)installed_entry_pointer)); } // Difference to new location int no_bytes_to_move = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, uint8*) + current_item_offset - installed_entry_pointer; uint8* curr_location = installed_entry_pointer; uint8* move_location = installed_entry_pointer + size_of_object; if (no_bytes_to_move){ memmove(move_location, curr_location, no_bytes_to_move); } copied_entry = RCT2_ADDRESS(0x140E9AC, uint8); memcpy(installed_entry_pointer, copied_entry, size_of_object); current_item_offset += size_of_object; RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32)++; }
/* initialize modules */ int link_initall(void) { output_debug("link_initall(): link startup in progress..."); glxlink *mod; for ( mod=glxlink::get_first() ; mod!=NULL ; mod=mod->get_next() ) { LINKLIST *item; output_debug("link_initall(): setting up %s link", mod->get_target()); // set default global list (if needed) if ( mod->get_globals()==NULL ) { GLOBALVAR *var = NULL; while ( (var=global_getnext(var))!=NULL ) { if ( var->prop!=NULL && var->prop->name!=NULL ) { LINKLIST *item = mod->add_global(var->prop->name); if ( item!=NULL ) item->data = (void*)var; else output_error("link_initall(): unable to link %s", var->prop->name); } else output_warning("link_initall(): a variable property definition is null"); } } else { // link global variables for ( item=mod->get_globals() ; item!=NULL ; item=mod->get_next(item) ) { if ( strcmp(item->name,"")==0 ) continue; item->data = (void*)global_find(item->name); if ( item->data==NULL ) output_error("link_initall(target='%s'): global '%s' is not found", mod->get_target(), item->name); } } // link objects if ( mod->get_objects()==NULL ) { // set default object list OBJECT *obj = NULL; for ( obj=object_get_first() ; obj!=NULL ; obj=object_get_next(obj) ) { // add named objects LINKLIST *item = NULL; if ( obj->name!=NULL ) item = mod->add_object(obj->name); else { char id[256]; sprintf(id,"%s:%d",obj->oclass->name,obj->id); item = mod->add_object(id); } item->data = (void*)obj; } } else { LINKLIST *item; // link global variables for ( item=mod->get_objects() ; item!=NULL ; item=mod->get_next(item) ) { if ( strcmp(item->name,"")==0 ) continue; OBJECT *obj = NULL; item->data = (void*)object_find_name(item->name); if ( item->data==NULL) output_error("link_initall(target='%s'): object '%s' is not found", mod->get_target(), item->name); } } // link exports for ( item=mod->get_exports() ; item!=NULL ; item=mod->get_next(item) ) { char objname[64], propname[64], varname[64]; if ( sscanf(item->name,"%[^.].%s %s",objname,propname,varname)==3 ) { OBJECTPROPERTY *objprop = (OBJECTPROPERTY*)malloc(sizeof(OBJECTPROPERTY)); objprop->obj = object_find_name(objname); if ( objprop->obj ) { objprop->prop = class_find_property(objprop->obj->oclass,propname); if ( objprop->prop==NULL ) output_error("link_initall(target='%s'): export '%s' property not found", mod->get_target(), item->name); else { item->data = objprop; strcpy(item->name,varname); } } else output_error("link_initall(target='%s'): export '%s' object not found", mod->get_target(), item->name); } else output_error("link_initall(target='%s'): '%s' is not a valid export specification", mod->get_target(), item->name); } // link imports for ( item=mod->get_imports() ; item!=NULL ; item=mod->get_next(item) ) { char objname[64], propname[64], varname[64]; if ( sscanf(item->name,"%[^.].%s %s",objname,propname,varname)==3 ) { OBJECTPROPERTY *objprop = (OBJECTPROPERTY*)malloc(sizeof(OBJECTPROPERTY)); objprop->obj = object_find_name(objname); if ( objprop->obj ) { objprop->prop = class_find_property(objprop->obj->oclass,propname); if ( objprop->prop==NULL ) output_error("link_initall(target='%s'): import '%s' property not found", mod->get_target(), item->name); else { item->data = objprop; strcpy(item->name,varname); } } else output_error("link_initall(target='%s'): import '%s' object not found", mod->get_target(), item->name); } else output_error("link_initall(target='%s'): '%s' is not a valid import specification", mod->get_target(), item->name); } // initialize link module if ( !mod->do_init() ) { output_error("link_initall(): link startup failed"); link_termall(); return 0; } } output_debug("link_initall(): link startup done ok"); atexit((void(*)(void))link_termall); return 1; }
/** Initialize the delta mode code This call must be completed before the first call to any delta mode code. If the call fails, no delta mode code can be executed. Failure does not affect whether event mode code can run. @return SUCCESS or FAILED **/ STATUS delta_init(void) { OBJECT *obj, **pObj; char temp_name_buff[64]; unsigned int n, toprank = 0; OBJECT ***ranklist; int *rankcount; MODULE *module; clock_t t = clock(); /* count qualified modules */ for ( module=module_get_first() ; module!=NULL ; module=module_get_next(module) ) { if ( 0 != module->deltadesired ){ // this could probably be counted in module_init()... delta_modulecount++; if (profile.module_list[0]!=0) strcat(profile.module_list,","); strcat(profile.module_list,module->name); } } /* if none, stop here */ if ( delta_modulecount==0 ){ goto Success; } /* allocate memory for qualified module list */ delta_modulelist = (MODULE**)malloc(sizeof(MODULE**)*delta_modulecount); if(0 == delta_modulelist){ output_error("unable to allocate memory for deltamode module list"); /* TROUBLESHOOT Deltamode operation requires more memory than is available. Try freeing up memory by making more heap available or making the model smaller. */ return FAILED; } /* build qualified module list */ delta_modulecount = 0; global_deltamode_updateorder[0]='\0'; for ( module=module_get_first() ; module!=NULL ; module=module_get_next(module) ) { if ( 0 != module->deltadesired ) { if ( delta_modulecount>0 ) strcat(global_deltamode_updateorder,","); strcat(global_deltamode_updateorder,module->name); delta_modulelist[delta_modulecount++] = module; } } /* count qualified objects */ for ( obj=object_get_first() ; obj!=NULL ; obj=object_get_next(obj) ) { if ( obj->flags&OF_DELTAMODE ) { if ( !obj->oclass->update ) output_debug("object '%s' requested deltamode updates but the class '%s' does not export the update function", object_name(obj, temp_name_buff, 63), obj->oclass->name); delta_objectcount++; if ( obj->rank > toprank ){ toprank = obj->rank; } } } /* if none, stop here */ if ( delta_objectcount==0 ){ goto Success; } /* allocate final object list */ delta_objectlist = (OBJECT**)malloc(sizeof(OBJECT*)*delta_objectcount); if ( delta_objectlist==NULL) { output_error("unable to allocate memory for deltamode object list"); /* TROUBLESHOOT Deltamode operation requires more memory than is available. Try freeing up memory by making more heap available or making the model smaller. */ return FAILED; } /* allocate rank lists */ ranklist = (OBJECT***)malloc(sizeof(OBJECT**)*(toprank+1)); if ( 0 == ranklist ){ output_error("unable to allocate memory for deltamode ranklist"); /* TROUBLESHOOT Deltamode operation requires more memory than is available. Try freeing up memory by making more heap available or making the model smaller. */ return FAILED; } memset(ranklist,0,sizeof(OBJECT**)*(toprank+1)); /* allocate rank counts */ rankcount = (int*)malloc(sizeof(int)*(toprank+1)); if ( 0 == rankcount ){ output_error("unable to allocate memory for deltamode rankcount"); /* TROUBLESHOOT Deltamode operation requires more memory than is available. Try freeing up memory by making more heap available or making the model smaller. */ return FAILED; } memset(rankcount,0,sizeof(int)*(toprank+1)); /* count qualified objects in each rank */ for ( obj=object_get_first() ; obj!=NULL ; obj=object_get_next(obj) ) { if ( obj->flags&OF_DELTAMODE ){ rankcount[obj->rank]++; } } /* allocate rank lists */ for ( n=0 ; n<=toprank ; n++) { if ( rankcount[n]>0 ) { ranklist[n] = (OBJECT**)malloc(sizeof(OBJECT*)*rankcount[n]); if ( !ranklist[n] ){ output_error("unable to allocate memory for deltamode rankcount %i", n); /* TROUBLESHOOT Deltamode operation requires more memory than is available. Try freeing up memory by making more heap available or making the model smaller. */ return FAILED; } rankcount[n] = 0; /* clear for index recount */ } else ranklist[n] = NULL; } /* assign qualified objects to rank lists */ for ( obj=object_get_first() ; obj!=NULL ; obj=object_get_next(obj) ) { if ( obj->flags&OF_DELTAMODE ){ ranklist[obj->rank][rankcount[obj->rank]++] = obj; } } /* build final object list */ pObj = delta_objectlist; for ( n=0 ; n<=toprank ; n++) { int m; for ( m=0 ; m<rankcount[n] ; m++ ){ *pObj++ = ranklist[n][m]; } if ( ranklist[n]!=NULL ){ free(ranklist[n]); ranklist[n] = NULL; } } /* release memory */ free(rankcount); rankcount = NULL; free(ranklist); ranklist = NULL; Success: profile.t_init += clock() - t; return SUCCESS; }
/** * * rct2: 0x006AADA3 */ static void window_editor_object_selection_scrollpaint() { int x, y, i, colour, colour2, numObjects, type; short scrollIndex; rct_object_entry *entry; rct_object_filters *filter; rct_window *w; rct_drawpixelinfo *dpi; uint8 *itemFlags; uint8 source; window_scrollpaint_get_registers(w, dpi, scrollIndex); colour = RCT2_ADDRESS(0x0141FC48, uint8)[w->colours[1] * 8]; colour = (colour << 24) | (colour << 16) | (colour << 8) | colour; gfx_clear(dpi, colour); numObjects = RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, sint32); entry = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, rct_object_entry*); itemFlags = RCT2_GLOBAL(0x009ADAEC, uint8*); y = 0; for (i = 0; i < numObjects; i++) { filter = get_object_filter(i); type = entry->flags & 0x0F; source = (entry->flags & 0xF0) >> 4; if (type == w->selected_tab && !(*itemFlags & 0x20) && filter_source(entry) && filter_string(entry) && filter_chunks(entry, filter)) { if (y + 12 >= dpi->y && y <= dpi->y + dpi->height) { // Draw checkbox if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER) && !(*itemFlags & 0x20)) gfx_fill_rect_inset(dpi, 2, y, 11, y + 10, w->colours[1], 0xE0); // Highlight background colour = 142; if (entry == (rct_object_entry*)w->var_494 && !(*itemFlags & 0x20)) { gfx_fill_rect(dpi, 0, y, w->width, y + 11, 0x2000031); colour = 14; } // Draw checkmark if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER) && (*itemFlags & 1)) { x = 2; RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, sint16) = colour == 14 ? -2 : -1; colour2 = w->colours[1] & 0x7F; if (*itemFlags & 0x1C) colour2 |= 0x40; gfx_draw_string(dpi, (char*)0x009DED72, colour2, x, y); } // Draw text char *buffer = (char*)0x0141ED68; *buffer = colour; strcpy(buffer + 1, object_get_name(entry)); if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER) { while (*buffer != 0 && *buffer != 9) buffer++; *buffer = 0; } if (*itemFlags & 0x20) { colour = w->colours[1] & 0x7F; RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, sint16) = -1; } else { colour = 0; RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, sint16) = 224; } x = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER ? 0 : 15; gfx_draw_string(dpi, (char*)0x0141ED68, colour, x, y); } y += 12; } entry = object_get_next(entry); itemFlags++; } }