VICE project coding guidelines
==============================

This document is intended to set some guidelines for people wanting to
contribute code to the VICE project.

There are two distinct parts to the VICE source code, the architecture code
parts which are located in src/arch, and the common code parts which are
located everywhere in src except in src/arch.

The architecture code parts are in their own respective directories and *may*
have their own coding style, however try to stick to these guidelines at least
for C code, if possible.

The common code however is used by all supported architectures and therefor
needs to be as portable as possible. To achieve this portability some
guidelines have to be followed.

Project Folders Hierarchy Descriptions
--------------------------------------
Here are short descriptions of the project code folders and their functions:

src/           - common code
 arch          - architecture specific code for various platforms (win, unix, amigaos, etc)
 c64           - c64 specific code
 c64/cart      - c64 cartridge specific code
 c64dtv        - c64 direct tv specific code
 c128          - commodore 128 specific code
 cbm2          - Commodore CBM-II computer emulator
 core          - various chip emulations (CIA, VIA and Cart specific chip emulations)
 crtc          - CRTC emulation
 diskimage     - various file types support (.d64, .d81, etc..)
 drive         - various disk drive hardware emulations and bus systems used (iec or ieee)
 fileio        - for accessing prg files directly
 fsdevice      - for host filesystem as if an iec device is used
 gfxoutputdrv  - screen capture (image and video drivers)
 iecbus        - iec bus handling
 imagecontents - disk and tape directory interface
 lib           - anything related to external libraries (ffmpeg codec, etc..)
 monitor       - code for built-in monitor
 parallel      - ieee488 emulation code
 pet           - pet computer specific emulation code
 platform      - platform specific discovery/reporting code (os, cpu, compiler used, etc..)
 plus4         - commodore plus4 specific code
 printerdrv    - specific printer type emulation and drivers
 raster        - raster-based video chip emulation
 resid folders - cycle exact sid engine (made by dag lem)
 rs232drv      - rs232 communication and modem code for interfacing with arch specific drivers
 rtc           - real time clock emulation used in some devices (fd2000/4000, ide64, etc..)
 serial        - iec interface code and real iec access (for using real drives on usb with vice)
 sid           - SID chip interface and emulation for fallback sid engine (fastsid)
 sounddrv      - framework specific sound drivers
 tape          - tape drive specific emulation and T64 support
 userport      - userport device emulation code
 vdc           - MOS8563 VDC emulation
 vdrive        - virtual drives code, opposed to "true drive emulation" found in drive folder
 vic20         - commodore vic20 specific code
 vicii         - almost cycle exact VICII emulation code for x64, x128, xcbm2, and x64dtv
 viciisc       - more cycle exact then vicii code emulation used in x64sc and xscpu64
 video         - pixel framebuffer to physical screen interface code


Cosmetic guidelines for all code
--------------------------------

To keep the code easy to follow please read the following statements:

- Use the types in <stdint.h> for fixed-width types, so `uint8_t` rather than
  `BYTE`, `uint16_t` for `WORD` and `uint32_t` for `DWORD`.

- Generally put the opening brace of a block at the end of the line ("cuddling"
  braces style), except at the beginning of a function, ie:

  void foo(int bar)
  {
      if (bar) {
          /* ... */
      }
  }


- No variable declarations after the first line of code, some compilers
  just can't handle it.


- One variable declaration per line, and especially don't mix plain types with
  pointers.

  Don't do this:

    int foo, bar, *huppel;

  Do this:
    int foo;
    int bar;
    int *huppel;

  Might look short and clever, but as soon as you want to change a single type,
  you'll either screw them all up, or have to split them anyway. Just don't.


  New block-level declarations are fine:

    if (foo) {
        int bar = 0;
        /* code using bar */
    }

  Perfectly valid even in C89, if a compiler can't handle this, get a proper
  compiler.

- For 'if' and 'for' always use braces.
  examples:

    if (foo) {
        ...
    }

    if (foo) {
        ...
    } else {
        ...
    }

    for (i = 0; i < 255; i++) {
        ...
    }

- A keyword should be followed by a space, so:
    if (foo == 0) { ... }
  not
    if(foo == 0) { ... }

  Exception: the sizeof operator, using sizeof as a "function" on a type should
             not use spaces, ie: sizeof(int), however using sizeof on an object
             should use spaces (ie: int *i; sizeof *i)

- Binary operators: use spaces around binary operators:
    int i = 1 + 2;
    unsigned int i <<= 3;

  But please don't use them with when accessing members of an object:
    foo->bar, not foo -> bar.

