33#include "table/strings.h"
74#define MKCOLOUR(x) TO_LE32(x)
81PACK(
struct BitmapFileHeader {
87static_assert(
sizeof(BitmapFileHeader) == 14);
92 int32_t width, height;
93 uint16_t planes, bitcount;
94 uint32_t compression, sizeimage, xpels, ypels, clrused, clrimp;
100 uint8_t blue, green, red, reserved;
102static_assert(
sizeof(
RgbQuad) == 4);
119 switch (pixelformat) {
120 case 8: bpp = 1;
break;
122 case 32: bpp = 3;
break;
124 default:
return false;
128 if (!of.has_value())
return false;
132 uint bytewidth =
Align(w * bpp, 4);
135 uint pal_size = pixelformat == 8 ?
sizeof(
RgbQuad) * 256 : 0;
138 BitmapFileHeader bfh;
139 bfh.type = TO_LE16(
'MB');
140 bfh.size = TO_LE32(
sizeof(BitmapFileHeader) +
sizeof(
BitmapInfoHeader) + pal_size +
static_cast<size_t>(bytewidth) * h);
142 bfh.off_bits = TO_LE32(
sizeof(BitmapFileHeader) +
sizeof(
BitmapInfoHeader) + pal_size);
147 bih.width = TO_LE32(w);
148 bih.height = TO_LE32(h);
149 bih.planes = TO_LE16(1);
150 bih.bitcount = TO_LE16(bpp * 8);
159 if (fwrite(&bfh,
sizeof(bfh), 1, f) != 1 || fwrite(&bih,
sizeof(bih), 1, f) != 1) {
163 if (pixelformat == 8) {
166 for (uint i = 0; i < 256; i++) {
167 rq[i].red = palette[i].r;
168 rq[i].green = palette[i].g;
169 rq[i].blue = palette[i].b;
173 if (fwrite(rq,
sizeof(rq), 1, f) != 1) {
179 uint maxlines =
Clamp(65536 / (w * pixelformat / 8), 16, 128);
181 std::vector<uint8_t> buff(maxlines * w * pixelformat / 8);
182 std::vector<uint8_t> line(bytewidth);
186 uint n = std::min(h, maxlines);
190 callb(userdata, buff.data(), h, w, n);
194 if (pixelformat == 8) {
196 memcpy(line.data(), buff.data() + n * w, w);
200 Colour *src = ((Colour *)buff.data()) + n * w;
201 uint8_t *dst = line.data();
202 for (uint i = 0; i < w; i++) {
203 dst[i * 3 ] = src[i].b;
204 dst[i * 3 + 1] = src[i].g;
205 dst[i * 3 + 2] = src[i].r;
209 if (fwrite(line.data(), bytewidth, 1, f) != 1) {
225#ifdef PNG_TEXT_SUPPORTED
233static void PNGAPI png_my_error(png_structp png_ptr, png_const_charp message)
235 Debug(misc, 0,
"[libpng] error: {} - {}", message, (
const char *)png_get_error_ptr(png_ptr));
236 longjmp(png_jmpbuf(png_ptr), 1);
239static void PNGAPI png_my_warning(png_structp png_ptr, png_const_charp message)
241 Debug(misc, 1,
"[libpng] warning: {} - {}", message, (
const char *)png_get_error_ptr(png_ptr));
261 uint bpp = pixelformat / 8;
266 if (pixelformat != 8 && pixelformat != 32)
return false;
269 if (!of.has_value())
return false;
272 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
const_cast<char *
>(name), png_my_error, png_my_warning);
274 if (png_ptr ==
nullptr) {
278 info_ptr = png_create_info_struct(png_ptr);
279 if (info_ptr ==
nullptr) {
280 png_destroy_write_struct(&png_ptr, (png_infopp)
nullptr);
284 if (setjmp(png_jmpbuf(png_ptr))) {
285 png_destroy_write_struct(&png_ptr, &info_ptr);
289 png_init_io(png_ptr, f);
291 png_set_filter(png_ptr, 0, PNG_FILTER_NONE);
293 png_set_IHDR(png_ptr, info_ptr, w, h, 8, pixelformat == 8 ? PNG_COLOR_TYPE_PALETTE : PNG_COLOR_TYPE_RGB,
294 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
296#ifdef PNG_TEXT_SUPPORTED
299 png_text_struct text[2];
300 memset(text, 0,
sizeof(text));
301 text[0].key =
const_cast<char *
>(
"Software");
302 text[0].text =
const_cast<char *
>(_openttd_revision);
303 text[0].text_length = strlen(_openttd_revision);
304 text[0].compression = PNG_TEXT_COMPRESSION_NONE;
307 message.reserve(1024);
309 message +=
"NewGRFs:\n";
310 if (_game_mode != GM_MENU) {
312 fmt::format_to(std::back_inserter(message),
"{:08X} {} {}\n", std::byteswap(c->ident.grfid),
FormatArrayAsHex(c->ident.md5sum), c->filename);
315 message +=
"\nCompanies:\n";
317 if (c->ai_info ==
nullptr) {
318 fmt::format_to(std::back_inserter(message),
"{:2d}: Human\n", (
int)c->index);
320 fmt::format_to(std::back_inserter(message),
"{:2d}: {} (v{})\n", (
int)c->index, c->ai_info->GetName(), c->ai_info->GetVersion());
323 text[1].key =
const_cast<char *
>(
"Description");
324 text[1].text =
const_cast<char *
>(message.c_str());
325 text[1].text_length = message.size();
326 text[1].compression = PNG_TEXT_COMPRESSION_zTXt;
327 png_set_text(png_ptr, info_ptr, text, 2);
330 if (pixelformat == 8) {
332 for (i = 0; i != 256; i++) {
333 rq[i].red = palette[i].r;
334 rq[i].green = palette[i].g;
335 rq[i].blue = palette[i].b;
338 png_set_PLTE(png_ptr, info_ptr, rq, 256);
341 png_write_info(png_ptr, info_ptr);
342 png_set_flush(png_ptr, 512);
344 if (pixelformat == 32) {
353 png_set_sBIT(png_ptr, info_ptr, &sig_bit);
355 if constexpr (std::endian::native == std::endian::little) {
356 png_set_bgr(png_ptr);
357 png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
359 png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
364 maxlines =
Clamp(65536 / w, 16, 128);
367 std::vector<uint8_t> buff(
static_cast<size_t>(w) * maxlines * bpp);
372 n = std::min(h - y, maxlines);
375 callb(userdata, buff.data(), y, w, n);
379 for (i = 0; i != n; i++) {
380 png_write_row(png_ptr, (png_bytep)buff.data() + i * w * bpp);
384 png_write_end(png_ptr, info_ptr);
385 png_destroy_write_struct(&png_ptr, &info_ptr);
398 uint8_t manufacturer;
405 uint8_t pal_small[16 * 3];
435 if (pixelformat == 32) {
436 Debug(misc, 0,
"Can't convert a 32bpp screenshot to PCX format. Please pick another format.");
439 if (pixelformat != 8 || w == 0)
return false;
442 if (!of.has_value())
return false;
445 memset(&pcx, 0,
sizeof(pcx));
448 pcx.manufacturer = 10;
452 pcx.xmax = TO_LE16(w - 1);
453 pcx.ymax = TO_LE16(h - 1);
454 pcx.hdpi = TO_LE16(320);
455 pcx.vdpi = TO_LE16(320);
458 pcx.cpal = TO_LE16(1);
459 pcx.width = pcx.pitch = TO_LE16(w);
460 pcx.height = TO_LE16(h);
463 if (fwrite(&pcx,
sizeof(pcx), 1, f) != 1) {
468 maxlines =
Clamp(65536 / w, 16, 128);
471 std::vector<uint8_t> buff(
static_cast<size_t>(w) * maxlines);
476 uint n = std::min(h - y, maxlines);
480 callb(userdata, buff.data(), y, w, n);
484 for (i = 0; i != n; i++) {
485 const uint8_t *bufp = buff.data() + i * w;
486 uint8_t runchar = bufp[0];
491 for (j = 1; j < w; j++) {
492 uint8_t ch = bufp[j];
494 if (ch != runchar || runcount >= 0x3f) {
495 if (runcount > 1 || (runchar & 0xC0) == 0xC0) {
496 if (fputc(0xC0 | runcount, f) == EOF) {
500 if (fputc(runchar, f) == EOF) {
510 if (runcount > 1 || (runchar & 0xC0) == 0xC0) {
511 if (fputc(0xC0 | runcount, f) == EOF) {
515 if (fputc(runchar, f) == EOF) {
522 if (fputc(12, f) == EOF) {
527 uint8_t tmp[256 * 3];
529 for (uint i = 0; i < 256; i++) {
530 tmp[i * 3 + 0] = palette[i].r;
531 tmp[i * 3 + 1] = palette[i].g;
532 tmp[i * 3 + 2] = palette[i].b;
534 success = fwrite(tmp,
sizeof(tmp), 1, f) == 1;
558 return _cur_screenshot_format->
extension;
566 _cur_screenshot_format = &format;
581 void *src = blitter->
MoveTo(_screen.dst_ptr, 0, y);
603 _screen.dst_ptr = buf;
604 _screen.width = pitch;
606 _screen.pitch = pitch;
613 dpi.width = vp->
width;
621 while (vp->
width - left != 0) {
622 wx = std::min(vp->
width - left, 1600);
634 _screen = old_screen;
669 for (uint serial = 1;; serial++) {
672 if (!generate)
break;
701 assert(width == 0 && height == 0);
712 vp->
width = _screen.width;
713 vp->
height = _screen.height;
718 assert(width == 0 && height == 0);
741 vp->overlay =
nullptr;
751 if (width == 0 || height == 0) {
764 vp->overlay =
nullptr;
795 uint8_t *buf = (uint8_t *)buffer;
816 for (uint i = 0; i <
lengthof(palette); i++) {
858 if (width * height > 8192 * 8192) {
968static void MinimapScreenCallback(
void *,
void *buf, uint y, uint pitch, uint n)
970 uint32_t *ubuf = (uint32_t *)buf;
971 uint num = (pitch * n);
972 for (uint i = 0; i < num; i++) {
973 uint row = y + (int)(i / pitch);
979 uint32_t colour_buf = 0;
AIInfo keeps track of all information of an AI, like Author, Description, ...
Class for backupping variables and making sure they are restored later.
static Blitter * GetCurrentBlitter()
Get the current active blitter (always set by calling SelectBlitter).
How all blitters should look like.
virtual void * MoveTo(void *video, int x, int y)=0
Move the destination pointer the requested amount x and y, keeping in mind any pitch and bpp of the r...
virtual uint8_t GetScreenDepth()=0
Get the screen depth this blitter works for.
virtual void CopyImageToBuffer(const void *video, void *dst, int width, int height, int dst_pitch)=0
Copy from the screen to a buffer in a palette format for 8bpp and RGBA format for 32bpp.
static std::optional< FileHandle > Open(const std::string &filename, const std::string &mode)
Open an RAII file handle if possible.
void QueueOnMainThread(std::function< void()> &&func)
Queue a function to be called on the main thread with game state lock held and video buffer locked.
static VideoDriver * GetInstance()
Get the currently active instance of the video driver.
Definition of stuff that is very close to a company, like the company struct itself.
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Functions related to companies.
@ COMPANY_SPECTATOR
The client is spectating.
#define Debug(category, level, format_string,...)
Ouptut a line of debugging information.
Function to handling different endian machines.
Functions related to errors.
@ WL_WARNING
Other information.
@ WL_ERROR
Errors (eg. saving/loading failed)
void ShowErrorMessage(StringID summary_msg, int x, int y, CommandCost cc)
Display an error message in a window.
Factory to 'query' all available blitters.
std::string _personal_dir
custom directory for personal settings, saves, newgrf, etc.
bool FileExists(const std::string &filename)
Test whether the given filename exists.
Functions for Standard In/Out file operations.
const char * FiosGetScreenshotDir()
Get the directory for screenshots.
bool _screen_disable_anim
Disable palette animation (important for 32bpp-anim blitter during giant screenshot)
Functions related to the gfx engine.
Palette _cur_palette
Current palette.
void DrawDirtyBlocks()
Repaints the rectangle blocks which are marked as 'dirty'.
Functions related to OTTD's landscape.
Point RemapCoords(int x, int y, int z)
Map 3D world or tile coordinate to equivalent 2D coordinate as used in the viewports and smallmap.
TileIndex TileAddXY(TileIndex tile, int x, int y)
Adds a given offset to a tile.
static debug_inline TileIndex TileXY(uint x, uint y)
Returns the TileIndex of a coordinate.
static debug_inline uint TileY(TileIndex tile)
Get the Y component of a tile.
static debug_inline uint TileX(TileIndex tile)
Get the X component of a tile.
constexpr T Align(const T x, uint n)
Return the smallest multiple of n equal or greater than x.
constexpr T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
void ShowQuery(StringID caption, StringID message, Window *parent, QueryCallbackProc *callback, bool focus)
Show a confirmation window with standard 'yes' and 'no' buttons The window is aligned to the centre o...
GRFConfigList _grfconfig
First item in list of current GRF set up.
Functions to find and configure NewGRFs.
declaration of OTTD revision dependent variables
A number of safeguards to prevent using unsafe methods.
std::string GenerateDefaultSaveName()
Get the default name for a savegame or screenshot.
Functions/types related to saving and loading games.
static void CurrentScreenCallback(void *, void *buf, uint y, uint pitch, uint n)
Callback of the screenshot generator that dumps the current video buffer.
const char * GetCurrentScreenshotExtension()
Get filename extension of current screenshot file format.
static void ScreenshotConfirmationCallback(Window *, bool confirmed)
Callback on the confirmation window for huge screenshots.
void ScreenshotCallback(void *userdata, void *buf, uint y, uint pitch, uint n)
Callback function signature for generating lines of pixel data to be written to the screenshot file.
void MakeScreenshotWithConfirm(ScreenshotType t)
Make a screenshot.
static ScreenshotType _confirmed_screenshot_type
Screenshot type the current query is about to confirm.
std::string _screenshot_format_name
Extension of the current screenshot format (corresponds with _cur_screenshot_format).
static bool MakeBMPImage(const char *name, ScreenshotCallback *callb, void *userdata, uint w, uint h, int pixelformat, const Colour *palette)
Generic .BMP writer.
static bool MakeSmallScreenshot(bool crashlog)
Make a screenshot of the current screen.
static void HeightmapCallback(void *, void *buffer, uint y, uint, uint n)
Callback for generating a heightmap.
bool MakeHeightmapScreenshot(const char *filename)
Make a heightmap of the current map.
static const char *const SCREENSHOT_NAME
Default filename of a saved screenshot.
void InitializeScreenshotFormats()
Initialize screenshot format information on startup, with _screenshot_format_name filled from the loa...
bool MakeMinimapWorldScreenshot()
Make a minimap screenshot.
static bool RealMakeScreenshot(ScreenshotType t, std::string name, uint32_t width, uint32_t height)
Make a screenshot.
static bool MakeLargeWorldScreenshot(ScreenshotType t, uint32_t width=0, uint32_t height=0)
Make a screenshot of the map.
static std::string _screenshot_name
Filename of the screenshot file.
bool MakeScreenshot(ScreenshotType t, std::string name, uint32_t width, uint32_t height)
Schedule making a screenshot.
void SetupScreenshotViewport(ScreenshotType t, Viewport *vp, uint32_t width, uint32_t height)
Configure a Viewport for rendering (a part of) the map into a screenshot.
static bool MakePNGImage(const char *name, ScreenshotCallback *callb, void *userdata, uint w, uint h, int pixelformat, const Colour *palette)
Generic .PNG file image writer.
std::string _full_screenshot_path
Pathname of the screenshot file.
static void LargeWorldCallback(void *userdata, void *buf, uint y, uint pitch, uint n)
generate a large piece of the world
static const ScreenshotFormat _screenshot_formats[]
Available screenshot formats.
static bool MakePCXImage(const char *name, ScreenshotCallback *callb, void *userdata, uint w, uint h, int pixelformat, const Colour *palette)
Generic .PCX file image writer.
static const char *const HEIGHTMAP_NAME
Default filename of a saved heightmap.
uint _heightmap_highest_peak
When saving a heightmap, this contains the highest peak on the map.
bool ScreenshotHandlerProc(const char *name, ScreenshotCallback *callb, void *userdata, uint w, uint h, int pixelformat, const Colour *palette)
Function signature for a screenshot generation routine for one of the available formats.
static const char * MakeScreenshotName(const char *default_fn, const char *ext, bool crashlog=false)
Construct a pathname for a screenshot file.
Functions to make screenshots.
ScreenshotType
Type of requested screenshot.
@ SC_VIEWPORT
Screenshot of viewport.
@ SC_CRASHLOG
Raw screenshot from blitter buffer.
@ SC_ZOOMEDIN
Fully zoomed in screenshot of the visible area.
@ SC_HEIGHTMAP
Heightmap of the world.
@ SC_WORLD
World screenshot.
@ SC_MINIMAP
Minimap screenshot.
@ SC_DEFAULTZOOM
Zoomed to default zoom level screenshot of the visible area.
void SetScreenshotWindowVisibility(bool hide)
Set the visibility of the screenshot window when taking a screenshot.
GUI functions related to screenshots.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
ClientSettings _settings_client
The current settings for this game.
uint32_t GetSmallMapOwnerPixels(TileIndex tile, TileType t, IncludeHeightmap include_heightmap)
Return the colour a tile would be displayed with in the small map in mode "Owner".
@ Never
Never include the heightmap.
Definition of base types and functions in a cross-platform compatible way.
#define lengthof(array)
Return the length of an fixed size array.
std::string FormatArrayAsHex(std::span< const uint8_t > data)
Format a byte array into a continuous hex string.
void SetDParam(size_t n, uint64_t v)
Set a string parameter v at index n in the global string parameter array.
void SetDParamStr(size_t n, const char *str)
This function is used to "bind" a C string to a OpenTTD dparam slot.
Functions related to OTTD's strings.
static const StringID INVALID_STRING_ID
Constant representing an invalid string (16bit in case it is used in savegames)
Class to backup a specific variable and restore it upon destruction of this object to prevent stack v...
GUISettings gui
settings related to the GUI
bool freeform_edges
allow terraforming the tiles at the map edges
Data about how and where to blit pixels.
ZoomLevel zoom_min
minimum zoom out level
ConstructionSettings construction
construction of things in-game
static uint SizeY()
Get the size of the map along the Y.
static IterateWrapper Iterate()
Returns an iterable ensemble of all Tiles.
static debug_inline uint SizeX()
Get the size of the map along the X.
static debug_inline uint Size()
Get the size of the map.
static debug_inline uint MaxX()
Gets the maximum X coordinate within the map, including MP_VOID.
Colour palette[256]
Current palette. Entry 0 has to be always fully transparent!
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
Format of palette data in BMP header.
Helper struct to ensure the video buffer is locked and ready for drawing.
Data structure for viewport, display of a part of the world.
int top
Screen coordinate top edge of the viewport.
int width
Screen width of the viewport.
ZoomLevel zoom
The zoom level of the viewport.
int virtual_top
Virtual top coordinate.
int virtual_left
Virtual left coordinate.
int virtual_width
width << zoom
int left
Screen coordinate left edge of the viewport.
int height
Screen height of the viewport.
int virtual_height
height << zoom
Data structure for an opened window.
ViewportData * viewport
Pointer to viewport data, if present.
Stuff related to the text buffer GUI.
Map writing/reading functions for tiles.
static debug_inline TileType GetTileType(Tile tile)
Get the tiletype of a given tile.
uint TilePixelHeight(Tile tile)
Returns the height of a tile in pixels.
static debug_inline uint TileHeight(Tile tile)
Returns the height of a tile.
static const uint TILE_SIZE
Tile size in world coordinates.
Base of all video drivers.
Functions related to (drawing on) viewports.
std::mutex lock
synchronization for playback status fields
Window * GetMainWindow()
Get the main window, i.e.
Window functions not directly related to making/drawing windows.
Functions, definitions and such used only by the GUI.
Functions related to zooming.
int ScaleByZoom(int value, ZoomLevel zoom)
Scale by zoom level, usually shift left (when zoom > ZOOM_LVL_MIN) When shifting right,...
int UnScaleByZoom(int value, ZoomLevel zoom)
Scale by zoom level, usually shift right (when zoom > ZOOM_LVL_MIN) When shifting right,...
@ ZOOM_LVL_WORLD_SCREENSHOT
Default zoom level for the world screen shot.
@ ZOOM_LVL_VIEWPORT
Default zoom level for viewports.