cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

docs_coding_guidelines.html (21816B)


      1<!-- HTML header for doxygen 1.8.14-->
      2<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
      3<html xmlns="http://www.w3.org/1999/xhtml">
      4<head>
      5<meta http-equiv="cache-control" content="max-age=86400"/>
      6<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
      7<meta http-equiv="X-UA-Compatible" content="IE=9"/>
      8<meta name="generator" content="Doxygen 1.8.20"/>
      9<meta name="viewport" content="width=device-width, initial-scale=1"/>
     10<title>GBDK 2020 Docs: Coding Guidelines</title>
     11<link href="tabs.css" rel="stylesheet" type="text/css"/>
     12<script type="text/javascript" src="jquery.js"></script>
     13<script type="text/javascript" src="dynsections.js"></script>
     14<link href="navtree.css" rel="stylesheet" type="text/css"/>
     15<script type="text/javascript" src="resize.js"></script>
     16<script type="text/javascript" src="navtreedata.js"></script>
     17<script type="text/javascript" src="navtree.js"></script>
     18<link href="search/search.css" rel="stylesheet" type="text/css"/>
     19<script type="text/javascript" src="search/searchdata.js"></script>
     20<script type="text/javascript" src="search/search.js"></script>
     21<link href="doxygen.css" rel="stylesheet" type="text/css" />
     22<link href="doxygen_extra.css" rel="stylesheet" type="text/css"/>
     23</head>
     24<body>
     25<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
     26<div id="titlearea">
     27<table cellspacing="0" cellpadding="0">
     28 <tbody>
     29 <tr style="height: 56px;">
     30  <td id="projectalign" style="padding-left: 0.5em;">
     31   <div id="projectname">GBDK 2020 Docs
     32   &#160;<span id="projectnumber">4.0.6</span>
     33   </div>
     34   <div id="projectbrief">API Documentation for GBDK 2020</div>
     35  </td>
     36 </tr>
     37 </tbody>
     38</table>
     39</div>
     40<!-- end header part -->
     41<!-- Generated by Doxygen 1.8.20 -->
     42<script type="text/javascript">
     43/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
     44var searchBox = new SearchBox("searchBox", "search",false,'Search');
     45/* @license-end */
     46</script>
     47<script type="text/javascript" src="menudata.js"></script>
     48<script type="text/javascript" src="menu.js"></script>
     49<script type="text/javascript">
     50/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
     51$(function() {
     52  initMenu('',true,false,'search.php','Search');
     53  $(document).ready(function() { init_search(); });
     54});
     55/* @license-end */</script>
     56<div id="main-nav"></div>
     57</div><!-- top -->
     58<div id="side-nav" class="ui-resizable side-nav-resizable">
     59  <div id="nav-tree">
     60    <div id="nav-tree-contents">
     61      <div id="nav-sync" class="sync"></div>
     62    </div>
     63  </div>
     64  <div id="splitbar" style="-moz-user-select:none;" 
     65       class="ui-resizable-handle">
     66  </div>
     67</div>
     68<script type="text/javascript">
     69/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
     70$(document).ready(function(){initNavTree('docs_coding_guidelines.html',''); initResizable(); });
     71/* @license-end */
     72</script>
     73<div id="doc-content">
     74<!-- window showing the filter options -->
     75<div id="MSearchSelectWindow"
     76     onmouseover="return searchBox.OnSearchSelectShow()"
     77     onmouseout="return searchBox.OnSearchSelectHide()"
     78     onkeydown="return searchBox.OnSearchSelectKey(event)">
     79</div>
     80
     81<!-- iframe showing the search results (closed by default) -->
     82<div id="MSearchResultsWindow">
     83<iframe src="javascript:void(0)" frameborder="0" 
     84        name="MSearchResults" id="MSearchResults">
     85</iframe>
     86</div>
     87
     88<div class="PageDoc"><div class="header">
     89  <div class="headertitle">
     90<div class="title">Coding Guidelines </div>  </div>
     91</div><!--header-->
     92<div class="contents">
     93<div class="textblock"><h1><a class="anchor" id="autotoc_md56"></a>
     94Learning C / C fundamentals</h1>
     95<p>Writing games and other programs with GBDK will be much easier with a basic understanding of the C language. In particular, understanding how to use C on "Embedded Platforms" (small computing systems, such as the Game Boy) can help you write better code (smaller, faster, less error prone) and avoid common pitfals.</p>
     96<p><a class="anchor" id="docs_c_tutorials"></a></p>
     97<h2><a class="anchor" id="autotoc_md57"></a>
     98General C tutorials</h2>
     99<ul>
    100<li><a href="https://www.learn-c.org/">https://www.learn-c.org/</a></li>
    101<li><a href="https://www.tutorialspoint.com/cprogramming/index.htm">https://www.tutorialspoint.com/cprogramming/index.htm</a></li>
    102</ul>
    103<h2><a class="anchor" id="autotoc_md58"></a>
    104Embedded C introductions</h2>
    105<ul>
    106<li><a href="http://dsp-book.narod.ru/CPES.pdf">http://dsp-book.narod.ru/CPES.pdf</a></li>
    107<li><a href="https://www.phaedsys.com/principals/bytecraft/bytecraftdata/bcfirststeps.pdf">https://www.phaedsys.com/principals/bytecraft/bytecraftdata/bcfirststeps.pdf</a></li>
    108</ul>
    109<h2><a class="anchor" id="autotoc_md59"></a>
    110Game Boy games in C</h2>
    111<ul>
    112<li><a href="https://gbdev.io/list.html#c">https://gbdev.io/list.html#c</a></li>
    113</ul>
    114<h1><a class="anchor" id="autotoc_md60"></a>
    115Understanding the hardware</h1>
    116<p>In addition to understanding the C language it's important to learn how the Game Boy hardware works. What it is capable of doing, what it isn't able to do, and what resources are available to work with. A good way to do this is by reading the <a class="el" href="docs_links_and_tools.html#Pandocs">Pandocs</a> and checking out the <a class="el" href="docs_links_and_tools.html#awesome_gb">awesome_gb</a> list.</p>
    117<h1><a class="anchor" id="autotoc_md61"></a>
    118Writing optimal C code for the Game Boy and SDCC</h1>
    119<p>The following guidelines can result in better code for the Game Boy, even though some of the guidance may be contrary to typical advice for general purpose computers that have more resources and speed.</p>
    120<h2><a class="anchor" id="autotoc_md62"></a>
    121Tools</h2>
    122<p><a class="anchor" id="const_gbtd_gbmb"></a></p>
    123<h3><a class="anchor" id="autotoc_md63"></a>
    124GBTD / GBMB, Arrays and the "const" keyword</h3>
    125<p><b>Important</b>: The old <a class="el" href="docs_links_and_tools.html#gbtd_gbmb">GBTD/GBMB</a> fails to include the <code>const</code> keyword when exporting to C source files for GBDK. That causes arrays to be created in RAM instead of ROM, which wastes RAM, uses a lot of ROM to initialize the RAM arrays and slows the compiler down a lot.</p>
    126<p>__Use of <a class="el" href="docs_links_and_tools.html#toxa_gbtd_gbmb">toxa's updated GBTD/GBMB</a> is highly recommended.__</p>
    127<p>If you wish to use the original tools, you must add the <code>const</code> keyword every time the graphics are re-exported to C source files.</p>
    128<h2><a class="anchor" id="autotoc_md64"></a>
    129Variables</h2>
    130<ul>
    131<li>Use 8-bit values as much as possible. They will be much more efficient and compact than 16 and 32 bit types.</li>
    132<li>Prefer unsigned variables to signed ones: The code generated will be generally more efficient, especially when comparing two values.</li>
    133<li>Use explicit types so you always know the size of your variables. <code>int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t</code> and <code>bool</code>. These are standard types defined in <code>stdint.h</code> (<code>#include &lt;stdint.h&gt;</code>) and <code>stdbool.h</code> (<code>#include &lt;stdbool.h&gt;</code>).</li>
    134<li>Global and local static variables are generally more efficient than local non-static variables (which go on the stack and are slower and can result in slower code).</li>
    135<li><a class="anchor" id="const_array_data"></a> <code>const</code> keyword: Use const for arrays, structs and variables with read-only (constant) data. It will reduce ROM, RAM and CPU usage significantly. Non-<code>const</code> values are loaded from ROM into RAM inefficiently, and there is no benefit in loading them into the limited available RAM if they aren't going to be changed.</li>
    136<li>Here is how to delcare <code>const</code> pointers and variables:<ul>
    137<li>non-const pointer to a const variable: <code>const uint8_t * some_pointer;</code></li>
    138<li>const pointer to a non-const variable: <code>uint8_t * const some_pointer;</code></li>
    139<li>const pointer to a const variable: <code>const uint8_t * const some_pointer;</code></li>
    140<li><a href="https://codeforwin.org/2017/11/constant-pointer-and-pointer-to-constant-in-c.html">https://codeforwin.org/2017/11/constant-pointer-and-pointer-to-constant-in-c.html</a></li>
    141<li><a href="https://stackoverflow.com/questions/21476869/constant-pointer-vs-pointer-to-constant">https://stackoverflow.com/questions/21476869/constant-pointer-vs-pointer-to-constant</a></li>
    142</ul>
    143</li>
    144<li>For calculated values that don't change, pre-compute results once and store the result. Using lookup-tables and the like can improve speed and reduce code size. Macros can sometimes help. It may be beneficial to do the calculations with an outside tool and then include the result as C code in a const array.</li>
    145<li>Use an advancing pointer (<code>someStruct-&gt;var = x; someStruct++</code>) to loop through arrays of structs instead of using indexing each time in the loop <code>someStruct[i].var = x</code>.</li>
    146<li>When modifying variables that are also changed in an Interrupt Service Routine (ISR), wrap them the relevant code block in a <code>__critical { }</code> block. See <a href="http://sdcc.sourceforge.net/doc/sdccman.pdf#section.3.9">http://sdcc.sourceforge.net/doc/sdccman.pdf#section.3.9</a></li>
    147<li>When using constants and literals the <code>U</code>, <code>L</code> and <code>UL</code> postfixes can be used.<ul>
    148<li><code>U</code> specifies that the constant is unsigned</li>
    149<li><code>L</code> specifies that the constant is long.</li>
    150<li>NOTE: In SDCC 3.6.0, the default for char changed from signed to unsigned. The manual says to use <code>--fsigned-char</code> for the old behavior, this option flag is included by default when compiling through <a class="el" href="docs_toolchain.html#lcc">lcc</a>.</li>
    151</ul>
    152</li>
    153</ul>
    154<p><a class="anchor" id="fixed_point_type"></a></p><ul>
    155<li>A fixed point type (<code>fixed</code>) is included with GBDK when precision greater than whole numbers is required for 8 bit range values (since floating point is not included in GBDK).</li>
    156</ul>
    157<p>See the "Simple Physics" sub-pixel example project.</p>
    158<p>Code example: </p><pre class="fragment">  fixed player[2];
    159  ...
    160  // Modify player position using it's 16 bit representation
    161  player[0].w += player_speed_x;
    162  player[1].w += player_speed_y;
    163  ...
    164  // Use only the upper 8 bits for setting the sprite position
    165  move_sprite(0, player[0].h ,player[1].h);
    166</pre><h2><a class="anchor" id="autotoc_md65"></a>
    167Code structure</h2>
    168<ul>
    169<li>Do not <code>#include</code> <code>.c</code> source files into other <code>.c</code> source files. Instead create <code>.h</code> header files for them and include those. <a href="https://www.tutorialspoint.com/cprogramming/c_header_files.htm">https://www.tutorialspoint.com/cprogramming/c_header_files.htm</a></li>
    170<li>Instead of using a blocking <a class="el" href="gb_8h.html#a2afae202a1f8ca59a12a6455bb909c5d">delay()</a> for things such as sprite animations/etc (which can prevent the rest of the game from continuing) many times it's better to use a counter which performs an action once every N frames. <a class="el" href="sms_8h.html#a78d2fd18666afec116f176d46debb4e7">sys_time</a> may be useful in these cases.</li>
    171<li>When processing for a given frame is done and it is time to wait before starting the next frame, <a class="el" href="gb_8h.html#acd186eb292d441f9389e77b545a55619">wait_vbl_done()</a> can be used. It uses HALT to put the CPU into a low power state until processing resumes. The CPU will wake up and resume processing at the end of the current frame when the Vertical Blanking interrupt is triggered.</li>
    172<li>Minimize use of multiplication, modulo with non-powers of 2, and division with non-powers of 2. These operations have no corresponding CPU instructions (software functions), and hence are time costly.<ul>
    173<li>SDCC has some optimizations for:<ul>
    174<li>Division by powers of 2. For example <code>n /= 4u</code> will be optimized to <code>n &gt;&gt;= 2</code>.</li>
    175<li>Modulo by powers of 2. For example: <code>(n % 8)</code> will be optimized to <code>(n &amp; 0x7)</code>.</li>
    176</ul>
    177</li>
    178<li>If you need decimal numbers to count or display a score, you can use the GBDK BCD (<a href="https://en.wikipedia.org/wiki/Binary-coded_decimal">binary coded decimal</a>) number functions. See: <a class="el" href="k_2bcd_8h.html">bcd.h</a> and the <code>BCD</code> example project included with GBDK.</li>
    179</ul>
    180</li>
    181<li>Avoid long lists of function parameters. Passing many parameters can add overhead, especially if the function is called often. When applicable globals and local static vars can be used instead.</li>
    182<li>Use inline functions if the function is short. (with the <code>inline</code> keyword, such as <code>inline uint8_t myFunction() { ... }</code>)</li>
    183<li>Do not use recursive functions</li>
    184</ul>
    185<h2><a class="anchor" id="autotoc_md66"></a>
    186GBDK API/Library</h2>
    187<ul>
    188<li>stdio.h: If you have other ways of printing text, avoid including <a class="el" href="stdio_8h.html">stdio.h</a> and using functions such as <a class="el" href="stdio_8h.html#ab403fa700816f08631ba75bc536f74d4">printf()</a>. Including it will use a large number of the background tiles for font characters. If stdio.h is not included then that space will be available for use with other tiles instead.</li>
    189<li>drawing.h: The Game Boy graphics hardware is not well suited to frame-buffer style graphics such as the kind provided in <a class="el" href="drawing_8h.html">drawing.h</a>. Due to that, most drawing functions (rectangles, circles, etc) will be slow . When possible it's much faster and more efficient to work with the tiles and tile maps that the Game Boy hardware is built around.</li>
    190<li><a class="el" href="gb_8h.html#aae433db7d8e3ee4c095c254b8abd7b8b">waitpad()</a> and <a class="el" href="sms_8h.html#a955d3733e5018f18b17a572aff45cf26">waitpadup</a> check for input in a loop that doesn't HALT at all, so the CPU will be maxed out until it returns. One alternative is to write a function with a loop that checks input with <a class="el" href="gb_8h.html#a176c477d759b814664785f3a0ad5e253">joypad()</a> and then waits a frame using <a class="el" href="gb_8h.html#acd186eb292d441f9389e77b545a55619">wait_vbl_done()</a> (which idles the CPU while waiting) before checking input again.</li>
    191<li><a class="el" href="gb_8h.html#a176c477d759b814664785f3a0ad5e253">joypad()</a>: When testing for multiple different buttons, it's best to read the joypad state <em>once</em> into a variable and then test using that variable (instead of making multiple calls).</li>
    192</ul>
    193<h2><a class="anchor" id="autotoc_md67"></a>
    194Toolchain</h2>
    195<ul>
    196<li>See SDCC optimizations: <a href="http://sdcc.sourceforge.net/doc/sdccman.pdf#section.8.1">http://sdcc.sourceforge.net/doc/sdccman.pdf#section.8.1</a></li>
    197<li>Use profiling. Look at the ASM generated by the compiler, write several versions of a function, compare them and choose the faster one.</li>
    198<li>Use the SDCC <code>--max-allocs-per-node</code> flag with large values, such as <code>50000</code>. <code>--opt-code-speed</code> has a much smaller effect.<ul>
    199<li>GBDK-2020 (after v4.0.1) compiles the library with <code>--max-allocs-per-node 50000</code>, but it must be turned on for your own code. <br  />
    200 (example: <code>lcc ... -Wf--max-allocs-per-node50000</code> or <code>sdcc ... --max-allocs-per-node 50000</code>).</li>
    201<li>The other code/speed flags are <code>--opt-code-speed</code> or <code>--opt-code-size</code>.</li>
    202</ul>
    203</li>
    204<li>Use current SDCC builds from <a href="http://sdcc.sourceforge.net/snap.php">http://sdcc.sourceforge.net/snap.php</a> <br  />
    205 The minimum required version of SDCC will depend on the GBDK-2020 release. See <a class="el" href="docs_releases.html">GBDK Releases</a></li>
    206<li>Learn some ASM and inspect the compiler output to understand what the compiler is doing and how your code gets translated. This can help with writing better C code and with debugging.</li>
    207</ul>
    208<p><a class="anchor" id="docs_chars_varargs"></a></p>
    209<h2><a class="anchor" id="autotoc_md68"></a>
    210chars and vararg functions</h2>
    211<p>In standard C when <code>chars</code> are passed to a function with variadic arguments (varargs, those delcared with <code>...</code> as a parameter), such as <a class="el" href="stdio_8h.html#ab403fa700816f08631ba75bc536f74d4">printf()</a>, those <code>chars</code> get automatically promoted to <code>ints</code>. For an 8 bit cpu such as the Game Boy's, this is not as efficient or desireable in most cases. So the default SDCC behavior, which GBDK-2020 expects, is that chars will remain chars and <em>not</em> get promoted to ints when <b>explicitly cast as chars while calling a varargs function</b>.</p>
    212<ul>
    213<li>They must be explicitly re-cast when passing them to a varargs function, even though they are already declared as chars.</li>
    214<li>Discussion in SDCC manual: <br  />
    215 <a href="http://sdcc.sourceforge.net/doc/sdccman.pdf#section.1.5">http://sdcc.sourceforge.net/doc/sdccman.pdf#section.1.5</a> <br  />
    216 <a href="http://sdcc.sourceforge.net/doc/sdccman.pdf#subsection.3.5.10">http://sdcc.sourceforge.net/doc/sdccman.pdf#subsection.3.5.10</a></li>
    217<li>If SDCC is invoked with -std-cxx (&ndash;std-c89, &ndash;std-c99, &ndash;std-c11, etc) then it will conform to standard C behavior and calling functions such as <a class="el" href="stdio_8h.html#ab403fa700816f08631ba75bc536f74d4">printf()</a> with chars may not work as expected.</li>
    218</ul>
    219<p>For example: </p><pre class="fragment">unsigned char i = 0x5A;
    220
    221// NO:
    222// The char will get promoted to an int, producing incorrect printf output
    223// The output will be: 5A 00
    224printf("%hx %hx", i, i);
    225
    226// YES:
    227// The char will remain a char and printf output will be as expected
    228// The output will be: 5A 5A
    229printf("%hx %hx", (unsigned char)i, (unsigned char)i);
    230</pre><p>Some functions that accept varargs:</p><ul>
    231<li><a class="el" href="emu__debug_8h.html#a586ce1ddfba9c35726887ca31f933963">EMU_printf</a>, <a class="el" href="drawing_8h.html#a5f7a0ed309f9526e9be285146559848c">gprintf()</a>, <a class="el" href="stdio_8h.html#ab403fa700816f08631ba75bc536f74d4">printf()</a>, <a class="el" href="stdio_8h.html#a31913a297ee18548c81d482ef6bdbe0f">sprintf()</a></li>
    232</ul>
    233<p>Also See:</p><ul>
    234<li>Other cases of char to int promotion: <a href="http://sdcc.sourceforge.net/doc/sdccman.pdf#chapter.6">http://sdcc.sourceforge.net/doc/sdccman.pdf#chapter.6</a></li>
    235</ul>
    236<h1><a class="anchor" id="autotoc_md69"></a>
    237When C isn't fast enough</h1>
    238<dl class="todo"><dt><b><a class="el" href="todo.html#_todo000003">Todo:</a></b></dt><dd>Update and verify this section for the modernized SDCC and toolchain</dd></dl>
    239<p>For many applications C is fast enough but in intensive functions are sometimes better written in assembler. This section deals with interfacing your core C program with fast assembly sub routines.</p>
    240<h2><a class="anchor" id="autotoc_md70"></a>
    241Calling convention</h2>
    242<p>sdcc in common with almost all C compilers prepends a '_' to any function names. For example the function printf(...) begins at the label _printf::. Note that all functions are declared global.</p>
    243<p>The parameters to a function are pushed in right to left order with no aligning - so a byte takes up a byte on the stack instead of the more natural word. So for example the function int store_byte( uint16_t addr, uint8_t byte) would push 'byte' onto the stack first then addr using a total of three bytes. As the return address is also pushed, the stack would contain: </p><pre class="fragment">  At SP+0 - the return address
    244
    245  At SP+2 - addr
    246
    247  At SP+4 - byte 
    248</pre><p>Note that the arguments that are pushed first are highest in the stack due to how the Game Boy's stack grows downwards.</p>
    249<p>The function returns in DE.</p>
    250<h2><a class="anchor" id="autotoc_md71"></a>
    251Variables and registers</h2>
    252<p>C normally expects registers to be preserved across a function call. However in the case above as DE is used as the return value and HL is used for anything, only BC needs to be preserved.</p>
    253<p>Getting at C variables is slightly tricky due to how local variables are allocated on the stack. However you shouldn't be using the local variables of a calling function in any case. Global variables can be accessed by name by adding an underscore.</p>
    254<h2><a class="anchor" id="autotoc_md72"></a>
    255Segments</h2>
    256<p>The use of segments for code, data and variables is more noticeable in assembler. GBDK and SDCC define a number of default segments - <code>_CODE</code>, <code>_DATA</code> and <code>_BSS</code>. Two extra segments <code>_HEADER</code> and <code>_HEAP</code> exist for the Game Boy header and malloc heap respectively.</p>
    257<p>The order these segments are linked together is determined by crt0.s and is currently <code>_CODE</code> in ROM, then <code>_DATA</code>, <code>_BSS</code>, <code>_HEAP</code> in WRAM, with <code>STACK</code> at the top of WRAM. <code>_HEAP</code> is placed after <code>_BSS</code> so that all spare memory is available for the malloc routines. To place code in other than the first two banks, use the segments <code>_CODE_x</code> where x is the 16kB bank number.</p>
    258<p>As the <code>_BSS</code> segment occurs outside the ROM area you can only use .ds to reserve space in it.</p>
    259<p>While you don't have to use the <code>_CODE</code> and <code>_DATA</code> distinctions in assembler you may wish to do so consistancy. </p>
    260</div></div><!-- contents -->
    261</div><!-- PageDoc -->
    262</div><!-- doc-content -->
    263<!-- HTML footer for doxygen 1.8.14-->
    264<!-- start footer part -->
    265<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
    266</div>
    267</body>
    268</html>