A menu you can open at any moment on your NES, SNES, Famicom or Super Famicom Classic — on the Home screen or in the middle of a game — to power off, back up your saves and settings, manage Wi-Fi and RetroArch, tweak the controllers and more. Other hmods can add their own entries and screens to it.
This is my continuation of CompCom's Options Menu (last release 1.3.4, 2019). Version 2 is a rewrite of the interface and a large part of the scripts:
- New look: smooth TTF fonts, preview icons, toggle switches, submenu markers and button hints, with colors you can change (
theme.cfg) - 9 languages: English, Français, Deutsch, Español, Italiano, Nederlands, Português, Русский, 日本語
- New menus: Controller (autofire, Home combo, Start on the 2nd Famicom controller), Diagnostics, Saved Games, Wi-Fi backups, epilepsy protection
- Safer behaviour: entries that need a USB/SD drive or a missing component are hidden instead of failing, and lists such as Wi-Fi backups let you delete entries
- NES/Famicom friendly: the opening combo is picked automatically for consoles without shoulder buttons
- A compat build for setups where another hmod replaces the console's
libstdc++
From my Mod Hub (recommended): in hakchi choose Modules → Manage mod repositories and add https://defkorns.github.io/hakchi-repo/. Then open Modules → DefKorns Store and install Options Menu from the Options Menu tab. Updates show up there automatically.
By hand: download options_menu.hmod from Releases, put it in hakchi's user_mods folder (or drag and drop it onto the hakchi window), then install it from hakchi (Modules → Install extra modules).
Installing it replaces CompCom's Options Menu (options_deluxe) and the old Hibernate mod, and keeps your button combo, language and Home combo settings.
Which build? Use
options_menu. Pickoptions_menu_compatonly if you have an hmod that replaces the console'slibstdc++(e.g. RetroArch 1.8.4 Xtreme SC) and the menu doesn't open with the normal build. Installing one removes the other.
Hold L + R for about a second. On consoles without shoulder buttons (NES Classic, Famicom Classic, Famicom Shonen Jump), hold B + Down instead. You can change the combo in Advanced Options → Controller.
| Button | Action |
|---|---|
| Up / Down | Move (hold to repeat) |
| A or Start | Run the entry or open its submenu (marked ›) |
| B | Back; closes the menu on the main screen |
| B (hold ~1 second) | Delete the selected entry, on lists that allow it — confirm with A |
The footer always shows the buttons for the current screen.
| Entry | What it does |
|---|---|
| Hibernate/Standby | Opens Swingflip's power menu (see below) |
| Shutdown Device | Safely turns the console off* |
| Reboot Device | Safely restarts the console* |
| RetroArch › | RetroArch settings, backups and BIOS files. Shown when RetroArch is installed |
| Network › | IP address, Wi-Fi scan and Wi-Fi config backups |
| Save Manager › | Back up, restore and clean up your saves. Needs a USB/SD drive |
| Language › | Menu language: Automatic follows the console's own language, or pick one. The menu restarts in the new language |
| Advanced Options › | Controller, diagnostics and system tools |
*Don't shut down or restart from the menu while RetroArch is running: exit RetroArch first, or you may lose saves.
Hibernate turns the screen off and keeps everything in memory, so waking up resumes exactly where you were. Standby uses even less power, but waking up boots the console from scratch. To wake it:
| Combo | From Hibernate | From Standby |
|---|---|---|
| L + R + Up | Resume | Reboot |
| L + R + Down | Reboot | Shut down |
Works with RetroArch Neo and with the _km RetroArch Xtreme (Ozone).
| Entry | What it does |
|---|---|
| Restore Default Settings (All) | Puts back the default RetroArch config and deletes every game/core override and remap |
| Restore Default Settings | Puts back the default RetroArch config, keeping overrides and remaps |
| Backup Settings to NAND / USB | Copies your RetroArch config to /etc/ra_backup/ or USB:/data/ra_backup/ |
| Restore Settings from NAND / USB | Restores the config from those backups |
| Transfer BIOS file(s) | Copies BIOS files to USB:/data/ra_bios and restores them from there to NAND |
| Delete all settings backups | Removes the NAND and USB backups |
| Delete game and core overrides | Removes only the overrides |
| Delete remap files | Removes only the remaps |
| Delete BIOS file(s) from NAND | Removes the BIOS files from NAND |
| Toggle RA and Canoe load screens | Turns the RetroArch and Canoe loading screens on or off |
The USB entries only show up with a USB/SD drive connected.
| Entry | What it does |
|---|---|
| Display IP Address | Shows your local and public IP |
| Reconnect | Restarts the network when you're not connected |
| Search for SSIDs | Lists the Wi-Fi networks in range |
| Backup Wifi Config (NAND / USB) | Saves your wpa_supplicant.conf to /etc/wifi_backup/<ssid> or /media/data/wifi_backup/<ssid> |
| Restore Wifi Config (NAND / USB) › | Lists your backups; pick one to restore it and reconnect, or hold B to delete it |
Restore entries only show up when there's a backup to restore.
Needs a USB/SD drive with your saves on it. One screen lists the actions on the left; the right panel explains the selected one and shows how many saves are on the console, in the USB backup, left over from removed games and moved aside. Every action asks for confirmation: Start + Select for the ones that overwrite or move saves, A for bringing back the saves of removed games, which never overwrites anything.
| Action | What it does |
|---|---|
| Backup Saved Games to USB | Mirrors your saves folder to /media/data/saves_backup. Saves you deleted since the last backup are removed from it too; system folders (FOLDER, hakchi, home-menu, mcp-state) are skipped |
| Restore Saved Games from USB › | Lists the saves in the backup (none marked); mark the ones you want back with A and press Start. They overwrite saves with the same name and leave the others alone. Select all restores the whole backup |
| Clean Saves of Removed Games › | Lists the save folders of games that are no longer in any menu (all marked; A unmarks) and moves the marked ones to /media/data/deleted_games_saves. Menu folders (CLV-S-*) are never touched |
| Restore Saves of Removed Games › | Lists what was moved aside; mark the ones you want back with A and press Start. A save already on the console is never overwritten |
In the long lists (here and in the Module Uninstaller), Left/Right page up and down on a tap and walk the list letter by letter while held; L/R jump a letter at a time.
The two "Removed Games" lists show the names of the removed games instead of their codes (CLV-H-ABCDE). Every time the console starts, it remembers the names of the games installed at that moment in game_names.txt in your saves folder, and a name stays there after its game is removed. The backup keeps the file with your saves, and a restore adds its names without replacing newer ones. Saves without a known name keep showing their code, two games with the same name show their code too, and empty save folders aren't listed. Getting the names never changes or moves a save.
Games removed before this version was installed were never seen on the console, so their names can only come from your Hakchi CE library. The console can't read your PC, so the PC sends them. With the console on and reachable by Hakchi CE (USB or Wi-Fi), run pc/push_game_names.ps1 from a PowerShell window:
.\push_game_names.ps1 --ip 192.168.1.50--ip: the console's IP address, shown in Hakchi CE or in Options Menu › Network › Display IP Address. Defaults to169.254.13.37, the console connected over USB.--hakchi-path: the Hakchi CE folder that has thegamesfolders. Usually not needed: the script looks in its own folder first, so copying it next tohakchi.exe(portable Hakchi CE) is enough. It also finds the library of an open Hakchi CE, andDocuments\hakchi2for non-portable installs.
If Windows refuses to run scripts, use powershell -ExecutionPolicy Bypass -File push_game_names.ps1 --ip 192.168.1.50.
The names it sends are added to the ones already on the console.
| Entry | What it does |
|---|---|
| Controller › | See below |
| Diagnostics › | See below |
| Toggle Write Access on USB | Makes the USB/SD drive writable even if you don't keep your saves on it (it's read-only otherwise). Not needed if you use USB saves |
| Epilepsy protection (NES) | The console's own dimming of fast flashes in NES/Famicom games. On by default; turn it off to see games exactly as they were. NES/Famicom only |
| Clear Cache | Asks the kernel to free cached memory. Rarely needed |
| Module Uninstaller | Remove installed hmods from the console (see below) |
Module Uninstaller: installed mods are on the left, the ones queued for removal on the right. A queues the selected mod, B takes the last one off the queue, Start exits — or, with mods queued, asks you to press Start + Select to remove them (B cancels). It lists hakchi's own modules too: only remove mods you installed yourself.
| Entry | What it does |
|---|---|
| Change Options Button Combo | Press the buttons you want to open the menu with. Restart the console afterwards. Overrides the automatic L+R / B+Down choice |
| Autofire | Turbo for the controllers, with Fast / Normal / Slow speed |
| Use X/Y as turbo A/B | X and Y act as turbo A and B |
| Home menu button combo | Turns off the combo that sends you from a game back to the Home menu, so you can't press it by accident |
| Start on 2nd controller | Famicom only: the 2nd Famicom controller has no Start button; this gives it one |
Changes apply right away, without restarting.
| Entry | What it does |
|---|---|
| System Information | Console type and region, hakchi/kernel/boot versions, firmware, free space on NAND and USB/SD, size of your saves |
| Display Temp | CPU temperature |
| Run Top | CPU and memory use and the running processes |
| Benchmark Tool | Mounts, CPU and RAM information, in 4 parts |
| RetroArch Debugger (USB logs) | Runs RetroArch in verbose mode and saves its config and log to /media/data/log/ |
| Dump File Structure (to USB) | Writes every file and folder, with permissions and links, to /media/data/log/Hakchi_file_structure.log |
| Save kernel log (to USB) | Writes dmesg to /media/data/log/dmesg.log |
The USB entries only show up with a USB/SD drive connected. They're the logs to attach when reporting a problem.
Your hmod can add entries and whole screens to the menu.
optiond waits for the button combo and launches options. Everything lives in /etc/options_menu/: each screen is a commands/ folder with one file per entry, and the scripts they run go in a scripts/ folder.
options takes these arguments (always call it by its full path, /etc/options_menu/options):
| Argument | Description |
|---|---|
--commandPath <folder> |
Commands folder for this screen |
--scriptPath <folder> |
Scripts folder, available as %script_dir% |
--title <key> |
Screen title (a translation key or plain text) |
One file per entry, named cNNNN_Name; entries are sorted by name. Each line is FIELD=value, no spaces around =, case sensitive.
| Field | Description |
|---|---|
COMMAND_NAME |
Label shown, or a translation key |
COMMAND_TYPE |
INTERNAL shows the command's output in the menu's console; EXTERNAL runs it with the menu paused; DOWNLOAD runs it on a progress screen with a bar (fed by the downloader's --progress lines on stdout) and a B to cancel, closing on its own when the command exits 0; CHOICE turns the entry into a value picker (see the CHOICE_* fields) |
COMMAND_STR |
Single-line command to run. Use a script for anything longer |
RESTART_UI |
External commands only. FALSE leaves the UI paused; resume it yourself with /bin/sh /etc/options_menu/scripts/ResumeUI.sh |
IGNORE_INTERRUPT |
TRUE: B doesn't interrupt an internal command while it runs |
USB_ONLY |
TRUE: only shown when a USB/SD drive is mounted |
ENABLE_IF |
Shell condition; the entry is only shown if it exits 0. /etc/preinit is sourced and script_init called first, so $rootfs, $mountpoint, $sftype... work, e.g. ENABLE_IF=[ -d "$rootfs/etc/wifi_backup" ] |
SUBMENU |
TRUE: draws ›, for entries that open another screen. Ignored on toggles |
CHILD |
TRUE: indents the entry under the one above it |
STATE_STR |
Command whose first output line is the entry's state (1/on/y/yes/true = on). Turns the entry into a toggle switch; COMMAND_STR still does the toggling |
DELETE_STR |
Command run when the user holds B on the entry and confirms — makes list entries deletable |
DELETE_CONFIRM_KEY |
Translation key for that confirmation; defaults to a generic "Delete this item?" |
DELETE_BLOCKED_KEY |
Translation key: holding B on the entry shows this message with a Back badge instead of asking to delete it, for entries that can't be removed right now |
PREVIEW_IMAGE |
PNG shown in the detail panel, scaled to fit |
CHOICE_LIST |
CHOICE only. Command printing one value<TAB>label<TAB>preview line per option; the label can be a translation key and the preview is optional |
CHOICE_GET |
CHOICE only. Prints the stored value; empty means Automatic |
CHOICE_SET |
CHOICE only. Stores the value picked, with %value% replaced by it (empty for Automatic) |
CHOICE_AUTO |
CHOICE only. Translation key of the Automatic option, shown when no value is stored |
CHOICE_RESOLVED |
CHOICE only. Prints the value Automatic stands for, so its label and preview can be shown |
COMMAND_STR, DELETE_STR and STATE_STR can use %options_path% (the folder with the options binary) and %script_dir% (the current --scriptPath).
The shared framework also reads a few grid-only fields (PREVIEW_NEAREST, PREVIEW_SQUARE, PREVIEW_GRID_COLS, PREVIEW_FIT_CONTAIN, PREVIEW_HIDE_LABEL). The menu itself always shows a list; they're for apps built on the shared framework that use a grid layout. PREVIEW_IMAGE_X/Y/WIDTH/HEIGHT from the original format are accepted and ignored.
Your scripts can source /etc/options_menu/scripts/om_functions for the helpers the menu's own scripts use. The main ones:
| Function | What it does |
|---|---|
translate <key> |
Prints the string for the menu's current language |
omSplash <key...> |
Draws one translated line per key, full screen |
omLoading [key...] |
Same, with a moving bar, until your script exits; "Loading" without keys |
omDownload <out> <url> [fallback...] |
Downloads a file, printing progress for a DOWNLOAD entry; exit code 3 means no free space |
omDownloadAll <list> <handler> [keep] |
Downloads a list of files over one connection |
omUnpack <tar.gz> <dir> |
Unpacks an archive if it fits, then removes it |
omReloadMenu / omReloadMenuLater |
Stops the UI and reloads the current Home folder, keeping your splash text on screen |
enableCmds / disableCmds <name...> |
Show or hide entries by renaming $enable_<name> / $disable_<name> |
Since 2.1.0, scripts started from the menu no longer hold /dev/fb0, so they can call chmenu (or anything else that runs uistop) without being killed. On 2.0.0 they still hold it: hand such a command to hakchi's remote-exec instead, by writing it to /var/exec.flag.
Strings live in /etc/options_menu/language/<code>.lang as KEY=Text; the chosen language is in /etc/options_menu/language.cfg. en-US is always loaded first, so missing keys fall back to English.
Your hmod can ship its own strings in /etc/options_menu/<your_mod>/lang/<code>.lang. Every such folder with an en-US.lang is merged in at startup.
/etc/options_menu/theme.cfg holds the UI colors, one Key=R,G,B per line (0–255, # for comments). It's read once at startup: reopen the menu to see a change. A missing file, line or key uses the default.
| Key | Default | Used for |
|---|---|---|
Bg |
12,15,22 |
Background |
Border |
42,44,51 |
Dividers, box outlines, unselected tile border |
Accent |
240,196,61 |
Selected entry border, section title bar, ›, highlights |
SelectedRowBg |
20,22,26 |
Selected entry and tile fill. If only Bg is set, it follows Bg (slightly lighter) so rounded corners don't show the old color |
Text |
255,255,255 |
Titles, entry labels, button hints |
TextDim |
141,141,147 |
Secondary text, e.g. column headers |
ScrollArrow |
follows Text |
List scroll arrows |
BadgeLetter |
28,22,22 |
Letter inside the button-hint badges |
BadgeA / BadgeADark |
76,175,110 / 46,107,66 |
A badge (Select): fill / rim |
BadgeB / BadgeBDark |
225,85,84 / 140,52,51 |
B badge (Back): fill / rim |
BadgeX / BadgeXDark |
108,142,191 / 63,89,127 |
Hold-to-delete hint: fill / rim |
BadgeStart / BadgeStartDark |
194,168,94 / 116,101,56 |
Start pill: fill / rim |
BadgeY / BadgeYDark |
201,123,132 / 143,71,80 |
Reserved |
CheckboxOn |
follows BadgeB |
Module Uninstaller: marked checkbox |
CheckboxOff |
follows TextDim |
Module Uninstaller: unmarked checkbox |
Apps built on the same framework read this file too, so they match the menu.
Preview images (/etc/options_menu/images/, 200×140 PNG) and the UI glyphs in images/ui/ are rendered from Bootstrap Icons. The images/ui/ glyphs are white and tinted with the theme colors at runtime.
git clone --recursive https://github.com/DefKorns/OptionsMenu.git
cd OptionsMenu
./build.sh # out/options_menu.hmod (./build.ps1 on PowerShell)
./build.sh FIX_LIBSTDCXX=1 # out/options_menu_compat.hmod
./build.sh MOD_VER=test-dev # override the version for a test buildbuild.sh builds the classicmini-cross-toolchain Docker image if needed and runs make inside it — no local ARM toolchain required. Outside Docker, the same Makefile works with SDL2, SDL2_ttf, libpng and make CROSS_PREFIX=arm-linux-gnueabihf-.
Packaging and versioning come from hmod-build: the version is the latest v* git tag, and the .hmod name has no version, so hakchi sees every release as the same mod. Pushing a tag builds both variants and publishes a GitHub Release (a prerelease for tags with a hyphen, e.g. v2.0.0-alpha5).
Bug reports, ideas and pull requests are welcome.
- Found a bug? Open a bug report. Say which console and build you have, and attach the logs from Advanced Options → Diagnostics (saved to
/media/data/log/) when you can. - Have an idea? Suggest a feature. For anything big, open an issue before writing code, so we can agree on the approach first.
- Want to send code?
- Fork the repository and create a branch from
master(git checkout -b fix/my-change). - Build with
./build.sh(and./build.sh FIX_LIBSTDCXX=1for the compat build) and test on a console. - Run
tests/run_tests.sh; it needs Docker. - Open a pull request that says what changed and how you tested it.
- Fork the repository and create a branch from
- Formatting:
.editorconfigsets it: UTF-8, LF line endings, a newline at the end of every file, no trailing whitespace, 4 spaces for C/C++, 2 spaces for shell scripts and YAML, tabs only in the Makefile. Most editors pick it up on their own; VS Code needs the EditorConfig extension..gitattributesstores every text file with LF, whatever yourcore.autocrlf. - Checks before each commit: pre-commit runs the same checks on the files you stage: whitespace and line endings (fixed for you), YAML and JSON,
shellcheck,markdownlintandcppcheck. Set it up once per clone withpip install pre-commitandpre-commit install;cppcheckhas to be installed separately and on yourPATH.pre-commit run --all-fileschecks everything. - Only change what you need: don't reformat, re-indent or strip whitespace in lines you aren't changing. A pull request that touches unrelated lines will be asked to drop them. The Style check on pull requests looks only at the lines you add.
- C++: the C++ Core Guidelines, C++14, and the layout of the code around yours: braces on their own line,
if(with no space. - Shell: POSIX
shfor BusyBoxash,snake_casevariables,camelCasefunctions,source(not.) for other scripts. Runshellcheckon what you change. - Comments: only for constraints the code can't show.
- CompCom — the original Options Menu
- DefKorns — version 2: the new interface, TTF text, theme colors and icons, translations, Network (with Advokaten), Wi-Fi backups, Save Manager, Controller and Diagnostics menus, build tooling
- Swingflip — Hibernate Mod and Hakchi-Option-Pack scripts
- BsLeNuL — RetroArch configuration scripts
- Advokaten — Network commands
- ThanosRD — layout and design of the original interface
- MadFranko008 — idea for the Saved Games backup
- KMFDManic and DanTheMan827 — answers and help whenever I had questions about how things work
Thanks to DNA64 (viral_dna) and Swingflip for always testing, and to Aranthys, AxelStone, BsLeNuL, DR1001, Patton Plays and ThanosRD.
- hakchi2 CE — the platform every mod here runs on
- CompCom's Options Menu — where this menu started
- SDL2, SDL2_ttf and FreeType — drawing and text
- libpng — images
- libcurl and its CA certificate bundle — downloads
- Bootstrap Icons — preview icons and UI glyphs (MIT License)
- Noto Sans JP — UI font, subset (SIL Open Font License, see
fonts/OFL.txt) - Misaki font by Num Kadoma — 8×8 kana and kanji glyphs
GPLv3 or later — see LICENSE.