-
Notifications
You must be signed in to change notification settings - Fork 2
/
HACKING
210 lines (159 loc) · 6.71 KB
/
HACKING
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
# Coding style guidelines
## Structure
The code is divided into the following directories:
* src/ - utility functions, tools
* game/ - game logic
* ui/ - UI implementations
* classic/ - the 1993 UI
* cmdline/ - experimental command line UI
* nop/ - dummy UI for tools
* hw/ - hardware abstraction
* sdl/ - libSDL
* 1/ - libSDL 1.2.x
* 2/ - libSDL 2.x
* alleg/ - Allegro
* 4/ - Allegro 4.x
* nop/ - dummy HW for tools
* os/ - Operating System; file paths
* unix/ - yay
* win32/ - boo
* msdos/ - wtf
Some facts:
* main is in hw/ (due to SDL)
* os/ knows nothing about game/, ui/ or hw/
* hw/ knows nothing about game/ or ui/
* game/ knows nothing about hw/
* ui/ is known via src/ui.h
* hw/ is known via src/hw.h
* os/ is known via src/os.h
* src/ knows game via the very narrow src/gameapi.h
(the exception is saveconv.c)
* ui/ knows all about game/
Different hw/ and ui/ implementations can be built with a single configure.
The resulting binaries follow a "1oom_$UI_$HW" naming convention.
## Style
- no tabs, 4 spaces for indentation
- always add the { } braces to if, do, while, for statements
- one space after a ',', if, do, while, for and return statements,
no space after function name:
if (func(4, 5) < 0) {
return (foo * 4) + 2;
}
- add spaces around +, -, *, /, =, == etc:
a = (22 + b * 4) / 7;
- have the opening brace on the same line as the statement,
unless the condition spills to multiple lines:
if (foo) {
...
}
if (1
&& really_long_name
&& (function_call(with_parameters) < and_a_comparison)
) {
...
}
- have the opening brace of a function in the next line:
int func(void)
{
...
}
- use C-style comments /* like here */
- function and variable names are lowercase with '_' for space
- defines and enums are UPPERCASE with '_' for space
- avoid global variables
- declare functions / data which are not used outside the module as static
- group static functions / data above others, separate with a /* --.. */ line
- avoid memory allocations after game startup
Do not use unsafe string functions like strcpy, strcat and sprintf. 1oom pbx
files may redefine most in-game strings, and besides, it's good practice.
There are replacement functions in src/lib.c which take an additional buffer
size argument and crash instead of overflowing the buffer.
Avoid declaring variables after the start of scope:
if (foo) {
int this_is_ok;
v = 123;
int this_is_frowned_upon;
...
}
Note that declaring the loop variable inside for is ok:
for (int i = 0; i < FOO; ++i) {
...
}
Otherwise, try to keep close to C89.
Avoid #ifdefs! No OS-specific #ifdefs are allowed in game/, ui/ or src/.
Acceptable ones include HAVE_SAMPLERATE etc and FEATURE_MODEBUG.
## On brevity
Comment only the unobvious or the big picture. Do not add inane comments like:
/* do stuff */
do_stuff();
Keep the commit message as one line of 70 characters or less. Do not end it
with a '.'. Save any explanatory paragraphs for the merge request.
## Portability
1oom is designed to be cross-platform and work on different Operating
Systems, processors and libraries. Bear this in mind when writing code.
Each hardware abstraction library will have its own directory in hw/.
Any and all of these must be buildable with one configure and produce
differently named binaries.
Do not use the `long` type (its size differs across platforms; use
`int` or `int64_t` depending on which you want).
Be careful with platform dependencies: do not use Windows API
functions outside os/win32/, for example. Do not use SDL outside of
hw/sdl/.
Tests for OS in configure.ac and use for example `IS_WINDOWS` instead of
the preprocessor `_WIN32`. The #defines can be used to identify the OS
if necessary. Try to avoid this if possible. Only consider them in hw/ or os/.
Hey, you there, OS X porter! Do not turn os/unix/ into an #ifdef shithole,
just copy it to os/osx/ and hack away.
Be careful of endianness! The the macros in bits.h to do endianness
conversion. Never assume that integer types have a particular byte
ordering. Similarly, never assume that fields inside a structure
are aligned in a particular way. This is most relevant when reading
or writing data to a file or a network pipe.
For signed integers, you shouldn’t assume that `(i >> n)` is the same as
`(i / (1 << n))`. However, most processors handle bitshifts of signed
integers properly, so it’s not a huge problem.
## GNU GPL and licensing
All code submitted to the project must be licensed under the GNU GPLv2 or a
compatible license.
## No thanks
An incomplete list of reasons for rejecting patches:
- new build systems: CMake, Visual Studio, XCode, ...
* This project uses automake etc. Maintaining multiple build systems
is bound to fail, especially with binary or otherwise messy project file
format. While automake etc are far from perfect, they are not an obstacle
for portability.
- new build dependencies
* There is no reason to require Turing-complete dependencies, for example
Python or Perl, to build this project.
(No, Debian libsdl1.2-dev depending on python is not an excuse.)
(Neither is src/version.sh.)
There is very little reason for tools (convert, ...) either.
Limiting build deps benefits portability.
- new buildtime data files
* This helps with the above item.
- new runtime data files
* This projects aims to have 0 extra files required besides the executable
and the LBX files. The lbxview font is an unfortunate compromise.
- new library dependencies
* Keeping the library dependencies at minimum helps portability.
These are considered on a case-by-case basis.
(Note that new hw/ are encouraged!)
- new optional libraries
* Keeping the amount of libraries reasonable helps to avoid #ifdef hell.
These are considered on a case-by-case basis.
Libs with unstable/numerous APIs are discouraged. (libpng, ffmpeg, ...)
- new picture formats
* There are plenty of tools for PCX file conversion.
Optional PNG support would likely require more lines of code than the
NIH PCX implementation. Don't even start with lossy formats.
- movie recording
* No.
- cosmetic OpenGL shaders
* No.
- Scale2x, HQ3x, ...
* Nearest/linear via OpenGL should be enough.
- software 2x, 3x, ... scaling
* Show a platform without OpenGL and with screen resolution exceeding 400x300
and port 1oom to it (configure.ac, os/FOO/, also hw/FOO/ if no SDL) then OK.
Otherwise -uiscale and nearest/linear via OpenGL should be enough.
If you *must* have some of these then have fun with your fork.