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