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
|
# 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.
Don't try to remove code that you don't think makes sense. It always has value
if it strictly matches the original.
## 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.
|