Skip to content

Commit 6fcbcd7

Browse files
author
sourcehold
committed
doc: add approach example
1 parent 7d31cf3 commit 6fcbcd7

2 files changed

Lines changed: 102 additions & 0 deletions

File tree

docs/conf.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
extensions = [
66
'sphinx.ext.autodoc',
77
'sphinx.ext.napoleon',
8+
'sphinx.ext.autosectionlabel',
89
]
910

1011
html_theme = 'furo'

docs/wiki-approach.rst

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,104 @@
11
Approach
22
===========
33

4+
Aims
5+
------
6+
7+
The two main aims are:
8+
9+
#. Replicating the original game's machine code using new source code (reimplementation)
10+
#. Providing modding opportunities in the new source code
11+
12+
Examples
13+
--------
14+
15+
Example 1: using macros and constants
16+
++++++++++++++++++++++++++++++++++++++
17+
18+
If the pseudo-C code of the original machine code looks like this:
19+
20+
.. code-block:: c++
21+
22+
void dealDamageToUnitFromFlyingEntity(int entityID, int unitID)
23+
{
24+
int entityType = entities[entityID].type;
25+
if (entityType == ARROW)
26+
{
27+
units[unitID].health -= 30;
28+
} else if(entityType == PEBBLE)
29+
{
30+
units[unitID].health -= 50;
31+
} else {
32+
units[unitID].health -= 20;
33+
}
34+
}
35+
36+
Then a reimplementation could look like below. Note the use of macros to define the
37+
damage as an (inline) constant or not depending on whether compilation for replication of the
38+
original code is desired (aim 1), or compilation for easier modding (:ref:`aim 2<Aims>`).
39+
40+
`View on godbolt.org <https://godbolt.org/z/5e485dh8r>`_
41+
42+
.. code-block:: c++
43+
44+
#define PERMIT_MODDING
45+
#ifdef PERMIT_MODDING
46+
#define CONST
47+
#else
48+
#define CONST const
49+
#endif
50+
51+
namespace Damage {
52+
namespace Entities {
53+
// A struct is used here to make modding easier as it strictly defines the ints
54+
// as next to each other in memory.
55+
typedef struct UnitDamage {
56+
int CONST fromArrow = 30;
57+
int CONST fromPebble = 50;
58+
int CONST fromOther = 20;
59+
} UnitDamage;
60+
UnitDamage CONST unitDamages;
61+
}
62+
}
63+
64+
/** These are stubs to make the godbolt compiler happy */
65+
// Note these are always const, as changing these values would break
66+
// compatibility with the original game
67+
namespace EntityTypes {
68+
int const ARROW = 10;
69+
int const PEBBLE = 20;
70+
}
71+
72+
typedef struct Entity {
73+
int type;
74+
} Entity;
75+
76+
typedef struct Unit {
77+
int health;
78+
} Unit;
79+
80+
Entity entities[100] {};
81+
Unit units[100] {};
82+
83+
/** End of stubs */
84+
void dealDamageToUnitFromFlyingEntity(int entityID, int unitID)
85+
{
86+
int entityType = entities[entityID].type;
87+
if (entityType == EntityTypes::ARROW)
88+
{
89+
units[unitID].health -= Damage::Entities::unitDamages.fromArrow;
90+
} else if(entityType == EntityTypes::PEBBLE)
91+
{
92+
units[unitID].health -= Damage::Entities::unitDamages.fromPebble;
93+
} else {
94+
units[unitID].health -= Damage::Entities::unitDamages.fromOther;
95+
}
96+
}
97+
98+
#pragma optimize("", off)
99+
int main(int argc, char** argv) {
100+
// This is written like this to avoid optimization by the compiler
101+
dealDamageToUnitFromFlyingEntity(atol(argv[0]), atol(argv[1]));
102+
103+
return 0;
104+
}

0 commit comments

Comments
 (0)