Installation de l'éditeur de map pour Doom : Yadex

Code source.

https://github.com/HackTechDev/YadexEditor

What this is

Yadex is a Doom/Doom II/Heretic/Hexen/Strife/ZDoom level (WAD) editor for Unix/X11, forked from DEU 5.21. It is written in a mixture of C (mostly atclib/ and compat/) and C++11 (src/), talks to X11 directly via Xlib (no toolkit), and predates most modern C++ conventions — expect a lot of global state, raw pointers, and old-style structs alongside newer, string/vector-based code.

Build

Requires GNU make (the makefile is named GNUmakefile on purpose — BSD make won't work), a C89 compiler, and a C++11 compiler, plus X11 dev headers (/usr/X11R6/{lib,include} by default; adjusted automatically for AIX/Solaris in the GNUmakefile).

./configure                       # writes obj/0/Makefile.config and config.h
make                               # builds everything (doc, yadex, .ygd files)
make yadex                        # just build the binary -> obj/0/yadex
make test A='-g heretic foo.wad'  # build (if needed) and run obj/0/yadex with args

Useful ./configure flags: --prefix PATH, --cc COMPILER, --cxx COMPILER.

Debug build (preferred while hacking — this is the maintainer's own habit):

make dyadex                 # debug binary -> dobj/0/yadex
make dtest A='-g heretic foo.wad'   # run it, also writes gprof.out
make dg                     # run dobj/0/yadex under gdb (use "set args ..." at the prompt)
make dd                     # same, under ddd

make showconf prints the resolved CC/CXX/CFLAGS/paths/etc — check this first when a build behaves unexpectedly. make clean removes build output for the current $SYSTEM variant; make dclean removes only the debug objects. There is no make check/unit test target — test/ holds WAD fixture data (levels, lumps, graphics, sounds) used for manual/interactive testing via make test/make dtest, not an automated test suite.

Object files are split per source tree into obj/<SYSTEM>/ and dobj/<SYSTEM>/ (symlinked from obj/0 and dobj/0), where SYSTEM is derived from uname, so multiple platforms can be built from one checkout without clobbering each other.

GNUmakefile also drives documentation and release packaging (make doc, make dist, make changes) — irrelevant for ordinary code changes.

Coding conventions

The project has an explicit style guide in docsrc/hackers_guide.html ("Coding standards" section); the essentials, still enforced by convention even though some of it predates C++ in this codebase:

  • BSD-style indent, width 2, 80-column lines, tabs every 8; braces at the same indent as the block they open, function bodies not indented one extra level.
  • snake_case for variables/functions, UPPER_CASE for enums/most macros.
  • British/Commonwealth spelling in identifiers (colour, not color).
  • Conditionals must test actual booleans, not raw pointers/strcmp() results/error-code ints — e.g. if (fopen(...) == NULL), not if (!fopen(...)).
  • Prefer y_snprintf() over sprintf(), strlcpy/strlcat (via compat/) over strcpy/strcat.
  • const for by-reference args that aren't mutated; static for functions/variables that aren't used outside their file.
  • The codebase is mid-migration from char */C-string APIs to std::string/std::vector (see recent git log: "More s/char/string/", "Less char, more string") and away from compat/compat.h includes that are no longer needed — when touching a file, prefer continuing that direction rather than reintroducing raw C-string plumbing, but don't do drive-by rewrites of unrelated code.

Architecture

Directory-based lump access

Like Doom itself, Yadex never reads WAD files directly by name at the point of use. It maintains an in-memory master directory: a linked list of MasterDirectory entries (global MasterDir), each pointing back to the Wad_file/WadFileInfo it came from (global WadFileList, one entry per open IWAD/PWAD). OpenMainWad() builds the directory from the IWAD; OpenPatchWad() layers a PWAD on top — if the same lump name exists in several wads, only the entry from the most-recently-loaded wad survives. CloseUnusedWadFiles() closes wads no longer referenced by any directory entry; there is deliberately no "unload a single pwad" operation (see docsrc/hackers_guide.html for why this is a known wart). Look up a lump with FindMasterDir(). See src/wadfile.h, src/wads.cc/wads2.cc, src/lumpdir.cc.

Wad endianness is always little-endian on disk; in-core integers are native-endian. All multi-byte WAD I/O must go through Wad_file::read_* (or the free wad_read_i16()/wad_read_i32() equivalents) to stay portable to big-endian hosts.

Level data

Level data (things, linedefs, sidedefs, vertices, sectors) lives in global arrays/counts declared in src/levels.h and defined in src/levels.cc (Things/NumThings, LineDefs/NumLineDefs, SideDefs (now a vector<SideDef>), Vertices/NumVertices, Sectors/NumSectors, plus MadeChanges/MadeMapChanges, map bounds, etc.). This is legacy global state, not a Level object (a long-standing FIXME — see the comment at the top of levels.h — is that it should become a class so multiple levels could be edited at once; don't assume that refactor has happened). Invariants that must hold at all times: Num* counts stay accurate, and vertex/sidedef/sector references are always either OBJ_NO_NONE or a valid index. SEGS/SSECTORS/NODES/BLOCKMAP/REJECT are not loaded into memory; on save, they're either copied byte-for-byte from the source file (if MadeMapChanges is false) or zeroed out (nodes need external rebuilding).

The editor loop and display

EditorLoop() (in src/editloop.cc) is the heart of the interactive editor: refresh display → wait for an event → process the event, repeat. Display is driven from edisplay_c::refresh() (see src/edisplay.h), which walks a set of widgets: decide if a full redraw is needed (need_to_clear()), clear()/undraw top-down or draw bottom-up, then update_display(). To reduce flicker on full redraws, output is buffered to an offscreen pixmap and blitted with XCopyArea() (gfx.cc switches transparently between window and pixmap targets); this can be disabled (no_pixmap) for slow/low-memory setups.

Selection

The selection is a singly linked list of SelectionList nodes holding just an objnum (the object type is implicit from the current edit mode — a selection can't mix object types). Manipulated via SelectObject(), UnSelectObject(), select_unselect_obj() (toggle), IsSelected(), ForgetSelection() in src/selectn.cc/selectn.h. There is deliberately no iterator helper; callers walk the linked list themselves.

Graphics

Img (src/img.h) is the in-memory representation of all game graphics (flats, patches, sprites, textures): a palette-indexed rectangular pixel buffer (img_pixel_t = one byte = index into PLAYPAL). Textures are composed by pasting patches onto a buffer. Loading goes through LoadPicture() (pictures) / DisplayFloorTexture() (flats) into an Img, then display_img() converts palette indices to the actual X11 pixel format and blits. Screenshots go the other way: window_to_rgbbmp() then rgbbmp_to_ppm().

Memory allocation

Use GetMemory()/FreeMemory() (and the GetFarMemory()/ FreeFarMemory() pair, mostly a DOS-era relic) instead of raw malloc/free. GetMemory() calls fatal_error() internally on failure, so callers don't need to check its return value; memory it allocates is safe to free() directly if needed.

Third-party/compat code

  • atclib/ — a bundled subset of Atclib (LGPL, by André Majorel), low-level C helpers (list/array primitives, string utilities). Treat as vendored; don't restyle it to match src/ conventions.
  • compat/ — small portability shims (strlcpy/strlcat, arc4random) only compiled in when ./configure determines the host libc lacks them (HAVE_STRL, HAVE_ARC4RANDOM in obj/0/Makefile.config).
  • ygd/ — game definition files (doom.ygd, heretic.ygd, hexen.ygd, zdoom.ygd, etc.) describing per-game thing types, linedef flags, textures, etc.; parsed at runtime, not compiled in.

Source layout notes

  • The full module list that gets compiled is enumerated explicitly in GNUmakefile (MODULES_YADEX, MODULES_ATCLIB, MODULES_COMPAT) — when adding a new .cc/.c file under src/, atclib/, or compat/, it must be added to the corresponding list or it will silently not build.
  • src/config.cc / src/config.h are generated by ./configure (copied from obj/0/) — don't hand-edit them.
  • src/credits.cc and src/version.cc are generated by make from docsrc/copyright and VERSION respectively — don't hand-edit them.