Skip to content

Releases: acwright/TMS9918-EDITOR

v2.0.2 — the file you double-clicked

Choose a tag to compare

@acwright acwright released this 11 Sep 02:09

A patch release over v2.0.1. No new capability, no change to the file format or the
exports — a project written by v2.0.1 opens here and the other way round. The web editor
is unchanged and still lives at
acwright.github.io/TMS9918-EDITOR.

Downloads

Platform File First run
macOS (Apple silicon) tms9918-editor-2.0.2-mac-arm64.dmg Signed and notarized — opens with no Gatekeeper prompt
Windows (x64) tms9918-editor-2.0.2-win-x64.exe Unsigned installer, so SmartScreen warns — More info → Run anyway
Linux (x64) tms9918-editor-2.0.2-linux-x86_64.AppImage chmod +x, then run
Linux (x64) tms9918-editor-2.0.2-linux-amd64.deb sudo apt install ./tms9918-editor-2.0.2-linux-amd64.deb

Double-clicking a project opens that project

On macOS, double-clicking a .tms9918 file while the app was closed opened whichever
document the app had open when it last quit. The file you clicked was reached only if it
happened to be that same document — otherwise it was simply dropped, with no error and
nothing on screen to say so. Double-clicking against the running app always worked, and
Windows and Linux were never affected.

Two halves of the launch were each right on their own. A double-click on macOS is
delivered as an open-file event that fires before the app is ready — measured at the
time, and the reason the handler is installed as early as it is — so the clicked path
waits in a queue until the editor is up and can ask for it. Meanwhile the app, finding no
document named on its command line (macOS never puts one there), fell back to reopening
whatever was open at the last quit. That fallback went through the same queue, and
overwrote the path the double-click had already put in it.

The launch now asks whether a document is already waiting before it reaches for the
remembered one, and the whole decision lives in one function rather than split across two
files. A launch that asked for nothing at all still returns you to the document you were
last in.

v2.0.1 — the byte field, and ⌘S

Choose a tag to compare

@acwright acwright released this 26 Aug 00:24

A patch release over v2.0.0. No new capability, no change to the file format or the
exports — a project written by v2.0.0 opens here and the other way round. The web editor
is unchanged and still lives at
acwright.github.io/TMS9918-EDITOR.

Downloads

Platform File First run
macOS (Apple silicon) tms9918-editor-2.0.1-mac-arm64.dmg Signed and notarized — opens with no Gatekeeper prompt
Windows (x64) tms9918-editor-2.0.1-win-x64.exe Unsigned installer, so SmartScreen warns — More info → Run anyway
Linux (x64) tms9918-editor-2.0.1-linux-x86_64.AppImage chmod +x, then run
Linux (x64) tms9918-editor-2.0.1-linux-amd64.deb sudo apt install ./tms9918-editor-2.0.1-linux-amd64.deb

Reading the bytes no longer costs you a character

Selecting the hex in the Character panel and then clicking another character replaced that
character with the one you had just been looking at. No paste, no copy — reading the bytes
was enough to lose a glyph, and nothing in the UI suggested a write was pending.

Three things lined up to do it. Focusing the field counted as beginning an edit, so a click
into it to select its text stopped the draft tracking the character. Blur committed that
draft whether or not anything had been typed. And the character set grid selects on
pointerdown, which fires before the field loses focus — so by the time the commit ran,
the character it wrote to was the one just clicked.

Focus alone is no longer an edit; only typing or pasting is. A commit is also refused when
the selection moved out from under it, so a click that ends an edit and lands on another
character abandons the edit rather than following you to it. The same field on the Sprite
panel is fixed by the same change.

Save

  • File ▸ Save prints ⌘S. The menu carried no key, which read as a bug rather than as
    the deliberate policy behind it — an accelerator fires the menu item and still delivers
    the keypress to the page, so most items still carry none. Save is the one place where
    running twice and running with a text field focused are both harmless, so it is the one
    item that opts in.
  • ⌘S now saves while a text field has focus, which it previously did not.
  • The shortcuts sheet calls it Save, the same word the menu uses, instead of "Save now".

