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 GetMapBugs(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 = 0;
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
75int 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) { Bug = (constname); }
82#include "mapbugs_list.h"
83#undef MAPBUG
84 if(Bug == -1)
85 {
86 return MAPBUGUPDATE_NOTFOUND;
87 }
88 if(pInternal)
89 {
90 return MAPBUGUPDATE_OVERRIDDEN;
91 }
92 m_Extra |= BugToFlag(Bug);
93 return MAPBUGUPDATE_OK;
94}
95
96void CMapBugs::Dump() const
97{
98 CMapBugsInternal *pInternal = (CMapBugsInternal *)m_pData;
99 unsigned int Flags;
100 if(pInternal)
101 {
102 Flags = pInternal->m_BugFlags;
103 }
104 else if(m_Extra)
105 {
106 Flags = m_Extra;
107 }
108 else
109 {
110 return;
111 }
112 char aBugs[NUM_BUGS + 1] = {0};
113 for(int i = 0; i < NUM_BUGS; i++)
114 {
115 aBugs[i] = IsBugFlagSet(Bug: i, BugFlags: Flags) ? 'X' : 'O';
116 }
117
118 dbg_msg(sys: "mapbugs", fmt: "enabling map compatibility mode %s", aBugs);
119 if(pInternal)
120 {
121 char aSha256[SHA256_MAXSTRSIZE];
122 sha256_str(digest: pInternal->m_Map.m_Sha256, str: aSha256, max_len: sizeof(aSha256));
123 dbg_msg(sys: "mapbugs", fmt: "map='%s' map_size=%d map_sha256=%s",
124 pInternal->m_Map.m_pName,
125 pInternal->m_Map.m_Size,
126 aSha256);
127 }
128}
129