Skip to content

Add ability to select Basic ROM (Atmos / Oric-1) via settings, URL parameter, and programs.json#4

Open
lxpollitt wants to merge 3 commits intolanceewing:masterfrom
lxpollitt:feature/rom-selection
Open

Add ability to select Basic ROM (Atmos / Oric-1) via settings, URL parameter, and programs.json#4
lxpollitt wants to merge 3 commits intolanceewing:masterfrom
lxpollitt:feature/rom-selection

Conversation

@lxpollitt
Copy link
Copy Markdown

Background motivation: I have multiple games I'm currently restoring from old tapes which I would like to share, but some of them do not run well with Atmos Basic 1.1 ROM, due to subtle differences compared to the original Oric-1 Basic 1.0 ROM.

This PR adds the ability to run games with either the Atmos (Basic 1.1, default) or Oric-1 (Basic 1.0) ROM, so programs that need a specific Oric model can be loaded cleanly. It's designed to be extensible if desired in the future - adding more ROMs in future should be straightforward appends to RomConfig.OPTIONS with the ROM file placed in assets/roms/.

Three ways to specify a ROM

Each has a clearly-defined scope:

  • Settings dialog (persisted in local storage) - allows users to specify which ROM files they want to use for local-file loads (drag-drop / file picker). A small gear icon tucked into the corner of the existing open-file button opens a dialog styled to match the existing help dialog on each platform.
  • ?rom= URL parameter - per-launch override for URLs that launch an individual program (#/slug or ?url=). Intended for sharing links to games that need a specific Oric model. Ignored on plain home-screen URLs.
  • rom field in programs.json - optional per-program property; lets curators specify the ROM for a program that needs one without affecting user settings. No existing entries changed, but available for future as needed.

Commits

Split into three logical commits for easier review:

  1. Housekeeping - ignore Cloudflare Wrangler's local cache in .gitignore; flip gradlew's executable bit so a fresh clone can run ./gradlew without chmod.
  2. ROM selection infrastructure and settings dialog - adds RomConfig, AppConfigItem.rom, DialogHandler.promptForOption (with native implementations on all three platforms: HTML <select> via dialog.js on GWT, Swing JOptionPane.showInputDialog on Desktop, AlertDialog.Builder.setSingleChoiceItems on Android), and the gear icon + settings dialog on the home screen.
  3. ?rom= URL parameter - per-launch override, documented in the README. Also fixes a pre-existing bug in the URL rebuild during program start: the conditional that inserted / before # was correct for URLs without a query string, but corrupted query values when one was present (the / would be concatenated into the last query parameter). Only revealed by this PR because ?rom= made query strings common on that code path.

New ROM file

assets/roms/basic10.rom (Oric-1 BASIC 1.0) source from defence-force.org, same source convention as the existing basic11b.rom.

Testing

  • GWT (web) - fully end-to-end tested in Chrome. All three ROM sources exercised, including URL-parameter edge cases (trailing-slash typo, unknown ROM id, bare home-screen URL, direct-load URL both via #/slug and ?url=). Built in programs rom field exercised by temporarily adding it to a programs.json entry.
  • Desktop (lwjgl3) - code follows the established platform-dialog pattern (JOptionPane.showInputDialog) but has not been directly run. I was unable to test the changes due to issue on macOS where UI buttons cause a spinning beach ball on click (reproduced on unmodified upstream/master). The Desktop ROM-selection changes in this PR are small and symmetric with the GWT and Android implementations but recommend worth a sanity check by someone with a working Desktop setup.
  • Android - same as Desktop: code follows the established pattern (AlertDialog.Builder.setSingleChoiceItems) but not directly run as I don't an Android device.

- Add .wrangler/ (Cloudflare Workers local cache) to .gitignore so
  it doesn't clutter working trees when using wrangler dev.
- Flip gradlew's mode bit from 0644 to 0755 so a fresh clone on a
  Unix-like system can run ./gradlew without a chmod step first.
Adds the ability to choose between Oric ROMs (Atmos BASIC 1.1 default,
Oric-1 BASIC 1.0). A settings cog on the home screen opens a dialog for
the user's default ROM, applied when loading local files (drag-drop /
file picker). Curated entries in programs.json can also declare their
required ROM via a new optional "rom" field.

- New RomConfig class centralises ROM Option list and the resolveRom()
  policy used by all three platforms.
- New optional AppConfigItem.rom field for programs.json entries.
- New DialogHandler.promptForOption, implemented natively on all three
  platforms: HTML <select> via dialog.js on GWT, JOptionPane on Desktop,
  AlertDialog.setSingleChoiceItems on Android.
- Settings cog on the home screen opens the new dialog.
- All three JOricRunner implementations now use RomConfig.resolveRom().
- basic10.rom (Oric-1 BASIC 1.0) added to assets/roms/.
Allows URLs like https://oric.games/?rom=oric1#/basic or
https://oric.games/?rom=oric1&url=... to request a specific ROM for
the program being launched. Primarily for sharing links to games that
need a specific Oric model. The parameter applies only on direct-load
URLs (hash route or ?url=); ?rom= on a bare home screen URL is ignored.
Unknown values silently fall back to the default.

- captureRomParamFromUrl() in GwtJOricRunner reads ?rom= at page load
  when a direct-load indicator is present.
- RomConfig.setUrlRomParam() / takeUrlRomParam() provide the capture /
  consume API (lenient about trailing-slash typos).
- resolveRom() consults the URL param first, ahead of the curator's
  rom field and the persisted preference.
- clearUrl() strips ?rom= when the user exits back to home (matches
  existing ?url= cleanup).
- README updated to document the parameter.

Also fixes a pre-existing bug in the URL rebuild during program start.
The old conditional added a '/' before '#' when the URL didn't end in
'/', which was correct for URLs without a query string but corrupted
query values when one was present (the '/' would be concatenated into
the last parameter). setPath(\"/\") guarantees the path-boundary '/' is
already in place, so the conditional is unnecessary — simplified to
always append \"#/<slug>\".
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant