## Compiling Doom Legacy 1.4x SDL

In order to compile Doom Legacy 1.4x SDL you'll need to have the following libraries installed on your system.
Make sure you install the developer packages of the libraries, which include both the runtime libraries (DLLs) and the stuff required during compilation (header files and import libraries).

NOTE: Most Linux distributions offer these libraries in the form of precompiled packages.

Library | Version | Ubuntu/Debian package | Description
--- | --- | --- | ---
SDL | 1.2.10+ | libsdl1.2-dev | Simple DirectMedia Layer. A multiplatform multimedia library.
SDL_mixer | 1.2.7+ | libsdl-mixer1.2-dev | A multichannel mixer library based on SDL.
OpenGL | 1.3+ | (several) | The standard cross-platform graphics library, usually comes with the OS.

You will require the following programs during the build process:

- GCC 3.3+, the Gnu Compiler Collection which, among other things, is a free C/C++ compiler.
  Linux systems most likely already have it installed.
- Has been compiled on Linux with Gnu 5.5.0.
- Has been compiled on Linux with Clang 3.8.0
- Windows users should install MinGW, a GCC port, and MSYS, a collection of POSIX utilities for Win32.
- Has been compiled on Windows XP with Mingw-32 5.0.2, and MSYS 1.0.11.
  Use the command "mingw32-make". Using the default "make" command invokes something else that does not work.

Download the Doom Legacy source. You can either get the source package or, for the latest code snapshot, checkout the legacy_one/trunk/ directory from the Subversion repository:

svn co https://doomlegacy.svn.sourceforge.net/svnroot/doomlegacy/legacy_one/trunk some_local_dir

From now on, your local copy of this directory will be referred to as TRUNK.

You can have multiple versions of the 'src' directory, such as d01, d02, d03, etc.. To compile these, cd to the src directory you wish to compile, and run 'make' from there. The src Makefile will find the BUILD directory.

### Make Options

The make_options file controls the make process.

Edit it to select various compiling options. Spelling of options must be exactly one of the specified choices.

- The "make_options" file must be created by you. It is customized to your preferences.
- Select the make_options_xx for your operation system, and copy it to make_options.
  Linux Example:
  `>> cp make_options_nix make_options`

  The make_options_xx will contain appropriate selections for your operating system. Copying options from a make_options file for a different operating system probably will not work.

- Lines that start with # are comments. To turn off an option, put a # at the beginning of that line. Lines without the # are active selections.
- MAKE_OPTIONS_PRESENT: this informs 'make' that the make_options file has been read. Leave it alone.
- OS: the operating system, such as LINUX, FREEBSD.
- SMIF: the port draw library, such as SDL, or X11.
- ARCH: the cpu architecture.

  You can build a binary customized to your processor. The examples work for most processors. It does not need to be exact, as processors will run binaries compiled for any older CPU versions of their line.

  See your compiler docs for the -march, -mcpu, and -mtune command line switches specifics. Without this line the compiler will select its default build target, such a generic32, or i386.

  For a modern x86 process, selecting "ARCH=-march=i686" will compile a binary for an x686, which will be smaller and faster than an x386 binary. The binary will run on any x686 compatible processor.

  If you have a specific processor, like an Athlon, then specifying that will have the compiler use specific optimizations for the Athlon. The resultant binary will run faster on an Athlon. It may run on other processors too, but in some cases this is not guaranteed.

- CD_MUSIC: if you don't have the music libraries, then turn off music by setting CD_MUSIC=0. The build will not have music.
- USEASM: use assembly code for certain operations. This used to be slightly faster code, but modern compilers will now beat this. The assembly is not updated often enough, so it may not be current. Avoid this unless you like pain.
- There are several install options for DoomLegacy. Each can be customized. See the next section.

### Install Options

The Makefile has options for installing the program. This is traditional for Linux makefiles. It is espcially useful when compiling your own binary.

You can use any other kind of installation too, such as copying the bin files to a "run" directory. Do not try to run DoomLegacy from the compile environment, as the run setup is quite different.

You can have several doomlegacy versions in your run directory. They may have any name you choose. I suggest making a name that identifies the variation, such as "dl_i686_athlon_v3".

You must have system permissions for the type of install. An ordinary user can only install_user.

`>> make install`
Provides install instructions.

The following are supported in "make_options":

- Install doomlegacy to the system.
  `>> make install_sys`
  INSTALL_SYS_DIR: the system directory where the binary will be installed.
  INSTALL_SHARE_DIR: the system directory where the support files will be installed.
- Install doomlegacy to the system games.
  `>> make install_games`
  INSTALL_GAMES_DIR: the system directory where the binary will be installed.
  INSTALL_SHARE_DIR: the system directory where the support files will be installed.
