Skip to content

Commit d0add0f

Browse files
secsomeCoroniaMetadorius
authored
Dehardcode the overlay 255 limit (#531)
This allows you to register and use more than 255 overlays <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Enhanced game overlay processing to improve the reliability and consistency of overlay configurations during loading and saving. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Coronia <[email protected]> Co-authored-by: Kerbiter <[email protected]>
1 parent f523f53 commit d0add0f

File tree

4 files changed

+235
-0
lines changed

4 files changed

+235
-0
lines changed

CREDITS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ This page lists all the individual contributions to the project by their author.
9797
- Customizable tooltip background
9898
- Parts of Ares calling code
9999
- Original `Arcing` elevation inaccuracy fix
100+
- Dehardcode 255 limit of `OverlayType`
100101
- **Otamaa (Fahroni, BoredEXE)**:
101102
- Help with CellSpread
102103
- Ported and fixed custom RadType code

docs/Fixed-or-Improved-Logics.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ This page describes all ingame logics that are fixed or improved in Phobos witho
225225
- Fixed the bug that infantry ignored `Passengers` and `SizeLimit` when entering buildings.
226226
- Fixed `VoiceDeploy` not played, when deployed through hot-key/command bar.
227227
- Fixed the bug that ships can travel on elevated bridges.
228+
- Dehardcoded 255 limit of `OverlayType`.
228229

229230
## Fixes / interactions with other extensions
230231

docs/Whats-New.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,7 @@ New:
376376
- [Use `InsigniaType` to set the properties of insignia in a batch](Miscellanous.md#insignia-type) (by Ollerus)
377377
- [Tiberium eater logic](New-or-Enhanced-Logics.md#tiberium-eater) (by NetsuNegi)
378378
- [Customize the damage taken when falling from a bridge](Fixed-or-Improved-Logics.md#customize-bridge-falling-down-damage) (by FlyStar)
379+
- Dehardcoded 255 limit of `OverlayType` (by secsome)
379380
380381
Vanilla fixes:
381382
- Fixed sidebar not updating queued unit numbers when adding or removing units when the production is on hold (by CrimRecya)

src/Misc/Hooks.Overlay.cpp

Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
#include <Helpers/Macro.h>
2+
#include <CCINIClass.h>
3+
#include <ScenarioClass.h>
4+
#include <OverlayClass.h>
5+
#include <OverlayTypeClass.h>
6+
#include <Straws.h>
7+
#include <Pipes.h>
8+
9+
struct OverlayReader
10+
{
11+
struct OverlayByteReader
12+
{
13+
OverlayByteReader(CCINIClass* pINI, const char* pSection)
14+
: ls{ TRUE, 0x2000 }, bs{ nullptr, 0 }
15+
{
16+
pBuffer = YRMemory::Allocate(512000);
17+
uuLength = pINI->ReadUUBlock(pSection, pBuffer, 512000);
18+
if (this->IsAvailable())
19+
{
20+
bs.Buffer.Buffer = pBuffer;
21+
bs.Buffer.Size = uuLength;
22+
bs.Buffer.Allocated = false;
23+
ls.Get_From(bs);
24+
}
25+
}
26+
27+
~OverlayByteReader()
28+
{
29+
YRMemory::Deallocate(pBuffer);
30+
}
31+
32+
bool IsAvailable() const { return uuLength > 0; }
33+
34+
unsigned char Get()
35+
{
36+
if (IsAvailable())
37+
{
38+
unsigned char ret;
39+
ls.Get(&ret, sizeof(ret));
40+
return ret;
41+
}
42+
return 0;
43+
}
44+
45+
size_t uuLength;
46+
void* pBuffer;
47+
LCWStraw ls;
48+
BufferStraw bs;
49+
};
50+
51+
size_t Get()
52+
{
53+
unsigned char ret[4];
54+
55+
ret[0] = ByteReaders[0].Get();
56+
ret[1] = ByteReaders[1].Get();
57+
ret[2] = ByteReaders[2].Get();
58+
ret[3] = ByteReaders[3].Get();
59+
60+
return ret[0] == 0xFF ? 0xFFFFFFFF : (ret[0] | (ret[1] << 8) | (ret[2] << 16) | (ret[3] << 24));
61+
}
62+
63+
OverlayReader(CCINIClass* pINI)
64+
:ByteReaders{ { pINI, "OverlayPack" }, { pINI, "OverlayPack2" }, { pINI, "OverlayPack3" }, { pINI, "OverlayPack4" }, }
65+
{}
66+
67+
private:
68+
OverlayByteReader ByteReaders[4];
69+
};
70+
71+
struct OverlayWriter
72+
{
73+
struct OverlayByteWriter
74+
{
75+
OverlayByteWriter(const char* pSection, size_t nBufferLength)
76+
: bp { nullptr,0 }, lp { FALSE,0x2000 }, uuLength { 0 }, lpSectionName { pSection }
77+
{
78+
this->Buffer = YRMemory::Allocate(nBufferLength);
79+
bp.Buffer.Buffer = this->Buffer;
80+
bp.Buffer.Size = nBufferLength;
81+
bp.Buffer.Allocated = false;
82+
lp.Put_To(bp);
83+
}
84+
85+
~OverlayByteWriter()
86+
{
87+
YRMemory::Deallocate(this->Buffer);
88+
}
89+
90+
void Put(unsigned char data)
91+
{
92+
uuLength += lp.Put(&data, 1);
93+
}
94+
95+
void PutBlock(CCINIClass* pINI)
96+
{
97+
pINI->Clear(this->lpSectionName, nullptr);
98+
pINI->WriteUUBlock(this->lpSectionName, this->Buffer, uuLength);
99+
}
100+
101+
const char* lpSectionName;
102+
size_t uuLength;
103+
void* Buffer;
104+
BufferPipe bp;
105+
LCWPipe lp;
106+
};
107+
108+
OverlayWriter(size_t nLen)
109+
: ByteWriters { { "OverlayPack", nLen}, { "OverlayPack2", nLen }, { "OverlayPack3", nLen }, { "OverlayPack4", nLen } }
110+
{ }
111+
112+
void Put(int nOverlay)
113+
{
114+
unsigned char bytes[4];
115+
bytes[0] = (nOverlay & 0xFF);
116+
bytes[1] = ((nOverlay >> 8) & 0xFF);
117+
bytes[2] = ((nOverlay >> 16) & 0xFF);
118+
bytes[3] = ((nOverlay >> 24) & 0xFF);
119+
ByteWriters[0].Put(bytes[0]);
120+
ByteWriters[1].Put(bytes[1]);
121+
ByteWriters[2].Put(bytes[2]);
122+
ByteWriters[3].Put(bytes[3]);
123+
}
124+
125+
void PutBlock(CCINIClass* pINI)
126+
{
127+
ByteWriters[0].PutBlock(pINI);
128+
ByteWriters[1].PutBlock(pINI);
129+
ByteWriters[2].PutBlock(pINI);
130+
ByteWriters[3].PutBlock(pINI);
131+
}
132+
133+
private:
134+
OverlayByteWriter ByteWriters[4];
135+
};
136+
137+
DEFINE_HOOK(0x5FD2E0, OverlayClass_ReadINI, 0x7)
138+
{
139+
GET(CCINIClass*, pINI, ECX);
140+
141+
pINI->CurrentSectionName = nullptr;
142+
pINI->CurrentSection = nullptr;
143+
144+
if (ScenarioClass::NewINIFormat > 1)
145+
{
146+
OverlayReader reader(pINI);
147+
148+
for (short i = 0; i < 0x200; ++i)
149+
{
150+
for (short j = 0; j < 0x200; ++j)
151+
{
152+
CellStruct mapCoord{ j,i };
153+
size_t nOvl = reader.Get();
154+
if (nOvl != 0xFFFFFFFF)
155+
{
156+
auto const pType = OverlayTypeClass::Array->GetItem(nOvl);
157+
if (pType->GetImage() || pType->CellAnim)
158+
{
159+
if (SessionClass::Instance->GameMode != GameMode::Campaign && pType->Crate)
160+
continue;
161+
if (!MapClass::Instance->CoordinatesLegal(mapCoord))
162+
continue;
163+
164+
auto pCell = MapClass::Instance->GetCellAt(mapCoord);
165+
auto const nOriginOvlData = pCell->OverlayData;
166+
GameCreate<OverlayClass>(pType, mapCoord, -1);
167+
168+
if (nOvl == 24 || nOvl == 25 || nOvl == 237 || nOvl == 238) // bridges
169+
pCell->OverlayData = nOriginOvlData;
170+
}
171+
}
172+
}
173+
}
174+
175+
auto pBuffer = YRMemory::Allocate(256000);
176+
size_t uuLength = pINI->ReadUUBlock("OverlayDataPack", pBuffer, 256000);
177+
if (uuLength > 0)
178+
{
179+
BufferStraw bs(pBuffer, uuLength);
180+
LCWStraw ls(TRUE, 0x2000);
181+
ls.Get_From(bs);
182+
183+
for (short i = 0; i < 0x200; ++i)
184+
{
185+
for (short j = 0; j < 0x200; ++j)
186+
{
187+
CellStruct mapCoord { j,i };
188+
unsigned char buffer;
189+
ls.Get(&buffer, sizeof(buffer));
190+
191+
if (MapClass::Instance->CoordinatesLegal(mapCoord))
192+
{
193+
auto pCell = MapClass::Instance->GetCellAt(mapCoord);
194+
pCell->OverlayData = buffer;
195+
}
196+
}
197+
}
198+
}
199+
YRMemory::Deallocate(pBuffer);
200+
}
201+
202+
AbstractClass::RemoveAllInactive();
203+
204+
return 0x5FD69A;
205+
}
206+
207+
DEFINE_HOOK(0x5FD6A0, OverlayClass_WriteINI, 0x6)
208+
{
209+
GET(CCINIClass*, pINI, ECX);
210+
211+
pINI->Clear("OVERLAY", nullptr);
212+
size_t len = DSurface::Alternate->Width * DSurface::Alternate->Height;
213+
OverlayWriter writer(len);
214+
OverlayWriter::OverlayByteWriter dataWriter("OverlayDataPack", len);
215+
216+
for (short i = 0; i < 0x200; ++i)
217+
{
218+
for (short j = 0; j < 0x200; ++j)
219+
{
220+
CellStruct mapCoord { j,i };
221+
auto const pCell = MapClass::Instance->GetCellAt(mapCoord);
222+
writer.Put(pCell->OverlayTypeIndex);
223+
dataWriter.Put(pCell->OverlayData);
224+
}
225+
}
226+
227+
writer.PutBlock(pINI);
228+
dataWriter.PutBlock(pINI);
229+
230+
return 0x5FD8EB;
231+
}
232+

0 commit comments

Comments
 (0)