v2.0.0 — Projects are files

Choose a tag to compare

@acwright acwright released this 23 Aug 16:34

Projects are files now. On the desktop, a project is a .tms9918 file you keep
wherever you want it — beside the assembly in a game's repository, most usefully —
that opens by double-click and goes through version control with everything else.
The web editor is unchanged and still lives at
acwright.github.io/TMS9918-EDITOR,
with its project list and its browser storage exactly as they were.

If you are upgrading from 1.6

The first launch says what is about to happen and copies your projects out of the
app's browser storage into ~/Documents/TMS9918 Editor, then puts them in Recent
Documents so they are one click away.

Nothing is moved. The originals stay in the app's browser storage until you press
Remove Browser Copies, and only copies that were actually written are ever removed.
A name already taken in that folder gets a number, and a project that could not be read
is named and skipped rather than dropped silently. If a copy goes wrong, the originals
are still there.

Downloads

Platform File First run
macOS (Apple silicon) tms9918-editor-2.0.0-mac-arm64.dmg Signed and notarized — opens with no Gatekeeper prompt
Windows (x64) tms9918-editor-2.0.0-win-x64.exe Unsigned installer, so SmartScreen warns — More info → Run anyway
Linux (x64) tms9918-editor-2.0.0-linux-x86_64.AppImage chmod +x, then run
Linux (x64) tms9918-editor-2.0.0-linux-amd64.deb sudo apt install ./tms9918-editor-2.0.0-linux-amd64.deb

The document app

  • Double-click a .tms9918 file and the editor launches straight into it — cold, or
    into the app already running. Drop one on the window and it opens. The file carries its
    own icon and its own named type, so Finder calls it a TMS9918 Editor Project.
  • A start screen instead of a project list: New Project…, New from Sample ▸,
    Open…, and Recent Documents, which are also in File ▸ Open Recent ▸. Quit with a
    document open and relaunching returns to it.
  • A File menu that reads like a document app's — New Project…, New from Sample ▸,
    Open…, Open Recent ▸ │ Close Document, Save, Save a Copy… │ Reveal in Finder (Show in
    Explorer
    on Windows, Show in Files on Linux).
  • Esc closes the document and returns to the start screen.
  • The app holds one document at a time. Comparing two charsets means closing one;
    multiple windows are the next thing on the list.

It lives in a git repository properly

  • The file is written to be read by git diff — one screen row per line, one character
    per line, a stable key order. A commit shows the eight bytes you changed, not one
    2000-character line.
  • An idle editor does not dirty your working tree. A project nobody edited is not
    rewritten.
  • A git checkout under a clean document reloads it in place and says so quietly. One
    under unsaved edits asks, naming both versions, and writes nothing until you answer.
  • Autosave cannot overwrite a checkout. Every write states what it expects to find on
    disk and is refused if the file moved — measured against a real repository, with the
    autosave firing 500 ms into a branch switch and the checkout still whole afterwards.
  • A document deleted behind the app's back is reported rather than silently recreated.

What you lose, said plainly

There is no project list on the desktop, because the file manager is one. Rename,
duplicate and delete are Finder or Explorer operations now
, not buttons in the app.
File ▸ Save a Copy… covers branching off a variant. This is the trade the whole release
rests on and it is a real one.

Also

  • Files downloaded from the web app — .tms9918.json — still open, through Open… or by
    dropping them on the window. They are deliberately not double-clickable: Windows
    associates on the last extension only, so claiming that one would claim .json
    system-wide.
  • A Download from either build is now named after the project, with the bare extension.
  • The web project manager now says where projects live and what clearing browsing data
    does to them.
  • Share links made in the browser resolve against the published web app rather than the
    desktop app's internal URL — a 1.6 defect.

Verified, and not

Both macOS builds were run out of their own dmgs: notarized and Gatekeeper-accepted, the
double-click path opens a document and the next launch returns to it, recents are recorded,
and a document opened and left alone stayed byte-identical. The Windows and Linux
double-click is declared and not driven
— the packages carry the association, but running
the NSIS installer is a real Windows job.

v1.6.1

Choose a tag to compare

