Numeric WorkBench is a portable PySide6 desktop application for numeric conversion, command expressions, workspace persistence and binary editing.
The project now contains two main workbenches:
Numeric WorkBench: a live Decimal, Binary, Hex (BE) and Hex (LE) converter with an expression command window.Binary Workbench: a tabbed binary and assembly editing environment focused on PSX MIPS R3000A workflows, symbols, versions, mapped internal files and repeatable patch work.
The in-app Guide remains the user-facing manual. This README focuses on project capabilities, technical structure and release/build notes.
- Converts between Decimal, Binary, Hex Big-Endian and Hex Little-Endian.
- Keeps typed converter content separate from formatted display output.
- Supports independent grouping and zero padding for each converter field.
- Evaluates arithmetic, comparison, bitwise and textual-operator expressions.
- Supports decimal,
0bbinary,b'...'binary,0xhexadecimal and plain hexadecimal command literals. - Stores variables, command history, converter state and preferences in context.
- Provides separate Variables and Logs windows for inspecting workspace state.
- Lets Logs preferences decide which command categories are persisted.
- Includes Binary Workbench for files, scratch assembly, tabs, versions, symbols, labels, internal files, offset regions, decoded text and search/navigation.
- Builds portable bundles for Windows, Linux and macOS through PyInstaller.
The numeric side combines a converter and a command window.
The converter has four fields:
Decimal: accepts digits0-9.Binary: accepts digits0and1.Hex (BE): accepts digits0-9and lettersA-F.Hex (LE): accepts digits0-9and lettersA-F.
Formatting is presentation-oriented. Grouping and zero padding change the effective display/conversion value without overwriting the raw text being edited. Odd hexadecimal input receives one leading zero before conversion so byte alignment stays stable.
Normal copy keeps the displayed text, including spaces. The small copy icon beside each converter field copies the same value without spaces.
The command window evaluates expressions and stores variables in the active context.
Supported numeric literals:
42
0b101010
b'101010
0x2A
002A
Assignments work with or without spaces:
gp=0x89823A
mask = 0xFF
bits=b'10101010
Operators:
Arithmetic: + - * / % **
Bitwise: & | ^ ~ << >>
Comparison: == != < > <= >=
Aliases: NOT AND OR XOR
Textual aliases are parsed only when they are explicit operators. Identifiers
such as AND_value, ORBIT, XOFFSET and NOT1 remain identifiers.
ANS stores the last successful command result. When Convert is enabled,
successful non-negative integer results are sent to the Decimal converter.
Variables and Logs open as separate reusable windows. Each row can be removed
individually. Logs are stored as submitted command/result pairs, and
Preferences > Logs controls whether assignment-only, unary-only, no-operator,
assignment and binary-operator expressions are persisted.
Binary Workbench is a separate window opened from the main toolbar. It is built around tabs, where each tab owns its file/source identity, rows, symbols, versions, navigation state and dirty state.
Open Fileopens binary or assembly/code files. Opening an already-open file switches to its existing tab.New Scratch Codecreates a temporary assembly tab for experiments.Internal Filesopens mapped ranges from a larger binary or disc image as focused tabs.Versionstores named edit sets and can restore or replace visible edited rows without immediately rewriting the original file.Go to,Find,HazardsandSelect Blockprovide focused navigation, delay-hazard review and selection.Environmenttools manage symbols, labels, offset regions, LBA file maps, custom commands and encoding tables.Preferencescontrols byte formatting, visible columns, edit rules, reference offsets, CPU architecture, block size, cache size and selection limits.
The main editor view is made of synchronized row surfaces:
Editor Assembly: the primary assembly editing surface.Bytes: encoded bytes for the same rows.Raw Instructions: preprocessed instruction text sent to assembly logic.File Offsetand optional reference offsets.Decoded Text, when enabled through view preferences and encoding tables.
Rows are represented by BinaryWorkbenchRowDTO, which carries offsets,
instruction text, byte text and original values. The editor tracks meaningful
edits through overlays rather than blindly rewriting full source data. Bytes
editing preserves comments and supports Backspace/Delete without shifting rows
when byte shifting rules protect existing offsets.
The PSX MIPS R3000A codec lives under src/core/binary_workbench/mips_r3000a.
It uses project fallback assemblers/disassemblers and can use capstone and
keystone when available. This keeps the editor usable while still allowing
better assembly/disassembly support in packaged builds.
Binary Workbench state is represented by BinaryWorkbenchStateDTO and
BinaryWorkbenchTabContextDTO.
The global state stores:
- open tabs;
- active tab id;
- shared view preference flag;
- last used directories;
- custom commands grouped by architecture;
- encoding tables;
- window size.
Each tab context stores:
- tab id, kind, display name and source path;
- CPU architecture and read mode;
- reference offsets and reference offset bases;
- labels, variables, equates and symbol offsets;
- internal file mappings and parent/child tab metadata;
- LBA sector size and offset regions;
- versions and active version name;
- workspace/module paths, checksums and directories;
- custom commands, navigation history and last open offset;
- original rows, current rows, file sizes, overlays and dirty state;
- view preferences for visible columns and decoded text tables.
Binary Workbench workspaces use a manifest plus module files instead of storing everything in one large JSON payload.
The manifest is stored under:
data/binary_workbench/workspaces
Module folders include:
Symbols
LBA File System
Versions
Offset Regions
The manifest records source identity, module paths, module directories, active version and view preferences. Module checksums are used to detect whether the tab data has changed. Symbols, LBA maps, versions and offset regions can be saved independently while still loading through the same tab workspace.
Binary Workbench uses two main caching systems.
CachedBinaryReader reads source files by block and keeps a limited LRU block
cache. block_size and cache_max_blocks are controlled by Advanced
Configuration. The reader can also apply byte overlays at read time, so edited
bytes are visible without forcing a full file rewrite.
SearchCacheService caches Find results by query and searched ranges. Entries
have a TTL, a maximum entry count and hit-count/last-use eviction. It can return
partial cached offsets, report missing ranges and validate offsets before reuse.
The cache is intentionally separated from heavy context persistence so search
speed does not bloat normal workspace load/save flows.
Symbols keep assembly readable:
- Variables use the
_nameform and are suited for addresses or offsets. - Equates use the
@nameform and are suited for immediate constants. - Raw Instructions shows resolved values after symbolic replacement.
Labels are detected from assembly rows and refreshed across tab/version changes.
Jump and branch operands that target labels can be clicked for navigation. Go To
can resolve file offsets, reference offsets, LBA values, labels, equates,
variables and named internal files. Clicking jump or branch targets records a
volatile per-tab/version return history, and Alt+G returns to the previous
clicked source offset. Reference-offset jumps use an explicit & prefix, such
as jal &0x801D9274, so standard file-offset jumps stay unambiguous.
Search > Hazards opens an independent range-based window for delay-hazard
review. It reuses Find-style Start Offset, End Offset and Length controls, keeps
results in a JSON hazard cache keyed by offset and lists each hazard beside the
corresponding instruction. Results remain navigable while the window stays open,
and Alt+H opens the Hazards window from the Search menu.
The MIPS editor marks delay hazards and invalid jump/branch targets only in Editor Assembly. Raw Instructions keeps showing the resolved instruction stream without warning backgrounds. Hazard detection includes branch/jump delay-slot cases and load/use register hazards. Invalid jump and branch targets account for alignment, file limits and selected reference-offset settings.
Rules separate fixed-row patching from byte-shifting edits. When byte shifting is disabled, valid original rows remain present and destructive selection deletes clear row content instead of removing protected offsets. Extra invalid rows can still be removed, and scratch-code tabs must be saved before workspace-backed symbols, versions or environment modules are created.
Versions are named edit sets. They can store instruction overlays, line-based instructions, comments and row payloads. A version can be loaded into a tab, updated from the current editor state and saved as a module without rewriting the original source file. Scratch tabs become workspace-capable after their first save links the tab to a real file path.
Internal file tabs are mapped through the configured LBA File System. They keep their parent source visible and map changes back to parent binary offsets, which avoids manual offset math when editing named files inside a larger image.
Editor commands are typed in Editor Assembly with a leading slash. /sp creates
a stack save/restore block. /li supports immediate loading, using a single
instruction when the value fits and lui/ori expansion when required. /where
creates branch-only loop templates with labels on the same line as their
instructions and delay-slot nop rows. Custom commands can store repeated
instruction blocks with optional register substitution.
Encoding tables map byte values to text for decoded text workflows. Find can search decoded text after the relevant table is available to the active context.
main.py official desktop launcher
build release build automation and PyInstaller config
src/core domain rules, converter, validators and binary logic
src/modules DTOs, constants, service contracts and use cases
src/controllers bridges between UI/presentation and use cases
src/presentation repositories, formatters and PySide6 UI components
src/main application composition and runtime defaults
tests automated tests
data local contexts, workspaces and runtime data
Important Binary Workbench areas:
src/core/binary_workbench
src/core/binary_workbench/mips_r3000a
src/core/binary_workbench/search_cache
src/core/binary_workbench/editor/commands
src/modules/binary_workbench_*.py
src/presentation/repository/binary_workbench_workspace
src/presentation/ui/components/binary_workbench
Runtime dependencies:
capstone==5.0.7
keystone-engine==0.9.2
packaging==25.0
PySide6==6.10.1
PySide6_Addons==6.10.1
PySide6_Essentials==6.10.1
QtAwesome==1.4.0
QtPy==2.4.3
shiboken6==6.10.1
Build dependency:
pyinstaller==6.16.0
python main.pyThe repository-root main.py file is the official app entrypoint.
Portable bundles are built natively per operating system.
make build OS=windows
make build OS=linux
make build OS=macosIf your shell does not expose the desired Python interpreter on PATH, override
it explicitly:
make build OS=windows PYTHON=/path/to/pythonBuild artifacts are emitted into:
dist/windows
dist/linux
dist/macos
Artifact names follow this format:
numeric-workbench-v2.1-<os>-<architecture>
v2.1 ships portable bundles only. Native installers are intentionally out of scope for this release.
The PyInstaller config keeps the bundle smaller by excluding unused Qt stacks
such as QtQuick, QML, WebEngine, Multimedia, OpenGL, SVG, PDF and several unused
Qt Addons. Binary Workbench assembly support keeps the dynamic capstone and
keystone imports available in packaged builds.
GitHub Actions builds portable artifacts natively on:
- Windows
- Linux
- macOS
Each release build job installs dependencies, runs tests, builds the portable artifact and uploads it as a workflow artifact.
pytestFor focused validation after build changes:
pytest tests/releaseUser feedback is necessary for the next development cycles. Please report bugs, unexpected editor behavior, confusing workflows and feature requests with enough context to reproduce the issue. This is especially important for Binary Workbench because real binary editing workflows expose edge cases that are hard to predict from isolated tests.
The project will need refactoring and better organization after the v2.1 feature cycle. The UI layer grew quickly and now contains responsibilities that should move toward controllers, presenters or core services. QSS files also need cleanup, several UI files are spread without their own focused subfolders, and some shared constants are duplicated across nearby systems. Future maintenance should reduce this coupling before adding large new features.