TITLE=GMENU ROUTE=/dos/gmenu LOCALE=en MODIFIED=1792417593 URL=https://wiki.teletypegames.org/dos/gmenu L=1 #16 L=2 #17 L=3 https://git.teletypegames.org/dos/gmenu L=4 https://git.teletypegames.org/dos/gmenu/releases/download/v2.3.0/GMENU-v2.3.0.zip L=5 https://git.teletypegames.org/dos/gmenu/releases/download/v2.3.0/GMENUPRG.EXE L=6 https://git.teletypegames.org/dos/gmenu/releases/download/v2.3.0/GMEDIT.EXE L=7 https://git.teletypegames.org/dos/gmenu/releases L=8 https://github.com/open-watcom/open-watcom-v2 q│ GMENU is a DOS program (C++, Open Watcom, 8086 code, about 45 KB). It lists q│ the game folders of one directory (c\COLLECTq by default) with their title, q│ genre, year and players, and starts the chosen game. It is not in memory q│ while the game runs, so the game gets all the free memory. q│ q│ Up to 1.1.1 GMENU was written in NASM assembly and its programs were c.COM q│ files; 2.0.0 is the same menu rewritten in C++, with the toolchain of q│ 1DOSINST, and its programs are cGMENUPRG.EXEq and cGMEDIT.EXEq. 2.1.0 builds it q│ in layers on 2DOSLIB, the library it shares with DOSINST; the menu is the q│ same. 2.3.0 starts from its cache without scanning the game folders, and q│ only the free memory limits the number of games. The store and the title of q│ the game list call it GMenu Launcher; the folder and the programs keep their q│ names. • bRepository:0 3git.teletypegames.org/dos/gmenu • bDownload v2.3.0:0 4GMENU-v2.3.0.zip · the executables alone: 5GMENUPRG.EXE, 6GMEDIT.EXE • bReleases:0 7git.teletypegames.org/dos/gmenu/releases i[Image: GMENU game list] r────────────────────────────────────────────────────────────────────────────── 1What it does 1════════════ • bGame list0 from each folder's cMETADATA.INI0 (or the first line of cNAME.TXT0, or the folder name). • bSearch0 as you type, in the titles, the folder names and the descriptions. • bFilters0 by genre (F2), year or decade (F3) and number of players (F4); favorites only (F7); games without cMETADATA.INI0 only (Shift+F7). • bSorting0 by title, year, genre or most played (F9); a random game (F10). • bFavorites0 (F6) and the blast 10 played games0 (F8); play count and last played date per game. • bDetail page0 (Enter): all the data, a scrollable multi-line description and the game's c.COM0 / c.EXE0 / c.BAT0 files to start. • bPlay0 with Ctrl+Enter or a double click (the cRUN0 command), bsetup0 with Ctrl+S. • bEditor0 (Ctrl+E, cGMEDIT.EXE0): creates or edits a game's cMETADATA.INI0 in a form. • Keyboard and mouse, including the wheel (CuteMouse WheelAPI). F1 lists all the keys. i[Image: GMENU detail page] 1Installation 1════════════ The quickest way on a networked DOS machine is 1DOSINST: cDOSINST INSTALL GMENU installs the latest release to cC:\APPS\GMENU0, and running it again updates it. By hand: 1. Download cGMENU-vX.Y.Z.zip0 from the releases and unzip it to the DOS drive, for example to cC:\APPS\GMENU\0 (the default, where DOSINST installs it). The menu needs cGMENU.BAT0 and cGMENUPRG.EXE0, and cGMEDIT.EXE0 for editing. 2. Put every game in its own folder under one common directory, with a cMETADATA.INI0 (or at least a cNAME.TXT0) in each: p C:\COLLECT\ p DOOM\ p METADATA.INI p DOOM.EXE p PRINCE\ p NAME.TXT <- first line: "Prince of Persia" p PRINCE.EXE 3. Set the game directory in cGMENU.BAT0 (the last argument of the cGMENUPRG.EXE line, keep c/B0): p %GMENU%PRG.EXE /B \COLLECT Another drive works too (cD:\GAMES0). c/A0 shows all files on the detail page, not only the executables. 4. Start it with cGMENU0. cGMENU.BAT0 finds its programs from the name it was started with, so the folder can be anywhere; started with the c.BAT extension (from Total Commander or Windows 98, say) it cannot, and runs them from cC:\APPS\GMENU0 (the cset GMENU=0 line: change it if the menu is elsewhere). In DOSBox it can start at boot: p [autoexec] p mount c /Users/.../Dosbox p c: p path Z:\;C:\APPS\GMENU p gmenu To update an installed menu, copy cGMENUPRG.EXE0, cGMEDIT.EXE0 and cGMENU.BAT0 into its folder, and set the game directory in cGMENU.BAT0 again. Coming from 1.x, the new cGMENU.BAT0 is a must: the old one starts cGMENUPRG.COM0, so the old c.COM files can be deleted. DOSINST does all of this, including the deleting. 1METADATA.INI 1════════════ Every line is optional, the keys are not case sensitive, c[GAME]0 and the lines starting with c;0 are ignored: p [GAME] p NAME=Doom p GENRE=Shooter p YEAR=1993 p PLAYERS=1-4 p DESCRIPTION=The whole description in one line... p DESCRIPTION=A second DESCRIPTION line starts a new line.\nSo does \n inside » p the text. p RUN=DOOM.EXE -nomusic p ARGS=-skill 3 p SETUP=SETUP.EXE t┌─────────────┬──────────────────────────────────────────────────────────────┐ t│h Key t│h Meaning t│ t├─────────────┼──────────────────────────────────────────────────────────────┤ t│0 cNAME0 t│0 The title. Without it: cNAME.TXT0, then the folder name. t│ t├─────────────┼──────────────────────────────────────────────────────────────┤ t│0 cGENRE0, cYEAR0 t│0 Shown in the list, used by the filters and the sorting. t│ t├─────────────┼──────────────────────────────────────────────────────────────┤ t│0 cPLAYERS0 t│0 A number (c20), a range (c1-40) or open-ended (c2+0). The filter t│ t│0 t│0 matches the ranges that contain the count. t│ t├─────────────┼──────────────────────────────────────────────────────────────┤ t│0 cDESCRIPTION0 t│0 c\n0 is a line break, c\\0 a backslash; several lines are joined t│ t│0 t│0 with line breaks. t│ t├─────────────┼──────────────────────────────────────────────────────────────┤ t│0 cRUN0 t│0 What Ctrl+Enter starts: a file of the game's folder with t│ t│0 t│0 optional arguments. t│ t├─────────────┼──────────────────────────────────────────────────────────────┤ t│0 cARGS0 t│0 Added to cRUN0, also when the cRUN0 file is started from the t│ t│0 t│0 detail page. t│ t├─────────────┼──────────────────────────────────────────────────────────────┤ t│0 cSETUP0 t│0 The setup command, started with Ctrl+S. t│ t└─────────────┴──────────────────────────────────────────────────────────────┘ 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 (cő0, cű0, cÁ0) become the closest one (cö0, cü0, cA0). bEditing with GMEDIT:0 Ctrl+E opens a form with the fields. A new file starts from what the folder tells (cNAME.TXT0, the only executable as cRUN0, the first cSETUP*0 / cINSTALL*0 as cSETUP0). 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: cGMEDIT C:\COLLECT\DOOM0. 1How it works 1════════════ cGMENU.BAT0 is a loop around the program, so the menu never stays in memory under a game: 1. cGMENU.BAT0 runs cGMENUPRG.EXE /B0 with the game directory. 2. When you choose a game, the program writes cGMENURUN.BAT0 (change drive and folder, start the game, change back) into its own folder and exits. 3. cGMENU.BAT0 calls cGMENURUN.BAT0, then starts the menu again — on the same game, with the same search, filters and sort order. Ctrl+E works the same way, only cGMENURUN.BAT0 starts cGMEDIT.EXE0. Without c/B0, the program only says that it must be started with cGMENU.BAT0. On start the menu takes the games from cGMENU.IDX0 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 cGMENU.IDX0 or one of another game directory, or bCtrl+F0 — lists the folders, rereads only the cMETADATA.INI0 / cNAME.TXT0 files whose date, time or size changed, and writes cGMENU.IDX0 again. New, removed or renamed game folders appear after Ctrl+F. Runtime files, next to cGMENUPRG.EXE0 (their formats did not change since 1.1.0, so an updated menu keeps its state; cGMENU.IDX0 got a new version in 2.3.0, so the first start after that update scans the folders once): t┌───────────┬────────────────────────────────────────────────────────────────┐ t│h File t│h Content t│ t├───────────┼────────────────────────────────────────────────────────────────┤ t│0 cGMENU.SEL0 t│0 Last game, search, filters, sort order, recent games t│ t├───────────┼────────────────────────────────────────────────────────────────┤ t│0 cGMENU.FAV0 t│0 Favorites, one folder name per line t│ t├───────────┼────────────────────────────────────────────────────────────────┤ t│0 cGMENU.STA0 t│0 Play count and last played date per game t│ t├───────────┼────────────────────────────────────────────────────────────────┤ t│0 cGMENU.IDX0 t│0 Cache of the game folders and their cMETADATA.INI0 / cNAME.TXT0 t│ t│0 t│0 data; Ctrl+F rebuilds it, and it can be deleted any time t│ t└───────────┴────────────────────────────────────────────────────────────────┘ 1Building and tests 1══════════════════ The build needs 8Open Watcom v2 (the snapshot release has macOS and Linux binaries; set cWATCOM0 to its folder if it is not c~/.local/opt/watcom0): p cd SOURCE p ./build.sh # GMENUPRG.EXE and GMEDIT.EXE into the parent folder p ./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 2DOSLIB page): cmodel0 (games, filters, the session, METADATA.INI), crepository0 (the files: game folders with the cGMENU.IDX cache, favorites, statistics, session, cGMENURUN.BAT0), cservice0 (the game list, starting a game, the pickers, GMEDIT's editing), ccontroller0 and cview0 (the pages), capp0 (puts them together), and cmain_gmenu.cpp0 / cmain_gmedit.cpp0 for DOS. cSOURCE/lib0 is DOSLIB. The default game directory comes from ccollect_dir in cgmenu.ini0. 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: p SOURCE/test/unit/run.sh The screen tests run the test versions in DOSBox: for each case of cSOURCE/test/cases.txt0 the keystrokes go into cTESTKEYS.TXT0, and when they run out the program saves the screen, which is compared with cSOURCE/test/expected/0. They need Python 3, Open Watcom and DOSBox (Staging or 0.74): p python3 SOURCE/test/run.py # all cases p python3 SOURCE/test/run.py --update # accept the current results 1Releases 1════════ Woodpecker builds and tests every push. A cvX.Y.Z0 tag also publishes a Gitea release with cRELEASE_NOTES.md0 as its text and three files: the cGMENU-vX.Y.Z.zip0 to install, and cGMENUPRG.EXE0 and cGMEDIT.EXE0 to update an installed menu. The same tag puts the menu into the 1DOSINST store (cftp://ftp.teletypegames.org/APPS0), with the tag as the version in its cINFO.INI0. The test step runs in the cdos-ci0 image of the Gitea registry (cgit.teletypegames.org/build/dos-ci:bookworm0), which has the toolchain preinstalled: cscripts/ci-toolchain.sh0 installs only when the image's versions differ from its pins. The screen tests run four cases at a time (cJOBS0, each in its own folder). The release step runs in the cci-tools0 image with nothing to install. The store step sends the folder as a tar over SSH to the server's cdeploy0 user (cdeploy-ssh0 image, referenced by digest), whose key is bound to one fixed command, cci-deploy0 (cinfra/host-config0); the pipeline needs no trusted volumes. p git tag v2.3.0 p git push origin v2.3.0 1Limitations 1═══════════ • 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, cRUN0 / cSETUP0 / cARGS0 60. cMETADATA.INI0 is read up to 4 KB, GMEDIT edits up to 8 KB. • The screen uses code page 437.