@acwright acwright released this 22 Aug 18:54

A patch release over v1.6.0. No new capability and no change to the file format or the
exports — this one is about using the editor on a small screen, and about the parts of the
UI that were sized to a fixed number rather than to the space they were given. The web
editor is unchanged and still lives at
acwright.github.io/TMS9918-EDITOR.

Downloads

Platform File First run
macOS (Apple silicon) tms9918-editor-1.6.1-mac-arm64.dmg Signed and notarized — opens with no Gatekeeper prompt
Windows (x64) tms9918-editor-1.6.1-win-x64.exe Unsigned installer, so SmartScreen warns — More info → Run anyway
Linux (x64) tms9918-editor-1.6.1-linux-x86_64.AppImage chmod +x, then run
Linux (x64) tms9918-editor-1.6.1-linux-amd64.deb sudo apt install ./tms9918-editor-1.6.1-linux-amd64.deb

Fits the space it is given

  • The screen and sprite views fill their panel. The fit was rounded down to a whole
    scale, so a viewport with room for 1.47× showed 1× — two thirds of the width wasted on a
    phone, and a whole step wasted on a desktop. The sprite preview had no fit at all and
    stopped at 12×, which is 384px however large the window. Both now fill, at any size.
  • The scale readout is the fit control. Press it to return to the fitted scale after
    zooming; + and − step to whole scales from wherever the fit landed.
  • The character set grid fills the width with 8, 16 or 32 glyphs a row instead of
    always 8. Columns double so a row stays a whole number of the 8-character groups the
    hardware works in, and Graphics I's colour groups still line up.

Usable on a phone

  • Every control is reachable. A fixed 320px pixel editor pinned the character, sprite
    and screen panels wider than a phone's column, and the column clipped the overflow — the
    shift, flip and colour controls were off-screen with no way to scroll to them.
  • Toolbars hold to two rows, folding their secondary tools behind a More button on
    small screens. They ran to four rows before.
  • Tooltips stay on screen instead of being cut off at the left and right edges.
  • The project list reads properly: the title no longer wraps, the modified date no
    longer truncates to Aug 22, 2026…, and a long project name gets the room it needs.
  • Both pickers start in their grid layout on a phone, where the scaled layouts shrink
    each glyph to a sliver. An explicit choice is still remembered and still wins.
  • Layout tooltips read as names again — Grid View rather than a paragraph explaining
    when to use it. They were the buttons' accessible names too.

v1.6.0 — Desktop builds + sprite picker views

Choose a tag to compare

@acwright acwright released this 20 Aug 05:44

The TMS9918 Editor is now a desktop app for macOS, Windows and Linux — and the
sprite picker gained two new layouts. The web editor is unchanged and still lives at
acwright.github.io/TMS9918-EDITOR.

Downloads

Platform File First run
macOS (Apple silicon) tms9918-editor-1.6.0-mac-arm64.dmg Signed and notarized — opens with no Gatekeeper prompt
Windows (x64) tms9918-editor-1.6.0-win-x64.exe Unsigned installer, so SmartScreen warns — More info → Run anyway
Linux (x64) tms9918-editor-1.6.0-linux-x86_64.AppImage chmod +x, then run
Linux (x64) tms9918-editor-1.6.0-linux-amd64.deb sudo apt install ./tms9918-editor-1.6.0-linux-amd64.deb

The desktop app

One renderer behind two shells — everything the web app does, the desktop app does. What
it adds:

  • A real menu bar, following the open project: a Sprite project says "Fill the
    sprite", a Multicolor project greys the pattern items, and the project list greys
    everything but New project. The keyboard map is unchanged and still lives behind ?.
  • Native save and open dialogs. Every export — assembly, BASIC, binary, PNG, project
    JSON — goes through the system save sheet, each kind remembering the folder you last
    used, instead of landing in ~/Downloads. Importing a project opens a real file panel.
  • Its own storage, in the app's userData directory rather than a browser profile,
    flushed to disk on the way out — an edit made a moment before you quit is there on
    relaunch.
  • A window that remembers itself, including which display it was on.