- Install doomlegacy to a user directory.
  `>> make install_user`
  INSTALL_USER_DIR: the user directory where the binary and suport files will be installed.
  INSTALL_LEGACYWAD_DIR: the directory where the support files will be installed.

### Compiling Legacy

1. Open a shell window, like console. Go to the TRUNK.
2. If you want a separate BUILD directory, then create it. Create bin, dep, objs directories there. The BUILD directory will need its own make_options file (see step 4). This allows you to compile SDL in one directory, and X11 in another.
   `>> make BUILD=x11 dirs`
3. The top level TRUNK is the default BUILD directory. The make_options file there will control the build, when BUILD is not specified.
4. Select and configure your make_options file. Copy one of the make_options_xx files to make_options of your BUILD directory. Edit your make_options to set your configure options.
   `>> cp make_options_nix x11/make_options`
5. Edit compile options in doomdef.c. These are options within DoomLegacy. Some features can be disabled to make a smaller binary. There are also some experimental code options, that are kept disabled.
6. To clean the build:
   `>> make clean`
7. To build the executable:
   `>> make`
8. To build a debug version:
   This puts the debugging symbols for the debugger in the binary. The debug version also forces DoomLegacy video to an 800x600 window, so the user can switch between the debugger window and the DoomLegacy window.
   `>> make DEBUG=1`
9. To build with bin, obj, dep, in a separate directory (example x11):
   `>> make BUILD=x11`
10. Example:
    `>> make BUILD=x11d clean`
11. Example:
    `>> make BUILD=x11d DEBUG=1 MIXER=1`
12. Example MinGW:
    Must use mingw32-make, not the make command from MSYS.
    `>> mingw32-make DEBUG=1 clean`
13. Read the Makefile for the help at the top of the file. This will document the latest commands.

## Coding rules and practices

- There is one subdirectory in the repository for each platform (SDL, X11, Win32 etc.). Ideally these subdirectories should contain all platform-dependent code.
- Do not commit tests or buggy code. Every revision should at least compile and link. If you absolutely feel you need to commit experimental code that does not fully work yet, use #ifdefs with a descriptive name to disable it.
- Fix any and all warnings the compiler gives. They are there for a reason.
- Keep the list of major bugs in ??? up-to-date.
- Doom Legacy is a Doom source port. Do not make noticeable changes to the gameplay without adding an user-controlled option (consvar for example) to disable them.
- Use the developer mailing list to keep other devs informed of your work. If you are not sure about whether a feature/change is a good idea or what is the best way to implement it, discuss it on the mailing list.
- Keep a log of your work in the _log directory. This will help other devs to keep up with you and makes it much simpler to update the what's new section of the docs when making a release.
- Use hard tabs when indenting code (i.e. spaces, not tab characters). Use either a 2 or 4 space tab size.
- Document all code, variables and functions must have names that are descriptive and help to understand the code (so no names like a2, ex, asdf2721...). Exception: variables that are entirely local in scope and have an obvious purpose, like for loop indices (i, j, k, s, t...) or coordinates (x, y, z, w...).
- Try not to have extern declarations and function prototypes in a .c file, they belong in the headers. Use static-scope variables and functions whenever you can to make it clear what their role is. Global variables are usually a bad idea.
- Do not overuse #ifdef. Especially avoid platform-dependent #ifdefs in the main code. Likewise, __BIG_ENDIAN__ and __LITTLE_ENDIAN__ conditionals only belong in m_swap.

## Know bugs/issues

     - splats on opengl/glide have serious z-problems and are not clipped
       to the seg
     - the splats should be in segs and not in linedefs, so we can clip it
       and render only when needed (actualy there is overdraw in opengl/3dfx)
     - when clientprediction2 is enabled (see doomdef.h) the spirit mobjs
       have some serious z problems when exiting/entering moving platforms
     - there is no splats on floors and ceiling, fab have begon but
       haven't finish
     - sprite that have transparent region (torch, lost soul...) are full
       transparent in 3dfx/opengl

