Android: build the hex monitor grid in code - #193
Merged
Merged
Conversation
The widget looked for a child "grid" from hex-monitor.xml, but this app never runs Builder.load over a widget XML — it constructs widgets directly — so the lookup found nothing, update() bailed out with "Grid not initialized" and the Hex Monitor section rendered an empty card on every device. Build the grid in the constructor, the way disassembled/hexdump/message-console build theirs, and drop the XML that described it. Two things the grid needed beyond the lookup, both measured on an API 36 emulator: row specs, because a GridLayout without them has one implicit row and stacks every label into it; and a default region a label-per-byte grid can actually render — Program Storage ($0600-$FFFF, 39424 bytes) exhausted the 200 MB heap and killed the app with an OutOfMemoryError, so the default is now Zero Page, as in the GNOME and web debuggers. Eight bytes per row instead of sixteen: only eleven columns fit the card, and the rest were unreachable.
JumpLink
added a commit
that referenced
this pull request
Sep 22, 2026
oxlint's unicorn/no-new-array is an error here, and CI's Code Quality job failed on it. A small named helper says what the string is for as well.
JumpLink
added a commit
that referenced
this pull request
Sep 22, 2026
JumpLink
added a commit
that referenced
this pull request
Sep 22, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
hex-monitor.tslooked up a child calledgrid, which only ever existed inhex-monitor.xml. Nothing loads that file: this app constructs its widgetsdirectly (
new HexMonitor()), and the onlyBuilder.loadcalls are insource-view.ts,gamepad.tsandmdx-view.ts. So the lookup found nothing,update()returned early, and the Hex Monitor section of the Debugger tab was anempty card.
Verified on an API 36 emulator before touching anything — the card is blank and
logcat carries the widget's own complaint:
The grid is now built in the constructor, the way
disassembled.ts,hexdump.tsand
message-console.tsbuild theirs, andhex-monitor.xmlis gone.What the grid needed beyond the lookup
Both found by running it, not by reading it.
Row specs. A
GridLayoutwith norowshas one implicit row and clamps everychild into it, so all 32 address rows would have stacked on top of each other.
update()now sizesrowsto the region.A default region a label-per-byte grid can render. The old default was Program
Storage,
$0600-$FFFF— 39424 bytes, upwards of forty thousandLabels. Thatexhausted the 200 MB heap and killed the app before a single row appeared:
The default is now Zero Page, which is what the GNOME (
hex-monitor.blpDropDown) and web (
Adw.ComboRow) debuggers select first. 256 bytes, 32 rows.Before / after
Same emulator, same crop, aligned on the section heading. The code reaching the
editor differs (typed in before, the Snake example loaded after) and does not
matter here: the monitor shows
$0000-$00ff, and neither program had run at thelast refresh, so
00is the right dump either way.Eight bytes per row, not sixteen
GNOME and web print sixteen into a source view that scrolls sideways. This is a
grid in a vertical
ScrollViewwith nowhere to go: at 420 dpi a byte column is60 px against roughly 850 px of card, so a sixteen-byte row rendered eleven
columns and
$0b-$0fof every row fell off the right edge, unreachable. Here isthat intermediate build — note the addresses stepping by
$10over elevencolumns:
Checks
gjsify format→gjsify format --check→gjsify lint→gjsify workspace @learn6502/core build→gjsify run build:android. The debug APK builds, and theafter screenshot is from that APK.
lintis in the list because the first pushfailed CI on
unicorn/no-new-array—gjsify format --checkdoes not cover it.Noticed while measuring, not fixed here
Adw.ViewSwitcherBar.revealdefaults to false (faithfully) andmain.tsneversets it, so the app has no tab navigation at all — the Debugger is reachable
only via the action button.
AdwClamp._allocate()in@gjsify/adwaita-nativescript0.51.1 callsString.prototype.spliton a childclassNamethat isundefinedfor any viewwithout a CSS class, which is what
editor.tshands it. Onmainthe app diesat startup with
TypeError: Cannot read properties of undefined (reading 'split'); the emulator run needed a localnode_modulespatch to get past it.That belongs upstream in gjsify.
"step"signal refreshes only the register panel, never themonitor (
game-console-event-bridge.ts), so single-stepping never redrawsmemory. Shared
common-uibehaviour, same on GNOME and web.🤖 Generated with Claude Code