Desktop projects are separate from the web app's. Move one across with Download and
Upload in the project list, or a share link.

Sprite picker, three ways

The sprite picker now matches the character set panel's three arrangements:

  • Sheet — the whole set as one scaled picture, as before.
  • Grid — fixed-size slots that wrap to the column width, so an 8×8 set is legible
    rather than 16 slots across a 440 px column.
  • List — one row a slot, carrying its number in both bases, the hardware patterns it
    occupies (pat 12 at 8×8, pat 48–51 for a 16×16 quad), its colour by name, and
    whether it is Blank (no pixels set) or Invisible (colour 0). The sheet cannot
    tell those two apart; a row can.

The choice is remembered, and is independent of the character set's layout.

Also

  • Both editors' Pages deploy is fixed — it had been publishing nothing since the renderer
    moved under src/renderer/.
  • CI now builds the Electron main and preload processes, which nothing gated before.

v1.5.0

Choose a tag to compare

@acwright acwright released this 19 Aug 05:30

Two pieces of polish on top of v1.4.1, neither touching the domain.

Character set views

The set had one arrangement — two scaled blocks of 128 — which stops being readable on a short window, where the glyphs shrink to fit rather than the panel scrolling. There are now three, and the choice is remembered per browser:

  • Blocks — the original view, unchanged.
  • Grid — glyphs at a fixed size, eight a row, scrolling; [ / ] keep the selection in view.
  • List — the index: one glyph a row beside its code in decimal and hex, marking the slots still blank. A listbox with arrows, PageUp / PageDown, and Home / End.

Fill / Clear / Invert move into the Character header beside the stepper — they act on the character, not on the pixel under the pointer. The wallpaper preview was retired in the same move.

The keyboard map

Three surfaces could disagree about a key: the handler that acted on it, the tooltip that advertised it, and the README that documented it. Now there is one map.

  • A help sheet listing every shortcut, opened by ? or the new Keyboard button in both headers — on a tablet, the shortcut that opens the sheet is the one key you cannot press.
  • The views dispatch on the action, so a key added to the map without a handler is a type error rather than a dead key, and the test suite fails if a key has no README row.
  • Matching is mode-aware: a sprite project pages animations with , / . and has no grid overlay, and multicolor has no character panel, so the pattern keys no longer fire there (they used to mutate an invisible charset and push undo entries). The sheet is filtered the same way.
  • Space and Enter now belong to whichever control has focus.
  • Labels follow the platform — ⇧⌘Z on Apple, Shift+Ctrl+Z elsewhere.

Full Changelog: v1.4.1...v1.5.0

v1.4.1

Choose a tag to compare

@acwright acwright released this 25 Jul 15:00

Two fixes on top of v1.4.0.

Sample grid orphaned its fifth card

The Load a Sample grid was pinned to four columns, set back when there were exactly four samples — so Sprite mode's Astro Ace wrapped onto a row of its own. The column count now comes from the sample list itself, so the row stays intact and a sixth sample can't reintroduce it. Cards stretch to the tallest description and stay level.

ShareDialog threw on every project-manager visit

Its immediate watcher ran during setup and read a ref declared 14 lines below it — a temporal-dead-zone ReferenceError, thrown on every mount since v1.3.0.

Impact was limited to a logged error rather than broken behaviour: the immediate run would have returned early anyway, and every later run happens after setup completes, so sharing itself always worked. Fixed by hoisting the declaration above the watcher.

Suite 409 green.

v1.4.0

Choose a tag to compare

@acwright acwright released this 25 Jul 14:47

Adds Sprite as a fifth project type, covering the one part of the TMS9918 the editor had never touched.

Sprites are a hardware layer that overlays Graphics I, Graphics II or Multicolor (never Text Mode), so a sprite project is a companion to a screen project rather than a variant of one — it has no screen of its own.

