/** * Resizes the pool so 'index' can be addressed * @param index index we will allocate later * @pre index >= this->size * @pre index < Tmax_size */ DEFINE_POOL_METHOD(inline void)::ResizeFor(size_t index) { assert(index >= this->size); assert(index < Tmax_size); size_t new_size = ::min(Tmax_size, Align(index + 1, Tgrowth_step)); this->data = ReallocT(this->data, new_size); MemSetT(this->data + this->size, 0, new_size - this->size); this->size = new_size; }
/** * Begin a paste process. * @param flags Flags for the command. * @param params What, where and how to paste. */ static void InitializePasting(DoCommandFlag flags, const CopyPasteParams ¶ms) { assert(_current_pasting == NULL); _current_pasting = new PastingState; _current_pasting->dc_flags = flags | DC_PASTE; _current_pasting->overal_cost = 0; _current_pasting->had_success = false; _current_pasting->err_summary = STR_ERROR_CAN_T_PASTE_HERE; _current_pasting->err_message = STR_ERROR_NOTHING_TO_DO; MemSetT(_current_pasting->err_params, 0, lengthof(_current_pasting->err_params)); _current_pasting->err_tile = INVALID_TILE; _current_pasting->last_result = CommandCost(STR_ERROR_NOTHING_TO_DO); }
/** * Save a custom playlist to settings after modification. * @param pl Playlist to store back */ void MusicSystem::SaveCustomPlaylist(PlaylistChoices pl) { byte *settings_pl; if (pl == PLCH_CUSTOM1) { settings_pl = _settings_client.music.custom_1; } else if (pl == PLCH_CUSTOM2) { settings_pl = _settings_client.music.custom_2; } else { return; } size_t num = 0; MemSetT(settings_pl, 0, NUM_SONGS_PLAYLIST); for (Playlist::const_iterator song = this->standard_playlists[pl].begin(); song != this->standard_playlists[pl].end(); ++song) { /* Music set indices in the settings playlist are 1-based, 0 means unused slot */ settings_pl[num++] = (byte)song->set_index + 1; } }
/** * Makes given index valid * @param size size of item * @param index index of item * @pre index < this->size * @pre this->Get(index) == NULL */ DEFINE_POOL_METHOD(inline void *)::AllocateItem(size_t size, size_t index) { assert(this->data[index] == NULL); this->first_unused = ::max(this->first_unused, index + 1); this->items++; Titem *item; if (Tcache && this->alloc_cache != NULL) { assert(sizeof(Titem) == size); item = (Titem *)this->alloc_cache; this->alloc_cache = this->alloc_cache->next; if (Tzero) MemSetT(item, 0); } else if (Tzero) { item = (Titem *)CallocT<byte>(size); } else { item = (Titem *)MallocT<byte>(size); } this->data[index] = item; item->index = (uint)index; return item; }
void DisplaySplashImage() { FILE *f = FioFOpenFile(SPLASH_IMAGE_FILE); if (f == NULL) return; png_byte header[8]; fread(header, sizeof(png_byte), 8, f); if (png_sig_cmp(header, 0, 8) != 0) { fclose(f); return; } png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp) NULL, png_my_error, png_my_warning); if (png_ptr == NULL) { fclose(f); return; } png_infop info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); fclose(f); return; } png_infop end_info = png_create_info_struct(png_ptr); if (end_info == NULL) { png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); fclose(f); return; } if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(f); return; } png_init_io(png_ptr, f); png_set_sig_bytes(png_ptr, 8); png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); uint width = png_get_image_width(png_ptr, info_ptr); uint height = png_get_image_height(png_ptr, info_ptr); uint bit_depth = png_get_bit_depth(png_ptr, info_ptr); uint color_type = png_get_color_type(png_ptr, info_ptr); if (color_type != PNG_COLOR_TYPE_PALETTE || bit_depth != 8) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(f); return; } if (!png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE)) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(f); return; } png_colorp palette; int num_palette; png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette); png_bytep *row_pointers = png_get_rows(png_ptr, info_ptr); if (width > (uint) _screen.width) width = _screen.width; if (height > (uint) _screen.height) height = _screen.height; uint xoff = (_screen.width - width) / 2; uint yoff = (_screen.height - height) / 2; switch (BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth()) { case 8: { uint8 *dst_ptr = (uint8 *)_screen.dst_ptr; /* Initialize buffer */ MemSetT(dst_ptr, 0xff, _screen.pitch * _screen.height); for (uint y = 0; y < height; y++) { uint8 *src = row_pointers[y]; uint8 *dst = dst_ptr + (yoff + y) * _screen.pitch + xoff; memcpy(dst, src, width); } for (int i = 0; i < num_palette; i++) { _cur_palette[i].a = i == 0 ? 0 : 0xff; _cur_palette[i].r = palette[i].red; _cur_palette[i].g = palette[i].green; _cur_palette[i].b = palette[i].blue; } _cur_palette[0xff].a = 0xff; _cur_palette[0xff].r = 0; _cur_palette[0xff].g = 0; _cur_palette[0xff].b = 0; _pal_first_dirty = 0; _pal_count_dirty = 256; break; } case 32: { uint32 *dst_ptr = (uint32 *)_screen.dst_ptr; /* Initialize buffer */ MemSetT(dst_ptr, 0, _screen.pitch * _screen.height); for (uint y = 0; y < height; y++) { uint8 *src = row_pointers[y]; uint32 *dst = dst_ptr + (yoff + y) * _screen.pitch + xoff; for (uint x = 0; x < width; x++) { dst[x] = palette[src[x]].blue | (palette[src[x]].green << 8) | (palette[src[x]].red << 16) | 0xff000000; } } break; } } png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(f); return; }
/** * Save the Ini file's data to the disk. * @param filename the file to save to. * @return true if saving succeeded. */ bool IniFile::SaveToDisk(const char *filename) { /* * First write the configuration to a (temporary) file and then rename * that file. This to prevent that when OpenTTD crashes during the save * you end up with a truncated configuration file. */ char file_new[MAX_PATH]; strecpy(file_new, filename, lastof(file_new)); strecat(file_new, ".new", lastof(file_new)); FILE *f = fopen(file_new, "w"); if (f == NULL) return false; for (const IniGroup *group = this->group; group != NULL; group = group->next) { if (group->comment) fputs(group->comment, f); fprintf(f, "[%s]\n", group->name); for (const IniItem *item = group->item; item != NULL; item = item->next) { if (item->comment != NULL) fputs(item->comment, f); /* protect item->name with quotes if needed */ if (strchr(item->name, ' ') != NULL || item->name[0] == '[') { fprintf(f, "\"%s\"", item->name); } else { fprintf(f, "%s", item->name); } fprintf(f, " = %s\n", item->value == NULL ? "" : item->value); } } if (this->comment) fputs(this->comment, f); /* * POSIX (and friends) do not guarantee that when a file is closed it is * flushed to the disk. So we manually flush it do disk if we have the * APIs to do so. We only need to flush the data as the metadata itself * (modification date etc.) is not important to us; only the real data is. */ #ifdef WITH_FDATASYNC int ret = fdatasync(fileno(f)); fclose(f); if (ret != 0) return false; #else fclose(f); #endif #if defined(WIN32) || defined(WIN64) /* _tcsncpy = strcpy is TCHAR is char, but isn't when TCHAR is wchar. */ #undef strncpy /* Allocate space for one more \0 character. */ TCHAR tfilename[MAX_PATH + 1], tfile_new[MAX_PATH + 1]; _tcsncpy(tfilename, OTTD2FS(filename), MAX_PATH); _tcsncpy(tfile_new, OTTD2FS(file_new), MAX_PATH); /* SHFileOperation wants a double '\0' terminated string. */ tfilename[MAX_PATH - 1] = '\0'; tfile_new[MAX_PATH - 1] = '\0'; tfilename[_tcslen(tfilename) + 1] = '\0'; tfile_new[_tcslen(tfile_new) + 1] = '\0'; /* Rename file without any user confirmation. */ SHFILEOPSTRUCT shfopt; MemSetT(&shfopt, 0); shfopt.wFunc = FO_MOVE; shfopt.fFlags = FOF_NOCONFIRMATION | FOF_NOCONFIRMMKDIR | FOF_NOERRORUI | FOF_SILENT; shfopt.pFrom = tfile_new; shfopt.pTo = tfilename; SHFileOperation(&shfopt); #else if (rename(file_new, filename) < 0) { DEBUG(misc, 0, "Renaming %s to %s failed; configuration not saved", file_new, filename); } #endif return true; }
/** * Additional map variety is provided by applying different curve maps * to different parts of the map. A randomized low resolution grid contains * which curve map to use on each part of the make. This filtered non-linearly * to smooth out transitions between curves, so each tile could have between * 100% of one map applied or 25% of four maps. * * The curve maps define different land styles, i.e. lakes, low-lands, hills * and mountain ranges, although these are dependent on the landscape style * chosen as well. * * The level parameter dictates the resolution of the grid. A low resolution * grid will result in larger continuous areas of a land style, a higher * resolution grid splits the style into smaller areas. * @param level Rough indication of the size of the grid sections to style. Small level means large grid sections. */ static void HeightMapCurves(uint level) { height_t mh = TGPGetMaxHeight() - I2H(1); // height levels above sea level only /** Basically scale height X to height Y. Everything in between is interpolated. */ struct control_point_t { height_t x; ///< The height to scale from. height_t y; ///< The height to scale to. }; /* Scaled curve maps; value is in height_ts. */ #define F(fraction) ((height_t)(fraction * mh)) const control_point_t curve_map_1[] = { { F(0.0), F(0.0) }, { F(0.8), F(0.13) }, { F(1.0), F(0.4) } }; const control_point_t curve_map_2[] = { { F(0.0), F(0.0) }, { F(0.53), F(0.13) }, { F(0.8), F(0.27) }, { F(1.0), F(0.6) } }; const control_point_t curve_map_3[] = { { F(0.0), F(0.0) }, { F(0.53), F(0.27) }, { F(0.8), F(0.57) }, { F(1.0), F(0.8) } }; const control_point_t curve_map_4[] = { { F(0.0), F(0.0) }, { F(0.4), F(0.3) }, { F(0.7), F(0.8) }, { F(0.92), F(0.99) }, { F(1.0), F(0.99) } }; #undef F /** Helper structure to index the different curve maps. */ struct control_point_list_t { size_t length; ///< The length of the curve map. const control_point_t *list; ///< The actual curve map. }; const control_point_list_t curve_maps[] = { { lengthof(curve_map_1), curve_map_1 }, { lengthof(curve_map_2), curve_map_2 }, { lengthof(curve_map_3), curve_map_3 }, { lengthof(curve_map_4), curve_map_4 }, }; height_t ht[lengthof(curve_maps)]; MemSetT(ht, 0, lengthof(ht)); /* Set up a grid to choose curve maps based on location; attempt to get a somewhat square grid */ float factor = sqrt((float)_height_map.size_x / (float)_height_map.size_y); uint sx = Clamp((int)(((1 << level) * factor) + 0.5), 1, 128); uint sy = Clamp((int)(((1 << level) / factor) + 0.5), 1, 128); byte *c = AllocaM(byte, sx * sy); for (uint i = 0; i < sx * sy; i++) { c[i] = Random() % lengthof(curve_maps); } /* Apply curves */ for (int x = 0; x < _height_map.size_x; x++) { /* Get our X grid positions and bi-linear ratio */ float fx = (float)(sx * x) / _height_map.size_x + 1.0f; uint x1 = (uint)fx; uint x2 = x1; float xr = 2.0f * (fx - x1) - 1.0f; xr = sin(xr * M_PI_2); xr = sin(xr * M_PI_2); xr = 0.5f * (xr + 1.0f); float xri = 1.0f - xr; if (x1 > 0) { x1--; if (x2 >= sx) x2--; } for (int y = 0; y < _height_map.size_y; y++) { /* Get our Y grid position and bi-linear ratio */ float fy = (float)(sy * y) / _height_map.size_y + 1.0f; uint y1 = (uint)fy; uint y2 = y1; float yr = 2.0f * (fy - y1) - 1.0f; yr = sin(yr * M_PI_2); yr = sin(yr * M_PI_2); yr = 0.5f * (yr + 1.0f); float yri = 1.0f - yr; if (y1 > 0) { y1--; if (y2 >= sy) y2--; } uint corner_a = c[x1 + sx * y1]; uint corner_b = c[x1 + sx * y2]; uint corner_c = c[x2 + sx * y1]; uint corner_d = c[x2 + sx * y2]; /* Bitmask of which curve maps are chosen, so that we do not bother * calculating a curve which won't be used. */ uint corner_bits = 0; corner_bits |= 1 << corner_a; corner_bits |= 1 << corner_b; corner_bits |= 1 << corner_c; corner_bits |= 1 << corner_d; height_t *h = &_height_map.height(x, y); /* Do not touch sea level */ if (*h < I2H(1)) continue; /* Only scale above sea level */ *h -= I2H(1); /* Apply all curve maps that are used on this tile. */ for (uint t = 0; t < lengthof(curve_maps); t++) { if (!HasBit(corner_bits, t)) continue; bool found = false; const control_point_t *cm = curve_maps[t].list; for (uint i = 0; i < curve_maps[t].length - 1; i++) { const control_point_t &p1 = cm[i]; const control_point_t &p2 = cm[i + 1]; if (*h >= p1.x && *h < p2.x) { ht[t] = p1.y + (*h - p1.x) * (p2.y - p1.y) / (p2.x - p1.x); found = true; break; } } assert(found); } /* Apply interpolation of curve map results. */ *h = (height_t)((ht[corner_a] * yri + ht[corner_b] * yr) * xri + (ht[corner_c] * yri + ht[corner_d] * yr) * xr); /* Readd sea level */ *h += I2H(1); } } }
static void HeightMapCurves(uint level) { height_t ht[lengthof(_curve_maps)]; MemSetT(ht, 0, lengthof(ht)); /* Set up a grid to choose curve maps based on location */ uint sx = Clamp(1 << level, 2, 32); uint sy = Clamp(1 << level, 2, 32); byte *c = AllocaM(byte, sx * sy); for (uint i = 0; i < sx * sy; i++) { c[i] = Random() % lengthof(_curve_maps); } /* Apply curves */ for (uint x = 0; x < _height_map.size_x; x++) { /* Get our X grid positions and bi-linear ratio */ float fx = (float)(sx * x) / _height_map.size_x + 0.5f; uint x1 = (uint)fx; uint x2 = x1; float xr = 2.0f * (fx - x1) - 1.0f; xr = sin(xr * M_PI_2); xr = sin(xr * M_PI_2); xr = 0.5f * (xr + 1.0f); float xri = 1.0f - xr; if (x1 > 0) { x1--; if (x2 >= sx) x2--; } for (uint y = 0; y < _height_map.size_y; y++) { /* Get our Y grid position and bi-linear ratio */ float fy = (float)(sy * y) / _height_map.size_y + 0.5f; uint y1 = (uint)fy; uint y2 = y1; float yr = 2.0f * (fy - y1) - 1.0f; yr = sin(yr * M_PI_2); yr = sin(yr * M_PI_2); yr = 0.5f * (yr + 1.0f); float yri = 1.0f - yr; if (y1 > 0) { y1--; if (y2 >= sy) y2--; } uint corner_a = c[x1 + sx * y1]; uint corner_b = c[x1 + sx * y2]; uint corner_c = c[x2 + sx * y1]; uint corner_d = c[x2 + sx * y2]; /* Bitmask of which curve maps are chosen, so that we do not bother * calculating a curve which won't be used. */ uint corner_bits = 0; corner_bits |= 1 << corner_a; corner_bits |= 1 << corner_b; corner_bits |= 1 << corner_c; corner_bits |= 1 << corner_d; height_t *h = &_height_map.height(x, y); /* Apply all curve maps that are used on this tile. */ for (uint t = 0; t < lengthof(_curve_maps); t++) { if (!HasBit(corner_bits, t)) continue; const control_point_t *cm = _curve_maps[t].list; for (uint i = 0; i < _curve_maps[t].length - 1; i++) { const control_point_t &p1 = cm[i]; const control_point_t &p2 = cm[i + 1]; if (*h >= p1.x && *h < p2.x) { ht[t] = p1.y + (*h - p1.x) * (p2.y - p1.y) / (p2.x - p1.x); break; } } } /* Apply interpolation of curve map results. */ *h = (height_t)((ht[corner_a] * yri + ht[corner_b] * yr) * xri + (ht[corner_c] * yri + ht[corner_d] * yr) * xr); } } }
/* Allocate a new Sound */ SoundEntry *AllocateSound() { SoundEntry *sound = _sounds.Append(); MemSetT(sound, 0); return sound; }