---
title: GMENU
url: 'https://wiki.teletypegames.org/dos/gmenu'
markdown: 'https://wiki.teletypegames.org/dos/gmenu.md'
lang: en
date: '2026-10-10'
description: 'GMENU is a DOS program (C++, Open Watcom, 8086 code, about 45 KB). It lists the game folders of one directory (\COLLECT by default) with their title, genre, year and players, and starts the chosen game. It is not in memory while the game runs, so the game gets all the free memory. Up to 1.1.1 GMEN…'
taxonomy:
  tag:
    - howto
---

# GMENU

> GMENU is a DOS program (C++, Open Watcom, 8086 code, about 45 KB). It lists the game folders of one directory (`\COLLECT` by default) with their title, genre, year and players, and starts the chosen game. It is not in memory while the game runs, so the game gets all the free memory.
> 
> Up to 1.1.1 GMENU was written in NASM assembly and its programs were `.COM` files; 2.0.0 is the same menu rewritten in C++, with the toolchain of [DOSINST](https://wiki.teletypegames.org/dos/dosinst), and its programs are `GMENUPRG.EXE` and `GMEDIT.EXE`. 2.1.0 builds it in layers on [DOSLIB](https://wiki.teletypegames.org/dos/doslib), the library it shares with DOSINST; the menu is the same. 2.3.0 starts from its cache without scanning the game folders, and only the free memory limits the number of games. The store and the title of the game list call it GMenu Launcher; the folder and the programs keep their names.

- **Repository:** [git.teletypegames.org/dos/gmenu](https://git.teletypegames.org/dos/gmenu)
- **Download v2.3.0:** [GMENU-v2.3.0.zip](https://git.teletypegames.org/dos/gmenu/releases/download/v2.3.0/GMENU-v2.3.0.zip) · the executables alone: [GMENUPRG.EXE](https://git.teletypegames.org/dos/gmenu/releases/download/v2.3.0/GMENUPRG.EXE), [GMEDIT.EXE](https://git.teletypegames.org/dos/gmenu/releases/download/v2.3.0/GMEDIT.EXE)
- **Releases:** [git.teletypegames.org/dos/gmenu/releases](https://git.teletypegames.org/dos/gmenu/releases)

![GMENU game list](https://wiki.teletypegames.org/wiki-assets/gmenu/gmenu-list.png)

---

# What it does

- **Game list** from each folder's `METADATA.INI` (or the first line of `NAME.TXT`, or the folder name).
- **Search** as you type, in the titles, the folder names and the descriptions.
- **Filters** by genre (F2), year or decade (F3) and number of players (F4); favorites only (F7); games without `METADATA.INI` only (Shift+F7).
- **Sorting** by title, year, genre or most played (F9); a random game (F10).
- **Favorites** (F6) and the **last 10 played games** (F8); play count and last played date per game.
- **Detail page** (Enter): all the data, a scrollable multi-line description and the game's `.COM` / `.EXE` / `.BAT` files to start.
- **Play** with Ctrl+Enter or a double click (the `RUN` command), **setup** with Ctrl+S.
- **Editor** (Ctrl+E, `GMEDIT.EXE`): creates or edits a game's `METADATA.INI` in a form.
- Keyboard and mouse, including the wheel (CuteMouse WheelAPI). F1 lists all the keys.

![GMENU detail page](https://wiki.teletypegames.org/wiki-assets/gmenu/gmenu-detail.png)

# Installation

The quickest way on a networked DOS machine is [DOSINST](https://wiki.teletypegames.org/dos/dosinst): `DOSINST INSTALL GMENU` installs the latest release to `C:\APPS\GMENU`, and running it again updates it. By hand:

1. Download `GMENU-vX.Y.Z.zip` from the releases and unzip it to the DOS drive, for example to `C:\APPS\GMENU\` (the default, where DOSINST installs it). The menu needs `GMENU.BAT` and `GMENUPRG.EXE`, and `GMEDIT.EXE` for editing.
2. Put every game in its own folder under one common directory, with a `METADATA.INI` (or at least a `NAME.TXT`) in each: ```
    C:\COLLECT\
     DOOM\
       METADATA.INI
       DOOM.EXE
     PRINCE\
       NAME.TXT      <- first line: "Prince of Persia"
       PRINCE.EXE
    ```
3. Set the game directory in `GMENU.BAT` (the last argument of the `GMENUPRG.EXE` line, keep `/B`): ```bat
    %GMENU%PRG.EXE /B \COLLECT
    ```

    Another drive works too (`D:\GAMES`). `/A` shows all files on the detail page, not only the executables.
4. Start it with `GMENU`. `GMENU.BAT` finds its programs from the name it was started with, so the folder can be anywhere; started with the `.BAT` extension (from Total Commander or Windows 98, say) it cannot, and runs them from `C:\APPS\GMENU` (the `set GMENU=` line: change it if the menu is elsewhere). In DOSBox it can start at boot: ```
    [autoexec]
    mount c /Users/.../Dosbox
    c:
    path Z:\;C:\APPS\GMENU
    gmenu
    ```

To update an installed menu, copy `GMENUPRG.EXE`, `GMEDIT.EXE` and `GMENU.BAT` into its folder, and set the game directory in `GMENU.BAT` again. Coming from 1.x, the new `GMENU.BAT` is a must: the old one starts `GMENUPRG.COM`, so the old `.COM` files can be deleted. DOSINST does all of this, including the deleting.

# METADATA.INI

Every line is optional, the keys are not case sensitive, `[GAME]` and the lines starting with `;` are ignored:

```ini
[GAME]
NAME=Doom
GENRE=Shooter
YEAR=1993
PLAYERS=1-4
DESCRIPTION=The whole description in one line...
DESCRIPTION=A second DESCRIPTION line starts a new line.\nSo does \n inside the text.
RUN=DOOM.EXE -nomusic
ARGS=-skill 3
SETUP=SETUP.EXE
```

| Key | Meaning |
|---|---|
| `NAME` | The title. Without it: `NAME.TXT`, then the folder name. |
| `GENRE`, `YEAR` | Shown in the list, used by the filters and the sorting. |
| `PLAYERS` | A number (`2`), a range (`1-4`) or open-ended (`2+`). The filter matches the ranges that contain the count. |
| `DESCRIPTION` | `\n` is a line break, `\\` a backslash; several lines are joined with line breaks. |
| `RUN` | What Ctrl+Enter starts: a file of the game's folder with optional arguments. |
| `ARGS` | Added to `RUN`, also when the `RUN` file is started from the detail page. |
| `SETUP` | The setup command, started with Ctrl+S. |

The files can be UTF-8 (with or without BOM) or code page 437. UTF-8 letters are converted to code page 437; the ones it does not have (`ő`, `ű`, `Á`) become the closest one (`ö`, `ü`, `A`).

**Editing with GMEDIT:** Ctrl+E opens a form with the fields. A new file starts from what the folder tells (`NAME.TXT`, the only executable as `RUN`, the first `SETUP*` / `INSTALL*` as `SETUP`). Saving rewrites only the changed values; comments, other keys and untouched values stay as they were. F2 saves, Esc cancels. It also runs on its own: `GMEDIT C:\COLLECT\DOOM`.

# How it works

`GMENU.BAT` is a loop around the program, so the menu never stays in memory under a game:

1. `GMENU.BAT` runs `GMENUPRG.EXE /B` with the game directory.
2. When you choose a game, the program writes `GMENURUN.BAT` (change drive and folder, start the game, change back) into its own folder and exits.
3. `GMENU.BAT` calls `GMENURUN.BAT`, then starts the menu again — on the same game, with the same search, filters and sort order.

Ctrl+E works the same way, only `GMENURUN.BAT` starts `GMEDIT.EXE`. Without `/B`, the program only says that it must be started with `GMENU.BAT`.

On start the menu takes the games from `GMENU.IDX` and does not look at the game folders, so it starts quickly on a slow machine with many games too; only the selected game is checked, so an edit with Ctrl+E shows at once. A scan — the first start, a missing `GMENU.IDX` or one of another game directory, or **Ctrl+F** — lists the folders, rereads only the `METADATA.INI` / `NAME.TXT` files whose date, time or size changed, and writes `GMENU.IDX` again. New, removed or renamed game folders appear after Ctrl+F.

Runtime files, next to `GMENUPRG.EXE` (their formats did not change since 1.1.0, so an updated menu keeps its state; `GMENU.IDX` got a new version in 2.3.0, so the first start after that update scans the folders once):

| File | Content |
|---|---|
| `GMENU.SEL` | Last game, search, filters, sort order, recent games |
| `GMENU.FAV` | Favorites, one folder name per line |
| `GMENU.STA` | Play count and last played date per game |
| `GMENU.IDX` | Cache of the game folders and their `METADATA.INI` / `NAME.TXT` data; Ctrl+F rebuilds it, and it can be deleted any time |

# Building and tests

The build needs [Open Watcom v2](https://github.com/open-watcom/open-watcom-v2) (the snapshot release has macOS and Linux binaries; set `WATCOM` to its folder if it is not `~/.local/opt/watcom`):

```sh
cd SOURCE
./build.sh          # GMENUPRG.EXE and GMEDIT.EXE into the parent folder
./build.sh test     # the test versions into SOURCE/build/
```

The source is in layers, each using only the ones below it through their interfaces (the rules are on the [DOSLIB](https://wiki.teletypegames.org/dos/doslib) page): `model` (games, filters, the session, METADATA.INI), `repository` (the files: game folders with the `GMENU.IDX` cache, favorites, statistics, session, `GMENURUN.BAT`), `service` (the game list, starting a game, the pickers, GMEDIT's editing), `controller` and `view` (the pages), `app` (puts them together), and `main_gmenu.cpp` / `main_gmedit.cpp` for DOS. `SOURCE/lib` is DOSLIB. The default game directory comes from `collect_dir` in `gmenu.ini`.

The unit tests run on the host without DOSBox, the whole menu and editor too, with scripted keys on an in-memory disk; they check the layers first:

```sh
SOURCE/test/unit/run.sh
```

The screen tests run the test versions in DOSBox: for each case of `SOURCE/test/cases.txt` the keystrokes go into `TESTKEYS.TXT`, and when they run out the program saves the screen, which is compared with `SOURCE/test/expected/`. They need Python 3, Open Watcom and DOSBox (Staging or 0.74):

```sh
python3 SOURCE/test/run.py              # all cases
python3 SOURCE/test/run.py --update     # accept the current results
```

# Releases

Woodpecker builds and tests every push. A raised `version` in `metadata.json`, pushed to master, gets its `vX.Y.Z` tag from the pipeline, and that tag also publishes a Gitea release with `RELEASE_NOTES.md` as its text and three files: the `GMENU-vX.Y.Z.zip` to install, and `GMENUPRG.EXE` and `GMEDIT.EXE` to update an installed menu. The same tag publishes the release to the catalog, and from there the menu goes into the [DOSINST](https://wiki.teletypegames.org/dos/dosinst) store (`ftp://ftp.teletypegames.org/APPS`), with the tag as the version in its `INFO.INI`. Every step is a command of the [dos-tools](https://wiki.teletypegames.org/platforms/dos) builder image (`git.teletypegames.org/build/dos-builder`), which has the toolchain preinstalled; the repo holds only the `platform: dos` marker and its `metadata.json`, whose `dos` block says what a release holds. The screen tests run four cases at a time (`JOBS`, each in its own folder). The Gitea release is made by the [WarpEngine](https://wiki.teletypegames.org/engines/warp-engine)'s shared release step from the files `dos-pack` lists. There is no store step: the DOSINST store is the engine's DOS shelf, which it rebuilds from the catalog on every publish, so the pipeline needs no deploy key.

```sh
# "version": "2.4.0" in metadata.json, then
git commit -am "Version 2.4.0"
git push origin master
```

# Limitations

- The number of game folders is limited only by the free memory (about 100 bytes per game plus its data, at most 16000); at most 600 files per folder are listed. The recent list keeps 10 games, the statistics the last 1000 played games.
- Title 50 characters, genre 24, year and players 10, description 2000, `RUN` / `SETUP` / `ARGS` 60. `METADATA.INI` is read up to 4 KB, GMEDIT edits up to 8 KB.
- The screen uses code page 437.

'; var prevLevel = 2; for (var i = 0; i < headings.length; i++) { var h = headings\[i\]; var text = h.textContent.trim(); var slug = text.toLowerCase() .replace(/\[áàâä\]/g,'a').replace(/\[éèêë\]/g,'e').replace(/\[íìîï\]/g,'i') .replace(/\[óòôöő\]/g,'o').replace(/\[úùûüű\]/g,'u') .replace(/\[^a-z0-9\]+/g, '-').replace(/^-|-$/g, ''); if (!slug) slug = 'heading-' + i; if (used\[slug\]) { slug += '-' + i; } used\[slug\] = true; h.id = slug; var level = parseInt(h.tagName.charAt(1)); var cls = level > 2 ? ' class="toc-child"' : ''; html += '- [' + text + '](#'%20+%20slug%20+%20')
'; } html += '
'; toc.innerHTML = html; // Scroll-spy: highlight current heading var links = toc.querySelectorAll('a'); var ids = \[\]; for (var j = 0; j < links.length; j++) ids.push(links\[j\].getAttribute('href').slice(1)); function updateActive() { var current = ''; for (var k = 0; k < ids.length; k++) { var el = document.getElementById(ids\[k\]); if (el && el.getBoundingClientRect().top <= 80) current = ids\[k\]; } for (var m = 0; m < links.length; m++) { links\[m\].parentNode.classList.toggle('active', links\[m\].getAttribute('href') === '#' + current); } } window.addEventListener('scroll', updateActive, { passive: true }); updateActive(); })();

---

## Navigation

- Parent: [DOS](https://wiki.teletypegames.org/dos.md)
- Previous: [DOSLIB](https://wiki.teletypegames.org/dos/doslib.md)
- Next: [TTGWIKI](https://wiki.teletypegames.org/dos/ttgwiki.md)