- Unary operators:
  Don't use spaces when using unary operators:
    ~0 is fine,
    ~ 0 isn't.

- Use boolean logic only when the context is clear and the thing tested can
  actually be considered boolean:

  Basically:
    `if (!strcmp(a b))` is WRONG since strcmp() returns three different values,
    0 when equal (which is what the ! tests against), < 0 when a < b, and
    > 0 when b > a.
    So please use `if (strcmp(a, b) == 0)`, a little more typing, but much more
    clear.

    We also seem to have a lot of functions returning either 0 on success, or
    -1 on error. And a lot of code using boolean logic on the return value.
    Please don't. Unfortunately this is so wide spread in the VICE code it's
    hard to fix.

- Use braces even when they are not really required, it makes expressions
  easier to read and allows to use advanced highlighting in the editor, ie

  if ((a + b) && (c != d)) {
      /* ... */
  }

    instead of

  if (a + b && c != d) {
      /* ... */
  }

- No 'clever' while/do trickery, unless required for preprocessor code. The
  following looks clever:

    while (*s++ != '\0');

  But this is clearer and will generate the same object code:

    while (*s != '\0') {
        s++;
    }

- To give the code a consistent look use specifiers named with prefixes
  like in the following examples:

    struct foobar_s {
        ...
    };

    typedef ... foobar_t;

    enum stuff_e {
        ...
    };

    union many_u {
        ...
    };

  Of course combinations may be used:

    typedef struct foobar_s {
        ...
    } foobar_t;

  Exceptions are basic type like BYTE, WORD, DWORD and code that follows a
  coding style of a certain architecture, e.g. UI code.

- Preprocessor macros which define constants or enumeration values should
  be written in capital letters.

   #define FORTYTWO 42

   typedef numbers_e {
       NUM_ZERO,
       NUM_ONE
   } numbers_t;



Common code guidelines
----------------------

Many different compilers are used to compile the common code parts.

- When using headers which are tested for in configure.proto don't assume they
  exist, use the #ifdef HAVE_*_H instead.

- Don't use C++ style comments (// comment), use C-style comments instead
  (/* comment */). This goes for C99 code as well.

- When adding header files use VICE_*_H as shown in the following example:


#ifndef VICE_RS232_H
#define VICE_RS232_H

...code...

#endif


- Don't use mixtures of tabs and spaces as indentation, using 4 spaces per
  level will make the code look the same no matter what editor you use.
  When changing an existing file, make sure the indentation style is the
  same throughout the source file.

- Avoid trailing whitespace. Many editors can show this and remove this.

- Refrain from using any non ASCII characters in source files, unless absolutely
  necessary. Previously a common trap were copyright headers - make sure to
  use latin letters only to write your name etc. or in other words: such chars
  should not be used anywhere, except in a few selected (usually translation
  related) files that contain tables of strings.
  The reason for this is that various tools get confused or even choke on any-
  thing that isnt the encoding they expect (and plain ascii always works). It
  also ensures that all files can be edited by anyone at any time without intro-
  ducing weird side effects.
  On a *nix system you may use the "file" command to check the files you
  changed, normally it should always say "ASCII text" (not ISO-8859, and
  definately not UTF-8 Unicode).

current exceptions from this rule are:

src/infocontrib.h:                 ISO-8859                     (generated file)

Keep in mind that editing the translation related files need special care, make
sure not to mess up the file by somehow converting the encoding!


Documentation
-------------

Please add documentation to code you add or alter.
We use Doxygen to document our code, add docblocks for each public function or
data structure, at a minimum. Adding documentation is boring and the discipline
to do that is even harder, but it'll help out your fellow (future) devs and
probably even you after not working on a piece of code for some time.


Adding new files to the svn repo
--------------------------------

When adding a *nix script file use the following svn properties:

svn:eol-style   LF
svn:mime-type   text/plain
svn:executable  *

When adding a windows/dos batch file use the following svn properties:

svn:eol-style   CRLF
svn:mime-type   text/plain
svn:executable  *

When adding a windows msvc template file use the following svn properties:

svn:eol-style   CRLF
svn:mime-type   text/plain

When adding an openwatcom target or project file use the following svn properties:

svn:eol-style   CRLF
svn:mime-type   text/plain

When adding a non-text file use only the correct mime-type.

For all other files use the following svn properties:

svn:eol-style   native
svn:mime-type   text/plain