## Explanation of the code

     3.1 The memory model (z_zone.c) (by BP) (revised WDJ)
     --------------------

     DoomLegacy allocates memory at begining and provides allocations of it via
     Z_Malloc functions.

     There are several compile-time options for the memory block allocation.
       PLAIN_MALLOC:  Substitute malloc for zone memory allocation.
            This ignores memory tags, and it cannot recover PU_LEVEL, PU_CACHE memory.
       TAGGED_MALLOC: Uses malloc, and uses memory tags.
       ZONE_ZALLOC:   The zone memory system, with preallocated memory.
                      The memory allocation size is set by #define, and command line switches.
       GROW_ZONE:	  An option that grows the zone memory allocation when needed.
       AGGRESSIVE_PURGE:  Aggressive purge of PU_CACHE, primarily as a
                      memory allocation test.

     Z_Malloc( int size, int tag, void* user )

     size: is the size in bytes
     tag:
       PU_STATIC:  Allocated static (like malloc does).
                   Call Z_Free to free it.
       PU_SOUND, PU_MUSIC: Static while playing. Specific to music uses.
       PU_LOCK_SB: Static and protected against changing tag or releasing.
                   Must change with PU_UNLOCK_CACHE to unlock it.
                   Used to protect status bar textures.
       PU_HWRPATCHINFO:  Hardware renderer texture cache only.
       PU_HWRPATCHCOLMIPMAP:  Hardware renderer texture cache only.
       PU_LUMP:    Generic allocation for lump reading.
                   At end of level, will be converted to PU_CACHE.
       PU_IN_USE:  Protected against other allocations while it is in use. The user
                   is expected to FREE it or change it to PU_CACHE when they are done.
                   At end of level, will be converted to PU_CACHE.
       PU_LEVEL:   Static until level is over, where a call to Z_FreeTag will
                   release all PU_LEVEL allocations, and their user ptrs set NULL.
       PU_LEVELSPEC: A PU_LEVEL for thinkers.
       PU_HWRPLANE:  A PU_LEVEL for hardware renderer planes.
       PU_PRIVCACHE: PU_CACHE allocation that is kept longer, until PU_CACHE is gone.
                   Used by expensive combined patch textures.
       PU_HWRCACHE: PU_CACHE for hardware renderer graphics.
       PU_CACHE:   Automatic free, when memory is needed by another Z_Malloc
                   allocation.  When Z_Malloc reuses it for another allocation,
    	       the user ptr will be set to NULL.
    	       When the user accesses a PU_CACHE allocation, where other allocation
    	       calls could have occurred, the user ptr must be checked for NULL,
    	       and the item reloaded when necessary.
    	       Change this allocation to a more protected tag when accessing
                   it around any code that does Z_Malloc allocation.

     (...)

     3.2 Hardware Texture model (by BP)
     --------------------------

     Eatch texture/patch/flats/pic in legacy are converted to hardware texture at
     runtime (the GlideMipmap_s structure (hw_data.h)). I will call hardware
     texture a gr_texture so there is no confusion.

     To remind you :
      - Texture are set of patch and are associate to linedefs (walls) can be
        upper, lower or middle texture. It can have hole on it.
      - patch are sprites (the doom patch are run of vertical lines)
      - flats are used for floors and ceiling of sectors and have size of 64x64
        it can't have hole on it
      - pic are new legacy format for picture, it can only handle plain texture
        like flats it is now used for hud in full screen for the main picture
        of legacy and for coronas (the format was extended to handle 32 bit color
        or intensity + alpha, not all are implemented at this time)

     Since patch, flat and pic are basic structure represented by only one lump in
     the wad, the wad loader allocate for eatch lump a GlideMipmap_s (cache3Dfx)
     and init data field to NULL. Since the data structure is allocated in
     PU_3DFXCACHE (like PU_CACHE) the data will be initilised when needed
     (hw_cache.c).

     The GlideMipmap_s structures for textures are initialized on
     HWR_PrepLevelCache (hw_cache.c) it is called in P_SetupLevel (load level)
     the number of textures is computed with TEXTURE1, TEXTURE2 lumps since this
     can be changed in runtime in legacy (load a wad while runing) it must be
     reallocated. Well, at this time it is realloceted at eatch level start. We
     can do better, since numtextures change only when a wad is loaded.

     The 3dfx driver use glide3, it load gr_texture in gr_texture memory of the
     card in fifo order when there is no more place it remove the first gr_texture,
     the downloaded field of GlideMipmap_s go to false and when needed it is
     reloaded in gr_texture memory. In OpenGl, since OpenGl keep texture in there
     own memory and handle gr_texture memory of the card we no more need to
     redownload it but if we not free time to time gr_texture memory in opengl,
     it will get alot of memory, so the gr_texture memory is cleared at eatch
     new level (same time of texture reallocation). Opengl and 3dfx link the
     loaded gr_texture with the nextmipmap field of GlideMipmap_s so before clear
     textures of the heap we MUST free gr_texture memory of OpenGl or 3dfx !

     Legacy can also draw patch with a differant colormap (thanks to Hurdler).
     When needed it create the same gr_texture but just with a differant colormap.
     This one is linked with the original in the GlideMipmap_s with the
     nextcolormap field.

     So when a polygone with a gr_texture must be drawn, first we check if the
     gr_textures is not allready loaded in hadware memory (downloaded field) if
     not then we check if gr_texture data is there (not grabbed by z_malloc
     function) if not we must recompute it eatch type of gr_texture (texture,
     patch, flat, pic have there own methode) the we can send the gr_texture
     to 3dfx or OpenGl.