1#include "mapbugs.h"
2
3#include <base/dbg.h>
4#include <base/str.h>
5
6struct CMapDescription
7{
8 const char *m_pName;
9 int m_Size;
10 SHA256_DIGEST m_Sha256;
11
12 bool operator==(const CMapDescription &Other) const
13 {
14 return str_comp(a: m_pName, b: Other.m_pName) == 0 &&
15 m_Size == Other.m_Size;
16 }
17};
18
19struct CMapBugsInternal
20{
21 CMapDescription m_Map;
22 unsigned int m_BugFlags;
23};
24
25static unsigned int BugToFlag(int Bug)
26{
27 unsigned int Result;
28 dbg_assert((unsigned)Bug < 8 * sizeof(Result), "invalid shift");
29 Result = (1 << Bug);
30 return Result;
31}
32
33static unsigned int IsBugFlagSet(int Bug, unsigned int BugFlags)
34{
35 return (BugFlags & BugToFlag(Bug)) != 0;
36}
37
38static SHA256_DIGEST s(const char *pSha256)
39{
40 SHA256_DIGEST Result;
41 dbg_assert(sha256_from_str(&Result, pSha256) == 0, "invalid sha256 in mapbugs");
42 return Result;
43}
44
45static CMapBugsInternal MAP_BUGS[] =
46 {
47 {.m_Map: {.m_pName: "Binary", .m_Size: 2022597, .m_Sha256: s(pSha256: "65b410e197fd2298ec270e89a84b762f6739d1d18089529f8ef6cf2104d3d600")}, .m_BugFlags: BugToFlag(Bug: BUG_GRENADE_DOUBLEEXPLOSION)}};
48
49CMapBugs CMapBugs::Create(const char *pName, int Size, SHA256_DIGEST Sha256)
50{
51 CMapDescription Map = {.m_pName: pName, .m_Size: Size, .m_Sha256: Sha256};
52 CMapBugs Result;
53 Result.m_Extra = 0;
54 for(auto &MapBug : MAP_BUGS)
55 {
56 if(Map == MapBug.m_Map)
57 {
58 Result.m_pData = &MapBug;
59 return Result;
60 }
61 }
62 Result.m_pData = nullptr;
63 return Result;
64}
65
66bool CMapBugs::Contains(int Bug) const
67{
68 CMapBugsInternal *pInternal = (CMapBugsInternal *)m_pData;
69 if(!pInternal)
70 {
71 return IsBugFlagSet(Bug, BugFlags: m_Extra);
72 }
73 return IsBugFlagSet(Bug, BugFlags: pInternal->m_BugFlags);
74}
75
76EMapBugUpdate CMapBugs::Update(const char *pBug)
77{
78 CMapBugsInternal *pInternal = (CMapBugsInternal *)m_pData;
79 int Bug = -1;
80 if(false) {}
81#define MAPBUG(constname, string) \
82 else if(str_comp(pBug, string) == 0) \
83 { \
84 Bug = (constname); \
85 }
86#include "mapbugs_list.h"
87#undef MAPBUG
88 if(Bug == -1)
89 {
90 return EMapBugUpdate::NOTFOUND;
91 }
92 if(pInternal)
93 {
94 return EMapBugUpdate::OVERRIDDEN;
95 }
96 m_Extra |= BugToFlag(Bug);
97 return EMapBugUpdate::OK;
98}
99
100void CMapBugs::Dump() const
101{
102 CMapBugsInternal *pInternal = (CMapBugsInternal *)m_pData;
103 unsigned int Flags;
104 if(pInternal)
105 {
106 Flags = pInternal->m_BugFlags;
107 }
108 else if(m_Extra)
109 {
110 Flags = m_Extra;
111 }
112 else
113 {
114 return;
115 }
116 char aBugs[NUM_BUGS + 1] = {0};
117 for(int i = 0; i < NUM_BUGS; i++)
118 {
119 aBugs[i] = IsBugFlagSet(Bug: i, BugFlags: Flags) ? 'X' : 'O';
120 }
121
122 dbg_msg(sys: "mapbugs", fmt: "enabling map compatibility mode %s", aBugs);
123 if(pInternal)
124 {
125 char aSha256[SHA256_MAXSTRSIZE];
126 sha256_str(digest: pInternal->m_Map.m_Sha256, str: aSha256, max_len: sizeof(aSha256));
127 dbg_msg(sys: "mapbugs", fmt: "map='%s' map_size=%d map_sha256=%s",
128 pInternal->m_Map.m_pName,
129 pInternal->m_Map.m_Size,
130 aSha256);
131 }
132}
133