Skip to content

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

opensaga.dev

Standalone GitHub Pages site for opensaga. This repository owns the landing page, shared design, progress explorer, Saga player, nudat archive explorer, and nusave save editor. CI and deployment builds always use the latest main of each source repository and record the exact revisions in build-info.json.

Route Application Input
/ Landing page and project FAQ Saga's committed matching metrics
/progress/ Interactive Saga decompilation statistics vendor/saga/matching.json
/play/ Experimental Saga WebAssembly player Bazel build and your own Android OBB
/nudat/ nudat archive explorer Rust library built to WASM and your local DAT/OBB
/nusave/ nusave save editor Rust library built to WASM and your local PC/Android save

nudat uses one connected explorer with a folder sidebar, back/forward/up navigation and breadcrumbs beside archive search. File sizes and compression stay in the file list; preview and file download share the right pane. Click anywhere on a file row or use the up/down keys to browse previews. It searches all archive paths, previews text with line numbers inline and in an expanded dialog, previews browser-supported images, audio, DDS and ETC1 textures, verifies archives, and downloads individual files or ZIPs of a folder, search results, or a selection. An included synthetic example makes the complete workflow available without original game assets. Long operations can be cancelled; an invalid replacement archive preserves the open archive. A Web Worker reads small Blob ranges through the library's generic reader API. Archives remain on your computer; large archives are never loaded in full into WASM memory. Text previews are limited to 1 MiB and 10,000 displayed lines; media previews are limited to 64 MiB and depend on browser codec support. Audio never autoplays and stops when leaving its preview. Downloading an individual entry is limited to the library's 512 MiB read limit; ZIP exports accumulate decoded output in browser memory.

nusave opens Windows PC and Android game saves and Android SuperOptions. Its summary and searchable tree use the library's schema and interpreted values. Sections contain levels, characters, areas, and missions, with minikits nested under their level. Selecting an item shows its controls; draft edits are retained when moving between branches. Edit values directly with numeric inputs, toggles, dropdowns, text fields, and named flag checkboxes. The library provides control types, limits, and choices; invalid edits preserve the current save. Create new Android saves/options, reset edits, and download saves with repaired derived fields or preserve their exact stored bytes. The application works in a Web Worker with a 16 MiB input limit. Unknown bytes and the detected platform layout are preserved; new saves use Android defaults rather than converting PC files.

Texture previews decode on the archive worker, without GPU compression extensions. Supported formats are DDS BC1–BC5 (DXT1–DXT5, ATI1/2 and equivalent DX10 formats), 16/24/32-bit RGB(A), and ETC1 in DDS, PKM, or KTX1 containers. This includes Saga's .etc1 and .android_etc1_tex DDS files and their nonstandard pixel-format header size. Previews show the base mip of the first face/layer, with a 16-megapixel limit; unsupported formats (including BC6/7, ETC2, and volume textures) show an error instead of a misleading image. The parser follows the Microsoft DDS documentation and Khronos ETC1 specification. The example archive contains generated DDS/ETC1 samples. Decoder tests cover colors, alpha, subblock orientation, row padding, container variants, and corrupt data.

Build and preview

Requirements: Node.js 24 + npm, Python 3.12+, Rust with wasm32-unknown-unknown, wasm-pack 0.15.0, and Bazelisk (Saga pins Bazel 9.2.0). Bazel downloads its Emscripten and C++ toolchains.

git clone --recurse-submodules https://github.com/opensagadev/opensaga.dev.git
cd opensaga.dev
npm ci
rustup target add wasm32-unknown-unknown
cargo install wasm-pack --version 0.15.0 --locked
npm run build
npm test
npm run serve

Open http://127.0.0.1:8000. dist/ is the complete deployable artifact. No original game assets or reference binaries are required to build the site. For a quick layout preview, use npm run build:preview, then npm run serve; that preview deliberately omits application binaries. To use a working Saga checkout locally: python3 scripts/build.py --saga ../saga.

Shared design and new applications

site/shared/ owns the shell, navigation, theme, typography, forms, buttons, tables, dialogs, and responsive layouts. Tailwind scans all templates and JS under site/; the build emits one stylesheet used by every application. The theme uses neutral surfaces, thin rules, and simple document layouts. Violet links and selection, gold folders, and the unchanged logo supply the color. Matching graphs retain the red-to-green score scale. It follows the system light/dark preference. Navigation, panels, buttons, inputs, tables, and focus states all use these shared tokens. There are no page-local stylesheets. site/apps.json supplies navigation and application titles; "wide": true gives an application the shared wide workspace. For mixed widths, "sectioned": true lets the content use separate site-container and site-container site-container-wide sections, as nudat does for its introduction and explorer. Workspaces use up to 1440px with outer gutters. Save fields and desktop archive lists flow with the page; section navigation and the archive preview stay alongside them while scrolling. The progress map has a near-screen-height viewport with a separate source filter sidebar. Shared tinted navigation areas, white content surfaces, and purple primary actions distinguish the tools without row-by-row borders. nusave groups labelled controls into a responsive form and keeps technical descriptions in expandable details. Existing /play/ and /progress/ links, including ?obb=, retain their behavior.

