mirror of https://github.com/OpenRCT2/OpenRCT2.git
clang-format ui/util/windows
This commit is contained in:
parent
abb097124c
commit
adb69a2fe8
|
@ -16,48 +16,122 @@ using namespace OpenRCT2::Drawing;
|
||||||
namespace OpenRCT2::Ui
|
namespace OpenRCT2::Ui
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Represents the window or screen that OpenRCT2 is presented on.
|
* Represents the window or screen that OpenRCT2 is presented on.
|
||||||
*/
|
*/
|
||||||
class DummyUiContext final : public IUiContext
|
class DummyUiContext final : public IUiContext
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
IWindowManager * const _windowManager = CreateDummyWindowManager();
|
IWindowManager* const _windowManager = CreateDummyWindowManager();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Update() override { }
|
void Update() override
|
||||||
void Draw(rct_drawpixelinfo * /*dpi*/) override { }
|
{
|
||||||
|
}
|
||||||
|
void Draw(rct_drawpixelinfo* /*dpi*/) override
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void CreateWindow() override { }
|
void CreateWindow() override
|
||||||
void CloseWindow() override { }
|
{
|
||||||
void RecreateWindow() override { }
|
}
|
||||||
void * GetWindow() override { return nullptr; }
|
void CloseWindow() override
|
||||||
int32_t GetWidth() override { return 0; }
|
{
|
||||||
int32_t GetHeight() override { return 0; }
|
}
|
||||||
int32_t GetScaleQuality() override { return 0; }
|
void RecreateWindow() override
|
||||||
void SetFullscreenMode(FULLSCREEN_MODE /*mode*/) override { }
|
{
|
||||||
std::vector<Resolution> GetFullscreenResolutions() override { return std::vector<Resolution>(); }
|
}
|
||||||
bool HasFocus() override { return false; }
|
void* GetWindow() override
|
||||||
bool IsMinimised() override { return false; }
|
{
|
||||||
bool IsSteamOverlayActive() override { return false; }
|
return nullptr;
|
||||||
void ProcessMessages() override { }
|
}
|
||||||
void TriggerResize() override { }
|
int32_t GetWidth() override
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int32_t GetHeight() override
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int32_t GetScaleQuality() override
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
void SetFullscreenMode(FULLSCREEN_MODE /*mode*/) override
|
||||||
|
{
|
||||||
|
}
|
||||||
|
std::vector<Resolution> GetFullscreenResolutions() override
|
||||||
|
{
|
||||||
|
return std::vector<Resolution>();
|
||||||
|
}
|
||||||
|
bool HasFocus() override
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool IsMinimised() override
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool IsSteamOverlayActive() override
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
void ProcessMessages() override
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void TriggerResize() override
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void ShowMessageBox(const std::string &/*message*/) override { }
|
void ShowMessageBox(const std::string& /*message*/) override
|
||||||
std::string ShowFileDialog(const FileDialogDesc &/*desc*/) override { return std::string(); }
|
{
|
||||||
std::string ShowDirectoryDialog(const std::string &/*title*/) override { return std::string(); }
|
}
|
||||||
|
std::string ShowFileDialog(const FileDialogDesc& /*desc*/) override
|
||||||
|
{
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
std::string ShowDirectoryDialog(const std::string& /*title*/) override
|
||||||
|
{
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
|
||||||
// Input
|
// Input
|
||||||
const CursorState * GetCursorState() override { return nullptr; }
|
const CursorState* GetCursorState() override
|
||||||
CURSOR_ID GetCursor() override { return CURSOR_ARROW; }
|
{
|
||||||
void SetCursor(CURSOR_ID /*cursor*/) override { }
|
return nullptr;
|
||||||
void SetCursorScale(uint8_t /*scale*/) override { }
|
}
|
||||||
void SetCursorVisible(bool /*value*/) override { }
|
CURSOR_ID GetCursor() override
|
||||||
void GetCursorPosition(int32_t * /*x*/, int32_t * /*y*/) override { }
|
{
|
||||||
void SetCursorPosition(int32_t /*x*/, int32_t /*y*/) override { }
|
return CURSOR_ARROW;
|
||||||
void SetCursorTrap(bool /*value*/) override { }
|
}
|
||||||
const uint8_t * GetKeysState() override { return nullptr; }
|
void SetCursor(CURSOR_ID /*cursor*/) override
|
||||||
const uint8_t * GetKeysPressed() override { return nullptr; }
|
{
|
||||||
void SetKeysPressed(uint32_t /*keysym*/, uint8_t /*scancode*/) override { }
|
}
|
||||||
|
void SetCursorScale(uint8_t /*scale*/) override
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void SetCursorVisible(bool /*value*/) override
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void GetCursorPosition(int32_t* /*x*/, int32_t* /*y*/) override
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void SetCursorPosition(int32_t /*x*/, int32_t /*y*/) override
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void SetCursorTrap(bool /*value*/) override
|
||||||
|
{
|
||||||
|
}
|
||||||
|
const uint8_t* GetKeysState() override
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
const uint8_t* GetKeysPressed() override
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
void SetKeysPressed(uint32_t /*keysym*/, uint8_t /*scancode*/) override
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
class X8DrawingEngineFactory final : public IDrawingEngineFactory
|
class X8DrawingEngineFactory final : public IDrawingEngineFactory
|
||||||
{
|
{
|
||||||
|
@ -73,10 +147,15 @@ namespace OpenRCT2::Ui
|
||||||
{
|
{
|
||||||
return std::make_shared<X8DrawingEngineFactory>();
|
return std::make_shared<X8DrawingEngineFactory>();
|
||||||
}
|
}
|
||||||
void DrawRainAnimation(IRainDrawer* rainDrawer, rct_drawpixelinfo* dpi, DrawRainFunc drawFunc) override { }
|
void DrawRainAnimation(IRainDrawer* rainDrawer, rct_drawpixelinfo* dpi, DrawRainFunc drawFunc) override
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
// Text input
|
// Text input
|
||||||
bool IsTextInputActive() override { return false; }
|
bool IsTextInputActive() override
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
TextInputSession* StartTextInput([[maybe_unused]] utf8* buffer, [[maybe_unused]] size_t bufferSize) override
|
TextInputSession* StartTextInput([[maybe_unused]] utf8* buffer, [[maybe_unused]] size_t bufferSize) override
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -87,7 +166,7 @@ namespace OpenRCT2::Ui
|
||||||
}
|
}
|
||||||
|
|
||||||
// In-game UI
|
// In-game UI
|
||||||
IWindowManager * GetWindowManager() override
|
IWindowManager* GetWindowManager() override
|
||||||
{
|
{
|
||||||
return _windowManager;
|
return _windowManager;
|
||||||
}
|
}
|
||||||
|
@ -98,9 +177,15 @@ namespace OpenRCT2::Ui
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ITitleSequencePlayer * GetTitleSequencePlayer() override { return nullptr; }
|
ITitleSequencePlayer* GetTitleSequencePlayer() override
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
~DummyUiContext() { delete _windowManager; }
|
~DummyUiContext()
|
||||||
|
{
|
||||||
|
delete _windowManager;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::shared_ptr<IUiContext> CreateDummyUiContext()
|
std::shared_ptr<IUiContext> CreateDummyUiContext()
|
||||||
|
|
|
@ -13,24 +13,59 @@ namespace OpenRCT2::Ui
|
||||||
{
|
{
|
||||||
class DummyWindowManager final : public IWindowManager
|
class DummyWindowManager final : public IWindowManager
|
||||||
{
|
{
|
||||||
void Init() override {};
|
void Init() override{};
|
||||||
rct_window * OpenWindow(rct_windowclass /*wc*/) override { return nullptr; }
|
rct_window* OpenWindow(rct_windowclass /*wc*/) override
|
||||||
rct_window * OpenView(uint8_t /*view*/) override { return nullptr; }
|
{
|
||||||
rct_window * OpenDetails(uint8_t /*type*/, int32_t /*id*/) override { return nullptr; }
|
return nullptr;
|
||||||
rct_window * ShowError(rct_string_id /*title*/, rct_string_id /*message*/) override { return nullptr; }
|
}
|
||||||
rct_window * OpenIntent(Intent * /*intent*/) override { return nullptr; };
|
rct_window* OpenView(uint8_t /*view*/) override
|
||||||
void BroadcastIntent(const Intent &/*intent*/) override { }
|
{
|
||||||
void ForceClose(rct_windowclass /*windowClass*/) override { }
|
return nullptr;
|
||||||
void UpdateMapTooltip() override { }
|
}
|
||||||
void HandleInput() override { }
|
rct_window* OpenDetails(uint8_t /*type*/, int32_t /*id*/) override
|
||||||
void HandleKeyboard(bool /*isTitle*/) override { }
|
{
|
||||||
std::string GetKeyboardShortcutString(int32_t /*shortcut*/) override { return std::string(); }
|
return nullptr;
|
||||||
void SetMainView(int32_t x, int32_t y, int32_t zoom, int32_t rotation) override { }
|
}
|
||||||
void UpdateMouseWheel() override { }
|
rct_window* ShowError(rct_string_id /*title*/, rct_string_id /*message*/) override
|
||||||
rct_window* GetOwner(const rct_viewport* viewport) override { return nullptr; }
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
rct_window* OpenIntent(Intent* /*intent*/) override
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
};
|
||||||
|
void BroadcastIntent(const Intent& /*intent*/) override
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void ForceClose(rct_windowclass /*windowClass*/) override
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void UpdateMapTooltip() override
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void HandleInput() override
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void HandleKeyboard(bool /*isTitle*/) override
|
||||||
|
{
|
||||||
|
}
|
||||||
|
std::string GetKeyboardShortcutString(int32_t /*shortcut*/) override
|
||||||
|
{
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
void SetMainView(int32_t x, int32_t y, int32_t zoom, int32_t rotation) override
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void UpdateMouseWheel() override
|
||||||
|
{
|
||||||
|
}
|
||||||
|
rct_window* GetOwner(const rct_viewport* viewport) override
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
IWindowManager * CreateDummyWindowManager()
|
IWindowManager* CreateDummyWindowManager()
|
||||||
{
|
{
|
||||||
return new DummyWindowManager();
|
return new DummyWindowManager();
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,12 +9,13 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "../Context.h"
|
||||||
|
#include "../common.h"
|
||||||
|
#include "../interface/Cursors.h"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "../common.h"
|
|
||||||
#include "../Context.h"
|
|
||||||
#include "../interface/Cursors.h"
|
|
||||||
|
|
||||||
struct rct_drawpixelinfo;
|
struct rct_drawpixelinfo;
|
||||||
interface ITitleSequencePlayer;
|
interface ITitleSequencePlayer;
|
||||||
|
@ -25,7 +26,8 @@ namespace OpenRCT2
|
||||||
{
|
{
|
||||||
interface IDrawingEngineFactory;
|
interface IDrawingEngineFactory;
|
||||||
interface IRainDrawer;
|
interface IRainDrawer;
|
||||||
using DrawRainFunc = void(*)(OpenRCT2::Drawing::IRainDrawer * rainDrawer, int32_t left, int32_t top, int32_t width, int32_t height);
|
using DrawRainFunc
|
||||||
|
= void (*)(OpenRCT2::Drawing::IRainDrawer* rainDrawer, int32_t left, int32_t top, int32_t width, int32_t height);
|
||||||
} // namespace Drawing
|
} // namespace Drawing
|
||||||
|
|
||||||
namespace Ui
|
namespace Ui
|
||||||
|
@ -39,7 +41,7 @@ namespace OpenRCT2
|
||||||
FULLSCREEN_DESKTOP,
|
FULLSCREEN_DESKTOP,
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool operator <(const Resolution& lhs, const Resolution& rhs)
|
inline bool operator<(const Resolution& lhs, const Resolution& rhs)
|
||||||
{
|
{
|
||||||
int32_t areaA = lhs.Width * lhs.Height;
|
int32_t areaA = lhs.Width * lhs.Height;
|
||||||
int32_t areaB = rhs.Width * rhs.Height;
|
int32_t areaB = rhs.Width * rhs.Height;
|
||||||
|
@ -50,13 +52,12 @@ namespace OpenRCT2
|
||||||
return areaA < areaB;
|
return areaA < areaB;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool operator ==(const Resolution& lhs, const Resolution& rhs)
|
inline bool operator==(const Resolution& lhs, const Resolution& rhs)
|
||||||
{
|
{
|
||||||
return lhs.Width == rhs.Width &&
|
return lhs.Width == rhs.Width && lhs.Height == rhs.Height;
|
||||||
lhs.Height == rhs.Height;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool operator !=(const Resolution& lhs, const Resolution& rhs)
|
inline bool operator!=(const Resolution& lhs, const Resolution& rhs)
|
||||||
{
|
{
|
||||||
return !(lhs == rhs);
|
return !(lhs == rhs);
|
||||||
}
|
}
|
||||||
|
@ -71,14 +72,14 @@ namespace OpenRCT2
|
||||||
{
|
{
|
||||||
struct Filter
|
struct Filter
|
||||||
{
|
{
|
||||||
std::string Name; // E.g. "Image Files"
|
std::string Name; // E.g. "Image Files"
|
||||||
std::string Pattern; // E.g. "*.png;*.jpg;*.gif"
|
std::string Pattern; // E.g. "*.png;*.jpg;*.gif"
|
||||||
};
|
};
|
||||||
|
|
||||||
FILE_DIALOG_TYPE Type = FILE_DIALOG_TYPE::OPEN;
|
FILE_DIALOG_TYPE Type = FILE_DIALOG_TYPE::OPEN;
|
||||||
std::string Title;
|
std::string Title;
|
||||||
std::string InitialDirectory;
|
std::string InitialDirectory;
|
||||||
std::string DefaultFilename;
|
std::string DefaultFilename;
|
||||||
std::vector<Filter> Filters;
|
std::vector<Filter> Filters;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -89,18 +90,18 @@ namespace OpenRCT2
|
||||||
{
|
{
|
||||||
virtual ~IUiContext() = default;
|
virtual ~IUiContext() = default;
|
||||||
|
|
||||||
virtual void Update() abstract;
|
virtual void Update() abstract;
|
||||||
virtual void Draw(rct_drawpixelinfo * dpi) abstract;
|
virtual void Draw(rct_drawpixelinfo * dpi) abstract;
|
||||||
|
|
||||||
// Window
|
// Window
|
||||||
virtual void CreateWindow() abstract;
|
virtual void CreateWindow() abstract;
|
||||||
virtual void CloseWindow() abstract;
|
virtual void CloseWindow() abstract;
|
||||||
virtual void RecreateWindow() abstract;
|
virtual void RecreateWindow() abstract;
|
||||||
virtual void * GetWindow() abstract;
|
virtual void* GetWindow() abstract;
|
||||||
virtual int32_t GetWidth() abstract;
|
virtual int32_t GetWidth() abstract;
|
||||||
virtual int32_t GetHeight() abstract;
|
virtual int32_t GetHeight() abstract;
|
||||||
virtual int32_t GetScaleQuality() abstract;
|
virtual int32_t GetScaleQuality() abstract;
|
||||||
virtual void SetFullscreenMode(FULLSCREEN_MODE mode) abstract;
|
virtual void SetFullscreenMode(FULLSCREEN_MODE mode) abstract;
|
||||||
virtual std::vector<Resolution> GetFullscreenResolutions() abstract;
|
virtual std::vector<Resolution> GetFullscreenResolutions() abstract;
|
||||||
virtual bool HasFocus() abstract;
|
virtual bool HasFocus() abstract;
|
||||||
virtual bool IsMinimised() abstract;
|
virtual bool IsMinimised() abstract;
|
||||||
|
@ -108,40 +109,42 @@ namespace OpenRCT2
|
||||||
virtual void ProcessMessages() abstract;
|
virtual void ProcessMessages() abstract;
|
||||||
virtual void TriggerResize() abstract;
|
virtual void TriggerResize() abstract;
|
||||||
|
|
||||||
virtual void ShowMessageBox(const std::string &message) abstract;
|
virtual void ShowMessageBox(const std::string& message) abstract;
|
||||||
virtual std::string ShowFileDialog(const FileDialogDesc &desc) abstract;
|
virtual std::string ShowFileDialog(const FileDialogDesc& desc) abstract;
|
||||||
virtual std::string ShowDirectoryDialog(const std::string &title) abstract;
|
virtual std::string ShowDirectoryDialog(const std::string& title) abstract;
|
||||||
|
|
||||||
// Input
|
// Input
|
||||||
virtual const CursorState * GetCursorState() abstract;
|
virtual const CursorState* GetCursorState() abstract;
|
||||||
virtual CURSOR_ID GetCursor() abstract;
|
virtual CURSOR_ID GetCursor() abstract;
|
||||||
virtual void SetCursor(CURSOR_ID cursor) abstract;
|
virtual void SetCursor(CURSOR_ID cursor) abstract;
|
||||||
virtual void SetCursorScale(uint8_t scale) abstract;
|
virtual void SetCursorScale(uint8_t scale) abstract;
|
||||||
virtual void SetCursorVisible(bool value) abstract;
|
virtual void SetCursorVisible(bool value) abstract;
|
||||||
virtual void GetCursorPosition(int32_t * x, int32_t * y) abstract;
|
virtual void GetCursorPosition(int32_t * x, int32_t * y) abstract;
|
||||||
virtual void SetCursorPosition(int32_t x, int32_t y) abstract;
|
virtual void SetCursorPosition(int32_t x, int32_t y) abstract;
|
||||||
virtual void SetCursorTrap(bool value) abstract;
|
virtual void SetCursorTrap(bool value) abstract;
|
||||||
virtual const uint8_t * GetKeysState() abstract;
|
virtual const uint8_t* GetKeysState() abstract;
|
||||||
virtual const uint8_t * GetKeysPressed() abstract;
|
virtual const uint8_t* GetKeysPressed() abstract;
|
||||||
virtual void SetKeysPressed(uint32_t keysym, uint8_t scancode) abstract;
|
virtual void SetKeysPressed(uint32_t keysym, uint8_t scancode) abstract;
|
||||||
|
|
||||||
// Drawing
|
// Drawing
|
||||||
virtual std::shared_ptr<Drawing::IDrawingEngineFactory> GetDrawingEngineFactory() abstract;
|
virtual std::shared_ptr<Drawing::IDrawingEngineFactory> GetDrawingEngineFactory() abstract;
|
||||||
virtual void DrawRainAnimation(OpenRCT2::Drawing::IRainDrawer* rainDrawer, rct_drawpixelinfo* dpi, OpenRCT2::Drawing::DrawRainFunc drawFunc) abstract;
|
virtual void DrawRainAnimation(
|
||||||
|
OpenRCT2::Drawing::IRainDrawer * rainDrawer, rct_drawpixelinfo * dpi, OpenRCT2::Drawing::DrawRainFunc drawFunc)
|
||||||
|
abstract;
|
||||||
|
|
||||||
// Text input
|
// Text input
|
||||||
virtual bool IsTextInputActive() abstract;
|
virtual bool IsTextInputActive() abstract;
|
||||||
virtual TextInputSession * StartTextInput(utf8 * buffer, size_t bufferSize) abstract;
|
virtual TextInputSession* StartTextInput(utf8 * buffer, size_t bufferSize) abstract;
|
||||||
virtual void StopTextInput() abstract;
|
virtual void StopTextInput() abstract;
|
||||||
|
|
||||||
// In-game UI
|
// In-game UI
|
||||||
virtual IWindowManager * GetWindowManager() abstract;
|
virtual IWindowManager* GetWindowManager() abstract;
|
||||||
|
|
||||||
// Clipboard
|
// Clipboard
|
||||||
virtual bool SetClipboardText(const utf8* target) abstract;
|
virtual bool SetClipboardText(const utf8* target) abstract;
|
||||||
|
|
||||||
// HACK Until all title logic is moved to libopenrct2ui, we will need to provide some services
|
// HACK Until all title logic is moved to libopenrct2ui, we will need to provide some services
|
||||||
virtual ITitleSequencePlayer * GetTitleSequencePlayer() abstract;
|
virtual ITitleSequencePlayer* GetTitleSequencePlayer() abstract;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::shared_ptr<IUiContext> CreateDummyUiContext();
|
std::shared_ptr<IUiContext> CreateDummyUiContext();
|
||||||
|
|
|
@ -9,11 +9,11 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include "../windows/Intent.h"
|
|
||||||
#include "../common.h"
|
#include "../common.h"
|
||||||
|
|
||||||
#include "../interface/Window.h"
|
#include "../interface/Window.h"
|
||||||
|
#include "../windows/Intent.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace OpenRCT2::Ui
|
namespace OpenRCT2::Ui
|
||||||
{
|
{
|
||||||
|
@ -24,12 +24,12 @@ namespace OpenRCT2::Ui
|
||||||
{
|
{
|
||||||
virtual ~IWindowManager() = default;
|
virtual ~IWindowManager() = default;
|
||||||
virtual void Init() abstract;
|
virtual void Init() abstract;
|
||||||
virtual rct_window * OpenWindow(rct_windowclass wc) abstract;
|
virtual rct_window* OpenWindow(rct_windowclass wc) abstract;
|
||||||
virtual rct_window * OpenView(uint8_t view) abstract;
|
virtual rct_window* OpenView(uint8_t view) abstract;
|
||||||
virtual rct_window * OpenDetails(uint8_t type, int32_t id) abstract;
|
virtual rct_window* OpenDetails(uint8_t type, int32_t id) abstract;
|
||||||
virtual rct_window * OpenIntent(Intent * intent) abstract;
|
virtual rct_window* OpenIntent(Intent * intent) abstract;
|
||||||
virtual void BroadcastIntent(const Intent &intent) abstract;
|
virtual void BroadcastIntent(const Intent& intent) abstract;
|
||||||
virtual rct_window * ShowError(rct_string_id title, rct_string_id message) abstract;
|
virtual rct_window* ShowError(rct_string_id title, rct_string_id message) abstract;
|
||||||
virtual void ForceClose(rct_windowclass windowClass) abstract;
|
virtual void ForceClose(rct_windowclass windowClass) abstract;
|
||||||
virtual void UpdateMapTooltip() abstract;
|
virtual void UpdateMapTooltip() abstract;
|
||||||
virtual void HandleInput() abstract;
|
virtual void HandleInput() abstract;
|
||||||
|
@ -40,5 +40,5 @@ namespace OpenRCT2::Ui
|
||||||
virtual rct_window* GetOwner(const rct_viewport* viewport) abstract;
|
virtual rct_window* GetOwner(const rct_viewport* viewport) abstract;
|
||||||
};
|
};
|
||||||
|
|
||||||
IWindowManager * CreateDummyWindowManager();
|
IWindowManager* CreateDummyWindowManager();
|
||||||
} // namespace OpenRCT2::Ui
|
} // namespace OpenRCT2::Ui
|
||||||
|
|
|
@ -7,20 +7,21 @@
|
||||||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#include <cstring>
|
#include "SawyerCoding.h"
|
||||||
|
|
||||||
#include "../core/Math.hpp"
|
#include "../core/Math.hpp"
|
||||||
#include "../platform/platform.h"
|
#include "../platform/platform.h"
|
||||||
#include "../scenario/Scenario.h"
|
#include "../scenario/Scenario.h"
|
||||||
#include "SawyerCoding.h"
|
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
static size_t decode_chunk_rle(const uint8_t* src_buffer, uint8_t* dst_buffer, size_t length);
|
static size_t decode_chunk_rle(const uint8_t* src_buffer, uint8_t* dst_buffer, size_t length);
|
||||||
static size_t decode_chunk_rle_with_size(const uint8_t* src_buffer, uint8_t* dst_buffer, size_t length, size_t dstSize);
|
static size_t decode_chunk_rle_with_size(const uint8_t* src_buffer, uint8_t* dst_buffer, size_t length, size_t dstSize);
|
||||||
|
|
||||||
static size_t encode_chunk_rle(const uint8_t *src_buffer, uint8_t *dst_buffer, size_t length);
|
static size_t encode_chunk_rle(const uint8_t* src_buffer, uint8_t* dst_buffer, size_t length);
|
||||||
static size_t encode_chunk_repeat(const uint8_t *src_buffer, uint8_t *dst_buffer, size_t length);
|
static size_t encode_chunk_repeat(const uint8_t* src_buffer, uint8_t* dst_buffer, size_t length);
|
||||||
static void encode_chunk_rotate(uint8_t *buffer, size_t length);
|
static void encode_chunk_rotate(uint8_t* buffer, size_t length);
|
||||||
|
|
||||||
bool gUseRLE = true;
|
bool gUseRLE = true;
|
||||||
|
|
||||||
|
@ -35,70 +36,74 @@ uint32_t sawyercoding_calculate_checksum(const uint8_t* buffer, size_t length)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* rct2: 0x006762E1
|
* rct2: 0x006762E1
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
size_t sawyercoding_write_chunk_buffer(uint8_t *dst_file, const uint8_t* buffer, sawyercoding_chunk_header chunkHeader) {
|
size_t sawyercoding_write_chunk_buffer(uint8_t* dst_file, const uint8_t* buffer, sawyercoding_chunk_header chunkHeader)
|
||||||
|
{
|
||||||
uint8_t *encode_buffer, *encode_buffer2;
|
uint8_t *encode_buffer, *encode_buffer2;
|
||||||
|
|
||||||
if (gUseRLE == false) {
|
if (gUseRLE == false)
|
||||||
if (chunkHeader.encoding == CHUNK_ENCODING_RLE || chunkHeader.encoding == CHUNK_ENCODING_RLECOMPRESSED) {
|
{
|
||||||
|
if (chunkHeader.encoding == CHUNK_ENCODING_RLE || chunkHeader.encoding == CHUNK_ENCODING_RLECOMPRESSED)
|
||||||
|
{
|
||||||
chunkHeader.encoding = CHUNK_ENCODING_NONE;
|
chunkHeader.encoding = CHUNK_ENCODING_NONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch (chunkHeader.encoding){
|
switch (chunkHeader.encoding)
|
||||||
case CHUNK_ENCODING_NONE:
|
{
|
||||||
memcpy(dst_file, &chunkHeader, sizeof(sawyercoding_chunk_header));
|
case CHUNK_ENCODING_NONE:
|
||||||
dst_file += sizeof(sawyercoding_chunk_header);
|
memcpy(dst_file, &chunkHeader, sizeof(sawyercoding_chunk_header));
|
||||||
memcpy(dst_file, buffer, chunkHeader.length);
|
dst_file += sizeof(sawyercoding_chunk_header);
|
||||||
//fwrite(&chunkHeader, sizeof(sawyercoding_chunk_header), 1, file);
|
memcpy(dst_file, buffer, chunkHeader.length);
|
||||||
//fwrite(buffer, 1, chunkHeader.length, file);
|
// fwrite(&chunkHeader, sizeof(sawyercoding_chunk_header), 1, file);
|
||||||
break;
|
// fwrite(buffer, 1, chunkHeader.length, file);
|
||||||
case CHUNK_ENCODING_RLE:
|
break;
|
||||||
encode_buffer = (uint8_t *)malloc(0x600000);
|
case CHUNK_ENCODING_RLE:
|
||||||
chunkHeader.length = (uint32_t)encode_chunk_rle(buffer, encode_buffer, chunkHeader.length);
|
encode_buffer = (uint8_t*)malloc(0x600000);
|
||||||
memcpy(dst_file, &chunkHeader, sizeof(sawyercoding_chunk_header));
|
chunkHeader.length = (uint32_t)encode_chunk_rle(buffer, encode_buffer, chunkHeader.length);
|
||||||
dst_file += sizeof(sawyercoding_chunk_header);
|
memcpy(dst_file, &chunkHeader, sizeof(sawyercoding_chunk_header));
|
||||||
memcpy(dst_file, encode_buffer, chunkHeader.length);
|
dst_file += sizeof(sawyercoding_chunk_header);
|
||||||
|
memcpy(dst_file, encode_buffer, chunkHeader.length);
|
||||||
|
|
||||||
free(encode_buffer);
|
free(encode_buffer);
|
||||||
break;
|
break;
|
||||||
case CHUNK_ENCODING_RLECOMPRESSED:
|
case CHUNK_ENCODING_RLECOMPRESSED:
|
||||||
encode_buffer = (uint8_t *)malloc(chunkHeader.length * 2);
|
encode_buffer = (uint8_t*)malloc(chunkHeader.length * 2);
|
||||||
encode_buffer2 = (uint8_t *)malloc(0x600000);
|
encode_buffer2 = (uint8_t*)malloc(0x600000);
|
||||||
chunkHeader.length = (uint32_t)encode_chunk_repeat(buffer, encode_buffer, chunkHeader.length);
|
chunkHeader.length = (uint32_t)encode_chunk_repeat(buffer, encode_buffer, chunkHeader.length);
|
||||||
chunkHeader.length = (uint32_t)encode_chunk_rle(encode_buffer, encode_buffer2, chunkHeader.length);
|
chunkHeader.length = (uint32_t)encode_chunk_rle(encode_buffer, encode_buffer2, chunkHeader.length);
|
||||||
memcpy(dst_file, &chunkHeader, sizeof(sawyercoding_chunk_header));
|
memcpy(dst_file, &chunkHeader, sizeof(sawyercoding_chunk_header));
|
||||||
dst_file += sizeof(sawyercoding_chunk_header);
|
dst_file += sizeof(sawyercoding_chunk_header);
|
||||||
memcpy(dst_file, encode_buffer2, chunkHeader.length);
|
memcpy(dst_file, encode_buffer2, chunkHeader.length);
|
||||||
|
|
||||||
free(encode_buffer2);
|
free(encode_buffer2);
|
||||||
free(encode_buffer);
|
free(encode_buffer);
|
||||||
break;
|
break;
|
||||||
case CHUNK_ENCODING_ROTATE:
|
case CHUNK_ENCODING_ROTATE:
|
||||||
encode_buffer = (uint8_t *)malloc(chunkHeader.length);
|
encode_buffer = (uint8_t*)malloc(chunkHeader.length);
|
||||||
memcpy(encode_buffer, buffer, chunkHeader.length);
|
memcpy(encode_buffer, buffer, chunkHeader.length);
|
||||||
encode_chunk_rotate(encode_buffer, chunkHeader.length);
|
encode_chunk_rotate(encode_buffer, chunkHeader.length);
|
||||||
memcpy(dst_file, &chunkHeader, sizeof(sawyercoding_chunk_header));
|
memcpy(dst_file, &chunkHeader, sizeof(sawyercoding_chunk_header));
|
||||||
dst_file += sizeof(sawyercoding_chunk_header);
|
dst_file += sizeof(sawyercoding_chunk_header);
|
||||||
memcpy(dst_file, encode_buffer, chunkHeader.length);
|
memcpy(dst_file, encode_buffer, chunkHeader.length);
|
||||||
|
|
||||||
free(encode_buffer);
|
free(encode_buffer);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return chunkHeader.length + sizeof(sawyercoding_chunk_header);
|
return chunkHeader.length + sizeof(sawyercoding_chunk_header);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t sawyercoding_decode_sv4(const uint8_t *src, uint8_t *dst, size_t length, size_t bufferLength)
|
size_t sawyercoding_decode_sv4(const uint8_t* src, uint8_t* dst, size_t length, size_t bufferLength)
|
||||||
{
|
{
|
||||||
// (0 to length - 4): RLE chunk
|
// (0 to length - 4): RLE chunk
|
||||||
// (length - 4 to length): checksum
|
// (length - 4 to length): checksum
|
||||||
return decode_chunk_rle_with_size(src, dst, length - 4, bufferLength);
|
return decode_chunk_rle_with_size(src, dst, length - 4, bufferLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t sawyercoding_decode_sc4(const uint8_t *src, uint8_t *dst, size_t length, size_t bufferLength)
|
size_t sawyercoding_decode_sc4(const uint8_t* src, uint8_t* dst, size_t length, size_t bufferLength)
|
||||||
{
|
{
|
||||||
// Uncompress
|
// Uncompress
|
||||||
size_t decodedLength = decode_chunk_rle_with_size(src, dst, length - 4, bufferLength);
|
size_t decodedLength = decode_chunk_rle_with_size(src, dst, length - 4, bufferLength);
|
||||||
|
@ -107,17 +112,18 @@ size_t sawyercoding_decode_sc4(const uint8_t *src, uint8_t *dst, size_t length,
|
||||||
for (size_t i = 0x60018; i <= std::min(decodedLength - 1, (size_t)0x1F8353); i++)
|
for (size_t i = 0x60018; i <= std::min(decodedLength - 1, (size_t)0x1F8353); i++)
|
||||||
dst[i] = dst[i] ^ 0x9C;
|
dst[i] = dst[i] ^ 0x9C;
|
||||||
|
|
||||||
for (size_t i = 0x60018; i <= std::min(decodedLength - 1, (size_t)0x1F8350); i += 4) {
|
for (size_t i = 0x60018; i <= std::min(decodedLength - 1, (size_t)0x1F8350); i += 4)
|
||||||
|
{
|
||||||
dst[i + 1] = ror8(dst[i + 1], 3);
|
dst[i + 1] = ror8(dst[i + 1], 3);
|
||||||
|
|
||||||
uint32_t *code = (uint32_t*)&dst[i];
|
uint32_t* code = (uint32_t*)&dst[i];
|
||||||
*code = rol32(*code, 9);
|
*code = rol32(*code, 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
return decodedLength;
|
return decodedLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t sawyercoding_encode_sv4(const uint8_t *src, uint8_t *dst, size_t length)
|
size_t sawyercoding_encode_sv4(const uint8_t* src, uint8_t* dst, size_t length)
|
||||||
{
|
{
|
||||||
size_t encodedLength;
|
size_t encodedLength;
|
||||||
uint32_t checksum;
|
uint32_t checksum;
|
||||||
|
@ -132,16 +138,18 @@ size_t sawyercoding_encode_sv4(const uint8_t *src, uint8_t *dst, size_t length)
|
||||||
return encodedLength + 4;
|
return encodedLength + 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t sawyercoding_decode_td6(const uint8_t *src, uint8_t *dst, size_t length)
|
size_t sawyercoding_decode_td6(const uint8_t* src, uint8_t* dst, size_t length)
|
||||||
{
|
{
|
||||||
return decode_chunk_rle(src, dst, length - 4);
|
return decode_chunk_rle(src, dst, length - 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t sawyercoding_encode_td6(const uint8_t* src, uint8_t* dst, size_t length){
|
size_t sawyercoding_encode_td6(const uint8_t* src, uint8_t* dst, size_t length)
|
||||||
|
{
|
||||||
size_t output_length = encode_chunk_rle(src, dst, length);
|
size_t output_length = encode_chunk_rle(src, dst, length);
|
||||||
|
|
||||||
uint32_t checksum = 0;
|
uint32_t checksum = 0;
|
||||||
for (size_t i = 0; i < output_length; i++){
|
for (size_t i = 0; i < output_length; i++)
|
||||||
|
{
|
||||||
uint8_t new_byte = ((checksum & 0xFF) + dst[i]) & 0xFF;
|
uint8_t new_byte = ((checksum & 0xFF) + dst[i]) & 0xFF;
|
||||||
checksum = (checksum & 0xFFFFFF00) + new_byte;
|
checksum = (checksum & 0xFFFFFF00) + new_byte;
|
||||||
checksum = rol32(checksum, 3);
|
checksum = rol32(checksum, 3);
|
||||||
|
@ -154,22 +162,24 @@ size_t sawyercoding_encode_td6(const uint8_t* src, uint8_t* dst, size_t length){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Based off of rct2: 0x006770C1 */
|
/* Based off of rct2: 0x006770C1 */
|
||||||
int32_t sawyercoding_validate_track_checksum(const uint8_t* src, size_t length){
|
int32_t sawyercoding_validate_track_checksum(const uint8_t* src, size_t length)
|
||||||
|
{
|
||||||
uint32_t file_checksum = *((uint32_t*)&src[length - 4]);
|
uint32_t file_checksum = *((uint32_t*)&src[length - 4]);
|
||||||
|
|
||||||
uint32_t checksum = 0;
|
uint32_t checksum = 0;
|
||||||
for (size_t i = 0; i < length - 4; i++){
|
for (size_t i = 0; i < length - 4; i++)
|
||||||
|
{
|
||||||
uint8_t new_byte = ((checksum & 0xFF) + src[i]) & 0xFF;
|
uint8_t new_byte = ((checksum & 0xFF) + src[i]) & 0xFF;
|
||||||
checksum = (checksum & 0xFFFFFF00) + new_byte;
|
checksum = (checksum & 0xFFFFFF00) + new_byte;
|
||||||
checksum = rol32(checksum, 3);
|
checksum = rol32(checksum, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (checksum - 0x1D4C1 == file_checksum)
|
if (checksum - 0x1D4C1 == file_checksum)
|
||||||
return 1; // .TD6
|
return 1; // .TD6
|
||||||
else if (checksum - 0x1A67C == file_checksum)
|
else if (checksum - 0x1A67C == file_checksum)
|
||||||
return 1; // .TD4
|
return 1; // .TD4
|
||||||
else if (checksum - 0x1A650 == file_checksum)
|
else if (checksum - 0x1A650 == file_checksum)
|
||||||
return 1; // .TD4
|
return 1; // .TD4
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -187,14 +197,18 @@ static size_t decode_chunk_rle(const uint8_t* src_buffer, uint8_t* dst_buffer, s
|
||||||
|
|
||||||
dst = dst_buffer;
|
dst = dst_buffer;
|
||||||
|
|
||||||
for (size_t i = 0; i < length; i++) {
|
for (size_t i = 0; i < length; i++)
|
||||||
|
{
|
||||||
rleCodeByte = src_buffer[i];
|
rleCodeByte = src_buffer[i];
|
||||||
if (rleCodeByte & 128) {
|
if (rleCodeByte & 128)
|
||||||
|
{
|
||||||
i++;
|
i++;
|
||||||
count = 257 - rleCodeByte;
|
count = 257 - rleCodeByte;
|
||||||
memset(dst, src_buffer[i], count);
|
memset(dst, src_buffer[i], count);
|
||||||
dst = (uint8_t*)((uintptr_t)dst + count);
|
dst = (uint8_t*)((uintptr_t)dst + count);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
memcpy(dst, src_buffer + i + 1, rleCodeByte + 1);
|
memcpy(dst, src_buffer + i + 1, rleCodeByte + 1);
|
||||||
dst = (uint8_t*)((uintptr_t)dst + rleCodeByte + 1);
|
dst = (uint8_t*)((uintptr_t)dst + rleCodeByte + 1);
|
||||||
i += rleCodeByte + 1;
|
i += rleCodeByte + 1;
|
||||||
|
@ -218,16 +232,20 @@ static size_t decode_chunk_rle_with_size(const uint8_t* src_buffer, uint8_t* dst
|
||||||
|
|
||||||
assert(length > 0);
|
assert(length > 0);
|
||||||
assert(dstSize > 0);
|
assert(dstSize > 0);
|
||||||
for (size_t i = 0; i < length; i++) {
|
for (size_t i = 0; i < length; i++)
|
||||||
|
{
|
||||||
rleCodeByte = src_buffer[i];
|
rleCodeByte = src_buffer[i];
|
||||||
if (rleCodeByte & 128) {
|
if (rleCodeByte & 128)
|
||||||
|
{
|
||||||
i++;
|
i++;
|
||||||
count = 257 - rleCodeByte;
|
count = 257 - rleCodeByte;
|
||||||
assert(dst + count <= dst_buffer + dstSize);
|
assert(dst + count <= dst_buffer + dstSize);
|
||||||
assert(i < length);
|
assert(i < length);
|
||||||
memset(dst, src_buffer[i], count);
|
memset(dst, src_buffer[i], count);
|
||||||
dst = (uint8_t*)((uintptr_t)dst + count);
|
dst = (uint8_t*)((uintptr_t)dst + count);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
assert(dst + rleCodeByte + 1 <= dst_buffer + dstSize);
|
assert(dst + rleCodeByte + 1 <= dst_buffer + dstSize);
|
||||||
assert(i + 1 < length);
|
assert(i + 1 < length);
|
||||||
memcpy(dst, src_buffer + i + 1, rleCodeByte + 1);
|
memcpy(dst, src_buffer + i + 1, rleCodeByte + 1);
|
||||||
|
@ -248,7 +266,7 @@ static size_t decode_chunk_rle_with_size(const uint8_t* src_buffer, uint8_t* dst
|
||||||
* Ensure dst_buffer is bigger than src_buffer then resize afterwards
|
* Ensure dst_buffer is bigger than src_buffer then resize afterwards
|
||||||
* returns length of dst_buffer
|
* returns length of dst_buffer
|
||||||
*/
|
*/
|
||||||
static size_t encode_chunk_rle(const uint8_t *src_buffer, uint8_t *dst_buffer, size_t length)
|
static size_t encode_chunk_rle(const uint8_t* src_buffer, uint8_t* dst_buffer, size_t length)
|
||||||
{
|
{
|
||||||
const uint8_t* src = src_buffer;
|
const uint8_t* src = src_buffer;
|
||||||
uint8_t* dst = dst_buffer;
|
uint8_t* dst = dst_buffer;
|
||||||
|
@ -256,18 +274,22 @@ static size_t encode_chunk_rle(const uint8_t *src_buffer, uint8_t *dst_buffer, s
|
||||||
uint8_t count = 0;
|
uint8_t count = 0;
|
||||||
const uint8_t* src_norm_start = src;
|
const uint8_t* src_norm_start = src;
|
||||||
|
|
||||||
while (src < end_src - 1){
|
while (src < end_src - 1)
|
||||||
|
{
|
||||||
if ((count && *src == src[1]) || count > 125){
|
if ((count && *src == src[1]) || count > 125)
|
||||||
|
{
|
||||||
*dst++ = count - 1;
|
*dst++ = count - 1;
|
||||||
memcpy(dst, src_norm_start, count);
|
memcpy(dst, src_norm_start, count);
|
||||||
dst += count;
|
dst += count;
|
||||||
src_norm_start += count;
|
src_norm_start += count;
|
||||||
count = 0;
|
count = 0;
|
||||||
}
|
}
|
||||||
if (*src == src[1]){
|
if (*src == src[1])
|
||||||
for (; (count < 125) && ((src + count) < end_src); count++){
|
{
|
||||||
if (*src != src[count]) break;
|
for (; (count < 125) && ((src + count) < end_src); count++)
|
||||||
|
{
|
||||||
|
if (*src != src[count])
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
*dst++ = 257 - count;
|
*dst++ = 257 - count;
|
||||||
*dst++ = *src;
|
*dst++ = *src;
|
||||||
|
@ -275,13 +297,16 @@ static size_t encode_chunk_rle(const uint8_t *src_buffer, uint8_t *dst_buffer, s
|
||||||
src_norm_start = src;
|
src_norm_start = src;
|
||||||
count = 0;
|
count = 0;
|
||||||
}
|
}
|
||||||
else{
|
else
|
||||||
|
{
|
||||||
count++;
|
count++;
|
||||||
src++;
|
src++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (src == end_src - 1)count++;
|
if (src == end_src - 1)
|
||||||
if (count){
|
count++;
|
||||||
|
if (count)
|
||||||
|
{
|
||||||
*dst++ = count - 1;
|
*dst++ = count - 1;
|
||||||
memcpy(dst, src_norm_start, count);
|
memcpy(dst, src_norm_start, count);
|
||||||
dst += count;
|
dst += count;
|
||||||
|
@ -289,7 +314,7 @@ static size_t encode_chunk_rle(const uint8_t *src_buffer, uint8_t *dst_buffer, s
|
||||||
return dst - dst_buffer;
|
return dst - dst_buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t encode_chunk_repeat(const uint8_t *src_buffer, uint8_t *dst_buffer, size_t length)
|
static size_t encode_chunk_repeat(const uint8_t* src_buffer, uint8_t* dst_buffer, size_t length)
|
||||||
{
|
{
|
||||||
if (length == 0)
|
if (length == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -302,26 +327,33 @@ static size_t encode_chunk_repeat(const uint8_t *src_buffer, uint8_t *dst_buffer
|
||||||
outLength += 2;
|
outLength += 2;
|
||||||
|
|
||||||
// Iterate through remainder of the source buffer
|
// Iterate through remainder of the source buffer
|
||||||
for (size_t i = 1; i < length; ) {
|
for (size_t i = 1; i < length;)
|
||||||
|
{
|
||||||
size_t searchIndex = (i < 32) ? 0 : (i - 32);
|
size_t searchIndex = (i < 32) ? 0 : (i - 32);
|
||||||
size_t searchEnd = i - 1;
|
size_t searchEnd = i - 1;
|
||||||
|
|
||||||
size_t bestRepeatIndex = 0;
|
size_t bestRepeatIndex = 0;
|
||||||
size_t bestRepeatCount = 0;
|
size_t bestRepeatCount = 0;
|
||||||
for (size_t repeatIndex = searchIndex; repeatIndex <= searchEnd; repeatIndex++) {
|
for (size_t repeatIndex = searchIndex; repeatIndex <= searchEnd; repeatIndex++)
|
||||||
|
{
|
||||||
size_t repeatCount = 0;
|
size_t repeatCount = 0;
|
||||||
size_t maxRepeatCount = std::min(std::min((size_t)7, searchEnd - repeatIndex), length - i - 1);
|
size_t maxRepeatCount = std::min(std::min((size_t)7, searchEnd - repeatIndex), length - i - 1);
|
||||||
// maxRepeatCount should not exceed length
|
// maxRepeatCount should not exceed length
|
||||||
assert(repeatIndex + maxRepeatCount < length);
|
assert(repeatIndex + maxRepeatCount < length);
|
||||||
assert(i + maxRepeatCount < length);
|
assert(i + maxRepeatCount < length);
|
||||||
for (size_t j = 0; j <= maxRepeatCount; j++) {
|
for (size_t j = 0; j <= maxRepeatCount; j++)
|
||||||
if (src_buffer[repeatIndex + j] == src_buffer[i + j]) {
|
{
|
||||||
|
if (src_buffer[repeatIndex + j] == src_buffer[i + j])
|
||||||
|
{
|
||||||
repeatCount++;
|
repeatCount++;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (repeatCount > bestRepeatCount) {
|
if (repeatCount > bestRepeatCount)
|
||||||
|
{
|
||||||
bestRepeatIndex = repeatIndex;
|
bestRepeatIndex = repeatIndex;
|
||||||
bestRepeatCount = repeatCount;
|
bestRepeatCount = repeatCount;
|
||||||
|
|
||||||
|
@ -331,12 +363,15 @@ static size_t encode_chunk_repeat(const uint8_t *src_buffer, uint8_t *dst_buffer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bestRepeatCount == 0) {
|
if (bestRepeatCount == 0)
|
||||||
|
{
|
||||||
*dst_buffer++ = 255;
|
*dst_buffer++ = 255;
|
||||||
*dst_buffer++ = src_buffer[i];
|
*dst_buffer++ = src_buffer[i];
|
||||||
outLength += 2;
|
outLength += 2;
|
||||||
i++;
|
i++;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
*dst_buffer++ = (uint8_t)((bestRepeatCount - 1) | ((32 - (i - bestRepeatIndex)) << 3));
|
*dst_buffer++ = (uint8_t)((bestRepeatCount - 1) | ((32 - (i - bestRepeatIndex)) << 3));
|
||||||
outLength++;
|
outLength++;
|
||||||
i += bestRepeatCount;
|
i += bestRepeatCount;
|
||||||
|
@ -346,11 +381,12 @@ static size_t encode_chunk_repeat(const uint8_t *src_buffer, uint8_t *dst_buffer
|
||||||
return outLength;
|
return outLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void encode_chunk_rotate(uint8_t *buffer, size_t length)
|
static void encode_chunk_rotate(uint8_t* buffer, size_t length)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
uint8_t code = 1;
|
uint8_t code = 1;
|
||||||
for (i = 0; i < length; i++) {
|
for (i = 0; i < length; i++)
|
||||||
|
{
|
||||||
buffer[i] = rol8(buffer[i], code);
|
buffer[i] = rol8(buffer[i], code);
|
||||||
code = (code + 2) % 8;
|
code = (code + 2) % 8;
|
||||||
}
|
}
|
||||||
|
@ -358,7 +394,7 @@ static void encode_chunk_rotate(uint8_t *buffer, size_t length)
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
int32_t sawyercoding_detect_file_type(const uint8_t *src, size_t length)
|
int32_t sawyercoding_detect_file_type(const uint8_t* src, size_t length)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
|
@ -366,7 +402,8 @@ int32_t sawyercoding_detect_file_type(const uint8_t *src, size_t length)
|
||||||
|
|
||||||
uint32_t checksum = *((uint32_t*)&src[length - 4]);
|
uint32_t checksum = *((uint32_t*)&src[length - 4]);
|
||||||
uint32_t actualChecksum = 0;
|
uint32_t actualChecksum = 0;
|
||||||
for (i = 0; i < length - 4; i++) {
|
for (i = 0; i < length - 4; i++)
|
||||||
|
{
|
||||||
actualChecksum = (actualChecksum & 0xFFFFFF00) | (((actualChecksum & 0xFF) + (uint8_t)src[i]) & 0xFF);
|
actualChecksum = (actualChecksum & 0xFFFFFF00) | (((actualChecksum & 0xFF) + (uint8_t)src[i]) & 0xFF);
|
||||||
actualChecksum = rol32(actualChecksum, 3);
|
actualChecksum = rol32(actualChecksum, 3);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,22 +13,24 @@
|
||||||
#include "../common.h"
|
#include "../common.h"
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
struct sawyercoding_chunk_header {
|
struct sawyercoding_chunk_header
|
||||||
|
{
|
||||||
uint8_t encoding;
|
uint8_t encoding;
|
||||||
uint32_t length;
|
uint32_t length;
|
||||||
};
|
};
|
||||||
assert_struct_size(sawyercoding_chunk_header, 5);
|
assert_struct_size(sawyercoding_chunk_header, 5);
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
enum
|
||||||
enum {
|
{
|
||||||
CHUNK_ENCODING_NONE,
|
CHUNK_ENCODING_NONE,
|
||||||
CHUNK_ENCODING_RLE,
|
CHUNK_ENCODING_RLE,
|
||||||
CHUNK_ENCODING_RLECOMPRESSED,
|
CHUNK_ENCODING_RLECOMPRESSED,
|
||||||
CHUNK_ENCODING_ROTATE
|
CHUNK_ENCODING_ROTATE
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum
|
||||||
|
{
|
||||||
FILE_VERSION_MASK = (3 << 0),
|
FILE_VERSION_MASK = (3 << 0),
|
||||||
FILE_VERSION_RCT1 = (0 << 0),
|
FILE_VERSION_RCT1 = (0 << 0),
|
||||||
FILE_VERSION_RCT1_AA = (1 << 0),
|
FILE_VERSION_RCT1_AA = (1 << 0),
|
||||||
|
@ -43,15 +45,15 @@ enum {
|
||||||
extern bool gUseRLE;
|
extern bool gUseRLE;
|
||||||
|
|
||||||
uint32_t sawyercoding_calculate_checksum(const uint8_t* buffer, size_t length);
|
uint32_t sawyercoding_calculate_checksum(const uint8_t* buffer, size_t length);
|
||||||
size_t sawyercoding_write_chunk_buffer(uint8_t *dst_file, const uint8_t *src_buffer, sawyercoding_chunk_header chunkHeader);
|
size_t sawyercoding_write_chunk_buffer(uint8_t* dst_file, const uint8_t* src_buffer, sawyercoding_chunk_header chunkHeader);
|
||||||
size_t sawyercoding_decode_sv4(const uint8_t *src, uint8_t *dst, size_t length, size_t bufferLength);
|
size_t sawyercoding_decode_sv4(const uint8_t* src, uint8_t* dst, size_t length, size_t bufferLength);
|
||||||
size_t sawyercoding_decode_sc4(const uint8_t *src, uint8_t *dst, size_t length, size_t bufferLength);
|
size_t sawyercoding_decode_sc4(const uint8_t* src, uint8_t* dst, size_t length, size_t bufferLength);
|
||||||
size_t sawyercoding_encode_sv4(const uint8_t *src, uint8_t *dst, size_t length);
|
size_t sawyercoding_encode_sv4(const uint8_t* src, uint8_t* dst, size_t length);
|
||||||
size_t sawyercoding_decode_td6(const uint8_t *src, uint8_t *dst, size_t length);
|
size_t sawyercoding_decode_td6(const uint8_t* src, uint8_t* dst, size_t length);
|
||||||
size_t sawyercoding_encode_td6(const uint8_t *src, uint8_t *dst, size_t length);
|
size_t sawyercoding_encode_td6(const uint8_t* src, uint8_t* dst, size_t length);
|
||||||
int32_t sawyercoding_validate_track_checksum(const uint8_t* src, size_t length);
|
int32_t sawyercoding_validate_track_checksum(const uint8_t* src, size_t length);
|
||||||
|
|
||||||
int32_t sawyercoding_detect_file_type(const uint8_t *src, size_t length);
|
int32_t sawyercoding_detect_file_type(const uint8_t* src, size_t length);
|
||||||
int32_t sawyercoding_detect_rct1_version(int32_t gameVersion);
|
int32_t sawyercoding_detect_rct1_version(int32_t gameVersion);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -7,9 +7,8 @@
|
||||||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#include <cctype>
|
#include "Util.h"
|
||||||
#include <cmath>
|
|
||||||
#include <ctime>
|
|
||||||
#include "../common.h"
|
#include "../common.h"
|
||||||
#include "../core/Guard.hpp"
|
#include "../core/Guard.hpp"
|
||||||
#include "../core/Math.hpp"
|
#include "../core/Math.hpp"
|
||||||
|
@ -17,9 +16,12 @@
|
||||||
#include "../localisation/Localisation.h"
|
#include "../localisation/Localisation.h"
|
||||||
#include "../platform/platform.h"
|
#include "../platform/platform.h"
|
||||||
#include "../title/TitleScreen.h"
|
#include "../title/TitleScreen.h"
|
||||||
#include "Util.h"
|
|
||||||
#include "zlib.h"
|
#include "zlib.h"
|
||||||
|
|
||||||
|
#include <cctype>
|
||||||
|
#include <cmath>
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
int32_t squaredmetres_to_squaredfeet(int32_t squaredMetres)
|
int32_t squaredmetres_to_squaredfeet(int32_t squaredMetres)
|
||||||
{
|
{
|
||||||
// 1 metre squared = 10.7639104 feet squared
|
// 1 metre squared = 10.7639104 feet squared
|
||||||
|
@ -47,39 +49,41 @@ int32_t mph_to_dmps(int32_t mph)
|
||||||
return (mph * 73243) >> 14;
|
return (mph * 73243) >> 14;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool filename_valid_characters(const utf8 *filename)
|
bool filename_valid_characters(const utf8* filename)
|
||||||
{
|
{
|
||||||
for (int32_t i = 0; filename[i] != '\0'; i++) {
|
for (int32_t i = 0; filename[i] != '\0'; i++)
|
||||||
if (filename[i] == '\\' || filename[i] == '/' || filename[i] == ':' || filename[i] == '?' ||
|
{
|
||||||
filename[i] == '*' || filename[i] == '<' || filename[i] == '>' || filename[i] == '|')
|
if (filename[i] == '\\' || filename[i] == '/' || filename[i] == ':' || filename[i] == '?' || filename[i] == '*'
|
||||||
|
|| filename[i] == '<' || filename[i] == '>' || filename[i] == '|')
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
utf8 *path_get_directory(const utf8 *path)
|
utf8* path_get_directory(const utf8* path)
|
||||||
{
|
{
|
||||||
// Find the last slash or backslash in the path
|
// Find the last slash or backslash in the path
|
||||||
char * filename = (char *)strrchr(path, *PATH_SEPARATOR);
|
char* filename = (char*)strrchr(path, *PATH_SEPARATOR);
|
||||||
char * filename_posix = (char *)strrchr(path, '/');
|
char* filename_posix = (char*)strrchr(path, '/');
|
||||||
filename = filename < filename_posix ? filename_posix : filename;
|
filename = filename < filename_posix ? filename_posix : filename;
|
||||||
|
|
||||||
// If the path is invalid (e.g. just a file name), return NULL
|
// If the path is invalid (e.g. just a file name), return NULL
|
||||||
if (filename == nullptr) {
|
if (filename == nullptr)
|
||||||
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *directory = _strdup(path);
|
char* directory = _strdup(path);
|
||||||
safe_strtrunc(directory, strlen(path) - strlen(filename) + 2);
|
safe_strtrunc(directory, strlen(path) - strlen(filename) + 2);
|
||||||
|
|
||||||
return directory;
|
return directory;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *path_get_filename(const utf8 *path)
|
const char* path_get_filename(const utf8* path)
|
||||||
{
|
{
|
||||||
// Find last slash or backslash in the path
|
// Find last slash or backslash in the path
|
||||||
char * filename = (char *)strrchr(path, *PATH_SEPARATOR);
|
char* filename = (char*)strrchr(path, *PATH_SEPARATOR);
|
||||||
char * filename_posix = (char *)strchr(path, '/');
|
char* filename_posix = (char*)strchr(path, '/');
|
||||||
filename = filename < filename_posix ? filename_posix : filename;
|
filename = filename < filename_posix ? filename_posix : filename;
|
||||||
|
|
||||||
// Checks if the path is valid (e.g. not just a file name)
|
// Checks if the path is valid (e.g. not just a file name)
|
||||||
|
@ -97,22 +101,22 @@ const char *path_get_filename(const utf8 *path)
|
||||||
|
|
||||||
// Returns the extension (dot inclusive) from the given path, or the end of the
|
// Returns the extension (dot inclusive) from the given path, or the end of the
|
||||||
// string when no extension was found.
|
// string when no extension was found.
|
||||||
const char *path_get_extension(const utf8 *path)
|
const char* path_get_extension(const utf8* path)
|
||||||
{
|
{
|
||||||
// Get the filename from the path
|
// Get the filename from the path
|
||||||
const char *filename = path_get_filename(path);
|
const char* filename = path_get_filename(path);
|
||||||
|
|
||||||
// Try to find the most-right dot in the filename
|
// Try to find the most-right dot in the filename
|
||||||
char * extension = (char *)strrchr(filename, '.');
|
char* extension = (char*)strrchr(filename, '.');
|
||||||
|
|
||||||
// When no dot was found, return a pointer to the null-terminator
|
// When no dot was found, return a pointer to the null-terminator
|
||||||
if (extension == nullptr)
|
if (extension == nullptr)
|
||||||
extension = (char *)strrchr(filename, '\0');
|
extension = (char*)strrchr(filename, '\0');
|
||||||
|
|
||||||
return extension;
|
return extension;
|
||||||
}
|
}
|
||||||
|
|
||||||
void path_set_extension(utf8 *path, const utf8 *newExtension, size_t size)
|
void path_set_extension(utf8* path, const utf8* newExtension, size_t size)
|
||||||
{
|
{
|
||||||
// Remove existing extension (check first if there is one)
|
// Remove existing extension (check first if there is one)
|
||||||
if (path_get_extension(path) < strrchr(path, '\0'))
|
if (path_get_extension(path) < strrchr(path, '\0'))
|
||||||
|
@ -121,7 +125,7 @@ void path_set_extension(utf8 *path, const utf8 *newExtension, size_t size)
|
||||||
path_append_extension(path, newExtension, size);
|
path_append_extension(path, newExtension, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void path_append_extension(utf8 *path, const utf8 *newExtension, size_t size)
|
void path_append_extension(utf8* path, const utf8* newExtension, size_t size)
|
||||||
{
|
{
|
||||||
// Append a dot to the filename if the new extension doesn't start with it
|
// Append a dot to the filename if the new extension doesn't start with it
|
||||||
if (newExtension[0] != '.')
|
if (newExtension[0] != '.')
|
||||||
|
@ -131,36 +135,39 @@ void path_append_extension(utf8 *path, const utf8 *newExtension, size_t size)
|
||||||
safe_strcat(path, newExtension, size);
|
safe_strcat(path, newExtension, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void path_remove_extension(utf8 *path)
|
void path_remove_extension(utf8* path)
|
||||||
{
|
{
|
||||||
// Find last dot in filename, and replace it with a null-terminator
|
// Find last dot in filename, and replace it with a null-terminator
|
||||||
char * lastDot = (char *)strrchr(path_get_filename(path), '.');
|
char* lastDot = (char*)strrchr(path_get_filename(path), '.');
|
||||||
if (lastDot != nullptr)
|
if (lastDot != nullptr)
|
||||||
*lastDot = '\0';
|
*lastDot = '\0';
|
||||||
else
|
else
|
||||||
log_warning("No extension found. (path = %s)", path);
|
log_warning("No extension found. (path = %s)", path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void path_end_with_separator(utf8 *path, size_t size) {
|
void path_end_with_separator(utf8* path, size_t size)
|
||||||
|
{
|
||||||
size_t length = strnlen(path, size);
|
size_t length = strnlen(path, size);
|
||||||
if (length >= size - 1) return;
|
if (length >= size - 1)
|
||||||
|
return;
|
||||||
|
|
||||||
if ((length == 0) || ((path[length - 1] != *PATH_SEPARATOR) && path[length - 1] != '/')) {
|
if ((length == 0) || ((path[length - 1] != *PATH_SEPARATOR) && path[length - 1] != '/'))
|
||||||
|
{
|
||||||
safe_strcat(path, PATH_SEPARATOR, size);
|
safe_strcat(path, PATH_SEPARATOR, size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t bitscanforward(int32_t source)
|
int32_t bitscanforward(int32_t source)
|
||||||
{
|
{
|
||||||
#if defined(_MSC_VER) && (_MSC_VER >= 1400) // Visual Studio 2005
|
#if defined(_MSC_VER) && (_MSC_VER >= 1400) // Visual Studio 2005
|
||||||
DWORD i;
|
DWORD i;
|
||||||
uint8_t success = _BitScanForward(&i, (uint32_t)source);
|
uint8_t success = _BitScanForward(&i, (uint32_t)source);
|
||||||
return success != 0 ? i : -1;
|
return success != 0 ? i : -1;
|
||||||
#elif defined(__GNUC__)
|
#elif defined(__GNUC__)
|
||||||
int32_t success = __builtin_ffs(source);
|
int32_t success = __builtin_ffs(source);
|
||||||
return success - 1;
|
return success - 1;
|
||||||
#else
|
#else
|
||||||
#pragma message "Falling back to iterative bitscan forward, consider using intrinsics"
|
#pragma message "Falling back to iterative bitscan forward, consider using intrinsics"
|
||||||
// This is a low-hanging optimisation boost, check if your compiler offers
|
// This is a low-hanging optimisation boost, check if your compiler offers
|
||||||
// any intrinsic.
|
// any intrinsic.
|
||||||
// cf. https://github.com/OpenRCT2/OpenRCT2/pull/2093
|
// cf. https://github.com/OpenRCT2/OpenRCT2/pull/2093
|
||||||
|
@ -169,26 +176,26 @@ int32_t bitscanforward(int32_t source)
|
||||||
return i;
|
return i;
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__))
|
#if defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__))
|
||||||
#include <cpuid.h>
|
#include <cpuid.h>
|
||||||
#define OpenRCT2_CPUID_GNUC_X86
|
#define OpenRCT2_CPUID_GNUC_X86
|
||||||
#elif defined(_MSC_VER) && (_MSC_VER >= 1500) && (defined(_M_X64) || defined(_M_IX86)) // VS2008
|
#elif defined(_MSC_VER) && (_MSC_VER >= 1500) && (defined(_M_X64) || defined(_M_IX86)) // VS2008
|
||||||
#include <intrin.h>
|
#include <intrin.h>
|
||||||
#include <nmmintrin.h>
|
#include <nmmintrin.h>
|
||||||
#define OpenRCT2_CPUID_MSVC_X86
|
#define OpenRCT2_CPUID_MSVC_X86
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef OPENRCT2_X86
|
#ifdef OPENRCT2_X86
|
||||||
static bool cpuid_x86(uint32_t * cpuid_outdata, int32_t eax)
|
static bool cpuid_x86(uint32_t* cpuid_outdata, int32_t eax)
|
||||||
{
|
{
|
||||||
#if defined(OpenRCT2_CPUID_GNUC_X86)
|
#if defined(OpenRCT2_CPUID_GNUC_X86)
|
||||||
int ret = __get_cpuid(eax, &cpuid_outdata[0], &cpuid_outdata[1], &cpuid_outdata[2], &cpuid_outdata[3]);
|
int ret = __get_cpuid(eax, &cpuid_outdata[0], &cpuid_outdata[1], &cpuid_outdata[2], &cpuid_outdata[3]);
|
||||||
return ret == 1;
|
return ret == 1;
|
||||||
#elif defined(OpenRCT2_CPUID_MSVC_X86)
|
#elif defined(OpenRCT2_CPUID_MSVC_X86)
|
||||||
__cpuid((int *)cpuid_outdata, (int)eax);
|
__cpuid((int*)cpuid_outdata, (int)eax);
|
||||||
return true;
|
return true;
|
||||||
#else
|
#else
|
||||||
return false;
|
return false;
|
||||||
|
@ -245,38 +252,35 @@ static bool bitcount_popcnt_available()
|
||||||
|
|
||||||
static int32_t bitcount_popcnt(uint32_t source)
|
static int32_t bitcount_popcnt(uint32_t source)
|
||||||
{
|
{
|
||||||
// Use CPUID defines to figure out calling style
|
// Use CPUID defines to figure out calling style
|
||||||
#if defined(OpenRCT2_CPUID_GNUC_X86)
|
#if defined(OpenRCT2_CPUID_GNUC_X86)
|
||||||
// use asm directly in order to actually emit the instruction : using
|
// use asm directly in order to actually emit the instruction : using
|
||||||
// __builtin_popcount results in an extra call to a library function.
|
// __builtin_popcount results in an extra call to a library function.
|
||||||
int32_t rv;
|
int32_t rv;
|
||||||
asm volatile ("popcnt %1,%0" : "=r"(rv) : "rm"(source) : "cc");
|
asm volatile("popcnt %1,%0" : "=r"(rv) : "rm"(source) : "cc");
|
||||||
return rv;
|
return rv;
|
||||||
#elif defined(OpenRCT2_CPUID_MSVC_X86)
|
#elif defined(OpenRCT2_CPUID_MSVC_X86)
|
||||||
return _mm_popcnt_u32(source);
|
return _mm_popcnt_u32(source);
|
||||||
#else
|
#else
|
||||||
openrct2_assert(false, "bitcount_popcnt() called, without support compiled in");
|
openrct2_assert(false, "bitcount_popcnt() called, without support compiled in");
|
||||||
return INT_MAX;
|
return INT_MAX;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t bitcount_lut(uint32_t source)
|
static int32_t bitcount_lut(uint32_t source)
|
||||||
{
|
{
|
||||||
// https://graphics.stanford.edu/~seander/bithacks.html
|
// https://graphics.stanford.edu/~seander/bithacks.html
|
||||||
static constexpr const uint8_t BitsSetTable256[256] =
|
static constexpr const uint8_t BitsSetTable256[256] = {
|
||||||
{
|
#define B2(n) n, (n) + 1, (n) + 1, (n) + 2
|
||||||
#define B2(n) n, (n) + 1, (n) + 1, (n) + 2
|
#define B4(n) B2(n), B2((n) + 1), B2((n) + 1), B2((n) + 2)
|
||||||
#define B4(n) B2(n), B2((n) + 1), B2((n) + 1), B2((n) + 2)
|
#define B6(n) B4(n), B4((n) + 1), B4((n) + 1), B4((n) + 2)
|
||||||
#define B6(n) B4(n), B4((n) + 1), B4((n) + 1), B4((n) + 2)
|
B6(0), B6(1), B6(1), B6(2)
|
||||||
B6(0), B6(1), B6(1), B6(2)
|
|
||||||
};
|
};
|
||||||
return BitsSetTable256[source & 0xff] +
|
return BitsSetTable256[source & 0xff] + BitsSetTable256[(source >> 8) & 0xff] + BitsSetTable256[(source >> 16) & 0xff]
|
||||||
BitsSetTable256[(source >> 8) & 0xff] +
|
+ BitsSetTable256[source >> 24];
|
||||||
BitsSetTable256[(source >> 16) & 0xff] +
|
|
||||||
BitsSetTable256[source >> 24];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t(*bitcount_fn)(uint32_t);
|
static int32_t (*bitcount_fn)(uint32_t);
|
||||||
|
|
||||||
void bitcount_init()
|
void bitcount_init()
|
||||||
{
|
{
|
||||||
|
@ -288,17 +292,16 @@ int32_t bitcount(uint32_t source)
|
||||||
return bitcount_fn(source);
|
return bitcount_fn(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool strequals(const char *a, const char *b, int32_t length, bool caseInsensitive)
|
bool strequals(const char* a, const char* b, int32_t length, bool caseInsensitive)
|
||||||
{
|
{
|
||||||
return caseInsensitive ?
|
return caseInsensitive ? _strnicmp(a, b, length) == 0 : strncmp(a, b, length) == 0;
|
||||||
_strnicmp(a, b, length) == 0 :
|
|
||||||
strncmp(a, b, length) == 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* case insensitive compare */
|
/* case insensitive compare */
|
||||||
int32_t strcicmp(char const *a, char const *b)
|
int32_t strcicmp(char const* a, char const* b)
|
||||||
{
|
{
|
||||||
for (;; a++, b++) {
|
for (;; a++, b++)
|
||||||
|
{
|
||||||
int32_t d = tolower(*a) - tolower(*b);
|
int32_t d = tolower(*a) - tolower(*b);
|
||||||
if (d != 0 || !*a)
|
if (d != 0 || !*a)
|
||||||
return d;
|
return d;
|
||||||
|
@ -312,42 +315,60 @@ int32_t strcicmp(char const *a, char const *b)
|
||||||
// - Guest 100
|
// - Guest 100
|
||||||
// - John v2.0
|
// - John v2.0
|
||||||
// - John v2.1
|
// - John v2.1
|
||||||
int32_t strlogicalcmp(char const *a, char const *b) {
|
int32_t strlogicalcmp(char const* a, char const* b)
|
||||||
for (;; a++, b++) {
|
{
|
||||||
|
for (;; a++, b++)
|
||||||
|
{
|
||||||
int32_t result = tolower(*a) - tolower(*b);
|
int32_t result = tolower(*a) - tolower(*b);
|
||||||
bool both_numeric = *a >= '0' && *a <= '9' && *b >= '0' && *b <= '9';
|
bool both_numeric = *a >= '0' && *a <= '9' && *b >= '0' && *b <= '9';
|
||||||
if (result != 0 || !*a || both_numeric) { // difference found || end of string
|
if (result != 0 || !*a || both_numeric)
|
||||||
if (both_numeric) { // a and b both start with a number
|
{ // difference found || end of string
|
||||||
|
if (both_numeric)
|
||||||
|
{ // a and b both start with a number
|
||||||
// Get the numbers in the string at current positions
|
// Get the numbers in the string at current positions
|
||||||
int32_t na = 0 , nb = 0;
|
int32_t na = 0, nb = 0;
|
||||||
for (; *a >= '0' && *a <= '9'; a++) { na *= 10; na += *a - '0'; }
|
for (; *a >= '0' && *a <= '9'; a++)
|
||||||
for (; *b >= '0' && *b <= '9'; b++) { nb *= 10; nb += *b - '0'; }
|
{
|
||||||
|
na *= 10;
|
||||||
|
na += *a - '0';
|
||||||
|
}
|
||||||
|
for (; *b >= '0' && *b <= '9'; b++)
|
||||||
|
{
|
||||||
|
nb *= 10;
|
||||||
|
nb += *b - '0';
|
||||||
|
}
|
||||||
// In case the numbers are the same
|
// In case the numbers are the same
|
||||||
if (na == nb)
|
if (na == nb)
|
||||||
continue;
|
continue;
|
||||||
return na - nb;
|
return na - nb;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
utf8 * safe_strtrunc(utf8 * text, size_t size)
|
utf8* safe_strtrunc(utf8* text, size_t size)
|
||||||
{
|
{
|
||||||
assert(text != nullptr);
|
assert(text != nullptr);
|
||||||
|
|
||||||
if (size == 0) return text;
|
if (size == 0)
|
||||||
|
return text;
|
||||||
|
|
||||||
const char *sourceLimit = text + size - 1;
|
const char* sourceLimit = text + size - 1;
|
||||||
char *ch = text;
|
char* ch = text;
|
||||||
char *last = text;
|
char* last = text;
|
||||||
uint32_t codepoint;
|
uint32_t codepoint;
|
||||||
while ((codepoint = utf8_get_next(ch, (const utf8 **)&ch)) != 0) {
|
while ((codepoint = utf8_get_next(ch, (const utf8**)&ch)) != 0)
|
||||||
if (ch <= sourceLimit) {
|
{
|
||||||
|
if (ch <= sourceLimit)
|
||||||
|
{
|
||||||
last = ch;
|
last = ch;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -356,66 +377,82 @@ utf8 * safe_strtrunc(utf8 * text, size_t size)
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *safe_strcpy(char * destination, const char * source, size_t size)
|
char* safe_strcpy(char* destination, const char* source, size_t size)
|
||||||
{
|
{
|
||||||
assert(destination != nullptr);
|
assert(destination != nullptr);
|
||||||
assert(source != nullptr);
|
assert(source != nullptr);
|
||||||
|
|
||||||
if (size == 0) return destination;
|
if (size == 0)
|
||||||
|
return destination;
|
||||||
|
|
||||||
char * result = destination;
|
char* result = destination;
|
||||||
|
|
||||||
bool truncated = false;
|
bool truncated = false;
|
||||||
const char *sourceLimit = source + size - 1;
|
const char* sourceLimit = source + size - 1;
|
||||||
const char *ch = source;
|
const char* ch = source;
|
||||||
uint32_t codepoint;
|
uint32_t codepoint;
|
||||||
while ((codepoint = utf8_get_next(ch, &ch)) != 0) {
|
while ((codepoint = utf8_get_next(ch, &ch)) != 0)
|
||||||
if (ch <= sourceLimit) {
|
{
|
||||||
|
if (ch <= sourceLimit)
|
||||||
|
{
|
||||||
destination = utf8_write_codepoint(destination, codepoint);
|
destination = utf8_write_codepoint(destination, codepoint);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
truncated = true;
|
truncated = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*destination = 0;
|
*destination = 0;
|
||||||
|
|
||||||
if (truncated) {
|
if (truncated)
|
||||||
|
{
|
||||||
log_warning("Truncating string \"%s\" to %d bytes.", result, size);
|
log_warning("Truncating string \"%s\" to %d bytes.", result, size);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *safe_strcat(char *destination, const char *source, size_t size)
|
char* safe_strcat(char* destination, const char* source, size_t size)
|
||||||
{
|
{
|
||||||
assert(destination != nullptr);
|
assert(destination != nullptr);
|
||||||
assert(source != nullptr);
|
assert(source != nullptr);
|
||||||
|
|
||||||
if (size == 0) {
|
if (size == 0)
|
||||||
|
{
|
||||||
return destination;
|
return destination;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *result = destination;
|
char* result = destination;
|
||||||
|
|
||||||
size_t i;
|
size_t i;
|
||||||
for (i = 0; i < size; i++) {
|
for (i = 0; i < size; i++)
|
||||||
if (*destination == '\0') {
|
{
|
||||||
|
if (*destination == '\0')
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
destination++;
|
destination++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool terminated = false;
|
bool terminated = false;
|
||||||
for (; i < size; i++) {
|
for (; i < size; i++)
|
||||||
if (*source != '\0') {
|
{
|
||||||
|
if (*source != '\0')
|
||||||
|
{
|
||||||
*destination++ = *source++;
|
*destination++ = *source++;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
*destination = *source;
|
*destination = *source;
|
||||||
terminated = true;
|
terminated = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!terminated) {
|
if (!terminated)
|
||||||
|
{
|
||||||
result[size - 1] = '\0';
|
result[size - 1] = '\0';
|
||||||
log_warning("Truncating string \"%s\" to %d bytes.", result, size);
|
log_warning("Truncating string \"%s\" to %d bytes.", result, size);
|
||||||
}
|
}
|
||||||
|
@ -423,7 +460,7 @@ char *safe_strcat(char *destination, const char *source, size_t size)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *safe_strcat_path(char *destination, const char *source, size_t size)
|
char* safe_strcat_path(char* destination, const char* source, size_t size)
|
||||||
{
|
{
|
||||||
path_end_with_separator(destination, size);
|
path_end_with_separator(destination, size);
|
||||||
if (source[0] == *PATH_SEPARATOR)
|
if (source[0] == *PATH_SEPARATOR)
|
||||||
|
@ -433,23 +470,25 @@ char *safe_strcat_path(char *destination, const char *source, size_t size)
|
||||||
return safe_strcat(destination, source, size);
|
return safe_strcat(destination, source, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *safe_strtrimleft(char *destination, const char *source, size_t size)
|
char* safe_strtrimleft(char* destination, const char* source, size_t size)
|
||||||
{
|
{
|
||||||
while (*source == ' ') {
|
while (*source == ' ')
|
||||||
|
{
|
||||||
source++;
|
source++;
|
||||||
}
|
}
|
||||||
return safe_strcpy(destination, source, size);
|
return safe_strcpy(destination, source, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !(defined(_GNU_SOURCE) || (defined(__DARWIN_C_LEVEL) && __DARWIN_C_LEVEL >= 200809L))
|
#if !(defined(_GNU_SOURCE) || (defined(__DARWIN_C_LEVEL) && __DARWIN_C_LEVEL >= 200809L))
|
||||||
char * strcasestr(const char * haystack, const char * needle)
|
char* strcasestr(const char* haystack, const char* needle)
|
||||||
{
|
{
|
||||||
const char * p1 = haystack;
|
const char* p1 = haystack;
|
||||||
const char * p2 = needle;
|
const char* p2 = needle;
|
||||||
const char * r = *p2 == 0 ? haystack : 0;
|
const char* r = *p2 == 0 ? haystack : 0;
|
||||||
|
|
||||||
while (*p1 != 0 && *p2 != 0) {
|
while (*p1 != 0 && *p2 != 0)
|
||||||
if (tolower((unsigned char) *p1) == tolower((unsigned char) *p2))
|
{
|
||||||
|
if (tolower((unsigned char)*p1) == tolower((unsigned char)*p2))
|
||||||
{
|
{
|
||||||
if (r == 0)
|
if (r == 0)
|
||||||
r = p1;
|
r = p1;
|
||||||
|
@ -461,7 +500,7 @@ char * strcasestr(const char * haystack, const char * needle)
|
||||||
if (r != 0)
|
if (r != 0)
|
||||||
p1 = r + 1;
|
p1 = r + 1;
|
||||||
|
|
||||||
if (tolower((unsigned char) *p1) == tolower((unsigned char) *p2))
|
if (tolower((unsigned char)*p1) == tolower((unsigned char)*p2))
|
||||||
{
|
{
|
||||||
r = p1;
|
r = p1;
|
||||||
p2++;
|
p2++;
|
||||||
|
@ -475,26 +514,28 @@ char * strcasestr(const char * haystack, const char * needle)
|
||||||
p1++;
|
p1++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return *p2 == 0 ? (char *) r : 0;
|
return *p2 == 0 ? (char*)r : 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool utf8_is_bom(const char *str)
|
bool utf8_is_bom(const char* str)
|
||||||
{
|
{
|
||||||
return str[0] == (char)(uint8_t)0xEF && str[1] == (char)(uint8_t)0xBB && str[2] == (char)(uint8_t)0xBF;
|
return str[0] == (char)(uint8_t)0xEF && str[1] == (char)(uint8_t)0xBB && str[2] == (char)(uint8_t)0xBF;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool str_is_null_or_empty(const char *str)
|
bool str_is_null_or_empty(const char* str)
|
||||||
{
|
{
|
||||||
return str == nullptr || str[0] == 0;
|
return str == nullptr || str[0] == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void util_srand(int32_t source) {
|
void util_srand(int32_t source)
|
||||||
|
{
|
||||||
srand(source);
|
srand(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Caveat: rand() might only return values up to 0x7FFF, which is the minimum specified in the C standard.
|
// Caveat: rand() might only return values up to 0x7FFF, which is the minimum specified in the C standard.
|
||||||
uint32_t util_rand() {
|
uint32_t util_rand()
|
||||||
|
{
|
||||||
return rand();
|
return rand();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -505,11 +546,12 @@ uint32_t util_rand() {
|
||||||
* @brief Inflates zlib-compressed data
|
* @brief Inflates zlib-compressed data
|
||||||
* @param data Data to be decompressed
|
* @param data Data to be decompressed
|
||||||
* @param data_in_size Size of data to be decompressed
|
* @param data_in_size Size of data to be decompressed
|
||||||
* @param data_out_size Pointer to a variable where output size will be written. If not 0, it will be used to set initial output buffer size.
|
* @param data_out_size Pointer to a variable where output size will be written. If not 0, it will be used to set initial output
|
||||||
|
* buffer size.
|
||||||
* @return Returns a pointer to memory holding decompressed data or NULL on failure.
|
* @return Returns a pointer to memory holding decompressed data or NULL on failure.
|
||||||
* @note It is caller's responsibility to free() the returned pointer once done with it.
|
* @note It is caller's responsibility to free() the returned pointer once done with it.
|
||||||
*/
|
*/
|
||||||
uint8_t *util_zlib_inflate(uint8_t *data, size_t data_in_size, size_t *data_out_size)
|
uint8_t* util_zlib_inflate(uint8_t* data, size_t data_in_size, size_t* data_out_size)
|
||||||
{
|
{
|
||||||
int32_t ret = Z_OK;
|
int32_t ret = Z_OK;
|
||||||
uLongf out_size = (uLong)*data_out_size;
|
uLongf out_size = (uLong)*data_out_size;
|
||||||
|
@ -521,25 +563,30 @@ uint8_t *util_zlib_inflate(uint8_t *data, size_t data_in_size, size_t *data_out_
|
||||||
out_size = std::min((uLongf)MAX_ZLIB_REALLOC, out_size);
|
out_size = std::min((uLongf)MAX_ZLIB_REALLOC, out_size);
|
||||||
}
|
}
|
||||||
uLongf buffer_size = out_size;
|
uLongf buffer_size = out_size;
|
||||||
uint8_t *buffer = (uint8_t *)malloc(buffer_size);
|
uint8_t* buffer = (uint8_t*)malloc(buffer_size);
|
||||||
do {
|
do
|
||||||
|
{
|
||||||
if (ret == Z_BUF_ERROR)
|
if (ret == Z_BUF_ERROR)
|
||||||
{
|
{
|
||||||
buffer_size *= 2;
|
buffer_size *= 2;
|
||||||
out_size = buffer_size;
|
out_size = buffer_size;
|
||||||
buffer = (uint8_t *)realloc(buffer, buffer_size);
|
buffer = (uint8_t*)realloc(buffer, buffer_size);
|
||||||
} else if (ret == Z_STREAM_ERROR) {
|
}
|
||||||
|
else if (ret == Z_STREAM_ERROR)
|
||||||
|
{
|
||||||
log_error("Your build is shipped with broken zlib. Please use the official build.");
|
log_error("Your build is shipped with broken zlib. Please use the official build.");
|
||||||
free(buffer);
|
free(buffer);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
} else if (ret < 0) {
|
}
|
||||||
|
else if (ret < 0)
|
||||||
|
{
|
||||||
log_error("Error uncompressing data.");
|
log_error("Error uncompressing data.");
|
||||||
free(buffer);
|
free(buffer);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
ret = uncompress(buffer, &out_size, data, (uLong)data_in_size);
|
ret = uncompress(buffer, &out_size, data, (uLong)data_in_size);
|
||||||
} while (ret != Z_OK);
|
} while (ret != Z_OK);
|
||||||
buffer = (uint8_t *)realloc(buffer, out_size);
|
buffer = (uint8_t*)realloc(buffer, out_size);
|
||||||
*data_out_size = out_size;
|
*data_out_size = out_size;
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
@ -552,19 +599,22 @@ uint8_t *util_zlib_inflate(uint8_t *data, size_t data_in_size, size_t *data_out_
|
||||||
* @return Returns a pointer to memory holding compressed data or NULL on failure.
|
* @return Returns a pointer to memory holding compressed data or NULL on failure.
|
||||||
* @note It is caller's responsibility to free() the returned pointer once done with it.
|
* @note It is caller's responsibility to free() the returned pointer once done with it.
|
||||||
*/
|
*/
|
||||||
uint8_t *util_zlib_deflate(const uint8_t *data, size_t data_in_size, size_t *data_out_size)
|
uint8_t* util_zlib_deflate(const uint8_t* data, size_t data_in_size, size_t* data_out_size)
|
||||||
{
|
{
|
||||||
int32_t ret = Z_OK;
|
int32_t ret = Z_OK;
|
||||||
uLongf out_size = (uLongf)*data_out_size;
|
uLongf out_size = (uLongf)*data_out_size;
|
||||||
uLong buffer_size = compressBound((uLong)data_in_size);
|
uLong buffer_size = compressBound((uLong)data_in_size);
|
||||||
uint8_t *buffer = (uint8_t *)malloc(buffer_size);
|
uint8_t* buffer = (uint8_t*)malloc(buffer_size);
|
||||||
do {
|
do
|
||||||
|
{
|
||||||
if (ret == Z_BUF_ERROR)
|
if (ret == Z_BUF_ERROR)
|
||||||
{
|
{
|
||||||
buffer_size *= 2;
|
buffer_size *= 2;
|
||||||
out_size = buffer_size;
|
out_size = buffer_size;
|
||||||
buffer = (uint8_t *)realloc(buffer, buffer_size);
|
buffer = (uint8_t*)realloc(buffer, buffer_size);
|
||||||
} else if (ret == Z_STREAM_ERROR) {
|
}
|
||||||
|
else if (ret == Z_STREAM_ERROR)
|
||||||
|
{
|
||||||
log_error("Your build is shipped with broken zlib. Please use the official build.");
|
log_error("Your build is shipped with broken zlib. Please use the official build.");
|
||||||
free(buffer);
|
free(buffer);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -572,20 +622,23 @@ uint8_t *util_zlib_deflate(const uint8_t *data, size_t data_in_size, size_t *dat
|
||||||
ret = compress(buffer, &out_size, data, (uLong)data_in_size);
|
ret = compress(buffer, &out_size, data, (uLong)data_in_size);
|
||||||
} while (ret != Z_OK);
|
} while (ret != Z_OK);
|
||||||
*data_out_size = out_size;
|
*data_out_size = out_size;
|
||||||
buffer = (uint8_t *)realloc(buffer, *data_out_size);
|
buffer = (uint8_t*)realloc(buffer, *data_out_size);
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Type-independent code left as macro to reduce duplicate code.
|
// Type-independent code left as macro to reduce duplicate code.
|
||||||
#define add_clamp_body(value, value_to_add, min_cap, max_cap) \
|
#define add_clamp_body(value, value_to_add, min_cap, max_cap) \
|
||||||
if ((value_to_add > 0) && (value > (max_cap - (value_to_add)))) { \
|
if ((value_to_add > 0) && (value > (max_cap - (value_to_add)))) \
|
||||||
value = max_cap; \
|
{ \
|
||||||
} \
|
value = max_cap; \
|
||||||
else if ((value_to_add < 0) && (value < (min_cap - (value_to_add)))) { \
|
} \
|
||||||
value = min_cap; \
|
else if ((value_to_add < 0) && (value < (min_cap - (value_to_add)))) \
|
||||||
} \
|
{ \
|
||||||
else { \
|
value = min_cap; \
|
||||||
value += value_to_add; \
|
} \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
value += value_to_add; \
|
||||||
}
|
}
|
||||||
|
|
||||||
int8_t add_clamp_int8_t(int8_t value, int8_t value_to_add)
|
int8_t add_clamp_int8_t(int8_t value, int8_t value_to_add)
|
||||||
|
@ -623,15 +676,17 @@ uint8_t lerp(uint8_t a, uint8_t b, float t)
|
||||||
if (t >= 1)
|
if (t >= 1)
|
||||||
return b;
|
return b;
|
||||||
|
|
||||||
int32_t range = b - a;
|
int32_t range = b - a;
|
||||||
int32_t amount = (int32_t)(range * t);
|
int32_t amount = (int32_t)(range * t);
|
||||||
return (uint8_t)(a + amount);
|
return (uint8_t)(a + amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
float flerp(float a, float b, float t)
|
float flerp(float a, float b, float t)
|
||||||
{
|
{
|
||||||
if (t <= 0) return a;
|
if (t <= 0)
|
||||||
if (t >= 1) return b;
|
return a;
|
||||||
|
if (t >= 1)
|
||||||
|
return b;
|
||||||
|
|
||||||
float range = b - a;
|
float range = b - a;
|
||||||
float amount = range * t;
|
float amount = range * t;
|
||||||
|
@ -657,11 +712,12 @@ uint8_t soft_light(uint8_t a, uint8_t b)
|
||||||
/**
|
/**
|
||||||
* strftime wrapper which appends to an existing string.
|
* strftime wrapper which appends to an existing string.
|
||||||
*/
|
*/
|
||||||
size_t strcatftime(char * buffer, size_t bufferSize, const char * format, const struct tm * tp)
|
size_t strcatftime(char* buffer, size_t bufferSize, const char* format, const struct tm* tp)
|
||||||
{
|
{
|
||||||
size_t stringLen = strnlen(buffer, bufferSize);
|
size_t stringLen = strnlen(buffer, bufferSize);
|
||||||
if (stringLen < bufferSize) {
|
if (stringLen < bufferSize)
|
||||||
char * dst = buffer + stringLen;
|
{
|
||||||
|
char* dst = buffer + stringLen;
|
||||||
size_t dstMaxSize = bufferSize - stringLen;
|
size_t dstMaxSize = bufferSize - stringLen;
|
||||||
return strftime(dst, dstMaxSize, format, tp);
|
return strftime(dst, dstMaxSize, format, tp);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,24 +10,25 @@
|
||||||
#ifndef _UTIL_H_
|
#ifndef _UTIL_H_
|
||||||
#define _UTIL_H_
|
#define _UTIL_H_
|
||||||
|
|
||||||
#include <time.h>
|
|
||||||
#include "../common.h"
|
#include "../common.h"
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
int32_t squaredmetres_to_squaredfeet(int32_t squaredMetres);
|
int32_t squaredmetres_to_squaredfeet(int32_t squaredMetres);
|
||||||
int32_t metres_to_feet(int32_t metres);
|
int32_t metres_to_feet(int32_t metres);
|
||||||
int32_t mph_to_kmph(int32_t mph);
|
int32_t mph_to_kmph(int32_t mph);
|
||||||
int32_t mph_to_dmps(int32_t mph);
|
int32_t mph_to_dmps(int32_t mph);
|
||||||
|
|
||||||
bool filename_valid_characters(const utf8 *filename);
|
bool filename_valid_characters(const utf8* filename);
|
||||||
|
|
||||||
char *path_get_directory(const utf8 *path);
|
char* path_get_directory(const utf8* path);
|
||||||
const char *path_get_filename(const utf8 *path);
|
const char* path_get_filename(const utf8* path);
|
||||||
const char *path_get_extension(const utf8 *path);
|
const char* path_get_extension(const utf8* path);
|
||||||
void path_set_extension(utf8 *path, const utf8 *newExtension, size_t size);
|
void path_set_extension(utf8* path, const utf8* newExtension, size_t size);
|
||||||
void path_append_extension(utf8 *path, const utf8 *newExtension, size_t size);
|
void path_append_extension(utf8* path, const utf8* newExtension, size_t size);
|
||||||
void path_remove_extension(utf8 *path);
|
void path_remove_extension(utf8* path);
|
||||||
void path_end_with_separator(utf8 *path, size_t size);
|
void path_end_with_separator(utf8* path, size_t size);
|
||||||
bool writeentirefile(const utf8 * path, const void * buffer, size_t length);
|
bool writeentirefile(const utf8* path, const void* buffer, size_t length);
|
||||||
|
|
||||||
bool sse41_available();
|
bool sse41_available();
|
||||||
bool avx2_available();
|
bool avx2_available();
|
||||||
|
@ -35,26 +36,26 @@ bool avx2_available();
|
||||||
int32_t bitscanforward(int32_t source);
|
int32_t bitscanforward(int32_t source);
|
||||||
void bitcount_init();
|
void bitcount_init();
|
||||||
int32_t bitcount(uint32_t source);
|
int32_t bitcount(uint32_t source);
|
||||||
bool strequals(const char *a, const char *b, int32_t length, bool caseInsensitive);
|
bool strequals(const char* a, const char* b, int32_t length, bool caseInsensitive);
|
||||||
int32_t strcicmp(char const *a, char const *b);
|
int32_t strcicmp(char const* a, char const* b);
|
||||||
int32_t strlogicalcmp(char const *a, char const *b);
|
int32_t strlogicalcmp(char const* a, char const* b);
|
||||||
utf8 * safe_strtrunc(utf8 * text, size_t size);
|
utf8* safe_strtrunc(utf8* text, size_t size);
|
||||||
char *safe_strcpy(char * destination, const char * source, size_t num);
|
char* safe_strcpy(char* destination, const char* source, size_t num);
|
||||||
char *safe_strcat(char *destination, const char *source, size_t size);
|
char* safe_strcat(char* destination, const char* source, size_t size);
|
||||||
char *safe_strcat_path(char *destination, const char *source, size_t size);
|
char* safe_strcat_path(char* destination, const char* source, size_t size);
|
||||||
char *safe_strtrimleft(char *destination, const char *source, size_t size);
|
char* safe_strtrimleft(char* destination, const char* source, size_t size);
|
||||||
#if !(defined(_GNU_SOURCE) || (defined(__DARWIN_C_LEVEL) && __DARWIN_C_LEVEL >= 200809L))
|
#if !(defined(_GNU_SOURCE) || (defined(__DARWIN_C_LEVEL) && __DARWIN_C_LEVEL >= 200809L))
|
||||||
char * strcasestr(const char * haystack, const char * needle);
|
char* strcasestr(const char* haystack, const char* needle);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool utf8_is_bom(const char *str);
|
bool utf8_is_bom(const char* str);
|
||||||
bool str_is_null_or_empty(const char *str);
|
bool str_is_null_or_empty(const char* str);
|
||||||
|
|
||||||
void util_srand(int32_t source);
|
void util_srand(int32_t source);
|
||||||
uint32_t util_rand();
|
uint32_t util_rand();
|
||||||
|
|
||||||
uint8_t *util_zlib_deflate(const uint8_t *data, size_t data_in_size, size_t *data_out_size);
|
uint8_t* util_zlib_deflate(const uint8_t* data, size_t data_in_size, size_t* data_out_size);
|
||||||
uint8_t *util_zlib_inflate(uint8_t *data, size_t data_in_size, size_t *data_out_size);
|
uint8_t* util_zlib_inflate(uint8_t* data, size_t data_in_size, size_t* data_out_size);
|
||||||
|
|
||||||
int8_t add_clamp_int8_t(int8_t value, int8_t value_to_add);
|
int8_t add_clamp_int8_t(int8_t value, int8_t value_to_add);
|
||||||
int16_t add_clamp_int16_t(int16_t value, int16_t value_to_add);
|
int16_t add_clamp_int16_t(int16_t value, int16_t value_to_add);
|
||||||
|
@ -65,6 +66,6 @@ uint8_t lerp(uint8_t a, uint8_t b, float t);
|
||||||
float flerp(float a, float b, float t);
|
float flerp(float a, float b, float t);
|
||||||
uint8_t soft_light(uint8_t a, uint8_t b);
|
uint8_t soft_light(uint8_t a, uint8_t b);
|
||||||
|
|
||||||
size_t strcatftime(char * buffer, size_t bufferSize, const char * format, const struct tm * tp);
|
size_t strcatftime(char* buffer, size_t bufferSize, const char* format, const struct tm* tp);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -7,16 +7,18 @@
|
||||||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#include <utility>
|
|
||||||
#include "../core/Guard.hpp"
|
|
||||||
#include "Intent.h"
|
#include "Intent.h"
|
||||||
|
|
||||||
|
#include "../core/Guard.hpp"
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
Intent::Intent(rct_windowclass windowclass)
|
Intent::Intent(rct_windowclass windowclass)
|
||||||
{
|
{
|
||||||
this->_Class = windowclass;
|
this->_Class = windowclass;
|
||||||
}
|
}
|
||||||
|
|
||||||
Intent * Intent::putExtra(uint32_t key, uint32_t value)
|
Intent* Intent::putExtra(uint32_t key, uint32_t value)
|
||||||
{
|
{
|
||||||
IntentData data = {};
|
IntentData data = {};
|
||||||
data.intVal.unsignedInt = value;
|
data.intVal.unsignedInt = value;
|
||||||
|
@ -27,7 +29,7 @@ Intent * Intent::putExtra(uint32_t key, uint32_t value)
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Intent * Intent::putExtra(uint32_t key, void * value)
|
Intent* Intent::putExtra(uint32_t key, void* value)
|
||||||
{
|
{
|
||||||
IntentData data = {};
|
IntentData data = {};
|
||||||
data.pointerVal = value;
|
data.pointerVal = value;
|
||||||
|
@ -38,7 +40,7 @@ Intent * Intent::putExtra(uint32_t key, void * value)
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Intent * Intent::putExtra(uint32_t key, int32_t value)
|
Intent* Intent::putExtra(uint32_t key, int32_t value)
|
||||||
{
|
{
|
||||||
IntentData data = {};
|
IntentData data = {};
|
||||||
data.intVal.signedInt = value;
|
data.intVal.signedInt = value;
|
||||||
|
@ -49,7 +51,7 @@ Intent * Intent::putExtra(uint32_t key, int32_t value)
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Intent * Intent::putExtra(uint32_t key, std::string value)
|
Intent* Intent::putExtra(uint32_t key, std::string value)
|
||||||
{
|
{
|
||||||
IntentData data = {};
|
IntentData data = {};
|
||||||
data.stringVal = std::move(value);
|
data.stringVal = std::move(value);
|
||||||
|
@ -60,7 +62,7 @@ Intent * Intent::putExtra(uint32_t key, std::string value)
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Intent * Intent::putExtra(uint32_t key, close_callback value)
|
Intent* Intent::putExtra(uint32_t key, close_callback value)
|
||||||
{
|
{
|
||||||
IntentData data = {};
|
IntentData data = {};
|
||||||
data.closeCallbackVal = value;
|
data.closeCallbackVal = value;
|
||||||
|
@ -76,7 +78,7 @@ rct_windowclass Intent::GetWindowClass() const
|
||||||
return this->_Class;
|
return this->_Class;
|
||||||
}
|
}
|
||||||
|
|
||||||
void * Intent::GetPointerExtra(uint32_t key) const
|
void* Intent::GetPointerExtra(uint32_t key) const
|
||||||
{
|
{
|
||||||
if (_Data.count(key) == 0)
|
if (_Data.count(key) == 0)
|
||||||
{
|
{
|
||||||
|
@ -85,7 +87,7 @@ void * Intent::GetPointerExtra(uint32_t key) const
|
||||||
|
|
||||||
auto data = _Data.at(key);
|
auto data = _Data.at(key);
|
||||||
openrct2_assert(data.type == IntentData::DT_POINTER, "Actual type doesn't match requested type");
|
openrct2_assert(data.type == IntentData::DT_POINTER, "Actual type doesn't match requested type");
|
||||||
return (void *) data.pointerVal;
|
return (void*)data.pointerVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Intent::GetUIntExtra(uint32_t key) const
|
uint32_t Intent::GetUIntExtra(uint32_t key) const
|
||||||
|
@ -116,7 +118,7 @@ std::string Intent::GetStringExtra(uint32_t key) const
|
||||||
{
|
{
|
||||||
if (_Data.count(key) == 0)
|
if (_Data.count(key) == 0)
|
||||||
{
|
{
|
||||||
return std::string {};
|
return std::string{};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto data = _Data.at(key);
|
auto data = _Data.at(key);
|
||||||
|
|
|
@ -9,22 +9,30 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <string>
|
|
||||||
#include "../common.h"
|
#include "../common.h"
|
||||||
#include "../interface/Window.h"
|
#include "../interface/Window.h"
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
struct IntentData
|
struct IntentData
|
||||||
{
|
{
|
||||||
enum DATATYPE { DT_INT, DT_STRING, DT_POINTER, DT_CLOSE_CALLBACK } type;
|
enum DATATYPE
|
||||||
|
{
|
||||||
|
DT_INT,
|
||||||
|
DT_STRING,
|
||||||
|
DT_POINTER,
|
||||||
|
DT_CLOSE_CALLBACK
|
||||||
|
} type;
|
||||||
|
|
||||||
union {
|
union
|
||||||
|
{
|
||||||
uint32_t unsignedInt;
|
uint32_t unsignedInt;
|
||||||
int32_t signedInt;
|
int32_t signedInt;
|
||||||
} intVal;
|
} intVal;
|
||||||
std::string stringVal;
|
std::string stringVal;
|
||||||
close_callback closeCallbackVal;
|
close_callback closeCallbackVal;
|
||||||
void * pointerVal;
|
void* pointerVal;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Intent
|
class Intent
|
||||||
|
@ -32,19 +40,20 @@ class Intent
|
||||||
private:
|
private:
|
||||||
rct_windowclass _Class;
|
rct_windowclass _Class;
|
||||||
std::map<uint32_t, IntentData> _Data;
|
std::map<uint32_t, IntentData> _Data;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Intent(rct_windowclass windowclass);
|
explicit Intent(rct_windowclass windowclass);
|
||||||
rct_windowclass GetWindowClass() const;
|
rct_windowclass GetWindowClass() const;
|
||||||
void * GetPointerExtra(uint32_t key) const;
|
void* GetPointerExtra(uint32_t key) const;
|
||||||
std::string GetStringExtra(uint32_t key) const;
|
std::string GetStringExtra(uint32_t key) const;
|
||||||
uint32_t GetUIntExtra(uint32_t key) const;
|
uint32_t GetUIntExtra(uint32_t key) const;
|
||||||
int32_t GetSIntExtra(uint32_t key) const;
|
int32_t GetSIntExtra(uint32_t key) const;
|
||||||
close_callback GetCloseCallbackExtra(uint32_t key) const;
|
close_callback GetCloseCallbackExtra(uint32_t key) const;
|
||||||
Intent * putExtra(uint32_t key, uint32_t value);
|
Intent* putExtra(uint32_t key, uint32_t value);
|
||||||
Intent * putExtra(uint32_t key, void * value);
|
Intent* putExtra(uint32_t key, void* value);
|
||||||
Intent * putExtra(uint32_t key, int32_t value);
|
Intent* putExtra(uint32_t key, int32_t value);
|
||||||
Intent * putExtra(uint32_t key, std::string value);
|
Intent* putExtra(uint32_t key, std::string value);
|
||||||
Intent * putExtra(uint32_t key, close_callback value);
|
Intent* putExtra(uint32_t key, close_callback value);
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
|
|
@ -7,12 +7,12 @@
|
||||||
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#include "../audio/audio.h"
|
|
||||||
#include "../Cheats.h"
|
#include "../Cheats.h"
|
||||||
#include "../Context.h"
|
#include "../Context.h"
|
||||||
#include "../core/Util.hpp"
|
|
||||||
#include "../Game.h"
|
#include "../Game.h"
|
||||||
#include "../Input.h"
|
#include "../Input.h"
|
||||||
|
#include "../audio/audio.h"
|
||||||
|
#include "../core/Util.hpp"
|
||||||
#include "../interface/Viewport.h"
|
#include "../interface/Viewport.h"
|
||||||
#include "../network/network.h"
|
#include "../network/network.h"
|
||||||
#include "../paint/VirtualFloor.h"
|
#include "../paint/VirtualFloor.h"
|
||||||
|
@ -39,23 +39,23 @@ void game_command_callback_pickup_guest(
|
||||||
{
|
{
|
||||||
switch (ecx)
|
switch (ecx)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
{
|
|
||||||
int32_t peepnum = eax;
|
|
||||||
rct_window * w = window_find_by_number(WC_PEEP, peepnum);
|
|
||||||
if (w)
|
|
||||||
{
|
{
|
||||||
tool_set(w, WC_PEEP__WIDX_PICKUP, TOOL_PICKER);
|
int32_t peepnum = eax;
|
||||||
}
|
rct_window* w = window_find_by_number(WC_PEEP, peepnum);
|
||||||
}
|
if (w)
|
||||||
break;
|
{
|
||||||
case 2:
|
tool_set(w, WC_PEEP__WIDX_PICKUP, TOOL_PICKER);
|
||||||
if (ebx == 0)
|
}
|
||||||
{
|
|
||||||
tool_cancel();
|
|
||||||
gPickupPeepImage = UINT32_MAX;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 2:
|
||||||
|
if (ebx == 0)
|
||||||
|
{
|
||||||
|
tool_cancel();
|
||||||
|
gPickupPeepImage = UINT32_MAX;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,12 +71,12 @@ void game_command_callback_hire_new_staff_member(
|
||||||
int32_t sprite_index = edi;
|
int32_t sprite_index = edi;
|
||||||
if (sprite_index == SPRITE_INDEX_NULL)
|
if (sprite_index == SPRITE_INDEX_NULL)
|
||||||
{
|
{
|
||||||
rct_window * window = window_find_by_class(WC_STAFF_LIST);
|
rct_window* window = window_find_by_class(WC_STAFF_LIST);
|
||||||
window_invalidate(window);
|
window_invalidate(window);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
rct_peep * peep = &get_sprite(sprite_index)->peep;
|
rct_peep* peep = &get_sprite(sprite_index)->peep;
|
||||||
auto intent = Intent(WC_PEEP);
|
auto intent = Intent(WC_PEEP);
|
||||||
intent.putExtra(INTENT_EXTRA_PEEP, peep);
|
intent.putExtra(INTENT_EXTRA_PEEP, peep);
|
||||||
context_open_intent(&intent);
|
context_open_intent(&intent);
|
||||||
|
@ -94,23 +94,23 @@ void game_command_callback_pickup_staff(
|
||||||
{
|
{
|
||||||
switch (ecx)
|
switch (ecx)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
{
|
|
||||||
int32_t peepnum = eax;
|
|
||||||
rct_window * w = window_find_by_number(WC_PEEP, peepnum);
|
|
||||||
if (w)
|
|
||||||
{
|
{
|
||||||
tool_set(w, WC_STAFF__WIDX_PICKUP, TOOL_PICKER);
|
int32_t peepnum = eax;
|
||||||
}
|
rct_window* w = window_find_by_number(WC_PEEP, peepnum);
|
||||||
}
|
if (w)
|
||||||
break;
|
{
|
||||||
case 2:
|
tool_set(w, WC_STAFF__WIDX_PICKUP, TOOL_PICKER);
|
||||||
if (ebx == 0)
|
}
|
||||||
{
|
|
||||||
tool_cancel();
|
|
||||||
gPickupPeepImage = UINT32_MAX;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 2:
|
||||||
|
if (ebx == 0)
|
||||||
|
{
|
||||||
|
tool_cancel();
|
||||||
|
gPickupPeepImage = UINT32_MAX;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,23 +131,23 @@ void game_command_callback_place_ride_entrance_or_exit(
|
||||||
[[maybe_unused]] int32_t edi,
|
[[maybe_unused]] int32_t edi,
|
||||||
[[maybe_unused]] int32_t ebp)
|
[[maybe_unused]] int32_t ebp)
|
||||||
{
|
{
|
||||||
audio_play_sound_at_location(
|
audio_play_sound_at_location(SOUND_PLACE_ITEM, gCommandPosition.x, gCommandPosition.y, gCommandPosition.z);
|
||||||
SOUND_PLACE_ITEM,
|
|
||||||
gCommandPosition.x,
|
|
||||||
gCommandPosition.y,
|
|
||||||
gCommandPosition.z
|
|
||||||
);
|
|
||||||
|
|
||||||
Ride *ride = get_ride(gRideEntranceExitPlaceRideIndex);
|
Ride* ride = get_ride(gRideEntranceExitPlaceRideIndex);
|
||||||
if (ride_are_all_possible_entrances_and_exits_built(ride)) {
|
if (ride_are_all_possible_entrances_and_exits_built(ride))
|
||||||
|
{
|
||||||
tool_cancel();
|
tool_cancel();
|
||||||
if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_NO_TRACK)) {
|
if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_NO_TRACK))
|
||||||
|
{
|
||||||
window_close_by_class(WC_RIDE_CONSTRUCTION);
|
window_close_by_class(WC_RIDE_CONSTRUCTION);
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
gRideEntranceExitPlaceType ^= 1;
|
gRideEntranceExitPlaceType ^= 1;
|
||||||
gCurrentToolWidget.widget_index = (gRideEntranceExitPlaceType == ENTRANCE_TYPE_RIDE_ENTRANCE) ?
|
gCurrentToolWidget.widget_index = (gRideEntranceExitPlaceType == ENTRANCE_TYPE_RIDE_ENTRANCE)
|
||||||
WC_RIDE_CONSTRUCTION__WIDX_ENTRANCE : WC_RIDE_CONSTRUCTION__WIDX_EXIT;
|
? WC_RIDE_CONSTRUCTION__WIDX_ENTRANCE
|
||||||
|
: WC_RIDE_CONSTRUCTION__WIDX_EXIT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,16 +155,24 @@ void game_command_callback_place_ride_entrance_or_exit(
|
||||||
*
|
*
|
||||||
* rct2: 0x006CA162
|
* rct2: 0x006CA162
|
||||||
*/
|
*/
|
||||||
money32 place_provisional_track_piece(int32_t rideIndex, int32_t trackType, int32_t trackDirection, int32_t liftHillAndAlternativeState, int32_t x, int32_t y, int32_t z)
|
money32 place_provisional_track_piece(
|
||||||
|
int32_t rideIndex,
|
||||||
|
int32_t trackType,
|
||||||
|
int32_t trackDirection,
|
||||||
|
int32_t liftHillAndAlternativeState,
|
||||||
|
int32_t x,
|
||||||
|
int32_t y,
|
||||||
|
int32_t z)
|
||||||
{
|
{
|
||||||
Ride *ride;
|
Ride* ride;
|
||||||
money32 result;
|
money32 result;
|
||||||
|
|
||||||
ride_construction_remove_ghosts();
|
ride_construction_remove_ghosts();
|
||||||
ride = get_ride(rideIndex);
|
ride = get_ride(rideIndex);
|
||||||
if (ride->type == RIDE_TYPE_MAZE)
|
if (ride->type == RIDE_TYPE_MAZE)
|
||||||
{
|
{
|
||||||
int32_t flags = GAME_COMMAND_FLAG_APPLY | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_5 | GAME_COMMAND_FLAG_GHOST; // 105
|
int32_t flags = GAME_COMMAND_FLAG_APPLY | GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_5
|
||||||
|
| GAME_COMMAND_FLAG_GHOST; // 105
|
||||||
result = maze_set_track(x, y, z, flags, true, 0, rideIndex, GC_SET_MAZE_TRACK_BUILD);
|
result = maze_set_track(x, y, z, flags, true, 0, rideIndex, GC_SET_MAZE_TRACK_BUILD);
|
||||||
if (result == MONEY32_UNDEFINED)
|
if (result == MONEY32_UNDEFINED)
|
||||||
return result;
|
return result;
|
||||||
|
@ -191,12 +199,19 @@ money32 place_provisional_track_piece(int32_t rideIndex, int32_t trackType, int3
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = game_do_command(x, 105 | (trackDirection << 8), y, rideIndex | (trackType << 8) | (liftHillAndAlternativeState << 16), GAME_COMMAND_PLACE_TRACK, z, 0);
|
result = game_do_command(
|
||||||
|
x,
|
||||||
|
105 | (trackDirection << 8),
|
||||||
|
y,
|
||||||
|
rideIndex | (trackType << 8) | (liftHillAndAlternativeState << 16),
|
||||||
|
GAME_COMMAND_PLACE_TRACK,
|
||||||
|
z,
|
||||||
|
0);
|
||||||
if (result == MONEY32_UNDEFINED)
|
if (result == MONEY32_UNDEFINED)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
int16_t z_begin, z_end;
|
int16_t z_begin, z_end;
|
||||||
const rct_track_coordinates * coords = get_track_coord_from_ride(ride, trackType);
|
const rct_track_coordinates* coords = get_track_coord_from_ride(ride, trackType);
|
||||||
if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_NO_TRACK))
|
if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_NO_TRACK))
|
||||||
{
|
{
|
||||||
z_begin = coords->z_begin;
|
z_begin = coords->z_begin;
|
||||||
|
@ -231,7 +246,8 @@ money32 place_provisional_track_piece(int32_t rideIndex, int32_t trackType, int3
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::tuple<bool, uint8_t> window_ride_construction_update_state_get_track_element() {
|
static std::tuple<bool, uint8_t> window_ride_construction_update_state_get_track_element()
|
||||||
|
{
|
||||||
auto intent = Intent(INTENT_ACTION_RIDE_CONSTRUCTION_UPDATE_PIECES);
|
auto intent = Intent(INTENT_ACTION_RIDE_CONSTRUCTION_UPDATE_PIECES);
|
||||||
context_broadcast_intent(&intent);
|
context_broadcast_intent(&intent);
|
||||||
|
|
||||||
|
@ -240,7 +256,8 @@ static std::tuple<bool, uint8_t> window_ride_construction_update_state_get_track
|
||||||
uint8_t startBank = _previousTrackBankEnd;
|
uint8_t startBank = _previousTrackBankEnd;
|
||||||
uint8_t endBank = _currentTrackBankEnd;
|
uint8_t endBank = _currentTrackBankEnd;
|
||||||
|
|
||||||
if (_rideConstructionState == RIDE_CONSTRUCTION_STATE_BACK) {
|
if (_rideConstructionState == RIDE_CONSTRUCTION_STATE_BACK)
|
||||||
|
{
|
||||||
startSlope = _currentTrackSlopeEnd;
|
startSlope = _currentTrackSlopeEnd;
|
||||||
endSlope = _previousTrackSlopeEnd;
|
endSlope = _previousTrackSlopeEnd;
|
||||||
startBank = _currentTrackBankEnd;
|
startBank = _currentTrackBankEnd;
|
||||||
|
@ -248,13 +265,16 @@ static std::tuple<bool, uint8_t> window_ride_construction_update_state_get_track
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t curve = _currentTrackCurve;
|
uint16_t curve = _currentTrackCurve;
|
||||||
if (curve == 0xFFFF) {
|
if (curve == 0xFFFF)
|
||||||
|
{
|
||||||
return std::make_tuple(false, 0);
|
return std::make_tuple(false, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool startsDiagonal = (_currentTrackPieceDirection & (1 << 2)) != 0;
|
bool startsDiagonal = (_currentTrackPieceDirection & (1 << 2)) != 0;
|
||||||
if (curve == TRACK_CURVE_LEFT_LARGE || curve == TRACK_CURVE_RIGHT_LARGE) {
|
if (curve == TRACK_CURVE_LEFT_LARGE || curve == TRACK_CURVE_RIGHT_LARGE)
|
||||||
if (_rideConstructionState == RIDE_CONSTRUCTION_STATE_BACK) {
|
{
|
||||||
|
if (_rideConstructionState == RIDE_CONSTRUCTION_STATE_BACK)
|
||||||
|
{
|
||||||
startsDiagonal = !startsDiagonal;
|
startsDiagonal = !startsDiagonal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -263,14 +283,20 @@ static std::tuple<bool, uint8_t> window_ride_construction_update_state_get_track
|
||||||
{
|
{
|
||||||
for (uint32_t i = 0; i < Util::CountOf(gTrackDescriptors); i++)
|
for (uint32_t i = 0; i < Util::CountOf(gTrackDescriptors); i++)
|
||||||
{
|
{
|
||||||
const track_descriptor * trackDescriptor = &gTrackDescriptors[i];
|
const track_descriptor* trackDescriptor = &gTrackDescriptors[i];
|
||||||
|
|
||||||
if (trackDescriptor->track_curve != curve) continue;
|
if (trackDescriptor->track_curve != curve)
|
||||||
if (trackDescriptor->starts_diagonal != startsDiagonal) continue;
|
continue;
|
||||||
if (trackDescriptor->slope_start != startSlope) continue;
|
if (trackDescriptor->starts_diagonal != startsDiagonal)
|
||||||
if (trackDescriptor->slope_end != endSlope) continue;
|
continue;
|
||||||
if (trackDescriptor->bank_start != startBank) continue;
|
if (trackDescriptor->slope_start != startSlope)
|
||||||
if (trackDescriptor->bank_end != endBank) continue;
|
continue;
|
||||||
|
if (trackDescriptor->slope_end != endSlope)
|
||||||
|
continue;
|
||||||
|
if (trackDescriptor->bank_start != startBank)
|
||||||
|
continue;
|
||||||
|
if (trackDescriptor->bank_end != endBank)
|
||||||
|
continue;
|
||||||
|
|
||||||
return std::make_tuple(true, trackDescriptor->track_element);
|
return std::make_tuple(true, trackDescriptor->track_element);
|
||||||
}
|
}
|
||||||
|
@ -278,40 +304,49 @@ static std::tuple<bool, uint8_t> window_ride_construction_update_state_get_track
|
||||||
return std::make_tuple(false, 0);
|
return std::make_tuple(false, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (curve & 0xFF) {
|
switch (curve & 0xFF)
|
||||||
case TRACK_ELEM_END_STATION:
|
{
|
||||||
case TRACK_ELEM_S_BEND_LEFT:
|
case TRACK_ELEM_END_STATION:
|
||||||
case TRACK_ELEM_S_BEND_RIGHT:
|
case TRACK_ELEM_S_BEND_LEFT:
|
||||||
if (startSlope != TRACK_SLOPE_NONE || endSlope != TRACK_SLOPE_NONE) {
|
case TRACK_ELEM_S_BEND_RIGHT:
|
||||||
return std::make_tuple(false, 0);
|
if (startSlope != TRACK_SLOPE_NONE || endSlope != TRACK_SLOPE_NONE)
|
||||||
}
|
{
|
||||||
|
|
||||||
if (startBank != TRACK_BANK_NONE || endBank != TRACK_BANK_NONE) {
|
|
||||||
return std::make_tuple(false, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::make_tuple(true, curve & 0xFF);
|
|
||||||
|
|
||||||
case TRACK_ELEM_LEFT_VERTICAL_LOOP:
|
|
||||||
case TRACK_ELEM_RIGHT_VERTICAL_LOOP:
|
|
||||||
if (startBank != TRACK_BANK_NONE || endBank != TRACK_BANK_NONE) {
|
|
||||||
return std::make_tuple(false, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_rideConstructionState == RIDE_CONSTRUCTION_STATE_BACK) {
|
|
||||||
if (endSlope != TRACK_SLOPE_DOWN_25) {
|
|
||||||
return std::make_tuple(false, 0);
|
return std::make_tuple(false, 0);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
if (startSlope != TRACK_SLOPE_UP_25) {
|
if (startBank != TRACK_BANK_NONE || endBank != TRACK_BANK_NONE)
|
||||||
|
{
|
||||||
return std::make_tuple(false, 0);
|
return std::make_tuple(false, 0);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return std::make_tuple(true, curve & 0xFF);
|
return std::make_tuple(true, curve & 0xFF);
|
||||||
|
|
||||||
default:
|
case TRACK_ELEM_LEFT_VERTICAL_LOOP:
|
||||||
return std::make_tuple(true, curve & 0xFF);
|
case TRACK_ELEM_RIGHT_VERTICAL_LOOP:
|
||||||
|
if (startBank != TRACK_BANK_NONE || endBank != TRACK_BANK_NONE)
|
||||||
|
{
|
||||||
|
return std::make_tuple(false, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_rideConstructionState == RIDE_CONSTRUCTION_STATE_BACK)
|
||||||
|
{
|
||||||
|
if (endSlope != TRACK_SLOPE_DOWN_25)
|
||||||
|
{
|
||||||
|
return std::make_tuple(false, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (startSlope != TRACK_SLOPE_UP_25)
|
||||||
|
{
|
||||||
|
return std::make_tuple(false, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::make_tuple(true, curve & 0xFF);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return std::make_tuple(true, curve & 0xFF);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -328,162 +363,205 @@ static std::tuple<bool, uint8_t> window_ride_construction_update_state_get_track
|
||||||
* @param[out] _properties (edirs16)
|
* @param[out] _properties (edirs16)
|
||||||
* @return (CF)
|
* @return (CF)
|
||||||
*/
|
*/
|
||||||
bool window_ride_construction_update_state(int32_t *_trackType, int32_t *_trackDirection, int32_t *_rideIndex, int32_t *_liftHillAndAlternativeState, int32_t *_x, int32_t *_y, int32_t *_z, int32_t *_properties) {
|
bool window_ride_construction_update_state(
|
||||||
|
int32_t* _trackType,
|
||||||
|
int32_t* _trackDirection,
|
||||||
|
int32_t* _rideIndex,
|
||||||
|
int32_t* _liftHillAndAlternativeState,
|
||||||
|
int32_t* _x,
|
||||||
|
int32_t* _y,
|
||||||
|
int32_t* _z,
|
||||||
|
int32_t* _properties)
|
||||||
|
{
|
||||||
uint8_t trackType, trackDirection, rideIndex;
|
uint8_t trackType, trackDirection, rideIndex;
|
||||||
uint16_t z, x, y, liftHillAndAlternativeState, properties;
|
uint16_t z, x, y, liftHillAndAlternativeState, properties;
|
||||||
|
|
||||||
auto updated_element = window_ride_construction_update_state_get_track_element();
|
auto updated_element = window_ride_construction_update_state_get_track_element();
|
||||||
if (!std::get<0>(updated_element)) {
|
if (!std::get<0>(updated_element))
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
trackType = std::get<1>(updated_element);
|
trackType = std::get<1>(updated_element);
|
||||||
liftHillAndAlternativeState = 0;
|
liftHillAndAlternativeState = 0;
|
||||||
rideIndex = _currentRideIndex;
|
rideIndex = _currentRideIndex;
|
||||||
if (_currentTrackLiftHill & CONSTRUCTION_LIFT_HILL_SELECTED) {
|
if (_currentTrackLiftHill & CONSTRUCTION_LIFT_HILL_SELECTED)
|
||||||
|
{
|
||||||
liftHillAndAlternativeState |= CONSTRUCTION_LIFT_HILL_SELECTED;
|
liftHillAndAlternativeState |= CONSTRUCTION_LIFT_HILL_SELECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_currentTrackAlternative & RIDE_TYPE_ALTERNATIVE_TRACK_TYPE) {
|
if (_currentTrackAlternative & RIDE_TYPE_ALTERNATIVE_TRACK_TYPE)
|
||||||
|
{
|
||||||
liftHillAndAlternativeState |= RIDE_TYPE_ALTERNATIVE_TRACK_TYPE;
|
liftHillAndAlternativeState |= RIDE_TYPE_ALTERNATIVE_TRACK_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ride *ride = get_ride(rideIndex);
|
Ride* ride = get_ride(rideIndex);
|
||||||
|
|
||||||
if (_enabledRidePieces & (1ULL << TRACK_SLOPE_STEEP_LONG)) {
|
if (_enabledRidePieces & (1ULL << TRACK_SLOPE_STEEP_LONG))
|
||||||
switch (trackType) {
|
{
|
||||||
case TRACK_ELEM_FLAT_TO_60_DEG_UP:
|
switch (trackType)
|
||||||
trackType = TRACK_ELEM_FLAT_TO_60_DEG_UP_LONG_BASE;
|
{
|
||||||
break;
|
case TRACK_ELEM_FLAT_TO_60_DEG_UP:
|
||||||
|
trackType = TRACK_ELEM_FLAT_TO_60_DEG_UP_LONG_BASE;
|
||||||
|
break;
|
||||||
|
|
||||||
case TRACK_ELEM_60_DEG_UP_TO_FLAT:
|
case TRACK_ELEM_60_DEG_UP_TO_FLAT:
|
||||||
trackType = TRACK_ELEM_60_DEG_UP_TO_FLAT_LONG_BASE;
|
trackType = TRACK_ELEM_60_DEG_UP_TO_FLAT_LONG_BASE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TRACK_ELEM_FLAT_TO_60_DEG_DOWN:
|
case TRACK_ELEM_FLAT_TO_60_DEG_DOWN:
|
||||||
trackType = TRACK_ELEM_60_DEG_UP_TO_FLAT_LONG_BASE_122;
|
trackType = TRACK_ELEM_60_DEG_UP_TO_FLAT_LONG_BASE_122;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TRACK_ELEM_60_DEG_DOWN_TO_FLAT:
|
case TRACK_ELEM_60_DEG_DOWN_TO_FLAT:
|
||||||
trackType = TRACK_ELEM_FLAT_TO_60_DEG_DOWN_LONG_BASE;
|
trackType = TRACK_ELEM_FLAT_TO_60_DEG_DOWN_LONG_BASE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TRACK_ELEM_DIAG_FLAT_TO_60_DEG_UP:
|
case TRACK_ELEM_DIAG_FLAT_TO_60_DEG_UP:
|
||||||
case TRACK_ELEM_DIAG_60_DEG_UP_TO_FLAT:
|
case TRACK_ELEM_DIAG_60_DEG_UP_TO_FLAT:
|
||||||
case TRACK_ELEM_DIAG_FLAT_TO_60_DEG_DOWN:
|
case TRACK_ELEM_DIAG_FLAT_TO_60_DEG_DOWN:
|
||||||
case TRACK_ELEM_DIAG_60_DEG_DOWN_TO_FLAT:
|
case TRACK_ELEM_DIAG_60_DEG_DOWN_TO_FLAT:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_TRACK_ELEMENTS_HAVE_TWO_VARIETIES) && _currentTrackAlternative & RIDE_TYPE_ALTERNATIVE_TRACK_PIECES) {
|
if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_TRACK_ELEMENTS_HAVE_TWO_VARIETIES)
|
||||||
if (ride->type != RIDE_TYPE_WATER_COASTER || trackType == TRACK_ELEM_FLAT || trackType == TRACK_ELEM_LEFT_QUARTER_TURN_5_TILES || trackType == TRACK_ELEM_RIGHT_QUARTER_TURN_5_TILES) {
|
&& _currentTrackAlternative & RIDE_TYPE_ALTERNATIVE_TRACK_PIECES)
|
||||||
|
{
|
||||||
|
if (ride->type != RIDE_TYPE_WATER_COASTER || trackType == TRACK_ELEM_FLAT
|
||||||
|
|| trackType == TRACK_ELEM_LEFT_QUARTER_TURN_5_TILES || trackType == TRACK_ELEM_RIGHT_QUARTER_TURN_5_TILES)
|
||||||
|
{
|
||||||
int16_t alternativeType = AlternativeTrackTypes[trackType];
|
int16_t alternativeType = AlternativeTrackTypes[trackType];
|
||||||
if (alternativeType > -1) {
|
if (alternativeType > -1)
|
||||||
trackType = (uint8_t) alternativeType;
|
{
|
||||||
|
trackType = (uint8_t)alternativeType;
|
||||||
}
|
}
|
||||||
liftHillAndAlternativeState &= ~CONSTRUCTION_LIFT_HILL_SELECTED;
|
liftHillAndAlternativeState &= ~CONSTRUCTION_LIFT_HILL_SELECTED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const rct_track_coordinates *trackCoordinates = get_track_coord_from_ride(ride, trackType);
|
const rct_track_coordinates* trackCoordinates = get_track_coord_from_ride(ride, trackType);
|
||||||
|
|
||||||
x = _currentTrackBeginX;
|
x = _currentTrackBeginX;
|
||||||
y = _currentTrackBeginY;
|
y = _currentTrackBeginY;
|
||||||
z = _currentTrackBeginZ;
|
z = _currentTrackBeginZ;
|
||||||
if (_rideConstructionState == RIDE_CONSTRUCTION_STATE_BACK) {
|
if (_rideConstructionState == RIDE_CONSTRUCTION_STATE_BACK)
|
||||||
|
{
|
||||||
z -= trackCoordinates->z_end;
|
z -= trackCoordinates->z_end;
|
||||||
trackDirection = _currentTrackPieceDirection ^ 0x02;
|
trackDirection = _currentTrackPieceDirection ^ 0x02;
|
||||||
trackDirection -= trackCoordinates->rotation_end;
|
trackDirection -= trackCoordinates->rotation_end;
|
||||||
trackDirection += trackCoordinates->rotation_begin;
|
trackDirection += trackCoordinates->rotation_begin;
|
||||||
trackDirection &= 0x03;
|
trackDirection &= 0x03;
|
||||||
|
|
||||||
if (trackCoordinates->rotation_begin & (1 << 2)) {
|
if (trackCoordinates->rotation_begin & (1 << 2))
|
||||||
|
{
|
||||||
trackDirection |= 0x04;
|
trackDirection |= 0x04;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (trackDirection & 0x03) {
|
switch (trackDirection & 0x03)
|
||||||
case 0:
|
{
|
||||||
x -= trackCoordinates->x;
|
case 0:
|
||||||
y -= trackCoordinates->y;
|
x -= trackCoordinates->x;
|
||||||
break;
|
y -= trackCoordinates->y;
|
||||||
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
x -= trackCoordinates->y;
|
x -= trackCoordinates->y;
|
||||||
y += trackCoordinates->x;
|
y += trackCoordinates->x;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
x += trackCoordinates->x;
|
x += trackCoordinates->x;
|
||||||
y += trackCoordinates->y;
|
y += trackCoordinates->y;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
x += trackCoordinates->y;
|
x += trackCoordinates->y;
|
||||||
y -= trackCoordinates->x;
|
y -= trackCoordinates->x;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
z -= trackCoordinates->z_begin;
|
z -= trackCoordinates->z_begin;
|
||||||
trackDirection = _currentTrackPieceDirection;
|
trackDirection = _currentTrackPieceDirection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool turnOffLiftHill = false;
|
bool turnOffLiftHill = false;
|
||||||
if (!(_enabledRidePieces & (1ULL << TRACK_LIFT_HILL_CURVE))) {
|
if (!(_enabledRidePieces & (1ULL << TRACK_LIFT_HILL_CURVE)))
|
||||||
if (TrackFlags[trackType] & TRACK_ELEM_FLAG_CURVE_ALLOWS_LIFT) {
|
{
|
||||||
|
if (TrackFlags[trackType] & TRACK_ELEM_FLAG_CURVE_ALLOWS_LIFT)
|
||||||
|
{
|
||||||
turnOffLiftHill = true;
|
turnOffLiftHill = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(TrackFlags[trackType] & TRACK_ELEM_FLAG_ALLOW_LIFT_HILL)) {
|
if (!(TrackFlags[trackType] & TRACK_ELEM_FLAG_ALLOW_LIFT_HILL))
|
||||||
|
{
|
||||||
turnOffLiftHill = true;
|
turnOffLiftHill = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (turnOffLiftHill && !gCheatsEnableChainLiftOnAllTrack) {
|
if (turnOffLiftHill && !gCheatsEnableChainLiftOnAllTrack)
|
||||||
|
{
|
||||||
liftHillAndAlternativeState &= ~CONSTRUCTION_LIFT_HILL_SELECTED;
|
liftHillAndAlternativeState &= ~CONSTRUCTION_LIFT_HILL_SELECTED;
|
||||||
_currentTrackLiftHill &= ~CONSTRUCTION_LIFT_HILL_SELECTED;
|
_currentTrackLiftHill &= ~CONSTRUCTION_LIFT_HILL_SELECTED;
|
||||||
|
|
||||||
if (trackType == TRACK_ELEM_LEFT_CURVED_LIFT_HILL || trackType == TRACK_ELEM_RIGHT_CURVED_LIFT_HILL) {
|
if (trackType == TRACK_ELEM_LEFT_CURVED_LIFT_HILL || trackType == TRACK_ELEM_RIGHT_CURVED_LIFT_HILL)
|
||||||
|
{
|
||||||
liftHillAndAlternativeState |= CONSTRUCTION_LIFT_HILL_SELECTED;
|
liftHillAndAlternativeState |= CONSTRUCTION_LIFT_HILL_SELECTED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (track_element_has_speed_setting(trackType))
|
||||||
if (track_element_has_speed_setting(trackType)) {
|
{
|
||||||
properties = _currentBrakeSpeed2;
|
properties = _currentBrakeSpeed2;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
properties = _currentSeatRotationAngle << 12;
|
properties = _currentSeatRotationAngle << 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_trackType != NULL)
|
||||||
if (_trackType != NULL) *_trackType = trackType;
|
*_trackType = trackType;
|
||||||
if (_trackDirection != NULL) *_trackDirection = trackDirection;
|
if (_trackDirection != NULL)
|
||||||
if (_rideIndex != NULL) *_rideIndex = rideIndex;
|
*_trackDirection = trackDirection;
|
||||||
if (_liftHillAndAlternativeState != NULL) *_liftHillAndAlternativeState = liftHillAndAlternativeState;
|
if (_rideIndex != NULL)
|
||||||
if (_x != NULL) *_x = x;
|
*_rideIndex = rideIndex;
|
||||||
if (_y != NULL) *_y = y;
|
if (_liftHillAndAlternativeState != NULL)
|
||||||
if (_z != NULL) *_z = z;
|
*_liftHillAndAlternativeState = liftHillAndAlternativeState;
|
||||||
if (_properties != NULL) *_properties = properties;
|
if (_x != NULL)
|
||||||
|
*_x = x;
|
||||||
|
if (_y != NULL)
|
||||||
|
*_y = y;
|
||||||
|
if (_z != NULL)
|
||||||
|
*_z = z;
|
||||||
|
if (_properties != NULL)
|
||||||
|
*_properties = properties;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void window_ride_construction_do_entrance_exit_check()
|
void window_ride_construction_do_entrance_exit_check()
|
||||||
{
|
{
|
||||||
rct_window *w = window_find_by_class(WC_RIDE_CONSTRUCTION);
|
rct_window* w = window_find_by_class(WC_RIDE_CONSTRUCTION);
|
||||||
Ride *ride = get_ride(_currentRideIndex);
|
Ride* ride = get_ride(_currentRideIndex);
|
||||||
|
|
||||||
if (w == NULL || ride == NULL) {
|
if (w == NULL || ride == NULL)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_rideConstructionState == RIDE_CONSTRUCTION_STATE_0) {
|
if (_rideConstructionState == RIDE_CONSTRUCTION_STATE_0)
|
||||||
|
{
|
||||||
w = window_find_by_class(WC_RIDE_CONSTRUCTION);
|
w = window_find_by_class(WC_RIDE_CONSTRUCTION);
|
||||||
if (w != NULL) {
|
if (w != NULL)
|
||||||
if (!ride_are_all_possible_entrances_and_exits_built(ride)) {
|
{
|
||||||
|
if (!ride_are_all_possible_entrances_and_exits_built(ride))
|
||||||
|
{
|
||||||
window_event_mouse_up_call(w, WC_RIDE_CONSTRUCTION__WIDX_ENTRANCE);
|
window_event_mouse_up_call(w, WC_RIDE_CONSTRUCTION__WIDX_ENTRANCE);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
_deferClose = true;
|
_deferClose = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -492,15 +570,17 @@ void window_ride_construction_do_entrance_exit_check()
|
||||||
|
|
||||||
void window_ride_construction_do_station_check()
|
void window_ride_construction_do_station_check()
|
||||||
{
|
{
|
||||||
Ride *ride = get_ride(_currentRideIndex);
|
Ride* ride = get_ride(_currentRideIndex);
|
||||||
if (ride != NULL) {
|
if (ride != NULL)
|
||||||
|
{
|
||||||
_stationConstructed = ride->num_stations != 0;
|
_stationConstructed = ride->num_stations != 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void window_ride_construction_mouseup_demolish_next_piece(int32_t x, int32_t y, int32_t z, int32_t direction, int32_t type)
|
void window_ride_construction_mouseup_demolish_next_piece(int32_t x, int32_t y, int32_t z, int32_t direction, int32_t type)
|
||||||
{
|
{
|
||||||
if (gGotoStartPlacementMode) {
|
if (gGotoStartPlacementMode)
|
||||||
|
{
|
||||||
z &= 0xFFF0;
|
z &= 0xFFF0;
|
||||||
_currentTrackBeginZ = z;
|
_currentTrackBeginZ = z;
|
||||||
_rideConstructionState = RIDE_CONSTRUCTION_STATE_FRONT;
|
_rideConstructionState = RIDE_CONSTRUCTION_STATE_FRONT;
|
||||||
|
@ -516,10 +596,12 @@ void window_ride_construction_mouseup_demolish_next_piece(int32_t x, int32_t y,
|
||||||
int32_t b4 = _currentTrackLiftHill;
|
int32_t b4 = _currentTrackLiftHill;
|
||||||
ride_construction_set_default_next_piece();
|
ride_construction_set_default_next_piece();
|
||||||
window_ride_construction_update_active_elements();
|
window_ride_construction_update_active_elements();
|
||||||
if (!ride_try_get_origin_element(_currentRideIndex, NULL)) {
|
if (!ride_try_get_origin_element(_currentRideIndex, NULL))
|
||||||
|
{
|
||||||
ride_initialise_construction_window(_currentRideIndex);
|
ride_initialise_construction_window(_currentRideIndex);
|
||||||
_currentTrackPieceDirection = direction & 3;
|
_currentTrackPieceDirection = direction & 3;
|
||||||
if (!(slope & 0x100)) {
|
if (!(slope & 0x100))
|
||||||
|
{
|
||||||
_currentTrackCurve = slope;
|
_currentTrackCurve = slope;
|
||||||
_previousTrackSlopeEnd = slopeEnd;
|
_previousTrackSlopeEnd = slopeEnd;
|
||||||
_currentTrackSlopeEnd = b2;
|
_currentTrackSlopeEnd = b2;
|
||||||
|
@ -531,16 +613,20 @@ void window_ride_construction_mouseup_demolish_next_piece(int32_t x, int32_t y,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
if (_rideConstructionState2 == RIDE_CONSTRUCTION_STATE_SELECTED ||
|
{
|
||||||
_rideConstructionState2 == RIDE_CONSTRUCTION_STATE_FRONT
|
if (_rideConstructionState2 == RIDE_CONSTRUCTION_STATE_SELECTED
|
||||||
) {
|
|| _rideConstructionState2 == RIDE_CONSTRUCTION_STATE_FRONT)
|
||||||
if (type == TRACK_ELEM_MIDDLE_STATION || type == TRACK_ELEM_BEGIN_STATION) {
|
{
|
||||||
|
if (type == TRACK_ELEM_MIDDLE_STATION || type == TRACK_ELEM_BEGIN_STATION)
|
||||||
|
{
|
||||||
type = TRACK_ELEM_END_STATION;
|
type = TRACK_ELEM_END_STATION;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_rideConstructionState2 == RIDE_CONSTRUCTION_STATE_BACK) {
|
if (_rideConstructionState2 == RIDE_CONSTRUCTION_STATE_BACK)
|
||||||
if (type == TRACK_ELEM_MIDDLE_STATION) {
|
{
|
||||||
|
if (type == TRACK_ELEM_MIDDLE_STATION)
|
||||||
|
{
|
||||||
type = TRACK_ELEM_BEGIN_STATION;
|
type = TRACK_ELEM_BEGIN_STATION;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -556,10 +642,12 @@ void window_ride_construction_mouseup_demolish_next_piece(int32_t x, int32_t y,
|
||||||
_currentTrackPieceType = type;
|
_currentTrackPieceType = type;
|
||||||
_currentTrackSelectionFlags = 0;
|
_currentTrackSelectionFlags = 0;
|
||||||
_rideConstructionArrowPulseTime = 0;
|
_rideConstructionArrowPulseTime = 0;
|
||||||
if (_rideConstructionState2 == RIDE_CONSTRUCTION_STATE_FRONT) {
|
if (_rideConstructionState2 == RIDE_CONSTRUCTION_STATE_FRONT)
|
||||||
|
{
|
||||||
ride_select_next_section();
|
ride_select_next_section();
|
||||||
}
|
}
|
||||||
else if (_rideConstructionState2 == RIDE_CONSTRUCTION_STATE_BACK) {
|
else if (_rideConstructionState2 == RIDE_CONSTRUCTION_STATE_BACK)
|
||||||
|
{
|
||||||
ride_select_previous_section();
|
ride_select_previous_section();
|
||||||
}
|
}
|
||||||
window_ride_construction_update_active_elements();
|
window_ride_construction_update_active_elements();
|
||||||
|
@ -585,7 +673,8 @@ void game_command_callback_place_banner(
|
||||||
int32_t edi,
|
int32_t edi,
|
||||||
[[maybe_unused]] int32_t ebp)
|
[[maybe_unused]] int32_t ebp)
|
||||||
{
|
{
|
||||||
if (ebx != MONEY32_UNDEFINED) {
|
if (ebx != MONEY32_UNDEFINED)
|
||||||
|
{
|
||||||
int32_t bannerId = edi;
|
int32_t bannerId = edi;
|
||||||
|
|
||||||
audio_play_sound_at_location(SOUND_PLACE_ITEM, gCommandPosition.x, gCommandPosition.y, gCommandPosition.z);
|
audio_play_sound_at_location(SOUND_PLACE_ITEM, gCommandPosition.x, gCommandPosition.y, gCommandPosition.z);
|
||||||
|
|
Loading…
Reference in New Issue