From 4d55d7d9aad8d3c2bedec371c165bbb848c3786b Mon Sep 17 00:00:00 2001 From: jbzdarkid Date: Fri, 8 Nov 2019 22:06:07 -0800 Subject: Looks like chained read/write isn't working --- App/Main.cpp | 21 ++-- Source/Memory.h | 140 +++++++++++++++++++++- Source/Panel.cpp | 337 ++++++++++++++++++++++++++++++---------------------- Source/Panel.h | 224 ++++++++-------------------------- Source/Randomizer.h | 136 --------------------- 5 files changed, 387 insertions(+), 471 deletions(-) diff --git a/App/Main.cpp b/App/Main.cpp index 39dd517..535a18e 100644 --- a/App/Main.cpp +++ b/App/Main.cpp @@ -27,12 +27,11 @@ #define TMP4 0x504 #include "Panel.h" -int panel = 0x33D4; -std::shared_ptr g_panel; +// int panel = 0x33D4; // Tutorial vault +int panel = 0x0005D; // Outside Tutorial Dots Tutorial 1 +Puzzle g_puzzle; /* ------- Temp ------- */ - - // Globals HWND g_hwnd; HWND g_seed; @@ -133,13 +132,10 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) CheckDlgButton(hwnd, SPEED_UP_AUTOSCROLLERS, !IsDlgButtonChecked(hwnd, SPEED_UP_AUTOSCROLLERS)); break; case TMP1: - g_panel = std::make_shared(g_witnessProc, panel); + g_puzzle = PuzzleSerializer(g_witnessProc).ReadPuzzle(panel); break; case TMP2: - if(g_panel) g_panel->Write(panel); - break; - case TMP4: - if(g_panel) g_panel->Serialize(); + PuzzleSerializer(g_witnessProc).WritePuzzle(g_puzzle, panel); break; } } @@ -223,10 +219,9 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance CreateCheckbox(10, 340, SPEED_UP_AUTOSCROLLERS); CreateLabel(30, 340, 205, L"Speed up various autoscrollers"); - // CreateButton(200, 100, 100, L"Read", TMP1); - // CreateButton(200, 130, 100, L"Write", TMP2); - // CreateButton(200, 160, 100, L"Random", TMP3); - // CreateButton(200, 190, 100, L"Dump", TMP4); + CreateButton(200, 100, 100, L"Read", TMP1); + CreateButton(200, 130, 100, L"Write", TMP2); + CreateButton(200, 190, 100, L"Dump", TMP4); g_witnessProc->StartHeartbeat(g_hwnd); diff --git a/Source/Memory.h b/Source/Memory.h index c19d92b..95de884 100644 --- a/Source/Memory.h +++ b/Source/Memory.h @@ -54,6 +54,7 @@ public: private: template std::vector ReadData(const std::vector& offsets, size_t numItems) { + if (numItems == 0) return {}; std::vector data; data.resize(numItems); for (int i=0; i<5; i++) { @@ -68,6 +69,7 @@ private: template void WriteData(const std::vector& offsets, const std::vector& data) { + if (data.empty()) return; for (int i=0; i<5; i++) { if (WriteProcessMemory(_handle, ComputeOffset(offsets), &data[0], sizeof(T) * data.size(), nullptr)) { return; @@ -97,4 +99,140 @@ private: friend class Temp; friend class ChallengeRandomizer; friend class Randomizer; -}; \ No newline at end of file +}; + +#if GLOBALS == 0x5B28C0 +#define PATH_COLOR 0xC8 +#define REFLECTION_PATH_COLOR 0xD8 +#define DOT_COLOR 0xF8 +#define ACTIVE_COLOR 0x108 +#define BACKGROUND_REGION_COLOR 0x118 +#define SUCCESS_COLOR_A 0x128 +#define SUCCESS_COLOR_B 0x138 +#define STROBE_COLOR_A 0x148 +#define STROBE_COLOR_B 0x158 +#define ERROR_COLOR 0x168 +#define PATTERN_POINT_COLOR 0x188 +#define PATTERN_POINT_COLOR_A 0x198 +#define PATTERN_POINT_COLOR_B 0x1A8 +#define SYMBOL_A 0x1B8 +#define SYMBOL_B 0x1C8 +#define SYMBOL_C 0x1D8 +#define SYMBOL_D 0x1E8 +#define SYMBOL_E 0x1F8 +#define PUSH_SYMBOL_COLORS 0x208 +#define OUTER_BACKGROUND 0x20C +#define OUTER_BACKGROUND_MODE 0x21C +#define TRACED_EDGES 0x230 +#define AUDIO_PREFIX 0x278 +#define POWER 0x2A8 +#define TARGET 0x2BC +#define POWER_OFF_ON_FAIL 0x2C0 +#define IS_CYLINDER 0x2FC +#define CYLINDER_Z0 0x300 +#define CYLINDER_Z1 0x304 +#define CYLINDER_RADIUS 0x308 +#define CURSOR_SPEED_SCALE 0x358 +#define NEEDS_REDRAW 0x384 +#define SPECULAR_ADD 0x398 +#define SPECULAR_POWER 0x39C +#define PATH_WIDTH_SCALE 0x3A4 +#define STARTPOINT_SCALE 0x3A8 +#define NUM_DOTS 0x3B8 +#define NUM_CONNECTIONS 0x3BC +#define MAX_BROADCAST_DISTANCE 0x3C0 +#define DOT_POSITIONS 0x3C8 +#define DOT_FLAGS 0x3D0 +#define DOT_CONNECTION_A 0x3D8 +#define DOT_CONNECTION_B 0x3E0 +#define DECORATIONS 0x420 +#define DECORATION_FLAGS 0x428 +#define DECORATION_COLORS 0x430 +#define NUM_DECORATIONS 0x438 +#define REFLECTION_DATA 0x440 +#define GRID_SIZE_X 0x448 +#define GRID_SIZE_Y 0x44C +#define STYLE_FLAGS 0x450 +#define SEQUENCE_LEN 0x45C +#define SEQUENCE 0x460 +#define DOT_SEQUENCE_LEN 0x468 +#define DOT_SEQUENCE 0x470 +#define DOT_SEQUENCE_LEN_REFLECTION 0x478 +#define DOT_SEQUENCE_REFLECTION 0x480 +#define NUM_COLORED_REGIONS 0x4A0 +#define COLORED_REGIONS 0x4A8 +#define PANEL_TARGET 0x4B0 +#define SPECULAR_TEXTURE 0x4D8 +#define CABLE_TARGET_2 0xD8 +#define AUDIO_LOG_NAME 0xC8 +#define OPEN_RATE 0xE8 +#define METADATA 0xF2 // sizeof(short) +#define HOTEL_EP_NAME 0x4BC640 +#elif GLOBALS == 0x62D0A0 +#define PATH_COLOR 0xC0 +#define REFLECTION_PATH_COLOR 0xD0 +#define DOT_COLOR 0xF0 +#define ACTIVE_COLOR 0x100 +#define BACKGROUND_REGION_COLOR 0x110 +#define SUCCESS_COLOR_A 0x120 +#define SUCCESS_COLOR_B 0x130 +#define STROBE_COLOR_A 0x140 +#define STROBE_COLOR_B 0x150 +#define ERROR_COLOR 0x160 +#define PATTERN_POINT_COLOR 0x180 +#define PATTERN_POINT_COLOR_A 0x190 +#define PATTERN_POINT_COLOR_B 0x1A0 +#define SYMBOL_A 0x1B0 +#define SYMBOL_B 0x1C0 +#define SYMBOL_C 0x1D0 +#define SYMBOL_D 0x1E0 +#define SYMBOL_E 0x1F0 +#define PUSH_SYMBOL_COLORS 0x200 +#define OUTER_BACKGROUND 0x204 +#define OUTER_BACKGROUND_MODE 0x214 +#define TRACED_EDGES 0x228 +#define AUDIO_PREFIX 0x270 +#define POWER 0x2A0 +#define TARGET 0x2B4 +#define POWER_OFF_ON_FAIL 0x2B8 +#define IS_CYLINDER 0x2F4 +#define CYLINDER_Z0 0x2F8 +#define CYLINDER_Z1 0x2FC +#define CYLINDER_RADIUS 0x300 +#define CURSOR_SPEED_SCALE 0x350 +#define NEEDS_REDRAW 0x37C +#define SPECULAR_ADD 0x38C +#define SPECULAR_POWER 0x390 +#define PATH_WIDTH_SCALE 0x39C +#define STARTPOINT_SCALE 0x3A0 +#define NUM_DOTS 0x3B4 +#define NUM_CONNECTIONS 0x3B8 +#define MAX_BROADCAST_DISTANCE 0x3BC +#define DOT_POSITIONS 0x3C0 +#define DOT_FLAGS 0x3C8 +#define DOT_CONNECTION_A 0x3D0 +#define DOT_CONNECTION_B 0x3D8 +#define DECORATIONS 0x418 +#define DECORATION_FLAGS 0x420 +#define DECORATION_COLORS 0x428 +#define NUM_DECORATIONS 0x430 +#define REFLECTION_DATA 0x438 +#define GRID_SIZE_X 0x440 +#define GRID_SIZE_Y 0x444 +#define STYLE_FLAGS 0x448 +#define SEQUENCE_LEN 0x454 +#define SEQUENCE 0x458 +#define DOT_SEQUENCE_LEN 0x460 +#define DOT_SEQUENCE 0x468 +#define DOT_SEQUENCE_LEN_REFLECTION 0x470 +#define DOT_SEQUENCE_REFLECTION 0x478 +#define NUM_COLORED_REGIONS 0x498 +#define COLORED_REGIONS 0x4A0 +#define PANEL_TARGET 0x4A8 +#define SPECULAR_TEXTURE 0x4D0 +#define CABLE_TARGET_2 0xD0 +#define AUDIO_LOG_NAME 0x0 +#define OPEN_RATE 0xE0 +#define METADATA 0x13A // sizeof(short) +#define HOTEL_EP_NAME 0x51E340 +#endif \ No newline at end of file diff --git a/Source/Panel.cpp b/Source/Panel.cpp index 43e9763..b6f0403 100644 --- a/Source/Panel.cpp +++ b/Source/Panel.cpp @@ -1,108 +1,36 @@ #include "Panel.h" -#include "Random.h" #include "Memory.h" -#include "Randomizer.h" -#include #pragma warning (disable:26451) +#pragma warning (disable:26812) -template -int find(const std::vector &data, T search, size_t startIndex = 0) { - for (size_t i=startIndex ; i(i); - } - return -1; -} - -Panel::Panel(const std::shared_ptr& memory, int id) : _memory(memory) { - _width = 2 * _memory->ReadPanelData(id, GRID_SIZE_X, 1)[0] - 1; - _height = 2 * _memory->ReadPanelData(id, GRID_SIZE_Y, 1)[0] - 1; - _grid.resize(_width); - for (auto& row : _grid) row.resize(_height); - - ReadIntersections(id); - ReadDecorations(id); -} - -void Panel::Write(int id) { - WriteIntersections(id); - WriteDecorations(id); - - _memory->WritePanelData(id, GRID_SIZE_X, {(_width + 1)/2}); - _memory->WritePanelData(id, GRID_SIZE_Y, {(_height + 1)/2}); -} - -nlohmann::json Panel::Serialize() { - nlohmann::json puzzle = { - {"pillar", false}, - {"dots", nlohmann::json::array()}, - {"gaps", nlohmann::json::array()}, - {"name", "Imported from The Witness :O"}, - {"regionCache", nlohmann::json::object()}, - }; - if (_grid.empty()) return {}; - puzzle["grid"] = nlohmann::json::array(); - - for (int x=0; x<_width; x++) { - for (int y=0; y<_height; y++) { - if (x%2 == 1 && y%2 == 1) { - puzzle["grid"][x][y] = Decoration_to_json(_grid[x][y]); - } else { - if (_grid[x][y] & IntersectionFlags::HAS_DOT) { - puzzle["dots"].emplace_back(nlohmann::json({{"x", x}, {"y", y}})); - } - puzzle["grid"][x][y] = false; - } - } - } - - puzzle["startPoints"] = nlohmann::json::array(); - for (auto [x, y] : _startpoints) { - nlohmann::json startPoint = {{"x", x}, {"y", y}}; - puzzle["startPoints"].emplace_back(startPoint); - } - puzzle["endPoints"] = nlohmann::json::array(); - for (Endpoint endpoint : _endpoints) { - puzzle["endPoints"].emplace_back(endpoint.to_json()); - } - - std::string out = puzzle.dump(); - return puzzle; -} +PuzzleSerializer::PuzzleSerializer(const std::shared_ptr& memory) : _memory(memory) {} -void Panel::ReadDecorations(int id) { - int numDecorations = _memory->ReadPanelData(id, NUM_DECORATIONS, 1)[0]; - std::vector decorations = _memory->ReadArray(id, DECORATIONS, numDecorations); +Puzzle PuzzleSerializer::ReadPuzzle(int id) { + Puzzle p; + p.width = 2 * _memory->ReadPanelData(id, GRID_SIZE_X, 1)[0] - 1; + p.height = 2 * _memory->ReadPanelData(id, GRID_SIZE_Y, 1)[0] - 1; + p.grid.resize(p.width); + for (auto& row : p.grid) row.resize(p.height); - for (int i=0; i decorations; - for (int y=_height-2; y>0; y-=2) { - for (int x=1; x<_width - 1; x+=2) { - decorations.push_back(_grid[x][y]); - } - } + ReadIntersections(p, id); + ReadDecorations(p, id); - _memory->WritePanelData(id, NUM_DECORATIONS, {static_cast(decorations.size())}); - _memory->WriteArray(id, DECORATIONS, decorations); + return p; } -void Panel::ReadIntersections(int id) { +void PuzzleSerializer::ReadIntersections(Puzzle& p, int id) { int numIntersections = _memory->ReadPanelData(id, NUM_DOTS, 1)[0]; std::vector intersectionFlags = _memory->ReadArray(id, DOT_FLAGS, numIntersections); int i = 0; for (;; i++) { - auto [x, y] = loc_to_xy(i); + auto [x, y] = loc_to_xy(p, i); if (y < 0) break; - if (intersectionFlags[i] & IntersectionFlags::IS_STARTPOINT) { - _startpoints.push_back({x, y}); + if (intersectionFlags[i] & Flags::IS_STARTPOINT) { + p.grid[x][y].start = true; } + p.grid[x][y].dot = FlagsToDot(intersectionFlags[i]); } int numConnections = _memory->ReadPanelData(id, NUM_CONNECTIONS, 1)[0]; @@ -112,34 +40,32 @@ void Panel::ReadIntersections(int id) { // Iterate the remaining intersections (endpoints, dots, gaps) for (; i < numIntersections; i++) { - if (intersectionFlags[i] & IntersectionFlags::IS_ENDPOINT) { + if (intersectionFlags[i] & Flags::IS_ENDPOINT) { for (int j=0; j intersections[2*location]) { - dir = Endpoint::Direction::RIGHT; + p.grid[x][y].end = Cell::Dir::RIGHT; } else if (intersections[2*i + 1] > intersections[2*location + 1]) { // y coordinate is 0 (bottom) 1 (top), so this check is reversed. - dir = Endpoint::Direction::UP; + p.grid[x][y].end = Cell::Dir::UP; } else { - dir = Endpoint::Direction::DOWN; + p.grid[x][y].end = Cell::Dir::DOWN; } - auto [x, y] = loc_to_xy(location); - _endpoints.push_back(Endpoint(x, y, dir)); break; } } - } else if (intersectionFlags[i] & IntersectionFlags::HAS_DOT) { + } else if (intersectionFlags[i] & Flags::HAS_DOT) { for (int j=0; jReadPanelData(id, NUM_DECORATIONS, 1)[0]; + std::vector decorations = _memory->ReadArray(id, DECORATIONS, numDecorations); + if (numDecorations != decorations.size()) return; // @Error! + + for (int i=0; i(); + p.grid[x][y].decoration = d; + d->type = static_cast(decorations[i] & 0xFF00); + switch(d->type) { + case Shape::Poly: + case Shape::RPoly: + case Shape::Ylop: + d->polyshape = decorations[i] & 0xFFFF0000; + break; + case Shape::Triangle: + d->count = decorations[i] & 0x000F0000; + break; + } + d->color = static_cast(decorations[i] & 0xF); + } +} + +void PuzzleSerializer::WritePuzzle(const Puzzle& p, int id) { + _memory->WritePanelData(id, GRID_SIZE_X, {(p.width + 1)/2}); + _memory->WritePanelData(id, GRID_SIZE_Y, {(p.height + 1)/2}); + + WriteIntersections(p, id); + WriteDecorations(p, id); + + _memory->WritePanelData(id, NEEDS_REDRAW, {1}); +} + +void PuzzleSerializer::WriteIntersections(const Puzzle& p, int id) { std::vector intersections; std::vector intersectionFlags; std::vector connections_a; std::vector connections_b; - double min = 0.1; - double max = 0.9; - double width_interval = (max - min) / (_width/2); - double height_interval = (max - min) / (_height/2); + float min = 0.1f; + float max = 0.9f; + float width_interval = (max - min) / (p.width/2); + float height_interval = (max - min) / (p.height/2); - // TODO(future): Stop using push_back and set these into explicit locations, unrequires loop iteration order - for (int y=_height-1; y>=0; y-=2) { - for (int x=0; x<_width; x+=2) { + // @Cleanup: If I write directly to locations, then I can remove this gross loop iterator. + for (int y=p.height-1; y>=0; y-=2) { + for (int x=0; x(min + (x/2) * width_interval)); intersections.push_back(static_cast(max - (y/2) * height_interval)); int flags = 0; - if (find(_startpoints, {x, y}) != -1) flags |= IntersectionFlags::IS_STARTPOINT; + if (p.grid[x][y].start) { + flags |= Flags::IS_STARTPOINT; + } intersectionFlags.push_back(flags); // Create connections for this intersection -- always write low -> high if (y > 0) { - connections_a.push_back(xy_to_loc(x, y-2)); - connections_b.push_back(xy_to_loc(x, y)); + connections_a.push_back(xy_to_loc(p, x, y-2)); + connections_b.push_back(xy_to_loc(p, x, y)); } if (x > 0) { - connections_a.push_back(xy_to_loc(x-2, y)); - connections_b.push_back(xy_to_loc(x, y)); + connections_a.push_back(xy_to_loc(p, x-2, y)); + connections_b.push_back(xy_to_loc(p, x, y)); } } } - for (Endpoint endpoint : _endpoints) { - connections_a.push_back(xy_to_loc(endpoint.GetX(), endpoint.GetY())); // Target to connect to - connections_b.push_back(static_cast(intersectionFlags.size())); // This endpoint - - double xPos = min + (endpoint.GetX()/2) * width_interval; - double yPos = max - (endpoint.GetY()/2) * height_interval; - if (endpoint.GetDir()== Endpoint::Direction::LEFT) { - xPos -= .05; - } else if (endpoint.GetDir() == Endpoint::Direction::RIGHT) { - xPos += .05; - } else if (endpoint.GetDir() == Endpoint::Direction::UP) { - yPos += .05; // Y position goes from 0 (bottom) to 1 (top), so this is reversed. - } else if (endpoint.GetDir() == Endpoint::Direction::DOWN) { - yPos -= .05; - } - intersections.push_back(static_cast(xPos)); - intersections.push_back(static_cast(yPos)); - intersectionFlags.push_back(IntersectionFlags::IS_ENDPOINT); - } + for (int x=0; x(intersectionFlags.size())); // This endpoint + + float xPos = min + (x/2) * width_interval; + float yPos = max - (y/2) * height_interval; + switch (p.grid[x][y].end) { + case Cell::Dir::LEFT: + xPos -= .05f; + break; + case Cell::Dir::RIGHT: + xPos += .05f; + break; + case Cell::Dir::UP: + yPos += .05f; // Y position goes from 0 (bottom) to 1 (top), so this is reversed. + break; + case Cell::Dir::DOWN: + yPos -= .05f; + break; + } + intersections.push_back(xPos); + intersections.push_back(yPos); + intersectionFlags.push_back(Flags::IS_ENDPOINT); + } + } // Dots - for (int y=0; y<_height; y++) { - for (int x=0; x<_width; x++) { - if (!(_grid[x][y] & IntersectionFlags::HAS_DOT)) continue; + for (int x=0; x(xPos)); - intersections.push_back(static_cast(yPos)); - intersectionFlags.push_back(_grid[x][y]); + float xPos = min + (x/2.0f) * width_interval; + float yPos = max - (y/2.0f) * height_interval; + intersections.push_back(xPos); + intersections.push_back(yPos); + intersectionFlags.push_back(flags); } } - _memory->WritePanelData(id, NUM_DOTS, {static_cast(intersectionFlags.size())}); _memory->WriteArray(id, DOT_POSITIONS, intersections); _memory->WriteArray(id, DOT_FLAGS, intersectionFlags); _memory->WritePanelData(id, NUM_CONNECTIONS, {static_cast(connections_a.size())}); _memory->WriteArray(id, DOT_CONNECTION_A, connections_a); _memory->WriteArray(id, DOT_CONNECTION_B, connections_b); - _memory->WritePanelData(id, NEEDS_REDRAW, {1}); } +void PuzzleSerializer::WriteDecorations(const Puzzle& p, int id) { + std::vector decorations; + for (int y=p.height-2; y>0; y-=2) { + for (int x=1; xcolor | d->type | d->count | d->polyshape); + } else { + decorations.push_back(0); + } + } + } + + _memory->WritePanelData(id, NUM_DECORATIONS, {static_cast(decorations.size())}); + _memory->WriteArray(id, DECORATIONS, decorations); +} + +std::tuple PuzzleSerializer::loc_to_xy(const Puzzle& p, int location) { + int height2 = (p.height - 1) / 2; + int width2 = (p.width + 1) / 2; + + int x = 2 * (location % width2); + int y = 2 * (height2 - location / width2); + return {x, y}; +} + +int PuzzleSerializer::xy_to_loc(const Puzzle& p, int x, int y) { + int height2 = (p.height - 1) / 2; + int width2 = (p.width + 1) / 2; + + int rowsFromBottom = height2 - y/2; + return rowsFromBottom * width2 + x/2; +} + +std::tuple PuzzleSerializer::dloc_to_xy(const Puzzle& p, int location) { + int height2 = (p.height - 3) / 2; + int width2 = (p.width - 1) / 2; + + int x = 2 * (location % width2) + 1; + int y = 2 * (height2 - location / width2) + 1; + return {x, y}; +} + +int PuzzleSerializer::xy_to_dloc(const Puzzle& p, int x, int y) { + int height2 = (p.height - 3) / 2; + int width2 = (p.width - 1) / 2; + + int rowsFromBottom = height2 - (y - 1)/2; + return rowsFromBottom * width2 + (x - 1)/2; +} + +Cell::Dot PuzzleSerializer::FlagsToDot(int flags) { + if (!(flags & Flags::HAS_DOT)) return Cell::Dot::NONE; + if (flags & Flags::DOT_IS_BLUE) { + return Cell::Dot::BLUE; + } else if (flags & Flags::DOT_IS_ORANGE) { + return Cell::Dot::YELLOW; + } else if (flags & Flags::DOT_IS_INVISIBLE) { + return Cell::Dot::INVISIBLE; + } else { + return Cell::Dot::BLACK; + } +} diff --git a/Source/Panel.h b/Source/Panel.h index 0d1af14..caa7b04 100644 --- a/Source/Panel.h +++ b/Source/Panel.h @@ -1,145 +1,45 @@ #pragma once -#include "json.hpp" -#include "Memory.h" - -enum IntersectionFlags { - IS_ENDPOINT = 0x1, - IS_STARTPOINT = 0x2, - IS_GAP = 0x10000, - HAS_DOT = 0x40020, - DOT_IS_BLUE = 0x100, - DOT_IS_ORANGE = 0x200, - DOT_IS_INVISIBLE = 0x1000, +#include +#include + +class Memory; + +enum Shape { + Stone = 0x100, + Star = 0x200, + Poly = 0x400, + Eraser = 0x500, + Triangle = 0x600, + RPoly = 0x1000, + Ylop = 0x2000, }; -/* - enum Style { - SYMMETRICAL = 0x2, - IS_2COLOR = 0x10, - HAS_DOTS = 0x4, - HAS_STARS = 0x40, - HAS_STONES = 0x100, - HAS_ERASERS = 0x1000, - HAS_SHAPERS = 0x2000, - }; -*/ - -class Endpoint { -public: - enum class Direction { - LEFT, - RIGHT, - UP, - DOWN - }; - - Endpoint(int x, int y, Direction dir) { - _x = x; - _y = y; - _dir = dir; - } - - int GetX() {return _x;} - void SetX(int x) {_x = x;} - int GetY() {return _y;} - void SetY(int y) {_y = y;} - Direction GetDir() {return _dir;} - void SetDir(Direction dir) {_dir = dir;} - - nlohmann::json to_json() { - nlohmann::json json = {{"x", _x}, {"y", _y}}; - if (_dir == Direction::LEFT) json["dir"] = "left"; - if (_dir == Direction::RIGHT) json["dir"] = "right"; - if (_dir == Direction::UP) json["dir"] = "up"; - if (_dir == Direction::DOWN) json["dir"] = "down"; - return json; - } - -private: - int _x, _y; - Direction _dir; +enum Color { + Black = 0x1, + White = 0x2, + Gray = 0x3, + Purple = 0x4, + Green = 0x5, + Cyan = 0x6, + Pink = 0x7, + Yellow = 0x8, + Blue = 0x9, + Orange = 0xA, }; -class Panel { -public: - Panel(const std::shared_ptr& memory, int id); - // explicit Panel(nlohmann::json json); - - void Write(int id); - nlohmann::json Serialize(); - -private: - // For testing - Panel() = default; - - void ReadIntersections(int id); - void WriteIntersections(int id); - void ReadDecorations(int id); - void WriteDecorations(int id); - - // TODO: Reflection data - // TODO: Decoration colors - - std::tuple loc_to_xy(int location) { - int height2 = (_height - 1) / 2; - int width2 = (_width + 1) / 2; - - int x = 2 * (location % width2); - int y = 2 * (height2 - location / width2); - return {x, y}; - } - - int xy_to_loc(int x, int y) { - int height2 = (_height - 1) / 2; - int width2 = (_width + 1) / 2; - - int rowsFromBottom = height2 - y/2; - return rowsFromBottom * width2 + x/2; - } - - std::tuple dloc_to_xy(int location) { - int height2 = (_height - 3) / 2; - int width2 = (_width - 1) / 2; - - int x = 2 * (location % width2) + 1; - int y = 2 * (height2 - location / width2) + 1; - return {x, y}; - } - - int xy_to_dloc(int x, int y) { - int height2 = (_height - 3) / 2; - int width2 = (_width - 1) / 2; - - int rowsFromBottom = height2 - (y - 1)/2; - return rowsFromBottom * width2 + (x - 1)/2; - } - - std::shared_ptr _memory; - - int _width, _height; - - std::vector> _grid; - std::vector _endpoints; - std::vector> _startpoints; - int _style; - - friend class PanelExtractionTests; -}; - -// V2 stuff here struct Decoration { - enum class Type {STONE, STAR, POLY, ERASER, TRIANGLE, RPOLY, YLOP}; - Type type; - // TODO: Color color; - uint32_t polyshape; - int count; // For triangles + Shape type; + Color color; + int polyshape; + // For triangles only + int count; }; struct Cell { bool start; enum class Dir {NONE, LEFT, RIGHT, UP, DOWN}; Dir end; - Decoration* decoration; + std::shared_ptr decoration; enum class Dot {NONE, BLACK, BLUE, YELLOW, INVISIBLE}; Dot dot; enum class Gap {NONE, BREAK, FULL}; @@ -149,7 +49,7 @@ struct Cell { struct Puzzle { int16_t height; int16_t width; - Cell** grid; + std::vector> grid; enum class Symmetry {NONE, X, Y, XY}; Symmetry sym; @@ -159,33 +59,11 @@ struct Puzzle { class PuzzleSerializer { public: PuzzleSerializer(const std::shared_ptr& memory); - Puzzle ReadPuzzle(int panelId); - void WritePuzzle(int panelId, const Puzzle& puzzle); - -//private: - enum Shape { - Stone = 0x100, - Star = 0x200, - Poly = 0x400, - Eraser = 0x500, - Triangle = 0x600, - RPoly = 0x1000, - Ylop = 0x2000, - }; - - enum Color { - Black = 0x1, - White = 0x2, - Gray = 0x3, - Purple = 0x4, - Green = 0x5, - Cyan = 0x6, - Pink = 0x7, - Yellow = 0x8, - Blue = 0x9, - Orange = 0xA, - }; + Puzzle ReadPuzzle(int id); + void WritePuzzle(const Puzzle& p, int id); +private: + // @Bug: Blue and orange are swapped? enum Flags { IS_ENDPOINT = 0x1, IS_STARTPOINT = 0x2, @@ -196,25 +74,17 @@ public: HAS_DOT = 0x40020, }; - std::shared_ptr _memory; -}; - -static nlohmann::json Decoration_to_json(int decoration) { - nlohmann::json json = {}; - int shape = decoration & 0x00000F00; - if (shape == PuzzleSerializer::Shape::Stone) json["type"] = "square"; - if (shape == PuzzleSerializer::Shape::Star) json["type"] = "star"; - if (shape == PuzzleSerializer::Shape::Poly) json["type"] = "poly"; - if (shape == PuzzleSerializer::Shape::Eraser) json["type"] = "eraser"; - if (shape == PuzzleSerializer::Shape::Triangle) json["type"] = "triangle"; + void ReadIntersections(Puzzle& p, int id); + void ReadDecorations(Puzzle& p, int id); + void WriteIntersections(const Puzzle& p, int id); + void WriteDecorations(const Puzzle& p, int id); - int color = decoration & 0x0000000F; - if (color == PuzzleSerializer::Color::Black) json["color"] = "black"; - if (color == PuzzleSerializer::Color::White) json["color"] = "white"; - if (color == PuzzleSerializer::Color::Gray) json["color"] = "gray"; - if (color == PuzzleSerializer::Color::Blue) json["color"] = "blue"; - if (color == PuzzleSerializer::Color::Green) json["color"] = "green"; + std::tuple loc_to_xy(const Puzzle& p, int location); + int xy_to_loc(const Puzzle& p, int x, int y); + // Decoration location + std::tuple dloc_to_xy(const Puzzle& p, int location); + int xy_to_dloc(const Puzzle& p, int x, int y); + Cell::Dot FlagsToDot(int flags); - if (json.empty()) return false; - return json; -} + std::shared_ptr _memory; +}; diff --git a/Source/Randomizer.h b/Source/Randomizer.h index d9ea700..87f1f59 100644 --- a/Source/Randomizer.h +++ b/Source/Randomizer.h @@ -47,139 +47,3 @@ private: friend class SwapTests_Shipwreck_Test; }; - -#if GLOBALS == 0x5B28C0 -#define PATH_COLOR 0xC8 -#define REFLECTION_PATH_COLOR 0xD8 -#define DOT_COLOR 0xF8 -#define ACTIVE_COLOR 0x108 -#define BACKGROUND_REGION_COLOR 0x118 -#define SUCCESS_COLOR_A 0x128 -#define SUCCESS_COLOR_B 0x138 -#define STROBE_COLOR_A 0x148 -#define STROBE_COLOR_B 0x158 -#define ERROR_COLOR 0x168 -#define PATTERN_POINT_COLOR 0x188 -#define PATTERN_POINT_COLOR_A 0x198 -#define PATTERN_POINT_COLOR_B 0x1A8 -#define SYMBOL_A 0x1B8 -#define SYMBOL_B 0x1C8 -#define SYMBOL_C 0x1D8 -#define SYMBOL_D 0x1E8 -#define SYMBOL_E 0x1F8 -#define PUSH_SYMBOL_COLORS 0x208 -#define OUTER_BACKGROUND 0x20C -#define OUTER_BACKGROUND_MODE 0x21C -#define TRACED_EDGES 0x230 -#define AUDIO_PREFIX 0x278 -#define POWER 0x2A8 -#define TARGET 0x2BC -#define POWER_OFF_ON_FAIL 0x2C0 -#define IS_CYLINDER 0x2FC -#define CYLINDER_Z0 0x300 -#define CYLINDER_Z1 0x304 -#define CYLINDER_RADIUS 0x308 -#define CURSOR_SPEED_SCALE 0x358 -#define NEEDS_REDRAW 0x384 -#define SPECULAR_ADD 0x398 -#define SPECULAR_POWER 0x39C -#define PATH_WIDTH_SCALE 0x3A4 -#define STARTPOINT_SCALE 0x3A8 -#define NUM_DOTS 0x3B8 -#define NUM_CONNECTIONS 0x3BC -#define MAX_BROADCAST_DISTANCE 0x3C0 -#define DOT_POSITIONS 0x3C8 -#define DOT_FLAGS 0x3D0 -#define DOT_CONNECTION_A 0x3D8 -#define DOT_CONNECTION_B 0x3E0 -#define DECORATIONS 0x420 -#define DECORATION_FLAGS 0x428 -#define DECORATION_COLORS 0x430 -#define NUM_DECORATIONS 0x438 -#define REFLECTION_DATA 0x440 -#define GRID_SIZE_X 0x448 -#define GRID_SIZE_Y 0x44C -#define STYLE_FLAGS 0x450 -#define SEQUENCE_LEN 0x45C -#define SEQUENCE 0x460 -#define DOT_SEQUENCE_LEN 0x468 -#define DOT_SEQUENCE 0x470 -#define DOT_SEQUENCE_LEN_REFLECTION 0x478 -#define DOT_SEQUENCE_REFLECTION 0x480 -#define NUM_COLORED_REGIONS 0x4A0 -#define COLORED_REGIONS 0x4A8 -#define PANEL_TARGET 0x4B0 -#define SPECULAR_TEXTURE 0x4D8 -#define CABLE_TARGET_2 0xD8 -#define AUDIO_LOG_NAME 0xC8 -#define OPEN_RATE 0xE8 -#define METADATA 0xF2 // sizeof(short) -#define HOTEL_EP_NAME 0x4BC640 -#elif GLOBALS == 0x62D0A0 -#define PATH_COLOR 0xC0 -#define REFLECTION_PATH_COLOR 0xD0 -#define DOT_COLOR 0xF0 -#define ACTIVE_COLOR 0x100 -#define BACKGROUND_REGION_COLOR 0x110 -#define SUCCESS_COLOR_A 0x120 -#define SUCCESS_COLOR_B 0x130 -#define STROBE_COLOR_A 0x140 -#define STROBE_COLOR_B 0x150 -#define ERROR_COLOR 0x160 -#define PATTERN_POINT_COLOR 0x180 -#define PATTERN_POINT_COLOR_A 0x190 -#define PATTERN_POINT_COLOR_B 0x1A0 -#define SYMBOL_A 0x1B0 -#define SYMBOL_B 0x1C0 -#define SYMBOL_C 0x1D0 -#define SYMBOL_D 0x1E0 -#define SYMBOL_E 0x1F0 -#define PUSH_SYMBOL_COLORS 0x200 -#define OUTER_BACKGROUND 0x204 -#define OUTER_BACKGROUND_MODE 0x214 -#define TRACED_EDGES 0x228 -#define AUDIO_PREFIX 0x270 -#define POWER 0x2A0 -#define TARGET 0x2B4 -#define POWER_OFF_ON_FAIL 0x2B8 -#define IS_CYLINDER 0x2F4 -#define CYLINDER_Z0 0x2F8 -#define CYLINDER_Z1 0x2FC -#define CYLINDER_RADIUS 0x300 -#define CURSOR_SPEED_SCALE 0x350 -#define NEEDS_REDRAW 0x37C -#define SPECULAR_ADD 0x38C -#define SPECULAR_POWER 0x390 -#define PATH_WIDTH_SCALE 0x39C -#define STARTPOINT_SCALE 0x3A0 -#define NUM_DOTS 0x3B4 -#define NUM_CONNECTIONS 0x3B8 -#define MAX_BROADCAST_DISTANCE 0x3BC -#define DOT_POSITIONS 0x3C0 -#define DOT_FLAGS 0x3C8 -#define DOT_CONNECTION_A 0x3D0 -#define DOT_CONNECTION_B 0x3D8 -#define DECORATIONS 0x418 -#define DECORATION_FLAGS 0x420 -#define DECORATION_COLORS 0x428 -#define NUM_DECORATIONS 0x430 -#define REFLECTION_DATA 0x438 -#define GRID_SIZE_X 0x440 -#define GRID_SIZE_Y 0x444 -#define STYLE_FLAGS 0x448 -#define SEQUENCE_LEN 0x454 -#define SEQUENCE 0x458 -#define DOT_SEQUENCE_LEN 0x460 -#define DOT_SEQUENCE 0x468 -#define DOT_SEQUENCE_LEN_REFLECTION 0x470 -#define DOT_SEQUENCE_REFLECTION 0x478 -#define NUM_COLORED_REGIONS 0x498 -#define COLORED_REGIONS 0x4A0 -#define PANEL_TARGET 0x4A8 -#define SPECULAR_TEXTURE 0x4D0 -#define CABLE_TARGET_2 0xD0 -#define AUDIO_LOG_NAME 0x0 -#define OPEN_RATE 0xE0 -#define METADATA 0x13A // sizeof(short) -#define HOTEL_EP_NAME 0x51E340 -#endif \ No newline at end of file -- cgit 1.4.1