Merge pull request #7066 from IntelOrca/refactor/memory-operations

Refactor memory operations 1
This commit is contained in:
Ted John 2018-01-26 11:41:19 +00:00 committed by GitHub
commit 8f1100c986
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 485 additions and 527 deletions

View File

@ -14,14 +14,15 @@
*****************************************************************************/ *****************************************************************************/
#pragma endregion #pragma endregion
#include <algorithm>
#include <list>
#include <vector>
#include <openrct2/common.h> #include <openrct2/common.h>
#include <SDL.h> #include <SDL.h>
#include <speex/speex_resampler.h> #include <speex/speex_resampler.h>
#include <list>
#include <openrct2/Context.h> #include <openrct2/Context.h>
#include <openrct2/core/Guard.hpp> #include <openrct2/core/Guard.hpp>
#include <openrct2/core/Math.hpp> #include <openrct2/core/Math.hpp>
#include <openrct2/core/Memory.hpp>
#include <openrct2/core/Util.hpp> #include <openrct2/core/Util.hpp>
#include <openrct2/audio/audio.h> #include <openrct2/audio/audio.h>
#include <openrct2/audio/AudioChannel.h> #include <openrct2/audio/AudioChannel.h>
@ -37,38 +38,6 @@
namespace OpenRCT2 { namespace Audio namespace OpenRCT2 { namespace Audio
{ {
struct Buffer
{
private:
void * _data = nullptr;
size_t _capacity = 0;
public:
void * GetData() const { return _data; }
void * GetData() { return _data; }
size_t GetCapacity() const { return _capacity; }
~Buffer()
{
Free();
}
void Free()
{
SafeFree(_data);
_capacity = 0;
}
void EnsureCapacity(size_t capacity)
{
if (_capacity < capacity)
{
_capacity = capacity;
_data = Memory::Reallocate(_data, capacity);
}
}
};
class AudioMixerImpl final : public IAudioMixer class AudioMixerImpl final : public IAudioMixer
{ {
private: private:
@ -86,9 +55,9 @@ namespace OpenRCT2 { namespace Audio
IAudioSource * _css1Sources[SOUND_MAXID] = { nullptr }; IAudioSource * _css1Sources[SOUND_MAXID] = { nullptr };
IAudioSource * _musicSources[PATH_ID_END] = { nullptr }; IAudioSource * _musicSources[PATH_ID_END] = { nullptr };
Buffer _channelBuffer; std::vector<uint8> _channelBuffer;
Buffer _convertBuffer; std::vector<uint8> _convertBuffer;
Buffer _effectBuffer; std::vector<uint8> _effectBuffer;
public: public:
AudioMixerImpl() AudioMixerImpl()
@ -159,9 +128,12 @@ namespace OpenRCT2 { namespace Audio
} }
// Free buffers // Free buffers
_channelBuffer.Free(); _channelBuffer.clear();
_convertBuffer.Free(); _channelBuffer.shrink_to_fit();
_effectBuffer.Free(); _convertBuffer.clear();
_convertBuffer.shrink_to_fit();
_effectBuffer.clear();
_effectBuffer.shrink_to_fit();
} }
void Lock() override void Lock() override
@ -252,7 +224,7 @@ namespace OpenRCT2 { namespace Audio
UpdateAdjustedSound(); UpdateAdjustedSound();
// Zero the output buffer // Zero the output buffer
Memory::Set(dst, 0, length); std::fill_n(dst, length, 0);
// Mix channels onto output buffer // Mix channels onto output buffer
auto it = _channels.begin(); auto it = _channels.begin();
@ -318,15 +290,15 @@ namespace OpenRCT2 { namespace Audio
// Read raw PCM from channel // Read raw PCM from channel
sint32 readSamples = (sint32)(numSamples * rate); sint32 readSamples = (sint32)(numSamples * rate);
size_t readLength = (size_t)(readSamples / cvt.len_ratio) * byteRate; size_t readLength = (size_t)(readSamples / cvt.len_ratio) * byteRate;
_channelBuffer.EnsureCapacity(readLength); _channelBuffer.resize(readLength);
size_t bytesRead = channel->Read(_channelBuffer.GetData(), readLength); size_t bytesRead = channel->Read(_channelBuffer.data(), readLength);
// Convert data to required format if necessary // Convert data to required format if necessary
void * buffer = nullptr; void * buffer = nullptr;
size_t bufferLen = 0; size_t bufferLen = 0;
if (mustConvert) if (mustConvert)
{ {
if (Convert(&cvt, _channelBuffer.GetData(), bytesRead)) if (Convert(&cvt, _channelBuffer.data(), bytesRead))
{ {
buffer = cvt.buf; buffer = cvt.buf;
bufferLen = cvt.len_cvt; bufferLen = cvt.len_cvt;
@ -338,7 +310,7 @@ namespace OpenRCT2 { namespace Audio
} }
else else
{ {
buffer = _channelBuffer.GetData(); buffer = _channelBuffer.data();
bufferLen = bytesRead; bufferLen = bytesRead;
} }
@ -352,9 +324,9 @@ namespace OpenRCT2 { namespace Audio
inRate = _format.freq; inRate = _format.freq;
outRate = _format.freq * (1 / rate); outRate = _format.freq * (1 / rate);
} }
_effectBuffer.EnsureCapacity(length); _effectBuffer.resize(length);
bufferLen = ApplyResample(channel, buffer, (sint32)(bufferLen / byteRate), numSamples, inRate, outRate); bufferLen = ApplyResample(channel, buffer, (sint32)(bufferLen / byteRate), numSamples, inRate, outRate);
buffer = _effectBuffer.GetData(); buffer = _effectBuffer.data();
} }
// Apply panning and volume // Apply panning and volume
@ -391,7 +363,7 @@ namespace OpenRCT2 { namespace Audio
resampler, resampler,
(const spx_int16_t *)srcBuffer, (const spx_int16_t *)srcBuffer,
&inLen, &inLen,
(spx_int16_t *)_effectBuffer.GetData(), (spx_int16_t *)_effectBuffer.data(),
&outLen); &outLen);
return outLen * byteRate; return outLen * byteRate;
@ -523,11 +495,11 @@ namespace OpenRCT2 { namespace Audio
if (len != 0 && cvt->len_mult != 0) if (len != 0 && cvt->len_mult != 0)
{ {
size_t reqConvertBufferCapacity = len * cvt->len_mult; size_t reqConvertBufferCapacity = len * cvt->len_mult;
_convertBuffer.EnsureCapacity(reqConvertBufferCapacity); _convertBuffer.resize(reqConvertBufferCapacity);
Memory::Copy(_convertBuffer.GetData(), src, len); std::copy_n((const uint8 *)src, len, _convertBuffer.data());
cvt->len = (sint32)len; cvt->len = (sint32)len;
cvt->buf = (uint8 *)_convertBuffer.GetData(); cvt->buf = (uint8 *)_convertBuffer.data();
if (SDL_ConvertAudio(cvt) >= 0) if (SDL_ConvertAudio(cvt) >= 0)
{ {
result = true; result = true;

View File

@ -14,10 +14,11 @@
*****************************************************************************/ *****************************************************************************/
#pragma endregion #pragma endregion
#include <algorithm>
#include <vector>
#include <openrct2/common.h> #include <openrct2/common.h>
#include <SDL.h> #include <SDL.h>
#include <openrct2/core/Math.hpp> #include <openrct2/core/Math.hpp>
#include <openrct2/core/Memory.hpp>
#include <openrct2/audio/AudioMixer.h> #include <openrct2/audio/AudioMixer.h>
#include <openrct2/audio/AudioSource.h> #include <openrct2/audio/AudioSource.h>
#include "AudioContext.h" #include "AudioContext.h"
@ -32,10 +33,15 @@ namespace OpenRCT2 { namespace Audio
class MemoryAudioSource final : public ISDLAudioSource class MemoryAudioSource final : public ISDLAudioSource
{ {
private: private:
AudioFormat _format = { 0 }; AudioFormat _format = { 0 };
uint8 * _data = nullptr; std::vector<uint8> _data;
size_t _length = 0; uint8 * _dataSDL = nullptr;
bool _isSDLWav = false; size_t _length = 0;
const uint8 * GetData()
{
return _dataSDL != nullptr ? _dataSDL : _data.data();
}
public: public:
~MemoryAudioSource() ~MemoryAudioSource()
@ -59,7 +65,12 @@ namespace OpenRCT2 { namespace Audio
if (offset < _length) if (offset < _length)
{ {
bytesToRead = (size_t)Math::Min<uint64>(len, _length - offset); bytesToRead = (size_t)Math::Min<uint64>(len, _length - offset);
Memory::Copy<void>(dst, _data + offset, bytesToRead);
auto src = GetData();
if (src != nullptr)
{
std::copy_n(src + offset, bytesToRead, (uint8 *)dst);
}
} }
return bytesToRead; return bytesToRead;
} }
@ -76,14 +87,13 @@ namespace OpenRCT2 { namespace Audio
{ {
SDL_AudioSpec audiospec = { 0 }; SDL_AudioSpec audiospec = { 0 };
uint32 audioLen; uint32 audioLen;
SDL_AudioSpec * spec = SDL_LoadWAV_RW(rw, false, &audiospec, &_data, &audioLen); SDL_AudioSpec * spec = SDL_LoadWAV_RW(rw, false, &audiospec, &_dataSDL, &audioLen);
if (spec != nullptr) if (spec != nullptr)
{ {
_format.freq = spec->freq; _format.freq = spec->freq;
_format.format = spec->format; _format.format = spec->format;
_format.channels = spec->channels; _format.channels = spec->channels;
_length = audioLen; _length = audioLen;
_isSDLWav = true;
result = true; result = true;
} }
else else
@ -129,13 +139,13 @@ namespace OpenRCT2 { namespace Audio
_format.format = AUDIO_S16LSB; _format.format = AUDIO_S16LSB;
_format.channels = waveFormat.channels; _format.channels = waveFormat.channels;
_data = new (std::nothrow) uint8[_length]; try
if (_data != nullptr)
{ {
SDL_RWread(rw, _data, _length, 1); _data.resize(_length);
SDL_RWread(rw, _data.data(), _length, 1);
result = true; result = true;
} }
else catch (const std::bad_alloc &)
{ {
log_verbose("Unable to allocate data"); log_verbose("Unable to allocate data");
} }
@ -156,21 +166,21 @@ namespace OpenRCT2 { namespace Audio
SDL_AudioCVT cvt; SDL_AudioCVT cvt;
if (SDL_BuildAudioCVT(&cvt, _format.format, _format.channels, _format.freq, format->format, format->channels, format->freq) >= 0) if (SDL_BuildAudioCVT(&cvt, _format.format, _format.channels, _format.freq, format->format, format->channels, format->freq) >= 0)
{ {
auto src = GetData();
auto cvtBuffer = std::vector<uint8>(_length * cvt.len_mult);
std::copy_n(src, _length, cvtBuffer.data());
cvt.len = (sint32)_length; cvt.len = (sint32)_length;
cvt.buf = new uint8[cvt.len * cvt.len_mult]; cvt.buf = cvtBuffer.data();
Memory::Copy(cvt.buf, _data, _length);
if (SDL_ConvertAudio(&cvt) >= 0) if (SDL_ConvertAudio(&cvt) >= 0)
{ {
cvtBuffer.resize(cvt.len_cvt);
Unload(); Unload();
_data = cvt.buf; _data = std::move(cvtBuffer);
_length = cvt.len_cvt; _length = cvt.len_cvt;
_format = *format; _format = *format;
return true; return true;
} }
else
{
delete[] cvt.buf;
}
} }
} }
return false; return false;
@ -179,19 +189,14 @@ namespace OpenRCT2 { namespace Audio
private: private:
void Unload() void Unload()
{ {
if (_data != nullptr) // Free our data
{ _data.clear();
if (_isSDLWav) _data.shrink_to_fit();
{
SDL_FreeWAV(_data); // Free SDL2's data
} SDL_FreeWAV(_dataSDL);
else _dataSDL = nullptr;
{
delete[] _data;
}
_data = nullptr;
}
_isSDLWav = false;
_length = 0; _length = 0;
} }
}; };

View File

@ -14,18 +14,17 @@
*****************************************************************************/ *****************************************************************************/
#pragma endregion #pragma endregion
#include <algorithm>
#include <openrct2/common.h> #include <openrct2/common.h>
#include <SDL.h> #include <SDL.h>
#include <openrct2/config/Config.h> #include <openrct2/config/Config.h>
#include <openrct2/core/Guard.hpp> #include <openrct2/core/Guard.hpp>
#include <openrct2/core/Memory.hpp>
#include <openrct2/drawing/IDrawingEngine.h> #include <openrct2/drawing/IDrawingEngine.h>
#include <openrct2/drawing/X8DrawingEngine.h> #include <openrct2/drawing/X8DrawingEngine.h>
#include <openrct2/Game.h>
#include <openrct2/ui/UiContext.h> #include <openrct2/ui/UiContext.h>
#include "DrawingEngines.h" #include "DrawingEngines.h"
#include <openrct2/Game.h>
using namespace OpenRCT2; using namespace OpenRCT2;
using namespace OpenRCT2::Drawing; using namespace OpenRCT2::Drawing;
using namespace OpenRCT2::Ui; using namespace OpenRCT2::Ui;
@ -121,7 +120,7 @@ private:
} }
// Copy pixels from the virtual screen buffer to the surface // Copy pixels from the virtual screen buffer to the surface
Memory::Copy<void>(_surface->pixels, _bits, _surface->pitch * _surface->h); std::copy_n(_bits, _surface->pitch * _surface->h, (uint8 *)_surface->pixels);
// Unlock the surface // Unlock the surface
if (SDL_MUSTLOCK(_surface)) if (SDL_MUSTLOCK(_surface))

View File

@ -16,33 +16,29 @@
#ifndef DISABLE_OPENGL #ifndef DISABLE_OPENGL
#include <algorithm>
#include <cmath> #include <cmath>
#include <unordered_map> #include <unordered_map>
#include <SDL.h> #include <SDL.h>
#include <openrct2/config/Config.h> #include <openrct2/config/Config.h>
#include <openrct2/core/Console.hpp> #include <openrct2/core/Console.hpp>
#include <openrct2/core/Math.hpp> #include <openrct2/drawing/Drawing.h>
#include <openrct2/core/Memory.hpp>
#include <openrct2/drawing/IDrawingContext.h> #include <openrct2/drawing/IDrawingContext.h>
#include <openrct2/drawing/IDrawingEngine.h> #include <openrct2/drawing/IDrawingEngine.h>
#include <openrct2/drawing/LightFX.h>
#include <openrct2/drawing/Rain.h> #include <openrct2/drawing/Rain.h>
#include <openrct2/interface/Screenshot.h> #include <openrct2/interface/Screenshot.h>
#include <openrct2/ui/UiContext.h>
#include <openrct2-ui/interface/Window.h>
#include <openrct2/Intro.h> #include <openrct2/Intro.h>
#include <openrct2/drawing/Drawing.h> #include <openrct2-ui/interface/Window.h>
#include <openrct2/drawing/LightFX.h> #include <openrct2/ui/UiContext.h>
#include "../DrawingEngines.h" #include "../DrawingEngines.h"
#include "GLSLTypes.h"
#include "OpenGLAPI.h"
#include "OpenGLFramebuffer.h"
#include "ApplyPaletteShader.h" #include "ApplyPaletteShader.h"
#include "DrawCommands.h" #include "DrawCommands.h"
#include "DrawLineShader.h" #include "DrawLineShader.h"
#include "DrawRectShader.h" #include "DrawRectShader.h"
#include "GLSLTypes.h"
#include "OpenGLAPI.h"
#include "OpenGLFramebuffer.h"
#include "SwapFramebuffer.h" #include "SwapFramebuffer.h"
#include "TextureCache.h" #include "TextureCache.h"
#include "TransparencyDepth.h" #include "TransparencyDepth.h"
@ -346,27 +342,27 @@ private:
uint8 * newBits = new uint8[newBitsSize]; uint8 * newBits = new uint8[newBitsSize];
if (_bits == nullptr) if (_bits == nullptr)
{ {
Memory::Set(newBits, 0, newBitsSize); std::fill_n(newBits, newBitsSize, 0);
} }
else else
{ {
if (_pitch == pitch) if (_pitch == pitch)
{ {
Memory::Copy(newBits, _bits, Math::Min(_bitsSize, newBitsSize)); std::copy_n(_bits, std::min(_bitsSize, newBitsSize), newBits);
} }
else else
{ {
uint8 * src = _bits; uint8 * src = _bits;
uint8 * dst = newBits; uint8 * dst = newBits;
uint32 minWidth = Math::Min(_width, width); uint32 minWidth = std::min(_width, width);
uint32 minHeight = Math::Min(_height, height); uint32 minHeight = std::min(_height, height);
for (uint32 y = 0; y < minHeight; y++) for (uint32 y = 0; y < minHeight; y++)
{ {
Memory::Copy(dst, src, minWidth); std::copy_n(src, minWidth, dst);
if (pitch - minWidth > 0) if (pitch - minWidth > 0)
{ {
Memory::Set(dst + minWidth, 0, pitch - minWidth); std::fill_n(dst + minWidth, pitch - minWidth, 0);
} }
src += _pitch; src += _pitch;
dst += pitch; dst += pitch;
@ -716,8 +712,8 @@ void OpenGLDrawingContext::DrawSpriteRawMasked(sint32 x, sint32 y, uint32 maskIm
sint32 drawOffsetX = g1ElementMask->x_offset; sint32 drawOffsetX = g1ElementMask->x_offset;
sint32 drawOffsetY = g1ElementMask->y_offset; sint32 drawOffsetY = g1ElementMask->y_offset;
sint32 drawWidth = Math::Min(g1ElementMask->width, g1ElementColour->width); sint32 drawWidth = std::min(g1ElementMask->width, g1ElementColour->width);
sint32 drawHeight = Math::Min(g1ElementMask->height, g1ElementColour->height); sint32 drawHeight = std::min(g1ElementMask->height, g1ElementColour->height);
sint32 left = x + drawOffsetX; sint32 left = x + drawOffsetX;
sint32 top = y + drawOffsetY; sint32 top = y + drawOffsetY;

View File

@ -16,9 +16,10 @@
#ifndef DISABLE_OPENGL #ifndef DISABLE_OPENGL
#include <algorithm>
#include <memory>
#include <openrct2/common.h> #include <openrct2/common.h>
#include <SDL_video.h> #include <SDL_video.h>
#include <openrct2/core/Memory.hpp>
#include "OpenGLFramebuffer.h" #include "OpenGLFramebuffer.h"
constexpr GLuint BACKBUFFER_ID = 0; constexpr GLuint BACKBUFFER_ID = 0;
@ -94,21 +95,20 @@ void OpenGLFramebuffer::GetPixels(rct_drawpixelinfo &dpi) const
{ {
assert(dpi.width == _width && dpi.height == _height); assert(dpi.width == _width && dpi.height == _height);
uint8 * pixels = Memory::Allocate<uint8>(_width * _height); auto pixels = std::make_unique<uint8[]>(_width * _height);
glBindTexture(GL_TEXTURE_2D, _texture); glBindTexture(GL_TEXTURE_2D, _texture);
glPixelStorei(GL_PACK_ALIGNMENT, 1); glPixelStorei(GL_PACK_ALIGNMENT, 1);
glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, pixels); glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, pixels.get());
// Flip pixels vertically on copy // Flip pixels vertically on copy
uint8 * src = pixels + ((_height - 1) * _width); uint8 * src = pixels.get() + ((_height - 1) * _width);
uint8 * dst = dpi.bits; uint8 * dst = dpi.bits;
for (sint32 y = 0; y < _height; y++) for (sint32 y = 0; y < _height; y++)
{ {
Memory::Copy(dst, src, _width); std::copy_n(src, _width, dst);
src -= _width; src -= _width;
dst += dpi.width + dpi.pitch; dst += dpi.width + dpi.pitch;
} }
Memory::Free(pixels);
} }
void OpenGLFramebuffer::SwapColourBuffer(OpenGLFramebuffer &other) void OpenGLFramebuffer::SwapColourBuffer(OpenGLFramebuffer &other)

View File

@ -16,29 +16,28 @@
#ifndef DISABLE_OPENGL #ifndef DISABLE_OPENGL
#include <openrct2/Context.h>
#include <openrct2/core/Console.hpp> #include <openrct2/core/Console.hpp>
#include <openrct2/core/FileStream.hpp> #include <openrct2/core/FileStream.hpp>
#include <openrct2/core/Memory.hpp>
#include <openrct2/core/Path.hpp> #include <openrct2/core/Path.hpp>
#include <openrct2/core/String.hpp> #include <openrct2/core/String.hpp>
#include <openrct2/PlatformEnvironment.h>
#include "OpenGLShaderProgram.h" #include "OpenGLShaderProgram.h"
#include <openrct2/platform/platform.h> using namespace OpenRCT2;
OpenGLShader::OpenGLShader(const char * name, GLenum type) OpenGLShader::OpenGLShader(const char * name, GLenum type)
{ {
_type = type; _type = type;
utf8 path[MAX_PATH]; auto path = GetPath(name);
GetPath(path, sizeof(path), name); auto sourceCode = ReadSourceCode(path);
char * sourceCode = ReadSourceCode(path); auto sourceCodeStr = sourceCode.c_str();
_id = glCreateShader(type); _id = glCreateShader(type);
glShaderSource(_id, 1, (const GLchar**)&sourceCode, nullptr); glShaderSource(_id, 1, (const GLchar * *)&sourceCodeStr, nullptr);
glCompileShader(_id); glCompileShader(_id);
Memory::Free(sourceCode);
GLint status; GLint status;
glGetShaderiv(_id, GL_COMPILE_STATUS, &status); glGetShaderiv(_id, GL_COMPILE_STATUS, &status);
if (status != GL_TRUE) if (status != GL_TRUE)
@ -47,7 +46,7 @@ OpenGLShader::OpenGLShader(const char * name, GLenum type)
glGetShaderInfoLog(_id, sizeof(buffer), nullptr, buffer); glGetShaderInfoLog(_id, sizeof(buffer), nullptr, buffer);
glDeleteShader(_id); glDeleteShader(_id);
Console::Error::WriteLine("Error compiling %s", path); Console::Error::WriteLine("Error compiling %s", path.c_str());
Console::Error::WriteLine(buffer); Console::Error::WriteLine(buffer);
throw std::runtime_error("Error compiling shader."); throw std::runtime_error("Error compiling shader.");
@ -64,22 +63,23 @@ GLuint OpenGLShader::GetShaderId()
return _id; return _id;
} }
void OpenGLShader::GetPath(char * buffer, size_t bufferSize, const char * name) std::string OpenGLShader::GetPath(const std::string &name)
{ {
platform_get_openrct_data_path(buffer, bufferSize); auto env = GetContext()->GetPlatformEnvironment();
Path::Append(buffer, bufferSize, "shaders"); auto shadersPath = env->GetDirectoryPath(DIRBASE::OPENRCT2, DIRID::SHADER);
Path::Append(buffer, bufferSize, name); auto path = Path::Combine(shadersPath, name);
if (_type == GL_VERTEX_SHADER) if (_type == GL_VERTEX_SHADER)
{ {
String::Append(buffer, bufferSize, ".vert"); path += ".vert";
} }
else else
{ {
String::Append(buffer, bufferSize, ".frag"); path += ".frag";
} }
return path;
} }
char * OpenGLShader::ReadSourceCode(const utf8 * path) std::string OpenGLShader::ReadSourceCode(const std::string &path)
{ {
auto fs = FileStream(path, FILE_MODE_OPEN); auto fs = FileStream(path, FILE_MODE_OPEN);
@ -89,9 +89,8 @@ char * OpenGLShader::ReadSourceCode(const utf8 * path)
throw IOException("Shader source too large."); throw IOException("Shader source too large.");
} }
utf8 * fileData = Memory::Allocate<utf8>((size_t)fileLength + 1); auto fileData = std::string((size_t)fileLength + 1, '\0');
fs.Read(fileData, fileLength); fs.Read((void *)fileData.data(), fileLength);
fileData[fileLength] = '\0';
return fileData; return fileData;
} }

View File

@ -16,6 +16,7 @@
#pragma once #pragma once
#include <string>
#include <openrct2/common.h> #include <openrct2/common.h>
#include "OpenGLAPI.h" #include "OpenGLAPI.h"
@ -34,8 +35,8 @@ public:
GLuint GetShaderId(); GLuint GetShaderId();
private: private:
void GetPath(char * buffer, size_t bufferSize, const char * name); std::string GetPath(const std::string &name);
static char * ReadSourceCode(const utf8 * path); static std::string ReadSourceCode(const std::string &path);
}; };
class OpenGLShaderProgram class OpenGLShaderProgram

View File

@ -16,12 +16,11 @@
#ifndef DISABLE_OPENGL #ifndef DISABLE_OPENGL
#include <vector> #include <algorithm>
#include <stdexcept> #include <stdexcept>
#include <openrct2/core/Memory.hpp> #include <vector>
#include "TextureCache.h"
#include <openrct2/drawing/Drawing.h> #include <openrct2/drawing/Drawing.h>
#include "TextureCache.h"
constexpr uint32 UNUSED_INDEX = 0xFFFFFFFF; constexpr uint32 UNUSED_INDEX = 0xFFFFFFFF;
@ -95,7 +94,7 @@ BasicTextureInfo TextureCache::GetOrLoadGlyphTexture(uint32 image, uint8 * palet
{ {
GlyphId glyphId; GlyphId glyphId;
glyphId.Image = image; glyphId.Image = image;
Memory::Copy<void>(&glyphId.Palette, palette, sizeof(glyphId.Palette)); std::copy_n(palette, sizeof(glyphId.Palette), (uint8 *)&glyphId.Palette);
auto kvp = _glyphTextureMap.find(glyphId); auto kvp = _glyphTextureMap.find(glyphId);
if (kvp != _glyphTextureMap.end()) if (kvp != _glyphTextureMap.end())
@ -290,8 +289,8 @@ void TextureCache::FreeTextures()
rct_drawpixelinfo TextureCache::CreateDPI(sint32 width, sint32 height) rct_drawpixelinfo TextureCache::CreateDPI(sint32 width, sint32 height)
{ {
size_t numPixels = width * height; size_t numPixels = width * height;
uint8 * pixels8 = Memory::Allocate<uint8>(numPixels); auto pixels8 = new uint8[numPixels];
Memory::Set(pixels8, 0, numPixels); std::fill_n(pixels8, numPixels, 0);
rct_drawpixelinfo dpi; rct_drawpixelinfo dpi;
dpi.bits = pixels8; dpi.bits = pixels8;
@ -306,7 +305,7 @@ rct_drawpixelinfo TextureCache::CreateDPI(sint32 width, sint32 height)
void TextureCache::DeleteDPI(rct_drawpixelinfo dpi) void TextureCache::DeleteDPI(rct_drawpixelinfo dpi)
{ {
Memory::Free(dpi.bits); delete dpi.bits;
} }
GLuint TextureCache::GetAtlasesTexture() GLuint TextureCache::GetAtlasesTexture()

View File

@ -19,7 +19,6 @@
#include <openrct2/core/Console.hpp> #include <openrct2/core/Console.hpp>
#include <openrct2/core/File.h> #include <openrct2/core/File.h>
#include <openrct2/core/FileStream.hpp> #include <openrct2/core/FileStream.hpp>
#include <openrct2/core/Memory.hpp>
#include <openrct2/core/Path.hpp> #include <openrct2/core/Path.hpp>
#include <openrct2/core/String.hpp> #include <openrct2/core/String.hpp>
#include <openrct2/PlatformEnvironment.h> #include <openrct2/PlatformEnvironment.h>

View File

@ -14,16 +14,20 @@
*****************************************************************************/ *****************************************************************************/
#pragma endregion #pragma endregion
#include <fstream>
#include <vector>
#include <openrct2/Context.h> #include <openrct2/Context.h>
#include <openrct2/OpenRCT2.h>
#include <openrct2/core/Math.hpp> #include <openrct2/core/Math.hpp>
#include <openrct2/core/Memory.hpp> #include <openrct2/core/String.hpp>
#include <openrct2-ui/windows/Window.h>
#include <openrct2-ui/interface/Widget.h>
#include <openrct2/localisation/Localisation.h> #include <openrct2/localisation/Localisation.h>
#include <openrct2/OpenRCT2.h>
#include <openrct2/platform/platform.h> #include <openrct2/platform/platform.h>
#include <openrct2/PlatformEnvironment.h>
#include <openrct2/util/Util.h> #include <openrct2/util/Util.h>
#include <openrct2-ui/windows/Window.h>
#include <openrct2-ui/interface/Widget.h>
using namespace OpenRCT2;
enum { enum {
WIDX_BACKGROUND, WIDX_BACKGROUND,
@ -89,10 +93,8 @@ static rct_window_event_list window_changelog_events = {
static bool window_changelog_read_file(); static bool window_changelog_read_file();
static void window_changelog_dispose_file(); static void window_changelog_dispose_file();
static char *_changelogText = nullptr; static std::string _changelogText;
static size_t _changelogTextSize = 0; static std::vector<const char *> _changelogLines;
static char **_changelogLines = nullptr;
static sint32 _changelogNumLines = 0;
static sint32 _changelogLongestLineWidth = 0; static sint32 _changelogLongestLineWidth = 0;
rct_window * window_changelog_open() rct_window * window_changelog_open()
@ -164,7 +166,7 @@ static void window_changelog_resize(rct_window *w)
static void window_changelog_scrollgetsize(rct_window *w, sint32 scrollIndex, sint32 *width, sint32 *height) static void window_changelog_scrollgetsize(rct_window *w, sint32 scrollIndex, sint32 *width, sint32 *height)
{ {
*width = _changelogLongestLineWidth + 4; *width = _changelogLongestLineWidth + 4;
*height = _changelogNumLines * 11; *height = (sint32)(_changelogLines.size() * 11);
} }
static void window_changelog_invalidate(rct_window *w) static void window_changelog_invalidate(rct_window *w)
@ -192,73 +194,85 @@ static void window_changelog_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi,
sint32 x = 3; sint32 x = 3;
sint32 y = 3; sint32 y = 3;
for (sint32 i = 0; i < _changelogNumLines; i++) { for (auto line : _changelogLines)
gfx_draw_string(dpi, _changelogLines[i], w->colours[0], x, y); {
gfx_draw_string(dpi, (char *)line, w->colours[0], x, y);
y += 11; y += 11;
} }
} }
static std::string GetChangelogPath()
{
auto env = GetContext()->GetPlatformEnvironment();
return env->GetFilePath(PATHID::CHANGELOG);
}
static std::string GetChangelogText()
{
auto path = GetChangelogPath();
#if defined(_WIN32) && !defined(__MINGW32__)
auto pathW = String::ToUtf16(path);
auto fs = std::ifstream(pathW, std::ios::in);
#else
auto fs = std::ifstream(path, std::ios::in);
#endif
if (!fs.is_open())
{
throw std::runtime_error("Unable to open " + path);
}
return std::string((std::istreambuf_iterator<char>(fs)), std::istreambuf_iterator<char>());
}
static bool window_changelog_read_file() static bool window_changelog_read_file()
{ {
window_changelog_dispose_file(); try
utf8 path[MAX_PATH]; {
platform_get_changelog_path(path, sizeof(path)); _changelogText = GetChangelogText();
if (!readentirefile(path, (void**)&_changelogText, &_changelogTextSize)) { }
catch (const std::bad_alloc &)
{
log_error("Unable to allocate memory for changelog.txt");
return false;
}
catch (const std::exception &)
{
log_error("Unable to read changelog.txt"); log_error("Unable to read changelog.txt");
return false; return false;
} }
void* new_memory = realloc(_changelogText, _changelogTextSize + 1);
if (new_memory == nullptr) {
log_error("Failed to reallocate memory for changelog text");
return false;
}
_changelogText = (char*)new_memory;
_changelogText[_changelogTextSize++] = 0;
char *start = _changelogText; // Non-const cast required until C++17 is enabled
if (_changelogTextSize >= 3 && utf8_is_bom(_changelogText)) auto * start = (char *)_changelogText.data();
if (_changelogText.size() >= 3 && utf8_is_bom(start))
{
start += 3; start += 3;
}
sint32 changelogLinesCapacity = 8; _changelogLines.clear();
_changelogLines = Memory::Allocate<utf8*>(changelogLinesCapacity * sizeof(char*)); _changelogLines.push_back(start);
_changelogLines[0] = start; auto ch = start;
_changelogNumLines = 1; while (*ch != '\0')
{
char *ch = start;
while (*ch != 0) {
uint8 c = *ch; uint8 c = *ch;
if (c == '\n') { if (c == '\n')
{
*ch++ = 0; *ch++ = 0;
_changelogNumLines++; _changelogLines.push_back(ch);
if (_changelogNumLines > changelogLinesCapacity) { }
changelogLinesCapacity *= 2; else if (utf8_is_format_code(c))
new_memory = realloc(_changelogLines, changelogLinesCapacity * sizeof(char*)); {
if (new_memory == nullptr) {
log_error("Failed to reallocate memory for change log lines");
return false;
}
_changelogLines = (char**)new_memory;
}
_changelogLines[_changelogNumLines - 1] = ch;
} else if (c < 32 || c > 122) {
// A character that won't be drawn or change state.
*ch++ = FORMAT_OUTLINE_OFF; *ch++ = FORMAT_OUTLINE_OFF;
} else { }
else
{
ch++; ch++;
} }
} }
new_memory = realloc(_changelogLines, _changelogNumLines * sizeof(char*));
if (new_memory == nullptr) {
log_error("Failed to reallocate memory for change log lines");
return false;
}
_changelogLines = (char**)new_memory;
gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM; gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM;
_changelogLongestLineWidth = 0; _changelogLongestLineWidth = 0;
for (sint32 i = 0; i < _changelogNumLines; i++) { for (auto line : _changelogLines)
sint32 width = gfx_get_string_width(_changelogLines[i]); {
auto width = gfx_get_string_width(line);
_changelogLongestLineWidth = Math::Max(width, _changelogLongestLineWidth); _changelogLongestLineWidth = Math::Max(width, _changelogLongestLineWidth);
} }
return true; return true;
@ -266,8 +280,7 @@ static bool window_changelog_read_file()
static void window_changelog_dispose_file() static void window_changelog_dispose_file()
{ {
SafeFree(_changelogText); _changelogText = std::string();
SafeFree(_changelogLines); _changelogLines.clear();
_changelogTextSize = 0; _changelogLines.shrink_to_fit();
_changelogNumLines = 0;
} }

View File

@ -14,32 +14,31 @@
*****************************************************************************/ *****************************************************************************/
#pragma endregion #pragma endregion
#include <openrct2-ui/windows/Window.h> #include <algorithm>
#include <cctype> #include <cctype>
#include <string> #include <string>
#include <vector>
#include <openrct2/audio/audio.h> #include <openrct2/audio/audio.h>
#include <openrct2/config/Config.h> #include <openrct2/config/Config.h>
#include <openrct2/Context.h> #include <openrct2/Context.h>
#include <openrct2/core/Memory.hpp>
#include <openrct2/Editor.h> #include <openrct2/Editor.h>
#include <openrct2/EditorObjectSelectionSession.h> #include <openrct2/EditorObjectSelectionSession.h>
#include <openrct2/Game.h> #include <openrct2/Game.h>
#include <openrct2-ui/interface/Widget.h>
#include <openrct2/localisation/Localisation.h> #include <openrct2/localisation/Localisation.h>
#include <openrct2/object/ObjectList.h>
#include <openrct2/object/ObjectManager.h> #include <openrct2/object/ObjectManager.h>
#include <openrct2/object/ObjectRepository.h> #include <openrct2/object/ObjectRepository.h>
#include <openrct2/object/RideObject.h> #include <openrct2/object/RideObject.h>
#include <openrct2/object/StexObject.h> #include <openrct2/object/StexObject.h>
#include <openrct2/object/ObjectList.h>
#include <openrct2/OpenRCT2.h> #include <openrct2/OpenRCT2.h>
#include <openrct2/platform/platform.h> #include <openrct2/platform/platform.h>
#include <openrct2/ride/RideGroupManager.h> #include <openrct2/ride/RideGroupManager.h>
#include <openrct2/sprites.h> #include <openrct2/sprites.h>
#include <openrct2/util/Util.h> #include <openrct2/util/Util.h>
#include <openrct2-ui/interface/Dropdown.h>
#include <openrct2/windows/Intent.h> #include <openrct2/windows/Intent.h>
#include <openrct2-ui/interface/Dropdown.h>
#include <openrct2-ui/interface/Widget.h>
#include <openrct2-ui/windows/Window.h>
enum { enum {
FILTER_RCT2 = (1 << 0), FILTER_RCT2 = (1 << 0),
@ -270,42 +269,34 @@ typedef struct list_item {
static rct_string_id get_ride_type_string_id(const ObjectRepositoryItem * item); static rct_string_id get_ride_type_string_id(const ObjectRepositoryItem * item);
typedef sint32(*sortFunc_t)(const void *, const void *); typedef bool (*sortFunc_t)(const list_item &, const list_item &);
static sint32 _numListItems = 0; static std::vector<list_item> _listItems;
static list_item *_listItems = nullptr;
static sint32 _listSortType = RIDE_SORT_TYPE; static sint32 _listSortType = RIDE_SORT_TYPE;
static bool _listSortDescending = false; static bool _listSortDescending = false;
static void * _loadedObject = nullptr; static void * _loadedObject = nullptr;
static void visible_list_dispose() static void visible_list_dispose()
{ {
SafeFree(_listItems); _listItems.clear();
_numListItems = 0; _listItems.shrink_to_fit();
} }
static sint32 visible_list_sort_ride_name(const void *rawA, const void *rawB) static bool visible_list_sort_ride_name(const list_item &a, const list_item &b)
{ {
list_item *a = (list_item*)rawA; auto nameA = a.repositoryItem->Name;
list_item *b = (list_item*)rawB; auto nameB = b.repositoryItem->Name;
return strcmp(nameA, nameB) < 0;
const char *nameA = a->repositoryItem->Name;
const char *nameB = b->repositoryItem->Name;
return strcmp(nameA, nameB);
} }
static sint32 visible_list_sort_ride_type(const void *rawA, const void *rawB) static bool visible_list_sort_ride_type(const list_item &a, const list_item &b)
{ {
list_item *a = (list_item*)rawA; auto rideTypeA = language_get_string(get_ride_type_string_id(a.repositoryItem));
list_item *b = (list_item*)rawB; auto rideTypeB = language_get_string(get_ride_type_string_id(b.repositoryItem));
const char *rideTypeA = language_get_string(get_ride_type_string_id(a->repositoryItem));
const char *rideTypeB = language_get_string(get_ride_type_string_id(b->repositoryItem));
sint32 result = strcmp(rideTypeA, rideTypeB); sint32 result = strcmp(rideTypeA, rideTypeB);
if (result != 0) return result != 0 ?
return result; result < 0 :
visible_list_sort_ride_name(a, b);
return visible_list_sort_ride_name(rawA, rawB);
} }
static void visible_list_refresh(rct_window *w) static void visible_list_refresh(rct_window *w)
@ -314,10 +305,7 @@ static void visible_list_refresh(rct_window *w)
visible_list_dispose(); visible_list_dispose();
w->selected_list_item = -1; w->selected_list_item = -1;
_listItems = Memory::AllocateArray<list_item>(numObjects);
_numListItems = 0;
list_item *currentListItem = &_listItems[0];
const ObjectRepositoryItem *items = object_repository_get_items(); const ObjectRepositoryItem *items = object_repository_get_items();
for (sint32 i = 0; i < numObjects; i++) { for (sint32 i = 0; i < numObjects; i++) {
uint8 selectionFlags = _objectSelectionFlags[i]; uint8 selectionFlags = _objectSelectionFlags[i];
@ -333,29 +321,25 @@ static void visible_list_refresh(rct_window *w)
filter->ride.category[0] = 0; filter->ride.category[0] = 0;
filter->ride.category[1] = 0; filter->ride.category[1] = 0;
filter->ride.ride_type = 0; filter->ride.ride_type = 0;
currentListItem->repositoryItem = item;
currentListItem->entry = (rct_object_entry *)&item->ObjectEntry; list_item currentListItem;
currentListItem->filter = filter; currentListItem.repositoryItem = item;
currentListItem->flags = &_objectSelectionFlags[i]; currentListItem.entry = (rct_object_entry *)&item->ObjectEntry;
currentListItem++; currentListItem.filter = filter;
_numListItems++; currentListItem.flags = &_objectSelectionFlags[i];
_listItems.push_back(std::move(currentListItem));
} }
} }
if (_numListItems == 0) if (_listItems.size() == 0)
{ {
visible_list_dispose(); visible_list_dispose();
window_invalidate(w);
return;
} }
else
_listItems = Memory::ReallocateArray(_listItems, _numListItems); {
if (_listItems == nullptr) {
_numListItems = 0;
log_error("Unable to reallocate list items");
} else {
sortFunc_t sortFunc = nullptr; sortFunc_t sortFunc = nullptr;
switch (_listSortType) { switch (_listSortType)
{
case RIDE_SORT_TYPE: case RIDE_SORT_TYPE:
sortFunc = visible_list_sort_ride_type; sortFunc = visible_list_sort_ride_type;
break; break;
@ -364,17 +348,14 @@ static void visible_list_refresh(rct_window *w)
break; break;
default: default:
log_warning("Wrong sort type %d, leaving list as-is.", _listSortType); log_warning("Wrong sort type %d, leaving list as-is.", _listSortType);
window_invalidate(w); break;
return;
} }
qsort(_listItems, _numListItems, sizeof(list_item), sortFunc); if (sortFunc != nullptr)
{
if (_listSortDescending) { std::sort(_listItems.begin(), _listItems.end(), sortFunc);
for (sint32 i = 0; i < _numListItems / 2; i++) { if (_listSortDescending)
sint32 ri = _numListItems - i - 1; {
list_item temp = _listItems[i]; std::reverse(_listItems.begin(), _listItems.end());
_listItems[i] = _listItems[ri];
_listItems[ri] = temp;
} }
} }
} }
@ -681,7 +662,7 @@ static void window_editor_object_selection_dropdown(rct_window *w, rct_widgetind
*/ */
static void window_editor_object_selection_scrollgetsize(rct_window *w, sint32 scrollIndex, sint32 *width, sint32 *height) static void window_editor_object_selection_scrollgetsize(rct_window *w, sint32 scrollIndex, sint32 *width, sint32 *height)
{ {
*height = _numListItems * 12; *height = (sint32)(_listItems.size() * 12);
} }
/** /**
@ -1110,7 +1091,7 @@ static void window_editor_object_selection_paint(rct_window *w, rct_drawpixelinf
*/ */
static void window_editor_object_selection_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, sint32 scrollIndex) static void window_editor_object_selection_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, sint32 scrollIndex)
{ {
sint32 x, y, i, colour, colour2; sint32 x, y, colour, colour2;
bool ridePage = (w->selected_tab == WINDOW_OBJECT_SELECTION_PAGE_RIDE_VEHICLES_ATTRACTIONS); bool ridePage = (w->selected_tab == WINDOW_OBJECT_SELECTION_PAGE_RIDE_VEHICLES_ATTRACTIONS);
@ -1118,27 +1099,26 @@ static void window_editor_object_selection_scrollpaint(rct_window *w, rct_drawpi
gfx_clear(dpi, paletteIndex); gfx_clear(dpi, paletteIndex);
y = 0; y = 0;
for (i = 0; i < _numListItems; i++) { for (const auto &listItem : _listItems)
list_item *listItem = &_listItems[i]; {
if (y + 12 >= dpi->y && y <= dpi->y + dpi->height) { if (y + 12 >= dpi->y && y <= dpi->y + dpi->height) {
// Draw checkbox // Draw checkbox
if (!(gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER) && !(*listItem->flags & 0x20)) if (!(gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER) && !(*listItem.flags & 0x20))
gfx_fill_rect_inset(dpi, 2, y, 11, y + 10, w->colours[1], INSET_RECT_F_E0); gfx_fill_rect_inset(dpi, 2, y, 11, y + 10, w->colours[1], INSET_RECT_F_E0);
// Highlight background // Highlight background
colour = COLOUR_BRIGHT_GREEN | COLOUR_FLAG_TRANSLUCENT; colour = COLOUR_BRIGHT_GREEN | COLOUR_FLAG_TRANSLUCENT;
if (listItem->entry == w->object_entry && !(*listItem->flags & OBJECT_SELECTION_FLAG_6)) { if (listItem.entry == w->object_entry && !(*listItem.flags & OBJECT_SELECTION_FLAG_6)) {
gfx_filter_rect(dpi, 0, y, w->width, y + 11, PALETTE_DARKEN_1); gfx_filter_rect(dpi, 0, y, w->width, y + 11, PALETTE_DARKEN_1);
colour = COLOUR_BRIGHT_GREEN; colour = COLOUR_BRIGHT_GREEN;
} }
// Draw checkmark // Draw checkmark
if (!(gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER) && (*listItem->flags & OBJECT_SELECTION_FLAG_SELECTED)) { if (!(gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER) && (*listItem.flags & OBJECT_SELECTION_FLAG_SELECTED)) {
x = 2; x = 2;
gCurrentFontSpriteBase = colour == COLOUR_BRIGHT_GREEN ? FONT_SPRITE_BASE_MEDIUM_EXTRA_DARK : FONT_SPRITE_BASE_MEDIUM_DARK; gCurrentFontSpriteBase = colour == COLOUR_BRIGHT_GREEN ? FONT_SPRITE_BASE_MEDIUM_EXTRA_DARK : FONT_SPRITE_BASE_MEDIUM_DARK;
colour2 = NOT_TRANSLUCENT(w->colours[1]); colour2 = NOT_TRANSLUCENT(w->colours[1]);
if (*listItem->flags & (OBJECT_SELECTION_FLAG_IN_USE | OBJECT_SELECTION_FLAG_ALWAYS_REQUIRED)) if (*listItem.flags & (OBJECT_SELECTION_FLAG_IN_USE | OBJECT_SELECTION_FLAG_ALWAYS_REQUIRED))
colour2 |= COLOUR_FLAG_INSET; colour2 |= COLOUR_FLAG_INSET;
gfx_draw_string(dpi, (char*)CheckBoxMarkString, colour2, x, y); gfx_draw_string(dpi, (char*)CheckBoxMarkString, colour2, x, y);
@ -1148,7 +1128,7 @@ static void window_editor_object_selection_scrollpaint(rct_window *w, rct_drawpi
char *bufferWithColour = gCommonStringFormatBuffer; char *bufferWithColour = gCommonStringFormatBuffer;
char *buffer = utf8_write_codepoint(bufferWithColour, colour); char *buffer = utf8_write_codepoint(bufferWithColour, colour);
if (*listItem->flags & OBJECT_SELECTION_FLAG_6) { if (*listItem.flags & OBJECT_SELECTION_FLAG_6) {
colour = w->colours[1] & 0x7F; colour = w->colours[1] & 0x7F;
gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM_DARK; gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM_DARK;
} }
@ -1159,14 +1139,14 @@ static void window_editor_object_selection_scrollpaint(rct_window *w, rct_drawpi
if (ridePage) { if (ridePage) {
// Draw ride type // Draw ride type
rct_string_id rideTypeStringId = get_ride_type_string_id(listItem->repositoryItem); rct_string_id rideTypeStringId = get_ride_type_string_id(listItem.repositoryItem);
safe_strcpy(buffer, language_get_string(rideTypeStringId), 256 - (buffer - bufferWithColour)); safe_strcpy(buffer, language_get_string(rideTypeStringId), 256 - (buffer - bufferWithColour));
gfx_draw_string(dpi, bufferWithColour, colour, x, y); gfx_draw_string(dpi, bufferWithColour, colour, x, y);
x = w->widgets[WIDX_LIST_SORT_RIDE].left - w->widgets[WIDX_LIST].left; x = w->widgets[WIDX_LIST_SORT_RIDE].left - w->widgets[WIDX_LIST].left;
} }
// Draw text // Draw text
safe_strcpy(buffer, listItem->repositoryItem->Name, 256 - (buffer - bufferWithColour)); safe_strcpy(buffer, listItem.repositoryItem->Name, 256 - (buffer - bufferWithColour));
if (gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER) { if (gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER) {
while (*buffer != 0 && *buffer != 9) while (*buffer != 0 && *buffer != 9)
buffer++; buffer++;
@ -1221,7 +1201,7 @@ static void window_editor_object_selection_set_pressed_tab(rct_window *w)
static sint32 get_object_from_object_selection(uint8 object_type, sint32 y) static sint32 get_object_from_object_selection(uint8 object_type, sint32 y)
{ {
sint32 listItemIndex = y / 12; sint32 listItemIndex = y / 12;
if (listItemIndex < 0 || listItemIndex >= _numListItems) if (listItemIndex < 0 || (size_t)listItemIndex >= _listItems.size())
return -1; return -1;
return listItemIndex; return listItemIndex;

View File

@ -14,11 +14,13 @@
*****************************************************************************/ *****************************************************************************/
#pragma endregion #pragma endregion
#include <string>
#include <vector>
#include <openrct2/Context.h> #include <openrct2/Context.h>
#include <openrct2/object/ObjectManager.h> #include <openrct2/object/ObjectManager.h>
#include <openrct2/ride/TrackDesignRepository.h> #include <openrct2/ride/TrackDesignRepository.h>
#include <openrct2/core/Math.hpp> #include <openrct2/core/Math.hpp>
#include <openrct2/core/Memory.hpp>
#include <openrct2-ui/windows/Window.h> #include <openrct2-ui/windows/Window.h>
#include <openrct2/audio/audio.h> #include <openrct2/audio/audio.h>
@ -94,10 +96,10 @@ static rct_window_event_list window_install_track_events = {
nullptr nullptr
}; };
static rct_track_td6 *_trackDesign; static rct_track_td6 * _trackDesign;
static utf8 *_trackPath; static std::string _trackPath;
static utf8 *_trackName; static std::string _trackName;
static uint8 *_trackDesignPreviewPixels; static std::vector<uint8> _trackDesignPreviewPixels;
static void window_install_track_update_preview(); static void window_install_track_update_preview();
static void window_install_track_design(rct_window *w); static void window_install_track_design(rct_window *w);
@ -142,9 +144,9 @@ rct_window * window_install_track_open(const utf8 *path)
w->track_list.track_list_being_updated = false; w->track_list.track_list_being_updated = false;
window_push_others_right(w); window_push_others_right(w);
_trackPath = _strdup(path); _trackPath = path;
_trackName = track_repository_get_name_from_path(path); _trackName = GetNameFromTrackPath(path);
_trackDesignPreviewPixels = Memory::AllocateArray<uint8>(4 * TRACK_PREVIEW_IMAGE_SIZE); _trackDesignPreviewPixels.resize(4 * TRACK_PREVIEW_IMAGE_SIZE);
window_install_track_update_preview(); window_install_track_update_preview();
window_invalidate(w); window_invalidate(w);
@ -158,9 +160,10 @@ rct_window * window_install_track_open(const utf8 *path)
*/ */
static void window_install_track_close(rct_window *w) static void window_install_track_close(rct_window *w)
{ {
SafeFree(_trackPath); _trackPath.clear();
SafeFree(_trackName); _trackName.clear();
SafeFree(_trackDesignPreviewPixels); _trackDesignPreviewPixels.clear();
_trackDesignPreviewPixels.shrink_to_fit();
track_design_dispose(_trackDesign); track_design_dispose(_trackDesign);
_trackDesign = nullptr; _trackDesign = nullptr;
} }
@ -229,7 +232,7 @@ static void window_install_track_paint(rct_window *w, rct_drawpixelinfo *dpi)
gfx_fill_rect(dpi, x, y, x + 369, y + 216, colour); gfx_fill_rect(dpi, x, y, x + 369, y + 216, colour);
rct_g1_element g1temp = { nullptr }; rct_g1_element g1temp = { nullptr };
g1temp.offset = _trackDesignPreviewPixels + (_currentTrackPieceDirection * TRACK_PREVIEW_IMAGE_SIZE); g1temp.offset = _trackDesignPreviewPixels.data() + (_currentTrackPieceDirection * TRACK_PREVIEW_IMAGE_SIZE);
g1temp.width = 370; g1temp.width = 370;
g1temp.height = 217; g1temp.height = 217;
g1temp.flags = G1_FLAG_BMP; g1temp.flags = G1_FLAG_BMP;
@ -400,15 +403,14 @@ static void window_install_track_text_input(rct_window *w, rct_widgetindex widge
return; return;
} }
free(_trackName); _trackName = text;
_trackName = _strdup(text);
window_event_mouse_up_call(w, WIDX_INSTALL); window_event_mouse_up_call(w, WIDX_INSTALL);
} }
static void window_install_track_update_preview() static void window_install_track_update_preview()
{ {
track_design_draw_preview(_trackDesign, _trackDesignPreviewPixels); track_design_draw_preview(_trackDesign, _trackDesignPreviewPixels.data());
} }
static void window_install_track_design(rct_window *w) static void window_install_track_design(rct_window *w)
@ -422,7 +424,7 @@ static void window_install_track_design(rct_window *w)
return; return;
} }
safe_strcat_path(destPath, _trackName, sizeof(destPath)); safe_strcat_path(destPath, _trackName.c_str(), sizeof(destPath));
path_append_extension(destPath, ".td6", sizeof(destPath)); path_append_extension(destPath, ".td6", sizeof(destPath));
if (platform_file_exists(destPath)) { if (platform_file_exists(destPath)) {
@ -433,11 +435,11 @@ static void window_install_track_design(rct_window *w)
WIDX_INSTALL, WIDX_INSTALL,
STR_SELECT_NEW_NAME_FOR_TRACK_DESIGN, STR_SELECT_NEW_NAME_FOR_TRACK_DESIGN,
STR_AN_EXISTING_TRACK_DESIGN_ALREADY_HAS_THIS_NAME, STR_AN_EXISTING_TRACK_DESIGN_ALREADY_HAS_THIS_NAME,
_trackName, _trackName.c_str(),
255 255
); );
} else { } else {
if (track_repository_install(_trackPath)) { if (track_repository_install(_trackPath.c_str())) {
window_close(w); window_close(w);
} else { } else {
context_show_error(STR_CANT_SAVE_TRACK_DESIGN, STR_NONE); context_show_error(STR_CANT_SAVE_TRACK_DESIGN, STR_NONE);

View File

@ -14,24 +14,24 @@
*****************************************************************************/ *****************************************************************************/
#pragma endregion #pragma endregion
#include <openrct2/OpenRCT2.h> #include <algorithm>
#include <openrct2/core/Math.hpp> #include <vector>
#include <openrct2/core/Util.hpp>
#include <openrct2/core/Memory.hpp>
#include <openrct2/Context.h>
#include <openrct2/audio/audio.h> #include <openrct2/audio/audio.h>
#include <openrct2/Cheats.h> #include <openrct2/Cheats.h>
#include <openrct2/Context.h>
#include <openrct2/core/Math.hpp>
#include <openrct2/core/Util.hpp>
#include <openrct2/Game.h> #include <openrct2/Game.h>
#include <openrct2/Input.h> #include <openrct2/Input.h>
#include <openrct2-ui/interface/Viewport.h>
#include <openrct2-ui/interface/Widget.h>
#include <openrct2/localisation/Localisation.h> #include <openrct2/localisation/Localisation.h>
#include <openrct2/OpenRCT2.h>
#include <openrct2/ride/Track.h> #include <openrct2/ride/Track.h>
#include <openrct2/world/Entrance.h> #include <openrct2/world/Entrance.h>
#include <openrct2/world/Footpath.h> #include <openrct2/world/Footpath.h>
#include <openrct2/world/Scenery.h> #include <openrct2/world/Scenery.h>
#include <openrct2-ui/interface/LandTool.h> #include <openrct2-ui/interface/LandTool.h>
#include <openrct2-ui/interface/Viewport.h>
#include <openrct2-ui/interface/Widget.h>
#include <openrct2-ui/windows/Window.h> #include <openrct2-ui/windows/Window.h>
#define MAP_COLOUR_2(colourA, colourB) ((colourA << 8) | colourB) #define MAP_COLOUR_2(colourA, colourB) ((colourA << 8) | colourB)
@ -175,7 +175,7 @@ static uint8 _activeTool;
static uint32 _currentLine; static uint32 _currentLine;
/** rct2: 0x00F1AD68 */ /** rct2: 0x00F1AD68 */
static uint8 (*_mapImageData)[MAP_WINDOW_MAP_SIZE][MAP_WINDOW_MAP_SIZE]; static std::vector<uint8> _mapImageData;
static sint32 _nextPeepSpawnIndex = 0; static sint32 _nextPeepSpawnIndex = 0;
@ -217,8 +217,12 @@ rct_window * window_map_open()
return w; return w;
} }
_mapImageData = Memory::Allocate<uint8[MAP_WINDOW_MAP_SIZE][MAP_WINDOW_MAP_SIZE]>(); try
if (_mapImageData == nullptr) { {
_mapImageData.resize(MAP_WINDOW_MAP_SIZE * MAP_WINDOW_MAP_SIZE);
}
catch (const std::bad_alloc &)
{
return nullptr; return nullptr;
} }
@ -284,7 +288,8 @@ void window_map_reset()
*/ */
static void window_map_close(rct_window *w) static void window_map_close(rct_window *w)
{ {
free(_mapImageData); _mapImageData.clear();
_mapImageData.shrink_to_fit();
if ((input_test_flag(INPUT_FLAG_TOOL_ACTIVE)) && if ((input_test_flag(INPUT_FLAG_TOOL_ACTIVE)) &&
gCurrentToolWidget.window_classification == w->classification && gCurrentToolWidget.window_classification == w->classification &&
gCurrentToolWidget.window_number == w->number) { gCurrentToolWidget.window_number == w->number) {
@ -889,7 +894,7 @@ static void window_map_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, sint32
gfx_clear(dpi, PALETTE_INDEX_10); gfx_clear(dpi, PALETTE_INDEX_10);
rct_g1_element g1temp = { nullptr }; rct_g1_element g1temp = { nullptr };
g1temp.offset = (uint8 *)_mapImageData; g1temp.offset = _mapImageData.data();
g1temp.width = MAP_WINDOW_MAP_SIZE; g1temp.width = MAP_WINDOW_MAP_SIZE;
g1temp.height = MAP_WINDOW_MAP_SIZE; g1temp.height = MAP_WINDOW_MAP_SIZE;
g1temp.x_offset = -8; g1temp.x_offset = -8;
@ -914,7 +919,7 @@ static void window_map_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, sint32
*/ */
static void window_map_init_map() static void window_map_init_map()
{ {
memset(_mapImageData, PALETTE_INDEX_10, sizeof(*_mapImageData)); std::fill(_mapImageData.begin(), _mapImageData.end(), PALETTE_INDEX_10);
_currentLine = 0; _currentLine = 0;
} }
@ -1653,12 +1658,11 @@ static uint16 map_window_get_pixel_colour_ride(sint32 x, sint32 y)
static void map_window_set_pixels(rct_window *w) static void map_window_set_pixels(rct_window *w)
{ {
uint16 colour = 0; uint16 colour = 0;
uint8 *destination;
sint32 x = 0, y = 0, dx = 0, dy = 0; sint32 x = 0, y = 0, dx = 0, dy = 0;
sint32 pos = (_currentLine * (MAP_WINDOW_MAP_SIZE - 1)) + MAXIMUM_MAP_SIZE_TECHNICAL - 1; sint32 pos = (_currentLine * (MAP_WINDOW_MAP_SIZE - 1)) + MAXIMUM_MAP_SIZE_TECHNICAL - 1;
LocationXY16 destinationPosition = MakeXY16(pos % MAP_WINDOW_MAP_SIZE, pos / MAP_WINDOW_MAP_SIZE); LocationXY16 destinationPosition = MakeXY16(pos % MAP_WINDOW_MAP_SIZE, pos / MAP_WINDOW_MAP_SIZE);
destination = &(*_mapImageData)[destinationPosition.y][destinationPosition.x]; auto destination = _mapImageData.data() + (destinationPosition.y * MAP_WINDOW_MAP_SIZE) + destinationPosition.x;
switch (get_current_rotation()) { switch (get_current_rotation()) {
case 0: case 0:
x = _currentLine * 32; x = _currentLine * 32;
@ -1709,7 +1713,7 @@ static void map_window_set_pixels(rct_window *w)
destinationPosition.x++; destinationPosition.x++;
destinationPosition.y++; destinationPosition.y++;
destination = &(*_mapImageData)[destinationPosition.y][destinationPosition.x]; destination = _mapImageData.data() + (destinationPosition.y * MAP_WINDOW_MAP_SIZE) + destinationPosition.x;
} }
_currentLine++; _currentLine++;
if (_currentLine >= MAXIMUM_MAP_SIZE_TECHNICAL) if (_currentLine >= MAXIMUM_MAP_SIZE_TECHNICAL)

View File

@ -14,13 +14,13 @@
*****************************************************************************/ *****************************************************************************/
#pragma endregion #pragma endregion
#include <openrct2-ui/windows/Window.h> #include <string>
#include <vector>
#include <openrct2/core/Memory.hpp>
#include <openrct2-ui/interface/Widget.h>
#include <openrct2/localisation/Localisation.h> #include <openrct2/localisation/Localisation.h>
#include <openrct2/object/ObjectManager.h> #include <openrct2/object/ObjectManager.h>
#include <openrct2/platform/platform.h> #include <openrct2/platform/platform.h>
#include <openrct2-ui/interface/Widget.h>
#include <openrct2-ui/windows/Window.h>
enum WINDOW_OBJECT_LOAD_ERROR_WIDGET_IDX { enum WINDOW_OBJECT_LOAD_ERROR_WIDGET_IDX {
WIDX_BACKGROUND, WIDX_BACKGROUND,
@ -96,9 +96,9 @@ static rct_window_event_list window_object_load_error_events = {
window_object_load_error_scrollpaint window_object_load_error_scrollpaint
}; };
static rct_object_entry * _invalid_entries = nullptr; static std::vector<rct_object_entry> _invalid_entries;
static sint32 highlighted_index = -1; static sint32 highlighted_index = -1;
static utf8 * file_path = nullptr; static std::string file_path;
/** /**
* Returns an rct_string_id that represents an rct_object_entry's type. * Returns an rct_string_id that represents an rct_object_entry's type.
@ -187,9 +187,7 @@ static void copy_object_names_to_clipboard(rct_window *w)
rct_window * window_object_load_error_open(utf8 * path, size_t numMissingObjects, const rct_object_entry * missingObjects) rct_window * window_object_load_error_open(utf8 * path, size_t numMissingObjects, const rct_object_entry * missingObjects)
{ {
size_t missingObjectsSize = numMissingObjects * sizeof(rct_object_entry); _invalid_entries = std::vector<rct_object_entry>(missingObjects, missingObjects + numMissingObjects);
_invalid_entries = Memory::AllocateArray<rct_object_entry>(numMissingObjects);
memcpy(_invalid_entries, missingObjects, missingObjectsSize);
// Check if window is already open // Check if window is already open
rct_window * window = window_bring_to_front_by_class(WC_OBJECT_LOAD_ERROR); rct_window * window = window_bring_to_front_by_class(WC_OBJECT_LOAD_ERROR);
@ -213,7 +211,7 @@ rct_window * window_object_load_error_open(utf8 * path, size_t numMissingObjects
// Refresh list items and path // Refresh list items and path
window->no_list_items = (uint16)numMissingObjects; window->no_list_items = (uint16)numMissingObjects;
file_path = strndup(path, strnlen(path, MAX_PATH)); file_path = path;
window_invalidate(window); window_invalidate(window);
return window; return window;
@ -221,7 +219,8 @@ rct_window * window_object_load_error_open(utf8 * path, size_t numMissingObjects
static void window_object_load_error_close(rct_window *w) static void window_object_load_error_close(rct_window *w)
{ {
SafeFree(_invalid_entries); _invalid_entries.clear();
_invalid_entries.shrink_to_fit();
} }
static void window_object_load_error_update(rct_window *w) static void window_object_load_error_update(rct_window *w)
@ -303,7 +302,7 @@ static void window_object_load_error_paint(rct_window *w, rct_drawpixelinfo *dpi
// Draw file name // Draw file name
set_format_arg(0, rct_string_id, STR_OBJECT_ERROR_WINDOW_FILE); set_format_arg(0, rct_string_id, STR_OBJECT_ERROR_WINDOW_FILE);
set_format_arg(2, utf8*, file_path); set_format_arg(2, utf8*, file_path.c_str());
gfx_draw_string_left_clipped(dpi, STR_BLACK_STRING, gCommonFormatArgs, COLOUR_BLACK, w->x + 5, w->y + 43, WW-5); gfx_draw_string_left_clipped(dpi, STR_BLACK_STRING, gCommonFormatArgs, COLOUR_BLACK, w->x + 5, w->y + 43, WW-5);
} }

View File

@ -141,7 +141,7 @@ static rct_window_event_list window_title_command_editor_events = {
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,
window_title_command_editor_tool_down, window_title_command_editor_tool_down,
nullptr, nullptr,
nullptr, nullptr,
nullptr, nullptr,

View File

@ -14,42 +14,45 @@
*****************************************************************************/ *****************************************************************************/
#pragma endregion #pragma endregion
#include <openrct2/config/Config.h> #include <vector>
#include <openrct2/scenario/ScenarioRepository.h>
#include <openrct2/scenario/ScenarioSources.h>
#include <openrct2/core/Memory.hpp>
#include <openrct2-ui/windows/Window.h>
#include <openrct2/audio/audio.h> #include <openrct2/audio/audio.h>
#include <openrct2/config/Config.h>
#include <openrct2/interface/themes.h>
#include <openrct2/localisation/Date.h> #include <openrct2/localisation/Date.h>
#include <openrct2/localisation/Localisation.h> #include <openrct2/localisation/Localisation.h>
#include <openrct2/scenario/ScenarioRepository.h>
#include <openrct2/scenario/ScenarioSources.h>
#include <openrct2/sprites.h> #include <openrct2/sprites.h>
#include <openrct2-ui/interface/Widget.h>
#include <openrct2/interface/themes.h>
#include <openrct2/util/Util.h> #include <openrct2/util/Util.h>
#include <openrct2-ui/interface/Widget.h>
#include <openrct2-ui/windows/Window.h>
#define INITIAL_NUM_UNLOCKED_SCENARIOS 5 #define INITIAL_NUM_UNLOCKED_SCENARIOS 5
enum { enum class LIST_ITEM_TYPE : uint8
LIST_ITEM_TYPE_HEADING, {
LIST_ITEM_TYPE_SCENARIO, HEADING,
LIST_ITEM_TYPE_END, SCENARIO,
}; };
typedef struct sc_list_item { struct sc_list_item
uint8 type; {
union { LIST_ITEM_TYPE type;
struct { union
{
struct
{
rct_string_id string_id; rct_string_id string_id;
} heading; } heading;
struct { struct
const scenario_index_entry *scenario; {
const scenario_index_entry * scenario;
bool is_locked; bool is_locked;
} scenario; } scenario;
}; };
} sc_list_item; };
static sc_list_item *_listItems = nullptr; static std::vector<sc_list_item> _listItems;
enum { enum {
WIDX_BACKGROUND, WIDX_BACKGROUND,
@ -250,7 +253,8 @@ static void window_scenarioselect_init_tabs(rct_window *w)
static void window_scenarioselect_close(rct_window *w) static void window_scenarioselect_close(rct_window *w)
{ {
SafeFree(_listItems); _listItems.clear();
_listItems.shrink_to_fit();
} }
static void window_scenarioselect_mouseup(rct_window *w, rct_widgetindex widgetIndex) static void window_scenarioselect_mouseup(rct_window *w, rct_widgetindex widgetIndex)
@ -277,12 +281,14 @@ static void window_scenarioselect_mousedown(rct_window *w, rct_widgetindex widge
static void window_scenarioselect_scrollgetsize(rct_window *w, sint32 scrollIndex, sint32 *width, sint32 *height) static void window_scenarioselect_scrollgetsize(rct_window *w, sint32 scrollIndex, sint32 *width, sint32 *height)
{ {
sint32 y = 0; sint32 y = 0;
for (sc_list_item *listItem = _listItems; listItem->type != LIST_ITEM_TYPE_END; listItem++) { for (const auto &listItem : _listItems)
switch (listItem->type) { {
case LIST_ITEM_TYPE_HEADING: switch (listItem.type)
{
case LIST_ITEM_TYPE::HEADING:
y += 18; y += 18;
break; break;
case LIST_ITEM_TYPE_SCENARIO: case LIST_ITEM_TYPE::SCENARIO:
y += 24; y += 24;
break; break;
} }
@ -296,17 +302,19 @@ static void window_scenarioselect_scrollgetsize(rct_window *w, sint32 scrollInde
*/ */
static void window_scenarioselect_scrollmousedown(rct_window *w, sint32 scrollIndex, sint32 x, sint32 y) static void window_scenarioselect_scrollmousedown(rct_window *w, sint32 scrollIndex, sint32 x, sint32 y)
{ {
for (sc_list_item *listItem = _listItems; listItem->type != LIST_ITEM_TYPE_END; listItem++) { for (const auto &listItem : _listItems)
switch (listItem->type) { {
case LIST_ITEM_TYPE_HEADING: switch (listItem.type)
{
case LIST_ITEM_TYPE::HEADING:
y -= 18; y -= 18;
break; break;
case LIST_ITEM_TYPE_SCENARIO: case LIST_ITEM_TYPE::SCENARIO:
y -= 24; y -= 24;
if (y < 0 && !listItem->scenario.is_locked) { if (y < 0 && !listItem.scenario.is_locked) {
audio_play_sound(SOUND_CLICK_1, 0, w->x + (w->width / 2)); audio_play_sound(SOUND_CLICK_1, 0, w->x + (w->width / 2));
gFirstTimeSaving = true; gFirstTimeSaving = true;
_callback(listItem->scenario.scenario->path); _callback(listItem.scenario.scenario->path);
if (_titleEditor) if (_titleEditor)
{ {
window_close(w); window_close(w);
@ -329,18 +337,20 @@ static void window_scenarioselect_scrollmouseover(rct_window *w, sint32 scrollIn
bool originalShowLockedInformation = _showLockedInformation; bool originalShowLockedInformation = _showLockedInformation;
_showLockedInformation = false; _showLockedInformation = false;
const scenario_index_entry *selected = nullptr; const scenario_index_entry *selected = nullptr;
for (sc_list_item *listItem = _listItems; listItem->type != LIST_ITEM_TYPE_END; listItem++) { for (const auto &listItem : _listItems)
switch (listItem->type) { {
case LIST_ITEM_TYPE_HEADING: switch (listItem.type)
{
case LIST_ITEM_TYPE::HEADING:
y -= 18; y -= 18;
break; break;
case LIST_ITEM_TYPE_SCENARIO: case LIST_ITEM_TYPE::SCENARIO:
y -= 24; y -= 24;
if (y < 0) { if (y < 0) {
if (listItem->scenario.is_locked) { if (listItem.scenario.is_locked) {
_showLockedInformation = true; _showLockedInformation = true;
} else { } else {
selected = listItem->scenario.scenario; selected = listItem.scenario.scenario;
} }
} }
break; break;
@ -483,30 +493,32 @@ static void window_scenarioselect_scrollpaint(rct_window *w, rct_drawpixelinfo *
sint32 listWidth = listWidget->right - listWidget->left - 12; sint32 listWidth = listWidget->right - listWidget->left - 12;
sint32 y = 0; sint32 y = 0;
for (sc_list_item *listItem = _listItems; listItem->type != LIST_ITEM_TYPE_END; listItem++) { for (const auto &listItem : _listItems)
{
if (y > dpi->y + dpi->height) { if (y > dpi->y + dpi->height) {
continue; continue;
} }
switch (listItem->type) { switch (listItem.type)
case LIST_ITEM_TYPE_HEADING: {
case LIST_ITEM_TYPE::HEADING:
{ {
const sint32 horizontalRuleMargin = 4; const sint32 horizontalRuleMargin = 4;
draw_category_heading(w, dpi, horizontalRuleMargin, listWidth - horizontalRuleMargin, y + 2, listItem->heading.string_id); draw_category_heading(w, dpi, horizontalRuleMargin, listWidth - horizontalRuleMargin, y + 2, listItem.heading.string_id);
y += 18; y += 18;
break; break;
} }
case LIST_ITEM_TYPE_SCENARIO: case LIST_ITEM_TYPE::SCENARIO:
{ {
// Draw hover highlight // Draw hover highlight
const scenario_index_entry *scenario = listItem->scenario.scenario; const scenario_index_entry *scenario = listItem.scenario.scenario;
bool isHighlighted = w->highlighted_scenario == scenario; bool isHighlighted = w->highlighted_scenario == scenario;
if (isHighlighted) { if (isHighlighted) {
gfx_filter_rect(dpi, 0, y, w->width, y + 23, PALETTE_DARKEN_1); gfx_filter_rect(dpi, 0, y, w->width, y + 23, PALETTE_DARKEN_1);
} }
bool isCompleted = scenario->highscore != nullptr; bool isCompleted = scenario->highscore != nullptr;
bool isDisabled = listItem->scenario.is_locked; bool isDisabled = listItem.scenario.is_locked;
// Draw scenario name // Draw scenario name
char buffer[64]; char buffer[64];
@ -574,12 +586,8 @@ static void draw_category_heading(rct_window *w, rct_drawpixelinfo *dpi, sint32
static void initialise_list_items(rct_window *w) static void initialise_list_items(rct_window *w)
{ {
SafeFree(_listItems);
size_t numScenarios = scenario_repository_get_count(); size_t numScenarios = scenario_repository_get_count();
size_t capacity = numScenarios + 16; _listItems.clear();
size_t length = 0;
_listItems = Memory::AllocateArray<sc_list_item>(capacity);
// Mega park unlock // Mega park unlock
const uint32 rct1RequiredCompletedScenarios = (1 << SC_MEGA_PARK) - 1; const uint32 rct1RequiredCompletedScenarios = (1 << SC_MEGA_PARK) - 1;
@ -596,8 +604,6 @@ static void initialise_list_items(rct_window *w)
if (_titleEditor && scenario->source_game == SCENARIO_SOURCE_OTHER) if (_titleEditor && scenario->source_game == SCENARIO_SOURCE_OTHER)
continue; continue;
sc_list_item *listItem;
// Category heading // Category heading
rct_string_id headingStringId = STR_NONE; rct_string_id headingStringId = STR_NONE;
if (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN || _titleEditor) { if (gConfigGeneral.scenario_select_mode == SCENARIO_SELECT_MODE_ORIGIN || _titleEditor) {
@ -623,70 +629,69 @@ static void initialise_list_items(rct_window *w)
} }
} }
if (headingStringId != STR_NONE) { if (headingStringId != STR_NONE)
// Ensure list capacity {
if (length == capacity) { sc_list_item headerItem;
capacity += 32; headerItem.type = LIST_ITEM_TYPE::HEADING;
_listItems = Memory::ReallocateArray(_listItems, capacity); headerItem.heading.string_id = headingStringId;
} _listItems.push_back(std::move(headerItem));
listItem = &_listItems[length++];
listItem->type = LIST_ITEM_TYPE_HEADING;
listItem->heading.string_id = headingStringId;
} }
// Ensure list capacity
if (length == capacity) {
capacity += 32;
_listItems = Memory::ReallocateArray(_listItems, capacity);
}
listItem = &_listItems[length++];
// Scenario // Scenario
listItem->type = LIST_ITEM_TYPE_SCENARIO; sc_list_item scenarioItem;
listItem->scenario.scenario = scenario; scenarioItem.type = LIST_ITEM_TYPE::SCENARIO;
if (is_locking_enabled(w)) { scenarioItem.scenario.scenario = scenario;
listItem->scenario.is_locked = numUnlocks <= 0; if (is_locking_enabled(w))
if (scenario->highscore == nullptr) { {
scenarioItem.scenario.is_locked = numUnlocks <= 0;
if (scenario->highscore == nullptr)
{
numUnlocks--; numUnlocks--;
} else { }
else
{
// Mark RCT1 scenario as completed // Mark RCT1 scenario as completed
if (scenario->sc_id < SC_MEGA_PARK) { if (scenario->sc_id < SC_MEGA_PARK)
{
rct1CompletedScenarios |= 1 << scenario->sc_id; rct1CompletedScenarios |= 1 << scenario->sc_id;
} }
} }
// If scenario is Mega Park, keep a reference to it // If scenario is Mega Park, keep a reference to it
if (scenario->sc_id == SC_MEGA_PARK) { if (scenario->sc_id == SC_MEGA_PARK)
megaParkListItemIndex = length - 1; {
megaParkListItemIndex = _listItems.size() - 1;
} }
} else {
listItem->scenario.is_locked = false;
} }
else
{
scenarioItem.scenario.is_locked = false;
}
_listItems.push_back(std::move(scenarioItem));
} }
length++;
_listItems = Memory::ReallocateArray(_listItems, capacity);
_listItems[length - 1].type = LIST_ITEM_TYPE_END;
// Mega park handling // Mega park handling
if (megaParkListItemIndex != SIZE_MAX) { if (megaParkListItemIndex != SIZE_MAX)
{
bool megaParkLocked = (rct1CompletedScenarios & rct1RequiredCompletedScenarios) != rct1RequiredCompletedScenarios; bool megaParkLocked = (rct1CompletedScenarios & rct1RequiredCompletedScenarios) != rct1RequiredCompletedScenarios;
_listItems[megaParkListItemIndex].scenario.is_locked = megaParkLocked; _listItems[megaParkListItemIndex].scenario.is_locked = megaParkLocked;
if (megaParkLocked && gConfigGeneral.scenario_hide_mega_park) { if (megaParkLocked && gConfigGeneral.scenario_hide_mega_park)
{
// Remove mega park // Remove mega park
size_t remainingItems = length - megaParkListItemIndex - 1; _listItems.pop_back();
memmove(&_listItems[megaParkListItemIndex], &_listItems[megaParkListItemIndex + 1], remainingItems);
// Remove empty headings // Remove empty headings
sint32 i = 0; for (auto it = _listItems.begin(); it != _listItems.end(); it++)
for (sc_list_item *listItem = _listItems; listItem->type != LIST_ITEM_TYPE_END; listItem++) { {
if (listItem->type == LIST_ITEM_TYPE_HEADING && (listItem + 1)->type != LIST_ITEM_TYPE_SCENARIO) { const auto &listItem = *it;
remainingItems = length - i - 1; if (listItem.type == LIST_ITEM_TYPE::HEADING)
memmove(&_listItems[i], &_listItems[i + 1], remainingItems); {
listItem--; if ((it + 1) == _listItems.end() ||
} else { (it + 1)->type == LIST_ITEM_TYPE::HEADING)
i++; {
_listItems.erase(it);
it--;
}
} }
} }
} }

View File

@ -14,23 +14,23 @@
*****************************************************************************/ *****************************************************************************/
#pragma endregion #pragma endregion
#include <openrct2-ui/windows/Window.h> #include <algorithm>
#include <vector>
#include <openrct2/audio/audio.h> #include <openrct2/audio/audio.h>
#include <openrct2/Cheats.h> #include <openrct2/Cheats.h>
#include <openrct2/Context.h> #include <openrct2/Context.h>
#include <openrct2/core/Math.hpp> #include <openrct2/core/Math.hpp>
#include <openrct2/core/Memory.hpp>
#include <openrct2/Game.h> #include <openrct2/Game.h>
#include <openrct2/Input.h> #include <openrct2/Input.h>
#include <openrct2-ui/interface/Viewport.h>
#include <openrct2-ui/interface/Widget.h>
#include <openrct2/localisation/Localisation.h> #include <openrct2/localisation/Localisation.h>
#include <openrct2/ride/Track.h> #include <openrct2/ride/Track.h>
#include <openrct2/ride/TrackData.h> #include <openrct2/ride/TrackData.h>
#include <openrct2/ride/TrackDesignRepository.h> #include <openrct2/ride/TrackDesignRepository.h>
#include <openrct2/sprites.h> #include <openrct2/sprites.h>
#include <openrct2/windows/Intent.h> #include <openrct2/windows/Intent.h>
#include <openrct2-ui/interface/Viewport.h>
#include <openrct2-ui/interface/Widget.h>
#include <openrct2-ui/windows/Window.h>
#define TRACK_MINI_PREVIEW_WIDTH 168 #define TRACK_MINI_PREVIEW_WIDTH 168
#define TRACK_MINI_PREVIEW_HEIGHT 78 #define TRACK_MINI_PREVIEW_HEIGHT 78
@ -104,7 +104,7 @@ static rct_window_event_list window_track_place_events = {
nullptr nullptr
}; };
static uint8 *_window_track_place_mini_preview; static std::vector<uint8> _window_track_place_mini_preview;
static sint16 _window_track_place_last_x; static sint16 _window_track_place_last_x;
static sint16 _window_track_place_last_y; static sint16 _window_track_place_last_y;
@ -135,7 +135,7 @@ static uint8 *draw_mini_preview_get_pixel_ptr(LocationXY16 pixel);
*/ */
static void window_track_place_clear_mini_preview() static void window_track_place_clear_mini_preview()
{ {
memset(_window_track_place_mini_preview, PALETTE_INDEX_TRANSPARENT, TRACK_MINI_PREVIEW_SIZE); std::fill(_window_track_place_mini_preview.begin(), _window_track_place_mini_preview.end(), PALETTE_INDEX_TRANSPARENT);
} }
#define swap(x, y) x = x ^ y; y = x ^ y; x = x ^ y; #define swap(x, y) x = x ^ y; y = x ^ y; x = x ^ y;
@ -153,7 +153,7 @@ rct_window * window_track_place_open(const track_design_file_ref *tdFileRef)
window_close_construction_windows(); window_close_construction_windows();
_window_track_place_mini_preview = Memory::Allocate<uint8>(TRACK_MINI_PREVIEW_SIZE); _window_track_place_mini_preview.resize(TRACK_MINI_PREVIEW_SIZE);
rct_window *w = window_create( rct_window *w = window_create(
0, 0,
@ -198,7 +198,8 @@ static void window_track_place_close(rct_window *w)
gMapSelectFlags &= ~MAP_SELECT_FLAG_ENABLE_CONSTRUCT; gMapSelectFlags &= ~MAP_SELECT_FLAG_ENABLE_CONSTRUCT;
gMapSelectFlags &= ~MAP_SELECT_FLAG_ENABLE_ARROW; gMapSelectFlags &= ~MAP_SELECT_FLAG_ENABLE_ARROW;
hide_gridlines(); hide_gridlines();
SafeFree(_window_track_place_mini_preview); _window_track_place_mini_preview.clear();
_window_track_place_mini_preview.shrink_to_fit();
track_design_dispose(_trackDesign); track_design_dispose(_trackDesign);
_trackDesign = nullptr; _trackDesign = nullptr;
} }
@ -468,7 +469,7 @@ static void window_track_place_paint(rct_window *w, rct_drawpixelinfo *dpi)
rct_drawpixelinfo clippedDpi; rct_drawpixelinfo clippedDpi;
if (clip_drawpixelinfo(&clippedDpi, dpi, w->x + 4, w->y + 18, 168, 78)) { if (clip_drawpixelinfo(&clippedDpi, dpi, w->x + 4, w->y + 18, 168, 78)) {
rct_g1_element g1temp = { nullptr }; rct_g1_element g1temp = { nullptr };
g1temp.offset = _window_track_place_mini_preview; g1temp.offset = _window_track_place_mini_preview.data();
g1temp.width = TRACK_MINI_PREVIEW_WIDTH; g1temp.width = TRACK_MINI_PREVIEW_WIDTH;
g1temp.height = TRACK_MINI_PREVIEW_HEIGHT; g1temp.height = TRACK_MINI_PREVIEW_HEIGHT;
gfx_set_g1_element(SPR_TEMP, &g1temp); gfx_set_g1_element(SPR_TEMP, &g1temp);

View File

@ -14,12 +14,10 @@
*****************************************************************************/ *****************************************************************************/
#pragma endregion #pragma endregion
#include <openrct2-ui/windows/Window.h> #include <vector>
#include <openrct2/audio/audio.h> #include <openrct2/audio/audio.h>
#include <openrct2/Context.h> #include <openrct2/Context.h>
#include <openrct2/core/Math.hpp> #include <openrct2/core/Math.hpp>
#include <openrct2/core/Memory.hpp>
#include <openrct2/core/String.hpp> #include <openrct2/core/String.hpp>
#include <openrct2/drawing/IDrawingEngine.h> #include <openrct2/drawing/IDrawingEngine.h>
#include <openrct2/Editor.h> #include <openrct2/Editor.h>
@ -30,7 +28,7 @@
#include <openrct2/ride/TrackDesignRepository.h> #include <openrct2/ride/TrackDesignRepository.h>
#include <openrct2/sprites.h> #include <openrct2/sprites.h>
#include <openrct2/windows/Intent.h> #include <openrct2/windows/Intent.h>
#include <vector> #include <openrct2-ui/windows/Window.h>
enum { enum {
WIDX_BACKGROUND, WIDX_BACKGROUND,
@ -108,13 +106,12 @@ static rct_window_event_list window_track_list_events = {
ride_list_item _window_track_list_item; ride_list_item _window_track_list_item;
static track_design_file_ref * _trackDesigns = nullptr; static std::vector<track_design_file_ref> _trackDesigns;
static size_t _trackDesignsCount = 0;
static utf8 _filterString[USER_STRING_MAX_LENGTH]; static utf8 _filterString[USER_STRING_MAX_LENGTH];
static std::vector<uint16> _filteredTrackIds; static std::vector<uint16> _filteredTrackIds;
static uint16 _loadedTrackDesignIndex; static uint16 _loadedTrackDesignIndex;
static rct_track_td6 * _loadedTrackDesign; static rct_track_td6 * _loadedTrackDesign;
static uint8 * _trackDesignPreviewPixels; static std::vector<uint8> _trackDesignPreviewPixels;
static void track_list_load_designs(ride_list_item item); static void track_list_load_designs(ride_list_item item);
static bool track_list_load_design_for_preview(utf8 *path); static bool track_list_load_design_for_preview(utf8 *path);
@ -171,7 +168,7 @@ rct_window * window_track_list_open(ride_list_item item)
// Start with first track highlighted // Start with first track highlighted
w->selected_list_item = 0; w->selected_list_item = 0;
if (_trackDesignsCount != 0 && !(gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER)) { if (_trackDesigns.size() != 0 && !(gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER)) {
w->selected_list_item = 1; w->selected_list_item = 1;
} }
@ -179,7 +176,7 @@ rct_window * window_track_list_open(ride_list_item item)
window_push_others_right(w); window_push_others_right(w);
_currentTrackPieceDirection = 2; _currentTrackPieceDirection = 2;
_trackDesignPreviewPixels = Memory::AllocateArray<uint8>(4 * TRACK_PREVIEW_IMAGE_SIZE); _trackDesignPreviewPixels.resize(4 * TRACK_PREVIEW_IMAGE_SIZE);
_loadedTrackDesign = nullptr; _loadedTrackDesign = nullptr;
_loadedTrackDesignIndex = TRACK_DESIGN_INDEX_UNLOADED; _loadedTrackDesignIndex = TRACK_DESIGN_INDEX_UNLOADED;
@ -194,7 +191,7 @@ static void window_track_list_filter_list()
// Nothing to filter, so fill the list with all indices // Nothing to filter, so fill the list with all indices
if (String::LengthOf(_filterString) == 0) if (String::LengthOf(_filterString) == 0)
{ {
for (uint16 i = 0; i < _trackDesignsCount; i++) for (uint16 i = 0; i < _trackDesigns.size(); i++)
_filteredTrackIds.push_back(i); _filteredTrackIds.push_back(i);
return; return;
@ -207,7 +204,7 @@ static void window_track_list_filter_list()
filterStringLower[i] = (utf8)tolower(filterStringLower[i]); filterStringLower[i] = (utf8)tolower(filterStringLower[i]);
// Fill the set with indices for tracks that match the filter // Fill the set with indices for tracks that match the filter
for (uint16 i = 0; i < _trackDesignsCount; i++) for (uint16 i = 0; i < _trackDesigns.size(); i++)
{ {
utf8 trackNameLower[USER_STRING_MAX_LENGTH]; utf8 trackNameLower[USER_STRING_MAX_LENGTH];
String::Set(trackNameLower, sizeof(trackNameLower), _trackDesigns[i].name); String::Set(trackNameLower, sizeof(trackNameLower), _trackDesigns[i].name);
@ -230,15 +227,16 @@ static void window_track_list_close(rct_window *w)
// Dispose track design and preview // Dispose track design and preview
track_design_dispose(_loadedTrackDesign); track_design_dispose(_loadedTrackDesign);
_loadedTrackDesign = nullptr; _loadedTrackDesign = nullptr;
SafeFree(_trackDesignPreviewPixels); _trackDesignPreviewPixels.clear();
_trackDesignPreviewPixels.shrink_to_fit();
// Dispose track list // Dispose track list
for (size_t i = 0; i < _trackDesignsCount; i++) { for (auto &trackDesign : _trackDesigns)
free(_trackDesigns[i].name); {
free(_trackDesigns[i].path); free(trackDesign.name);
free(trackDesign.path);
} }
SafeFree(_trackDesigns); _trackDesigns.clear();
_trackDesignsCount = 0;
// If gScreenAge is zero, we're already in the process // If gScreenAge is zero, we're already in the process
// of loading the track manager, so we shouldn't try // of loading the track manager, so we shouldn't try
@ -501,7 +499,7 @@ static void window_track_list_paint(rct_window *w, rct_drawpixelinfo *dpi)
sint32 listItemIndex = w->selected_list_item; sint32 listItemIndex = w->selected_list_item;
if (gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER) if (gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER)
{ {
if (_trackDesignsCount == 0 || listItemIndex == -1) if (_trackDesigns.size() == 0 || listItemIndex == -1)
return; return;
} }
else { else {
@ -538,7 +536,7 @@ static void window_track_list_paint(rct_window *w, rct_drawpixelinfo *dpi)
} }
rct_g1_element g1temp = { nullptr }; rct_g1_element g1temp = { nullptr };
g1temp.offset = _trackDesignPreviewPixels + (_currentTrackPieceDirection * TRACK_PREVIEW_IMAGE_SIZE); g1temp.offset = _trackDesignPreviewPixels.data() + (_currentTrackPieceDirection * TRACK_PREVIEW_IMAGE_SIZE);
g1temp.width = 370; g1temp.width = 370;
g1temp.height = 217; g1temp.height = 217;
g1temp.flags = G1_FLAG_BMP; g1temp.flags = G1_FLAG_BMP;
@ -684,7 +682,7 @@ static void window_track_list_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi,
sint32 y = 0; sint32 y = 0;
size_t listIndex = 0; size_t listIndex = 0;
if (gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER) { if (gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER) {
if (_trackDesignsCount == 0) { if (_trackDesigns.size() == 0) {
// No track designs // No track designs
gfx_draw_string_left(dpi, STR_NO_TRACK_DESIGNS_OF_THIS_TYPE, nullptr, COLOUR_BLACK, x, y - 1); gfx_draw_string_left(dpi, STR_NO_TRACK_DESIGNS_OF_THIS_TYPE, nullptr, COLOUR_BLACK, x, y - 1);
return; return;
@ -735,6 +733,7 @@ static void window_track_list_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi,
static void track_list_load_designs(ride_list_item item) static void track_list_load_designs(ride_list_item item)
{ {
auto repo = GetTrackDesignRepository();
if (!RideGroupManager::RideTypeHasRideGroups(item.type)) if (!RideGroupManager::RideTypeHasRideGroups(item.type))
{ {
char entry[9]; char entry[9];
@ -747,13 +746,14 @@ static void track_list_load_designs(ride_list_item item)
entryPtr = entry; entryPtr = entry;
} }
} }
_trackDesignsCount = track_repository_get_items_for_ride(&_trackDesigns, item.type, entryPtr);
_trackDesigns = repo->GetItemsForObjectEntry(item.type, String::ToStd(entryPtr));
} }
else else
{ {
rct_ride_entry *rideEntry = get_ride_entry(item.entry_index); auto rideEntry = get_ride_entry(item.entry_index);
const RideGroup * rideGroup = RideGroupManager::GetRideGroup(item.type, rideEntry); auto rideGroup = RideGroupManager::GetRideGroup(item.type, rideEntry);
_trackDesignsCount = track_repository_get_items_for_ride_group(&_trackDesigns, item.type, rideGroup); _trackDesigns = repo->GetItemsForRideGroup(item.type, rideGroup);
} }
window_track_list_filter_list(); window_track_list_filter_list();
@ -767,7 +767,7 @@ static bool track_list_load_design_for_preview(utf8 *path)
_loadedTrackDesign = track_design_open(path); _loadedTrackDesign = track_design_open(path);
if (_loadedTrackDesign != nullptr && drawing_engine_get_type() != DRAWING_ENGINE_OPENGL) { if (_loadedTrackDesign != nullptr && drawing_engine_get_type() != DRAWING_ENGINE_OPENGL) {
track_design_draw_preview(_loadedTrackDesign, _trackDesignPreviewPixels); track_design_draw_preview(_loadedTrackDesign, _trackDesignPreviewPixels.data());
return true; return true;
} }
return false; return false;

View File

@ -99,6 +99,8 @@ private:
return DIRBASE::RCT1; return DIRBASE::RCT1;
case PATHID::SCORES_RCT2: case PATHID::SCORES_RCT2:
return DIRBASE::RCT2; return DIRBASE::RCT2;
case PATHID::CHANGELOG:
return DIRBASE::DOCUMENTATION;
case PATHID::NETWORK_GROUPS: case PATHID::NETWORK_GROUPS:
case PATHID::NETWORK_SERVERS: case PATHID::NETWORK_SERVERS:
case PATHID::NETWORK_USERS: case PATHID::NETWORK_USERS:
@ -134,6 +136,7 @@ IPlatformEnvironment * OpenRCT2::CreatePlatformEnvironment()
basePaths[(size_t)DIRBASE::USER] = Path::Combine(Platform::GetFolderPath(SPECIAL_FOLDER::USER_DATA), subDirectory); basePaths[(size_t)DIRBASE::USER] = Path::Combine(Platform::GetFolderPath(SPECIAL_FOLDER::USER_DATA), subDirectory);
basePaths[(size_t)DIRBASE::CONFIG] = Path::Combine(Platform::GetFolderPath(SPECIAL_FOLDER::USER_CONFIG), subDirectory); basePaths[(size_t)DIRBASE::CONFIG] = Path::Combine(Platform::GetFolderPath(SPECIAL_FOLDER::USER_CONFIG), subDirectory);
basePaths[(size_t)DIRBASE::CACHE] = Path::Combine(Platform::GetFolderPath(SPECIAL_FOLDER::USER_CACHE), subDirectory); basePaths[(size_t)DIRBASE::CACHE] = Path::Combine(Platform::GetFolderPath(SPECIAL_FOLDER::USER_CACHE), subDirectory);
basePaths[(size_t)DIRBASE::DOCUMENTATION] = Platform::GetDocsPath();
// Override paths that have been specified via the command line // Override paths that have been specified via the command line
if (!String::IsNullOrEmpty(gCustomRCT2DataPath)) if (!String::IsNullOrEmpty(gCustomRCT2DataPath))
@ -151,6 +154,11 @@ IPlatformEnvironment * OpenRCT2::CreatePlatformEnvironment()
basePaths[(size_t)DIRBASE::CACHE] = gCustomUserDataPath; basePaths[(size_t)DIRBASE::CACHE] = gCustomUserDataPath;
} }
if (basePaths[(size_t)DIRBASE::DOCUMENTATION].empty())
{
basePaths[(size_t)DIRBASE::DOCUMENTATION] = basePaths[(size_t)DIRBASE::OPENRCT2];
}
auto env = OpenRCT2::CreatePlatformEnvironment(basePaths); auto env = OpenRCT2::CreatePlatformEnvironment(basePaths);
// Now load the config so we can get the RCT1 and RCT2 paths // Now load the config so we can get the RCT1 and RCT2 paths
@ -206,7 +214,7 @@ const char * PlatformEnvironment::DirectoryNamesOpenRCT2[] =
"scenario", // SCENARIO "scenario", // SCENARIO
"screenshot", // SCREENSHOT "screenshot", // SCREENSHOT
"sequence", // SEQUENCE "sequence", // SEQUENCE
"shader", // SHADER "shaders", // SHADER
"themes", // THEME "themes", // THEME
"track", // TRACK "track", // TRACK
}; };
@ -225,5 +233,6 @@ const char * PlatformEnvironment::FileNames[] =
"highscores.dat", // SCORES "highscores.dat", // SCORES
"scores.dat", // SCORES (LEGACY) "scores.dat", // SCORES (LEGACY)
"Saved Games" PATH_SEPARATOR "scores.dat", // SCORES (RCT2) "Saved Games" PATH_SEPARATOR "scores.dat", // SCORES (RCT2)
"changelog.txt" // CHANGELOG
}; };
// clang-format on // clang-format on

View File

@ -31,8 +31,9 @@ namespace OpenRCT2
USER, // Base directory for OpenRCT2 user content. USER, // Base directory for OpenRCT2 user content.
CONFIG, // Base directory for OpenRCT2 configuration. CONFIG, // Base directory for OpenRCT2 configuration.
CACHE, // Base directory for OpenRCT2 cache files. CACHE, // Base directory for OpenRCT2 cache files.
DOCUMENTATION, // Base directory for OpenRCT2 doc files.
}; };
constexpr sint32 DIRBASE_COUNT = 6; constexpr sint32 DIRBASE_COUNT = 7;
using DIRBASE_VALUES = std::string[DIRBASE_COUNT]; using DIRBASE_VALUES = std::string[DIRBASE_COUNT];
enum class DIRID enum class DIRID
@ -67,6 +68,7 @@ namespace OpenRCT2
SCORES, // Scenario scores (highscores.dat). SCORES, // Scenario scores (highscores.dat).
SCORES_LEGACY, // Scenario scores, legacy (scores.dat). SCORES_LEGACY, // Scenario scores, legacy (scores.dat).
SCORES_RCT2, // Scenario scores, rct2 (\Saved Games\scores.dat). SCORES_RCT2, // Scenario scores, rct2 (\Saved Games\scores.dat).
CHANGELOG, // Notable changes to the game between versions, distributed with the game.
}; };
/** /**

View File

@ -69,11 +69,6 @@ float platform_get_default_scale() {
return displayScale; return displayScale;
} }
void platform_get_changelog_path(utf8 *outPath, size_t outSize)
{
STUB();
}
bool platform_get_steam_path(utf8 * outPath, size_t outSize) bool platform_get_steam_path(utf8 * outPath, size_t outSize)
{ {
return false; return false;

View File

@ -108,27 +108,6 @@ void platform_posix_sub_resolve_openrct_data_path(utf8 *out, size_t size) {
} }
} }
/**
* Default directory fallback is:
* - <exePath>/doc
* - /usr/share/doc/openrct2
*/
static void platform_posix_sub_resolve_openrct_doc_path(utf8 *out, size_t size) {
static const utf8 *searchLocations[] = {
"./doc",
"/usr/share/doc/openrct2",
};
for (auto searchLocation : searchLocations)
{
log_verbose("Looking for OpenRCT2 doc path at %s", searchLocation);
if (platform_directory_exists(searchLocation))
{
safe_strcpy(out, searchLocation, size);
return;
}
}
}
uint16 platform_get_locale_language(){ uint16 platform_get_locale_language(){
const char *langString = setlocale(LC_MESSAGES, ""); const char *langString = setlocale(LC_MESSAGES, "");
if(langString != NULL){ if(langString != NULL){
@ -218,12 +197,6 @@ uint8 platform_get_locale_measurement_format(){
return MEASUREMENT_FORMAT_METRIC; return MEASUREMENT_FORMAT_METRIC;
} }
void platform_get_changelog_path(utf8 *outPath, size_t outSize)
{
platform_posix_sub_resolve_openrct_doc_path(outPath, outSize);
safe_strcat_path(outPath, "changelog.txt", outSize);
}
bool platform_get_steam_path(utf8 * outPath, size_t outSize) bool platform_get_steam_path(utf8 * outPath, size_t outSize)
{ {
const char * steamRoot = getenv("STEAMROOT"); const char * steamRoot = getenv("STEAMROOT");

View File

@ -34,6 +34,11 @@ namespace Platform
return std::string(); return std::string();
} }
} }
std::string GetDocsPath()
{
return std::string();
}
} }
#endif #endif

View File

@ -18,6 +18,7 @@
#include <pwd.h> #include <pwd.h>
#include "../core/Path.hpp" #include "../core/Path.hpp"
#include "platform.h"
#include "Platform2.h" #include "Platform2.h"
namespace Platform namespace Platform
@ -44,6 +45,24 @@ namespace Platform
return std::string(); return std::string();
} }
} }
std::string GetDocsPath()
{
static const utf8 * searchLocations[] =
{
"./doc",
"/usr/share/doc/openrct2",
};
for (auto searchLocation : searchLocations)
{
log_verbose("Looking for OpenRCT2 doc path at %s", searchLocation);
if (platform_directory_exists(searchLocation))
{
return searchLocation;
}
}
return std::string();
}
} }
#endif #endif

View File

@ -147,6 +147,11 @@ namespace Platform
return path; return path;
} }
std::string GetDocsPath()
{
return std::string();
}
static SYSTEMTIME TimeToSystemTime(std::time_t timestamp) static SYSTEMTIME TimeToSystemTime(std::time_t timestamp)
{ {
LONGLONG ll = Int32x32To64(timestamp, 10000000) + 116444736000000000; LONGLONG ll = Int32x32To64(timestamp, 10000000) + 116444736000000000;

View File

@ -39,6 +39,11 @@ namespace Platform
return std::string(); return std::string();
} }
} }
std::string GetDocsPath()
{
return std::string();
}
} }
#endif #endif

View File

@ -36,6 +36,7 @@ namespace Platform
std::string GetEnvironmentVariable(const std::string &name); std::string GetEnvironmentVariable(const std::string &name);
std::string GetFolderPath(SPECIAL_FOLDER folder); std::string GetFolderPath(SPECIAL_FOLDER folder);
std::string GetInstallPath(); std::string GetInstallPath();
std::string GetDocsPath();
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__FreeBSD__) #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__FreeBSD__)
std::string GetEnvironmentPath(const char * name); std::string GetEnvironmentPath(const char * name);

View File

@ -244,12 +244,6 @@ void platform_get_openrct_data_path(utf8 *outPath, size_t outSize)
safe_strcpy(outPath, _openrctDataDirectoryPath, outSize); safe_strcpy(outPath, _openrctDataDirectoryPath, outSize);
} }
void platform_get_changelog_path(utf8 *outPath, size_t outSize)
{
safe_strcpy(outPath, gExePath, outSize);
safe_strcat_path(outPath, "changelog.txt", outSize);
}
bool platform_get_steam_path(utf8 * outPath, size_t outSize) bool platform_get_steam_path(utf8 * outPath, size_t outSize)
{ {
wchar_t * wSteamPath; wchar_t * wSteamPath;

View File

@ -127,7 +127,6 @@ uint8 platform_get_locale_measurement_format();
uint8 platform_get_locale_temperature_format(); uint8 platform_get_locale_temperature_format();
uint8 platform_get_locale_date_format(); uint8 platform_get_locale_date_format();
bool platform_process_is_elevated(); bool platform_process_is_elevated();
void platform_get_changelog_path(utf8 *outPath, size_t outSize);
bool platform_get_steam_path(utf8 * outPath, size_t outSize); bool platform_get_steam_path(utf8 * outPath, size_t outSize);
#ifndef NO_TTF #ifndef NO_TTF

View File

@ -114,7 +114,7 @@ rct_track_td6 * track_design_open(const utf8 * path)
if (td6 != nullptr) if (td6 != nullptr)
{ {
td6->name = track_repository_get_name_from_path(path); td6->name = String::Duplicate(GetNameFromTrackPath(path).c_str());
return td6; return td6;
} }
} }

View File

@ -49,7 +49,7 @@ enum TRACK_REPO_ITEM_FLAGS
TRIF_READ_ONLY = (1 << 0), TRIF_READ_ONLY = (1 << 0),
}; };
static std::string GetNameFromTrackPath(const std::string &path) std::string GetNameFromTrackPath(const std::string &path)
{ {
std::string name = Path::GetFileNameWithoutExtension(path); std::string name = Path::GetFileNameWithoutExtension(path);
//The track name should be the file name until the first instance of a dot //The track name should be the file name until the first instance of a dot
@ -222,7 +222,7 @@ public:
* @param entry The entry name to build a track list for. Leave empty to build track list for the non-separated types (e.g. Hyper-Twister, Car Ride) * @param entry The entry name to build a track list for. Leave empty to build track list for the non-separated types (e.g. Hyper-Twister, Car Ride)
* @return * @return
*/ */
size_t GetItemsForObjectEntry(track_design_file_ref * * outRefs, uint8 rideType, const std::string &entry) const override std::vector<track_design_file_ref> GetItemsForObjectEntry(uint8 rideType, const std::string &entry) const override
{ {
std::vector<track_design_file_ref> refs; std::vector<track_design_file_ref> refs;
const IObjectRepository * repo = GetObjectRepository(); const IObjectRepository * repo = GetObjectRepository();
@ -252,11 +252,10 @@ public:
} }
} }
*outRefs = Collections::ToArray(refs); return refs;
return refs.size();
} }
size_t GetItemsForRideGroup(track_design_file_ref **outRefs, uint8 rideType, const RideGroup * rideGroup) const override std::vector<track_design_file_ref> GetItemsForRideGroup(uint8 rideType, const RideGroup * rideGroup) const override
{ {
std::vector<track_design_file_ref> refs; std::vector<track_design_file_ref> refs;
const IObjectRepository * repo = GetObjectRepository(); const IObjectRepository * repo = GetObjectRepository();
@ -281,8 +280,7 @@ public:
} }
} }
*outRefs = Collections::ToArray(refs); return refs;
return refs.size();
} }
void Scan() override void Scan() override
@ -418,18 +416,6 @@ extern "C"
repo->Scan(); repo->Scan();
} }
size_t track_repository_get_items_for_ride(track_design_file_ref * * outRefs, uint8 rideType, const utf8 * entry)
{
ITrackDesignRepository * repo = GetTrackDesignRepository();
return repo->GetItemsForObjectEntry(outRefs, rideType, String::ToStd(entry));
}
size_t track_repository_get_items_for_ride_group(track_design_file_ref * * outRefs, uint8 rideType, const RideGroup * rideGroup)
{
ITrackDesignRepository * repo = GetTrackDesignRepository();
return repo->GetItemsForRideGroup(outRefs, rideType, rideGroup);
}
bool track_repository_delete(const utf8 * path) bool track_repository_delete(const utf8 * path)
{ {
ITrackDesignRepository * repo = GetTrackDesignRepository(); ITrackDesignRepository * repo = GetTrackDesignRepository();
@ -449,9 +435,4 @@ extern "C"
std::string newPath = repo->Install(srcPath); std::string newPath = repo->Install(srcPath);
return !newPath.empty(); return !newPath.empty();
} }
utf8 * track_repository_get_name_from_path(const utf8 * path)
{
return String::Duplicate(GetNameFromTrackPath(path));
}
} }

View File

@ -42,12 +42,10 @@ interface ITrackDesignRepository
virtual size_t GetCount() const abstract; virtual size_t GetCount() const abstract;
virtual size_t GetCountForObjectEntry(uint8 rideType, const std::string &entry) const abstract; virtual size_t GetCountForObjectEntry(uint8 rideType, const std::string &entry) const abstract;
virtual size_t GetCountForRideGroup(uint8 rideType, const RideGroup * rideGroup) const abstract; virtual size_t GetCountForRideGroup(uint8 rideType, const RideGroup * rideGroup) const abstract;
virtual size_t GetItemsForObjectEntry(track_design_file_ref * * outRefs, virtual std::vector<track_design_file_ref> GetItemsForObjectEntry(uint8 rideType,
uint8 rideType, const std::string &entry) const abstract;
const std::string &entry) const abstract; virtual std::vector<track_design_file_ref> GetItemsForRideGroup(uint8 rideType,
virtual size_t GetItemsForRideGroup(track_design_file_ref **outRefs, const RideGroup * rideGroup) const abstract;
uint8 rideType,
const RideGroup * rideGroup) const abstract;
virtual void Scan() abstract; virtual void Scan() abstract;
virtual bool Delete(const std::string &path) abstract; virtual bool Delete(const std::string &path) abstract;
@ -57,6 +55,7 @@ interface ITrackDesignRepository
ITrackDesignRepository * CreateTrackDesignRepository(OpenRCT2::IPlatformEnvironment * env); ITrackDesignRepository * CreateTrackDesignRepository(OpenRCT2::IPlatformEnvironment * env);
ITrackDesignRepository * GetTrackDesignRepository(); ITrackDesignRepository * GetTrackDesignRepository();
std::string GetNameFromTrackPath(const std::string &path);
#endif #endif
@ -65,9 +64,6 @@ extern "C"
{ {
#endif #endif
void track_repository_scan(); void track_repository_scan();
size_t track_repository_get_items_for_ride(track_design_file_ref * * outRefs, uint8 rideType, const utf8 * entry);
size_t track_repository_get_items_for_ride_group(track_design_file_ref * * outRefs, uint8 rideType, const RideGroup * rideGroup);
utf8 * track_repository_get_name_from_path(const utf8 *path);
bool track_repository_delete(const utf8 *path); bool track_repository_delete(const utf8 *path);
bool track_repository_rename(const utf8 *path, const utf8 *newName); bool track_repository_rename(const utf8 *path, const utf8 *newName);
bool track_repository_install(const utf8 *srcPath); bool track_repository_install(const utf8 *srcPath);