Sprite editor

  • 8×8 or 16×16 patterns. A 16×16 sprite is four hardware patterns in column-major order (top-left, bottom-left, top-right, bottom-right); the editor shows one 16×16 grid with the quadrant seams marked and handles the interleaving.
  • Size and magnification are project settings, matching VDP register 1 where both are global bits. Switching between 8×8 and 16×16 only regroups the 256 patterns — no pixels are lost either way.
  • One colour per sprite, with a backdrop behind transparent pixels. Colour 0 is legal and means invisible; the picker marks those slots so they aren't mistaken for empty ones.
  • A sprite sheet picker showing every slot in its own colour.

Animations

Name any number of frame sequences and play them back at 1–30 fps over the backdrop, with hardware 1×/2× magnification applied. Reorder, retarget, scrub — every structural change undoable.

Export

Table Bytes Contents
sprite_patterns 2048 All 256 patterns, already in hardware quadrant order
sprite_colors 256 (8×8) or 64 (16×16) One byte per sprite, for Sprite Attribute Table byte 4
sprite_anim_<name> one per frame Pattern numbers (slot × 4 at 16×16), for attribute byte 3

All five formats apply — 6502 (ca65), Z80, BASIC DATA, binary — plus PNG as a sprite sheet or an animation film strip.

Sample

Astro Ace — a ship cycling its exhaust, a walking alien, and a four-frame explosion that cools from yellow to dark red.

Fixes

  • Three colour-union sites narrowed by elimination and silently assumed Graphics II; a fifth colour model turned these into type errors, now narrowed positively.
  • The localStorage index guard hard-coded its list of modes — the bug that hid saved Multicolor projects in Round 3. It now derives from the mode table, so a future mode can't reintroduce it.

Suite 406 green; type-check, lint and the Pages build clean.

v1.3.1

Choose a tag to compare

@acwright acwright released this 24 Jul 19:32

A small patch round giving the project manager room to breathe. Round 5 added a fifth per-row action (Share Link) and the manager's narrow column ran out of space — project names truncated mid-word while the page sat in a max-w-3xl column with empty space either side.

Changes

  • Wider manager page — max-w-3xl → max-w-5xl. The editor is already full-bleed; only the manager was constrained.
  • Timestamp out of the name button — it was the third item inside the clickable open-project button, competing with the name for width. As its own sibling it can shrink or wrap without ever forcing the name to truncate, and tabular-nums aligns the dates down the list.
  • Rows wrap instead of compressing — below sm the name takes a full line and the timestamp + action cluster share the line beneath it (timestamp left, actions right). Above sm it stays a single line. The five coarse-pointer targets keep their full size on a phone.
  • Sample grid goes 4-up — sm:grid-cols-2 lg:grid-cols-4; with four samples the old three-column grid left one card orphaned at the new width.

Presentation only — no domain, store, or persistence changes. Suite 245 green; type-check, lint, and production build clean.

Full changelog: v1.3.0...v1.3.1

v1.3.0

Choose a tag to compare

@acwright acwright released this 24 Jul 19:15

Round 5 — export label casing, a screen pointer status line, and share links.

Label case for assembly export

The export dialog gains a Labels picker for 6502 (ca65) and Z80 output: snake_case (default), ALL CAPS, camelCase, or PascalCase. The choice is remembered between sessions. Only cases that are valid assembler identifiers are offered — kebab-case would emit a - operator. Default output is byte-identical to v1.2.1.

Screen pointer status

A live readout under the screen canvas showing the pointer's cell coordinates, the cell's top-left pixel, and the mode-relevant fact under the cursor:

  • Text / Graphics I / II — the character code in hex and decimal
  • Graphics I — the character's colour group (0–31)
  • Graphics II — the screen third, named as the charset when independent
  • Multicolor — the palette index and colour name

With the pointer off the canvas it shows the screen's dimensions instead.

Share links

A Share Link button on each project in the project manager produces a URL carrying the entire project — character sets, colours, and every screen — gzip-compressed into the URL fragment:

https://acwright.github.io/TMS9918-EDITOR/#p=1H4sIA…

Nothing is uploaded; fragments never reach a server, so the link is the project. Opening one offers to add a copy to that browser. The dialog reports the link's length and warns past ~2,000 characters, where some chat apps truncate URLs. Damaged or truncated links fail with a clear message rather than a blank app.


245 tests green; type-check, lint, and the Pages build clean.