Add a manifest entry and a site/apps/<id>/index.html content fragment. The builder wraps it in site/shared/layout.html and copies its JavaScript files. Use ordinary semantic HTML and the shared site-section, site-title, site-subtitle, site-intro, site-actions, and field-label classes. Add reusable UI components to site/shared/theme.css. The migrated player and progress explorer retain their complete HTML templates and receive the same shared header, head, and footer.

crates/nudat-web and crates/nusave-web are thin WASM adapters. Save parsing, checksums, schema, summaries, and validated edits live in the nusave library; filesystem operations live in its CLI. Archive parsing, compression and validation belong to nudat. Its library is portable by default; filesystem operations and terminal dependencies belong to the separate CLI crate. The library handles Read, Seek, and Write sources, while the native CLI owns files, directories, temporary staging, and thread scheduling.

The progress explorer keeps its summary at the reading width and its map in a wider workspace around 90% of the desktop viewport height. Scroll over the map or use its zoom buttons to zoom; drag to pan. Labels are on by default, including source-unit headings in the function-size view, and can be toggled off. Source files can be searched in the sidebar. Matching graphs retain the red-to-green score scale.

Regenerate the synthetic nudat example with python3 scripts/create_example.py --nudat /path/to/nudat. The checked-in archive contains only generated demonstration files.

Staging

Every production deployment also builds the staging branch, if it exists, into https://opensaga.dev/staging/. Pushing to staging requests a new deployment from main. Unlike production, staging builds its own scripts and uses its pinned submodules as-is, so it can point at unmerged Saga, nudat or nusave commits. Staging pages carry a banner and a noindex tag. A failed staging build is reported as a warning and does not block production.

To stage a change, reset staging to the branch under test, pin the submodules it needs and push:

git checkout -B staging my-feature
git -C vendor/saga fetch origin my-saga-branch
git -C vendor/saga checkout FETCH_HEAD
git commit -am "Stage my-feature with my-saga-branch"
git push --force origin staging

Source versions

Production and pull request checks always build the latest main of Saga, nudat and nusave: pages.yml runs git submodule update --remote before building and never commits the result. The commits recorded for the submodules only serve as a starting checkout and as the pins for staging, so they never need bumping for production. To build against the same sources locally:

git submodule update --init --remote vendor/saga vendor/nudat vendor/nusave
git submodule foreach 'git submodule update --init --recursive'
cargo update -p nudat -p nusave
npm run build
npm test

Each deployment includes build-info.json with the exact source revisions. Because every build refreshes all applications, a site-only push never rolls back an application, and a pull request sees upstream breakage before merge.

Deployment

.github/workflows/pages.yml builds all WASM applications, compiles shared styles, assembles all pages, and validates the result on main pushes and pull requests. Main pushes/manual dispatches upload dist/ as a Pages artifact; pull requests only build and test. This repository publishes https://opensaga.dev/ using GitHub Actions. The repository Actions variable PAGES_DEPLOY_ENABLED is set to true; setting it to false pauses publishing while retaining build checks.

Saga, nudat, and nusave each have a notify-pages.yml workflow that dispatches this repository's pages.yml on pushes to main (and can be run manually). The Actions secret OPENSAGA_PAGES_TOKEN is configured in all three source repositories. It uses a fine-grained personal access token restricted to opensagadev/opensaga.dev with Actions: read and write. When rotating it, update the secret in all three repositories and approve the token for the organization if required. The source repositories' automatic GITHUB_TOKEN cannot dispatch workflows in another repository. If the dedicated secret is missing, the notification step skips with a warning.

To rebuild manually with the latest application sources:

gh workflow run pages.yml --repo opensagadev/opensaga.dev --ref main

GitHub Pages is configured on this repository with GitHub Actions as its source and opensaga.dev as its custom domain. The Saga migration removes its old Pages deployment; source repositories only notify this repository. The apex domain uses GitHub Pages IP addresses; www redirects to the apex domain over HTTPS. CNAME in the build artifact alone does not configure an Actions deployment; the repository's Pages settings own the domain.

Saga's threaded player has a /play/-scoped isolation service worker; other applications use normal browser isolation. Remote OBB sources must permit CORS. For local assets, use the player's file selector.

Asset credits

The existing opensaga branding was migrated from Saga. Stud proportions refer to James Jessiman's LDraw 6141, CC BY 4.0. Discord and GitHub icons come from Simple Icons 16.31.0 (CC0). D3 (ISC) and fflate (MIT) are bundled locally from their pinned npm packages. Copyrighted game assets are not included.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages