From fd2fa2211dc09c9030601fde1afd2f7823b22ed8 Mon Sep 17 00:00:00 2001 From: jbzdarkid Date: Sat, 16 Nov 2019 21:15:59 -0800 Subject: Cleanup tabs -> spaces, actually free memory --- Source/Memory.cpp | 9 +- Source/Memory.h | 132 ++++++++++---------- Source/PuzzlerSerializer.cpp | 280 +++++++++++++++++++++---------------------- Source/Randomizer.cpp | 80 ++++++------- Source/Randomizer2.cpp | 41 +------ 5 files changed, 256 insertions(+), 286 deletions(-) (limited to 'Source') diff --git a/Source/Memory.cpp b/Source/Memory.cpp index e240b90..d90c402 100644 --- a/Source/Memory.cpp +++ b/Source/Memory.cpp @@ -8,16 +8,17 @@ #undef PROCESSENTRY32 #undef Process32Next -Memory::Memory(const std::wstring& processName) : _processName(processName) { -} +Memory::Memory(const std::wstring& processName) : _processName(processName) {} Memory::~Memory() { if (_threadActive) { _threadActive = false; _thread.join(); } + if (_handle != nullptr) { - CloseHandle(_handle); + for (uintptr_t addr : _allocations) VirtualFreeEx(_handle, (void*)addr, 0, MEM_RELEASE); + CloseHandle(_handle); } } @@ -133,7 +134,7 @@ int Memory::ExecuteSigScans() { for (int i=0; i<0x200000; i+=0x1000) { std::vector data = ReadData({i}, 0x1100); - + for (auto& [scanBytes, sigScan] : _sigScans) { if (sigScan.found) continue; int index = find(data, scanBytes); diff --git a/Source/Memory.h b/Source/Memory.h index af4f0ae..70a271e 100644 --- a/Source/Memory.h +++ b/Source/Memory.h @@ -19,103 +19,103 @@ enum class ProcStatus { // http://stackoverflow.com/q/32798185 // http://stackoverflow.com/q/36018838 // http://stackoverflow.com/q/1387064 +// https://github.com/fkloiber/witness-trainer/blob/master/source/foreign_process_memory.cpp class Memory final : public std::enable_shared_from_this { public: - Memory(const std::wstring& processName); - ~Memory(); + Memory(const std::wstring& processName); + ~Memory(); void StartHeartbeat(HWND window, std::chrono::milliseconds beat = std::chrono::milliseconds(1000)); - Memory(const Memory& memory) = delete; - Memory& operator=(const Memory& other) = delete; + Memory(const Memory& memory) = delete; + Memory& operator=(const Memory& other) = delete; - template - std::vector ReadArray(int panel, int offset, int size) { - return ReadData({GLOBALS, 0x18, panel*8, offset, 0}, size); - } + template + std::vector ReadArray(int id, int offset, int size) { + return ReadData({GLOBALS, 0x18, id*8, offset, 0}, size); + } - template - void WriteArray(int panel, int offset, const std::vector& data) { - WriteData({GLOBALS, 0x18, panel*8, offset, 0}, data); - } + template + void WriteArray(int id, int offset, const std::vector& data) { + WriteData({GLOBALS, 0x18, id*8, offset, 0}, data); + } - template - void WriteNewArray(int panel, int offset, const std::vector& data) { - std::vector newAddr = {Allocate(data.size() * sizeof(T))}; - WritePanelData(panel, offset, newAddr); - WriteArray(panel, offset, data); - } + template + void WriteNewArray(int id, int offset, const std::vector& data) { + uintptr_t addr = VirtualAllocEx(_handle, nullptr, data.size() * sizeof(T), MEM_RESERVE | MEM_COMMIT, MEM_READWRITE); + _allocations.emplace_back(addr); + WriteEntityData(id, offset, addr); + WriteArray(id, offset, data); + } - template - std::vector ReadPanelData(int panel, int offset, size_t size) { - return ReadData({GLOBALS, 0x18, panel*8, offset}, size); - } + template + std::vector ReadEntityData(int id, int offset, size_t size) { + return ReadData({GLOBALS, 0x18, id*8, offset}, size); + } - template - void WritePanelData(int panel, int offset, const std::vector& data) { - WriteData({GLOBALS, 0x18, panel*8, offset}, data); - } + template + void WriteEntityData(int id, int offset, const std::vector& data) { + WriteData({GLOBALS, 0x18, id*8, offset}, data); + } - void AddSigScan(const std::vector& scanBytes, const std::function& scanFunc); - int ExecuteSigScans(); + void AddSigScan(const std::vector& scanBytes, const std::function& scanFunc); + int ExecuteSigScans(); private: - template - std::vector ReadData(const std::vector& offsets, size_t numItems) { + template + std::vector ReadData(const std::vector& offsets, size_t numItems) { if (numItems == 0) return {}; - std::vector data; - data.resize(numItems); + std::vector data; + data.resize(numItems); void* computedOffset = ComputeOffset(offsets); - for (int i=0; i<5; i++) { - if (ReadProcessMemory(_handle, computedOffset, &data[0], sizeof(T) * numItems, nullptr)) { + for (int i=0; i<5; i++) { + if (ReadProcessMemory(_handle, computedOffset, &data[0], sizeof(T) * numItems, nullptr)) { if (i != 0) { int k = 0; } - return data; - } - } - ThrowError(); - return {}; - } + return data; + } + } + ThrowError(); + return {}; + } - template - void WriteData(const std::vector& offsets, const std::vector& data) { + template + void WriteData(const std::vector& offsets, const std::vector& data) { if (data.empty()) return; void* computedOffset = ComputeOffset(offsets); - for (int i=0; i<5; i++) { - if (WriteProcessMemory(_handle, computedOffset, &data[0], sizeof(T) * data.size(), nullptr)) { + for (int i=0; i<5; i++) { + if (WriteProcessMemory(_handle, computedOffset, &data[0], sizeof(T) * data.size(), nullptr)) { if (i != 0) { int k = 0; } - return; - } - } - ThrowError(); - } + return; + } + } + ThrowError(); + } void Heartbeat(HWND window); - bool Initialize(); - void ThrowError(); - void* ComputeOffset(std::vector offsets); - uintptr_t Allocate(size_t bytes); + bool Initialize(); + void ThrowError(); + void* ComputeOffset(std::vector offsets); int _previousFrame = 0; bool _threadActive = false; std::thread _thread; std::wstring _processName; - std::map _computedAddresses; - uintptr_t _baseAddress = 0; - HANDLE _handle = nullptr; - uintptr_t _freeMem = 0; - uintptr_t _freeMemEnd = 0; - struct SigScan { - std::function scanFunc; - bool found; - }; - std::map, SigScan> _sigScans; + std::map _computedAddresses; + uintptr_t _baseAddress = 0; + HANDLE _handle = nullptr; + std::vector _allocations; + struct SigScan { + std::function scanFunc; + bool found; + }; + std::map, SigScan> _sigScans; - friend class Temp; - friend class ChallengeRandomizer; - friend class Randomizer; + friend class Temp; + friend class ChallengeRandomizer; + friend class Randomizer; }; #if GLOBALS == 0x5B28C0 diff --git a/Source/PuzzlerSerializer.cpp b/Source/PuzzlerSerializer.cpp index abdfafd..2ba0ce7 100644 --- a/Source/PuzzlerSerializer.cpp +++ b/Source/PuzzlerSerializer.cpp @@ -7,22 +7,22 @@ PuzzleSerializer::PuzzleSerializer(const std::shared_ptr& memory) : _memory(memory) {} Puzzle PuzzleSerializer::ReadPuzzle(int id) { - int width = 2 * _memory->ReadPanelData(id, GRID_SIZE_X, 1)[0] - 1; - int height = 2 * _memory->ReadPanelData(id, GRID_SIZE_Y, 1)[0] - 1; + int width = 2 * _memory->ReadEntityData(id, GRID_SIZE_X, 1)[0] - 1; + int height = 2 * _memory->ReadEntityData(id, GRID_SIZE_Y, 1)[0] - 1; if (width < 0 || height < 0) return Puzzle(); // @Error: Grid size should be always positive? Looks like the starting panels break this rule, though. - int numIntersections = _memory->ReadPanelData(id, NUM_DOTS, 1)[0]; - _intersectionFlags = _memory->ReadArray(id, DOT_FLAGS, numIntersections); - int numConnections = _memory->ReadPanelData(id, NUM_CONNECTIONS, 1)[0]; - _connectionsA = _memory->ReadArray(id, DOT_CONNECTION_A, numConnections); - _connectionsB = _memory->ReadArray(id, DOT_CONNECTION_B, numConnections); - _intersectionLocations = _memory->ReadArray(id, DOT_POSITIONS, numIntersections*2); + int numIntersections = _memory->ReadEntityData(id, NUM_DOTS, 1)[0]; + _intersectionFlags = _memory->ReadArray(id, DOT_FLAGS, numIntersections); + int numConnections = _memory->ReadEntityData(id, NUM_CONNECTIONS, 1)[0]; + _connectionsA = _memory->ReadArray(id, DOT_CONNECTION_A, numConnections); + _connectionsB = _memory->ReadArray(id, DOT_CONNECTION_B, numConnections); + _intersectionLocations = _memory->ReadArray(id, DOT_POSITIONS, numIntersections*2); Puzzle p; p.NewGrid(width, height); - ReadIntersections(p); + ReadIntersections(p); ReadExtras(p); - ReadDecorations(p, id); + ReadDecorations(p, id); ReadSequence(p, id); return p; } @@ -34,28 +34,28 @@ void PuzzleSerializer::WritePuzzle(const Puzzle& p, int id) { _intersectionLocations.clear(); MIN = 0.1f; - MAX = 0.9f; - WIDTH_INTERVAL = (MAX - MIN) / (p.width/2); - HEIGHT_INTERVAL = (MAX - MIN) / (p.height/2); + MAX = 0.9f; + WIDTH_INTERVAL = (MAX - MIN) / (p.width/2); + HEIGHT_INTERVAL = (MAX - MIN) / (p.height/2); HORIZ_GAP_SIZE = WIDTH_INTERVAL / 2; VERTI_GAP_SIZE = HEIGHT_INTERVAL / 2; - WriteIntersections(p); + WriteIntersections(p); WriteDots(p); WriteGaps(p); WriteEndpoints(p); WriteDecorations(p, id); WriteSequence(p, id); - _memory->WritePanelData(id, GRID_SIZE_X, {(p.width + 1)/2}); - _memory->WritePanelData(id, GRID_SIZE_Y, {(p.height + 1)/2}); - _memory->WritePanelData(id, NUM_DOTS, {static_cast(_intersectionFlags.size())}); - _memory->WriteArray(id, DOT_POSITIONS, _intersectionLocations); - _memory->WriteArray(id, DOT_FLAGS, _intersectionFlags); - _memory->WritePanelData(id, NUM_CONNECTIONS, {static_cast(_connectionsA.size())}); - _memory->WriteArray(id, DOT_CONNECTION_A, _connectionsA); - _memory->WriteArray(id, DOT_CONNECTION_B, _connectionsB); - _memory->WritePanelData(id, NEEDS_REDRAW, {1}); + _memory->WriteEntityData(id, GRID_SIZE_X, {(p.width + 1)/2}); + _memory->WriteEntityData(id, GRID_SIZE_Y, {(p.height + 1)/2}); + _memory->WriteEntityData(id, NUM_DOTS, {static_cast(_intersectionFlags.size())}); + _memory->WriteArray(id, DOT_POSITIONS, _intersectionLocations); + _memory->WriteArray(id, DOT_FLAGS, _intersectionFlags); + _memory->WriteEntityData(id, NUM_CONNECTIONS, {static_cast(_connectionsA.size())}); + _memory->WriteArray(id, DOT_CONNECTION_A, _connectionsA); + _memory->WriteArray(id, DOT_CONNECTION_B, _connectionsB); + _memory->WriteEntityData(id, NEEDS_REDRAW, {1}); } void PuzzleSerializer::ReadIntersections(Puzzle& p) { @@ -70,78 +70,78 @@ void PuzzleSerializer::ReadIntersections(Puzzle& p) { for (int j=0; j<_intersectionFlags.size(); j++) { if (_intersectionFlags[_connectionsA[j]] & Flags::IS_ENDPOINT) break; if (_intersectionFlags[_connectionsB[j]] & Flags::IS_ENDPOINT) break; - float x1 = _intersectionLocations[2*_connectionsA[j]]; - float y1 = _intersectionLocations[2*_connectionsA[j]+1]; - float x2 = _intersectionLocations[2*_connectionsB[j]]; - float y2 = _intersectionLocations[2*_connectionsB[j]+1]; + float x1 = _intersectionLocations[2*_connectionsA[j]]; + float y1 = _intersectionLocations[2*_connectionsA[j]+1]; + float x2 = _intersectionLocations[2*_connectionsB[j]]; + float y2 = _intersectionLocations[2*_connectionsB[j]+1]; auto [x, y] = loc_to_xy(p, _connectionsA[j]); - - if (x1 < x2) x++; - else if (x1 > x2) x--; - else if (y1 < y2) y--; - else if (y1 > y2) y++; + + if (x1 < x2) x++; + else if (x1 > x2) x--; + else if (y1 < y2) y--; + else if (y1 > y2) y++; p.grid[x][y].gap = Cell::Gap::NONE; } } void PuzzleSerializer::ReadExtras(Puzzle& p) { // This iterates bottom-top, left-right - int i = 0; - for (; i < _intersectionFlags.size(); i++) { + int i = 0; + for (; i < _intersectionFlags.size(); i++) { int flags = _intersectionFlags[i]; - auto [x, y] = loc_to_xy(p, i); - if (y < 0) break; // This is the expected exit point - if (flags & Flags::IS_STARTPOINT) { + auto [x, y] = loc_to_xy(p, i); + if (y < 0) break; // This is the expected exit point + if (flags & Flags::IS_STARTPOINT) { p.grid[x][y].start = true; - } + } p.grid[x][y].dot = FlagsToDot(flags); if (flags & Flags::HAS_NO_CONN) { p.grid[x][y].gap = Cell::Gap::FULL; } - } + } - // Iterate the remaining intersections (endpoints, dots, gaps) - for (; i < _intersectionFlags.size(); i++) { + // Iterate the remaining intersections (endpoints, dots, gaps) + for (; i < _intersectionFlags.size(); i++) { int location = FindConnection(i); - if (location == -1) continue; // @Error: Unable to find connection point + if (location == -1) continue; // @Error: Unable to find connection point // (x1, y1) location of this intersection // (x2, y2) location of the connected intersection - float x1 = _intersectionLocations[2*i]; - float y1 = _intersectionLocations[2*i+1]; - float x2 = _intersectionLocations[2*location]; - float y2 = _intersectionLocations[2*location+1]; + float x1 = _intersectionLocations[2*i]; + float y1 = _intersectionLocations[2*i+1]; + float x2 = _intersectionLocations[2*location]; + float y2 = _intersectionLocations[2*location+1]; auto [x, y] = loc_to_xy(p, location); - if (_intersectionFlags[i] & Flags::IS_ENDPOINT) { + if (_intersectionFlags[i] & Flags::IS_ENDPOINT) { // Our x coordinate is less than the target's - if (x1 < x2) p.grid[x][y].end = Cell::Dir::LEFT; - else if (x1 > x2) p.grid[x][y].end = Cell::Dir::RIGHT; + if (x1 < x2) p.grid[x][y].end = Cell::Dir::LEFT; + else if (x1 > x2) p.grid[x][y].end = Cell::Dir::RIGHT; // Note that Y coordinates are reversed: 0.0 (bottom) 1.0 (top) - else if (y1 < y2) p.grid[x][y].end = Cell::Dir::DOWN; + else if (y1 < y2) p.grid[x][y].end = Cell::Dir::DOWN; else if (y1 > y2) p.grid[x][y].end = Cell::Dir::UP; - } else if (_intersectionFlags[i] & Flags::HAS_DOT) { - if (x1 < x2) x--; - else if (x1 > x2) x++; - else if (y1 < y2) y++; - else if (y1 > y2) y--; + } else if (_intersectionFlags[i] & Flags::HAS_DOT) { + if (x1 < x2) x--; + else if (x1 > x2) x++; + else if (y1 < y2) y++; + else if (y1 > y2) y--; p.grid[x][y].dot = FlagsToDot(_intersectionFlags[i]); } else if (_intersectionFlags[i] & Flags::HAS_ONE_CONN) { - if (x1 < x2) x--; - else if (x1 > x2) x++; - else if (y1 < y2) y++; - else if (y1 > y2) y--; + if (x1 < x2) x--; + else if (x1 > x2) x++; + else if (y1 < y2) y++; + else if (y1 > y2) y--; p.grid[x][y].gap = Cell::Gap::BREAK; } - } + } } void PuzzleSerializer::ReadDecorations(Puzzle& p, int id) { - int numDecorations = _memory->ReadPanelData(id, NUM_DECORATIONS, 1)[0]; - std::vector decorations = _memory->ReadArray(id, DECORATIONS, numDecorations); + int numDecorations = _memory->ReadEntityData(id, NUM_DECORATIONS, 1)[0]; + std::vector decorations = _memory->ReadArray(id, DECORATIONS, numDecorations); if (numDecorations > 0) p.hasDecorations = true; - for (int i=0; i(); p.grid[x][y].decoration = d; d->type = static_cast(decorations[i] & 0xFF00); @@ -156,11 +156,11 @@ void PuzzleSerializer::ReadDecorations(Puzzle& p, int id) { break; } d->color = static_cast(decorations[i] & 0xF); - } + } } void PuzzleSerializer::ReadSequence(Puzzle& p, int id) { - int sequenceLength = _memory->ReadPanelData(id, SEQUENCE_LEN, 1)[0]; + int sequenceLength = _memory->ReadEntityData(id, SEQUENCE_LEN, 1)[0]; std::vector sequence = _memory->ReadArray(id, SEQUENCE, sequenceLength); for (int location : sequence) { @@ -170,15 +170,15 @@ void PuzzleSerializer::ReadSequence(Puzzle& p, int id) { } void PuzzleSerializer::WriteIntersections(const Puzzle& p) { - // @Cleanup: If I write directly to locations, then I can simplify this gross loop iterator. + // @Cleanup: If I write directly to locations, then I can simplify this gross loop iterator. // int numIntersections = (p.width / 2 + 1) * (p.height / 2 + 1); // Grided intersections - for (int y=p.height-1; y>=0; y-=2) { - for (int x=0; x=0; y-=2) { + for (int x=0; x 0 && p.grid[x][y-1].gap != Cell::Gap::FULL) { - _connectionsA.push_back(xy_to_loc(p, x, y-2)); - _connectionsB.push_back(xy_to_loc(p, x, y)); + if (y > 0 && p.grid[x][y-1].gap != Cell::Gap::FULL) { + _connectionsA.push_back(xy_to_loc(p, x, y-2)); + _connectionsB.push_back(xy_to_loc(p, x, y)); flags |= Flags::HAS_VERTI_CONN; numConnections++; - } + } // Bottom connection if (y < p.height - 1 && p.grid[x][y+1].gap != Cell::Gap::FULL) { flags |= Flags::HAS_VERTI_CONN; numConnections++; } // Left connection - if (x > 0 && p.grid[x-1][y].gap != Cell::Gap::FULL) { - _connectionsA.push_back(xy_to_loc(p, x-2, y)); - _connectionsB.push_back(xy_to_loc(p, x, y)); + if (x > 0 && p.grid[x-1][y].gap != Cell::Gap::FULL) { + _connectionsA.push_back(xy_to_loc(p, x-2, y)); + _connectionsB.push_back(xy_to_loc(p, x, y)); flags |= Flags::HAS_HORIZ_CONN; numConnections++; - } + } // Right connection if (x < p.width - 1 && p.grid[x+1][y].gap != Cell::Gap::FULL) { flags |= Flags::HAS_HORIZ_CONN; @@ -227,9 +227,9 @@ void PuzzleSerializer::WriteIntersections(const Puzzle& p) { if (numConnections == 0) flags |= HAS_NO_CONN; if (numConnections == 1) flags |= HAS_ONE_CONN; - _intersectionFlags.push_back(flags); - } - } + _intersectionFlags.push_back(flags); + } + } } void PuzzleSerializer::WriteEndpoints(const Puzzle& p) { @@ -237,27 +237,27 @@ void PuzzleSerializer::WriteEndpoints(const Puzzle& p) { for (int y=0; y(_intersectionFlags.size())); + _connectionsB.push_back(static_cast(_intersectionFlags.size())); auto [xPos, yPos] = xy_to_pos(p, x, y); switch (p.grid[x][y].end) { case Cell::Dir::LEFT: - xPos -= .05f; + xPos -= .05f; break; case Cell::Dir::RIGHT: - xPos += .05f; + xPos += .05f; break; case Cell::Dir::UP: - yPos += .05f; // Y position goes from 0 (bottom) to 1 (top), so this is reversed. + yPos += .05f; // Y position goes from 0 (bottom) to 1 (top), so this is reversed. break; case Cell::Dir::DOWN: - yPos -= .05f; + yPos -= .05f; break; } _endpointLocations.emplace_back(x, y, static_cast(_intersectionFlags.size())); - _intersectionLocations.push_back(xPos); - _intersectionLocations.push_back(yPos); - _intersectionFlags.push_back(Flags::IS_ENDPOINT); + _intersectionLocations.push_back(xPos); + _intersectionLocations.push_back(yPos); + _intersectionFlags.push_back(Flags::IS_ENDPOINT); } } } @@ -265,32 +265,32 @@ void PuzzleSerializer::WriteEndpoints(const Puzzle& p) { void PuzzleSerializer::WriteDots(const Puzzle& p) { for (int x=0; x A for connections. To remove, add the horiz/verti check, see gaps. int other_connection = _connectionsB[connectionLocation]; - _connectionsB[connectionLocation] = static_cast(_intersectionFlags.size()); - _connectionsA.push_back(other_connection); - _connectionsB.push_back(static_cast(_intersectionFlags.size())); + _connectionsB[connectionLocation] = static_cast(_intersectionFlags.size()); + _connectionsA.push_back(other_connection); + _connectionsB.push_back(static_cast(_intersectionFlags.size())); - // Add this dot to the end + // Add this dot to the end auto [xPos, yPos] = xy_to_pos(p, x, y); - _intersectionLocations.push_back(xPos); - _intersectionLocations.push_back(yPos); + _intersectionLocations.push_back(xPos); + _intersectionLocations.push_back(yPos); int flags = Flags::HAS_DOT; switch (p.grid[x][y].dot) { @@ -307,27 +307,27 @@ void PuzzleSerializer::WriteDots(const Puzzle& p) { break; } _intersectionFlags.push_back(flags); - } - } + } + } } void PuzzleSerializer::WriteGaps(const Puzzle& p) { for (int x=0; x(_intersectionFlags.size()); - _intersectionLocations.push_back(xPos); - _intersectionLocations.push_back(yPos + VERTI_GAP_SIZE / 2); + _intersectionLocations.push_back(xPos); + _intersectionLocations.push_back(yPos + VERTI_GAP_SIZE / 2); _intersectionFlags.push_back(Flags::HAS_ONE_CONN | Flags::HAS_VERTI_CONN); _connectionsA.push_back(xy_to_loc(p, x, y+1)); _connectionsB.push_back(static_cast(_intersectionFlags.size())); - _intersectionLocations.push_back(xPos); - _intersectionLocations.push_back(yPos - VERTI_GAP_SIZE / 2); + _intersectionLocations.push_back(xPos); + _intersectionLocations.push_back(yPos - VERTI_GAP_SIZE / 2); _intersectionFlags.push_back(Flags::HAS_ONE_CONN | Flags::HAS_VERTI_CONN); } else if (y%2 == 0) { // Horizontal gap _connectionsA[connectionLocation] = xy_to_loc(p, x-1, y); _connectionsB[connectionLocation] = static_cast(_intersectionFlags.size()); - _intersectionLocations.push_back(xPos - HORIZ_GAP_SIZE / 2); - _intersectionLocations.push_back(yPos); + _intersectionLocations.push_back(xPos - HORIZ_GAP_SIZE / 2); + _intersectionLocations.push_back(yPos); _intersectionFlags.push_back(Flags::HAS_ONE_CONN | Flags::HAS_HORIZ_CONN); _connectionsA.push_back(xy_to_loc(p, x+1, y)); _connectionsB.push_back(static_cast(_intersectionFlags.size())); - _intersectionLocations.push_back(xPos + HORIZ_GAP_SIZE / 2); - _intersectionLocations.push_back(yPos); + _intersectionLocations.push_back(xPos + HORIZ_GAP_SIZE / 2); + _intersectionLocations.push_back(yPos); _intersectionFlags.push_back(Flags::HAS_ONE_CONN | Flags::HAS_HORIZ_CONN); } - } - } + } + } } void PuzzleSerializer::WriteDecorations(const Puzzle& p, int id) { if (!p.hasDecorations) return; - std::vector decorations; - for (int y=p.height-2; y>0; y-=2) { - for (int x=1; x 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); + _memory->WriteEntityData(id, NUM_DECORATIONS, {static_cast(decorations.size())}); + _memory->WriteArray(id, DECORATIONS, decorations); } void PuzzleSerializer::WriteSequence(const Puzzle& p, int id) { @@ -399,7 +399,7 @@ void PuzzleSerializer::WriteSequence(const Puzzle& p, int id) { } } - _memory->WritePanelData(id, SEQUENCE_LEN, {static_cast(sequence.size())}); + _memory->WriteEntityData(id, SEQUENCE_LEN, {static_cast(sequence.size())}); _memory->WriteNewArray(id, SEQUENCE, sequence); } @@ -438,7 +438,7 @@ int PuzzleSerializer::xy_to_dloc(const Puzzle& p, int x, int y) const { } std::tuple PuzzleSerializer::xy_to_pos(const Puzzle& p, int x, int y) const { - return { + return { MIN + (x/2.0f) * WIDTH_INTERVAL, MAX - (y/2.0f) * HEIGHT_INTERVAL }; @@ -454,8 +454,8 @@ Cell::Dot PuzzleSerializer::FlagsToDot(int flags) const { int PuzzleSerializer::FindConnection(int location) const { for (int j=0; j<_connectionsA.size(); j++) { - if (_connectionsA[j] == location) return _connectionsB[j]; - if (_connectionsB[j] == location) return _connectionsA[j]; + if (_connectionsA[j] == location) return _connectionsB[j]; + if (_connectionsB[j] == location) return _connectionsA[j]; } return -1; } diff --git a/Source/Randomizer.cpp b/Source/Randomizer.cpp index 14583f8..2545c8f 100644 --- a/Source/Randomizer.cpp +++ b/Source/Randomizer.cpp @@ -156,35 +156,35 @@ void Randomizer::Randomize() { void Randomizer::AdjustSpeed() { // Desert Surface Final Control - _memory->WritePanelData(0x09F95, OPEN_RATE, {0.04f}); // 4x + _memory->WriteEntityData(0x09F95, OPEN_RATE, {0.04f}); // 4x // Swamp Sliding Bridge - _memory->WritePanelData(0x0061A, OPEN_RATE, {0.1f}); // 4x + _memory->WriteEntityData(0x0061A, OPEN_RATE, {0.1f}); // 4x // Mountain 2 Elevator - _memory->WritePanelData(0x09EEC, OPEN_RATE, {0.075f}); // 3x + _memory->WriteEntityData(0x09EEC, OPEN_RATE, {0.075f}); // 3x } void Randomizer::RandomizeLasers() { Randomize(lasers, SWAP::TARGETS); // Read the target of keep front laser, and write it to keep back laser. - std::vector keepFrontLaserTarget = _memory->ReadPanelData(0x0360E, TARGET, 1); - _memory->WritePanelData(0x03317, TARGET, keepFrontLaserTarget); + std::vector keepFrontLaserTarget = _memory->ReadEntityData(0x0360E, TARGET, 1); + _memory->WriteEntityData(0x03317, TARGET, keepFrontLaserTarget); } void Randomizer::PreventSnipes() { // Distance-gate swamp snipe 1 to prevent RNG swamp snipe - _memory->WritePanelData(0x17C05, MAX_BROADCAST_DISTANCE, {15.0}); + _memory->WriteEntityData(0x17C05, MAX_BROADCAST_DISTANCE, {15.0}); // Distance-gate shadows laser to prevent sniping through the bars - _memory->WritePanelData(0x19650, MAX_BROADCAST_DISTANCE, {2.5}); + _memory->WriteEntityData(0x19650, MAX_BROADCAST_DISTANCE, {2.5}); } // Private methods void Randomizer::RandomizeTutorial() { // Disable tutorial cursor speed modifications (not working?) - _memory->WritePanelData(0x00295, CURSOR_SPEED_SCALE, {1.0}); - _memory->WritePanelData(0x0C373, CURSOR_SPEED_SCALE, {1.0}); - _memory->WritePanelData(0x00293, CURSOR_SPEED_SCALE, {1.0}); - _memory->WritePanelData(0x002C2, CURSOR_SPEED_SCALE, {1.0}); + _memory->WriteEntityData(0x00295, CURSOR_SPEED_SCALE, {1.0}); + _memory->WriteEntityData(0x0C373, CURSOR_SPEED_SCALE, {1.0}); + _memory->WriteEntityData(0x00293, CURSOR_SPEED_SCALE, {1.0}); + _memory->WriteEntityData(0x002C2, CURSOR_SPEED_SCALE, {1.0}); } void Randomizer::RandomizeSymmetry() { @@ -198,11 +198,11 @@ void Randomizer::RandomizeDesert() { Randomize(desertPanels, SWAP::LINES); // Turn off desert surface 8 - _memory->WritePanelData(0x09F94, POWER, {0.0, 0.0}); + _memory->WriteEntityData(0x09F94, POWER, {0.0, 0.0}); // Turn off desert flood final - _memory->WritePanelData(0x18076, POWER, {0.0, 0.0}); + _memory->WriteEntityData(0x18076, POWER, {0.0, 0.0}); // Change desert floating target to desert flood final - _memory->WritePanelData(0x17ECA, TARGET, {0x18077}); + _memory->WriteEntityData(0x17ECA, TARGET, {0x18077}); } void Randomizer::RandomizeQuarry() { @@ -210,14 +210,14 @@ void Randomizer::RandomizeQuarry() { void Randomizer::RandomizeTreehouse() { // Ensure that whatever pivot panels we have are flagged as "pivotable" - int panelFlags = _memory->ReadPanelData(0x17DD1, STYLE_FLAGS, 1)[0]; - _memory->WritePanelData(0x17DD1, STYLE_FLAGS, {panelFlags | 0x8000}); - panelFlags = _memory->ReadPanelData(0x17CE3, STYLE_FLAGS, 1)[0]; - _memory->WritePanelData(0x17CE3, STYLE_FLAGS, {panelFlags | 0x8000}); - panelFlags = _memory->ReadPanelData(0x17DB7, STYLE_FLAGS, 1)[0]; - _memory->WritePanelData(0x17DB7, STYLE_FLAGS, {panelFlags | 0x8000}); - panelFlags = _memory->ReadPanelData(0x17E52, STYLE_FLAGS, 1)[0]; - _memory->WritePanelData(0x17E52, STYLE_FLAGS, {panelFlags | 0x8000}); + int panelFlags = _memory->ReadEntityData(0x17DD1, STYLE_FLAGS, 1)[0]; + _memory->WriteEntityData(0x17DD1, STYLE_FLAGS, {panelFlags | 0x8000}); + panelFlags = _memory->ReadEntityData(0x17CE3, STYLE_FLAGS, 1)[0]; + _memory->WriteEntityData(0x17CE3, STYLE_FLAGS, {panelFlags | 0x8000}); + panelFlags = _memory->ReadEntityData(0x17DB7, STYLE_FLAGS, 1)[0]; + _memory->WriteEntityData(0x17DB7, STYLE_FLAGS, {panelFlags | 0x8000}); + panelFlags = _memory->ReadEntityData(0x17E52, STYLE_FLAGS, 1)[0]; + _memory->WriteEntityData(0x17E52, STYLE_FLAGS, {panelFlags | 0x8000}); } void Randomizer::RandomizeKeep() { @@ -225,9 +225,9 @@ void Randomizer::RandomizeKeep() { void Randomizer::RandomizeShadows() { // Change the shadows tutorial cable to only activate avoid - _memory->WritePanelData(0x319A8, CABLE_TARGET_2, {0}); + _memory->WriteEntityData(0x319A8, CABLE_TARGET_2, {0}); // Change shadows avoid 8 to power shadows follow - _memory->WritePanelData(0x1972F, TARGET, {0x1C34C}); + _memory->WriteEntityData(0x1972F, TARGET, {0x1C34C}); std::vector randomOrder(shadowsPanels.size(), 0); std::iota(randomOrder.begin(), randomOrder.end(), 0); @@ -236,9 +236,9 @@ void Randomizer::RandomizeShadows() { RandomizeRange(randomOrder, SWAP::NONE, 16, 21); // Follow ReassignTargets(shadowsPanels, randomOrder); // Turn off original starting panel - _memory->WritePanelData(shadowsPanels[0], POWER, {0.0f, 0.0f}); + _memory->WriteEntityData(shadowsPanels[0], POWER, {0.0f, 0.0f}); // Turn on new starting panel - _memory->WritePanelData(shadowsPanels[randomOrder[0]], POWER, {1.0f, 1.0f}); + _memory->WriteEntityData(shadowsPanels[randomOrder[0]], POWER, {1.0f, 1.0f}); } void Randomizer::RandomizeTown() { @@ -298,7 +298,7 @@ void Randomizer::RandomizeMountain() { // Randomize final pillars order std::vector targets = {pillars[0] + 1}; for (const int pillar : pillars) { - int target = _memory->ReadPanelData(pillar, TARGET, 1)[0]; + int target = _memory->ReadEntityData(pillar, TARGET, 1)[0]; targets.push_back(target); } targets[5] = pillars[5] + 1; @@ -309,17 +309,17 @@ void Randomizer::RandomizeMountain() { RandomizeRange(randomOrder, SWAP::NONE, 5, 9); // Right Pillars 1-4 ReassignTargets(pillars, randomOrder, targets); // Turn off original starting panels - _memory->WritePanelData(pillars[0], POWER, {0.0f, 0.0f}); - _memory->WritePanelData(pillars[5], POWER, {0.0f, 0.0f}); + _memory->WriteEntityData(pillars[0], POWER, {0.0f, 0.0f}); + _memory->WriteEntityData(pillars[5], POWER, {0.0f, 0.0f}); // Turn on new starting panels - _memory->WritePanelData(pillars[randomOrder[0]], POWER, {1.0f, 1.0f}); - _memory->WritePanelData(pillars[randomOrder[5]], POWER, {1.0f, 1.0f}); + _memory->WriteEntityData(pillars[randomOrder[0]], POWER, {1.0f, 1.0f}); + _memory->WriteEntityData(pillars[randomOrder[5]], POWER, {1.0f, 1.0f}); } void Randomizer::RandomizeChallenge() { ChallengeRandomizer cr(_memory, Random::RandInt(1, 0x7FFFFFFF)); // 0 will trigger an "RNG not initialized" block for (int panel : challengePanels) { - _memory->WritePanelData(panel, POWER_OFF_ON_FAIL, {0}); + _memory->WriteEntityData(panel, POWER_OFF_ON_FAIL, {0}); } } @@ -420,10 +420,10 @@ void Randomizer::SwapPanels(int panel1, int panel2, int flags) { } for (auto const& [offset, size] : offsets) { - std::vector panel1data = _memory->ReadPanelData(panel1, offset, size); - std::vector panel2data = _memory->ReadPanelData(panel2, offset, size); - _memory->WritePanelData(panel2, offset, panel1data); - _memory->WritePanelData(panel1, offset, panel2data); + std::vector panel1data = _memory->ReadEntityData(panel1, offset, size); + std::vector panel2data = _memory->ReadEntityData(panel2, offset, size); + _memory->WriteEntityData(panel2, offset, panel1data); + _memory->WriteEntityData(panel1, offset, panel2data); } } @@ -433,7 +433,7 @@ void Randomizer::ReassignTargets(const std::vector& panels, const std::vect // The first panel may not have a wire to power it, so we use the panel ID itself. targets = {panels[0] + 1}; for (const int panel : panels) { - int target = _memory->ReadPanelData(panel, TARGET, 1)[0]; + int target = _memory->ReadEntityData(panel, TARGET, 1)[0]; targets.push_back(target); } } @@ -441,17 +441,17 @@ void Randomizer::ReassignTargets(const std::vector& panels, const std::vect for (size_t i=0; iWritePanelData(panels[order[i]], TARGET, {panelTarget}); + _memory->WriteEntityData(panels[order[i]], TARGET, {panelTarget}); } } void Randomizer::ReassignNames(const std::vector& panels, const std::vector& order) { std::vector names; for (const int panel : panels) { - names.push_back(_memory->ReadPanelData(panel, AUDIO_LOG_NAME, 1)[0]); + names.push_back(_memory->ReadEntityData(panel, AUDIO_LOG_NAME, 1)[0]); } for (int i=0; iWritePanelData(panels[i], AUDIO_LOG_NAME, {names[order[i]]}); + _memory->WriteEntityData(panels[i], AUDIO_LOG_NAME, {names[order[i]]}); } } diff --git a/Source/Randomizer2.cpp b/Source/Randomizer2.cpp index 81b6874..d9c00c0 100644 --- a/Source/Randomizer2.cpp +++ b/Source/Randomizer2.cpp @@ -233,40 +233,6 @@ void Randomizer2::RandomizeKeep() { // *** Hedges 3 ** { - std::vector audioMarkers = { - 0x000034a9, - 0x000034b1, - 0x000034be, - 0x000034c4, - 0x000034cb, - 0x000034cc, - 0x000034cd, - 0x000034ce, - 0x000034df, - 0x000034e0, - 0x000034e1, - 0x000034e2, - 0x000034f3, - 0x000131cb, - 0x00017e34, - 0x00017e6f, - 0x00017e76, - 0x00017e77, - 0x00017e7a, - 0x00017e7e, - 0x00017e8b, - 0x00017e8d, - 0x00017eb5, - 0x000394a4, - 0x0003b54e, - }; - std::vector good; - for (int marker : audioMarkers) { - // std::vector assetName = _memory->ReadArray(marker, 0xD8, 100); - std::vector name = {'m', 'a', 'z', 'e', '_', 'p', 'e', 'b', 'b', 'l', 'e', '\0'}; - _memory->WriteNewArray(marker, 0xD8, name); - } - Puzzle p; p.NewGrid(4, 4); @@ -283,6 +249,9 @@ void Randomizer2::RandomizeKeep() { p.grid[0][8].start = true; p.grid[8][2].end = Cell::Dir::RIGHT; + std::vector pebbleMarkers = {0x034a9, 0x034b1, 0x034be, 0x034c4}; + + std::vector cutEdges = Randomizer2Core::CutEdgesToBeUnique(p); assert(cutEdges.size() == 7); for (Pos pos : cutEdges) { @@ -352,9 +321,9 @@ void Randomizer2::SetGate(int panel, int X, int Y) { } SetPos(panel, x, y, 19.2f); - _memory->WritePanelData(panel, ORIENTATION, {0.0f, 0.0f, z, w}); + _memory->WriteEntityData(panel, ORIENTATION, {0.0f, 0.0f, z, w}); } void Randomizer2::SetPos(int panel, float x, float y, float z) { - _memory->WritePanelData(panel, POSITION, {x, y, z}); + _memory->WriteEntityData(panel, POSITION, {x, y, z}); } \ No newline at end of file -- cgit 1.4.1