Skip to content

Latest commit

 

History

History
325 lines (238 loc) · 23.5 KB

README.md

File metadata and controls

325 lines (238 loc) · 23.5 KB

Options Menu

Build Issues License: GPL v3

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++

Install

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. Pick options_menu_compat only if you have an hmod that replaces the console's libstdc++ (e.g. RetroArch 1.8.4 Xtreme SC) and the menu doesn't open with the normal build. Installing one removes the other.

Opening it

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.

Menus

Main menu

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

RetroArch

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.

Network

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.

Save Manager

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.

Game names

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 to 169.254.13.37, the console connected over USB.
  • --hakchi-path: the Hakchi CE folder that has the games folders. Usually not needed: the script looks in its own folder first, so copying it next to hakchi.exe (portable Hakchi CE) is enough. It also finds the library of an open Hakchi CE, and Documents\hakchi2 for 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.

Advanced Options

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.

Controller

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.

Diagnostics

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.

For mod developers

Your hmod can add entries and whole screens to the menu.

How it works

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)

Command files

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.

Script helpers

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.

Translations

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.

Colors

/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.

Icons

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.

Building

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 build

build.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).

Contributing

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?
    1. Fork the repository and create a branch from master (git checkout -b fix/my-change).
    2. Build with ./build.sh (and ./build.sh FIX_LIBSTDCXX=1 for the compat build) and test on a console.
    3. Run tests/run_tests.sh; it needs Docker.
    4. Open a pull request that says what changed and how you tested it.

Code style

  • Formatting: .editorconfig sets 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. .gitattributes stores every text file with LF, whatever your core.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, markdownlint and cppcheck. Set it up once per clone with pip install pre-commit and pre-commit install; cppcheck has to be installed separately and on your PATH. pre-commit run --all-files checks 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 sh for BusyBox ash, snake_case variables, camelCase functions, source (not .) for other scripts. Run shellcheck on what you change.
  • Comments: only for constraints the code can't show.

Credits

  • 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

Testing

Thanks to DNA64 (viral_dna) and Swingflip for always testing, and to Aranthys, AxelStone, BsLeNuL, DR1001, Patton Plays and ThanosRD.

Acknowledgments

License

GPLv3 or later — see LICENSE.