Skip to content

Latest commit

 

History

History
146 lines (114 loc) · 12.2 KB

FILEHOST-API.md

File metadata and controls

146 lines (114 loc) · 12.2 KB

MEGA65 Filehost: integration notes

Researched 2026-10-16 against https://files.mega65.org. The Filehost has no documented public API. The endpoints below are the ones the site's own pages call. They may change without notice, so the client parses every response defensively and caches the last good copy.

Notation: verified means a live response was observed; inferred means it was read from site JavaScript or deduced.

Conventions (verified)

  • Base URL: https://files.mega65.org/php/. Requests are POST with a form-encoded body, as the site sends them. A plain GET also works for the parameterless lists.
  • Content type: responses are JSON but labelled Content-Type: text/html, with Cache-Control: no-store. A fresh PHPSESSID cookie is set every time, but no session is needed for read access.
  • Response shapes are inconsistent. Some endpoints return arrays and others return objects with numeric keys plus a state field. state: "EMPTY" means not found, restricted, or no permission.
  • Field formats vary:
    • dates appear as 2021/06/02, 17 Jul 2022 and 2026-10-16 01:58:16;
    • os has a leading space;
    • downloads is space-padded;
    • rating may be null, "", "-" or "5.0 (2)".
  • No checksums are published. The app records size and SHA-256 itself in a manifest.json next to each download.
  • Terms: robots.txt returns 404, and the Terms of Use contain no clause on automated access. The app sends a descriptive User-Agent, caches the catalogue for 6 hours, and fetches details only when they are needed.

Endpoints used by MEGA65 GUI

Endpoint Params Use Shape
readfilespublic.php none Main catalogue: 520 public files, latest version only [{fileid, title, category, type, os, rating, downloads, search, published, sortdate, versionid, filename, size, location, author, …}]
readfiledetail.php fileid (UUID or linkid) Detail pane [{state:"OK", title, description, linkid, category, type, os, rating, ratingcount, downloads, pal, ntsc, versionid, filename, size, version, location, coretext, romtext, published, author}] or [{"state":"EMPTY"}]
readversionlistpublic.php fileid Version history [{fileid, version, versionid, filename, size, comment, published, active:"Y"/"N", location}], newest first

Other read endpoints (not used yet)

Endpoint What it returns
readgallerypublic.php Thumbnails
readmedias.php Screenshots and videos, with objectid and origin=F
readcomments.php Comments and ratings
readpagesearch.php Search across all object types, with search
readtopten.php Top-ten lists
readcategorychart.php Category counts
readarticledetail.php Articles
readcontent.php Terms and privacy pages

Write and auth endpoints

  • Used: login.php and logout.php (see Sign-in), plus savefileupload.php and savefileupdate.php on the MEGA65 File Host Upload page (see My File Uploads below).
  • Never called: request.php, redeem.php, saveupdatedownload.php, savecomment.php, savescore*.php, savemediaupload.php, savemedialink.php, savedeletemedia.php, savedeletefileversion.php, saveupdateversion.php, saveupdateview.php.

Downloads (verified)

  • URL: resolve location against /php/, so ../files/m/x_AbC123.7z becomes https://files.mega65.org/files/m/x_AbC123.7z.
  • Served statically by Apache, with Content-Length, ETag, Last-Modified and Accept-Ranges: bytes. The client resumes partial downloads with Range.
  • No Content-Disposition header, and the stored name has a random suffix. The file is saved under the API's filename instead.

The un-parameterised version list

readversionlistpublic.php without fileid returns 982 rows for only 325 files and omits the release packages. It is not suitable for release discovery. Always pass fileid.

Identifying official releases (verified)

  • What counts as a stable core package:
    • author == "MEGA65"
    • category == "Firmware"
    • type == "Release Package"
    • the title contains "Release Package" and not "Development"
  • Target board: taken from the parentheses in the title, e.g. MEGA65 Core Release Package (mega65r6) no ROM.
  • The Filehost version field is a per-file revision counter, not the MEGA65 release number. The release number is parsed from the package file name:
    • mega65r6-release-0.97.2-03b24c6-norom.7z gives target, release, commit hash and a no-ROM flag;
    • legacy names look like MEGA65-R3-Rel_0_9-norom.7z;
    • the version comment ("Release 0.97 …") is the fallback.
  • The R6 package also contains the R5 (beta PCB) core. There is no public R4 package.
  • Package layout (0.97.2, verified by extracting it):
    • <name>/sdcard-files/ holds the SD-card files (FREEZER.M65 etc.);
    • <name>/*.cor and *.bit are the cores;
    • beta-pcb/ holds the R5 core;
    • extra/HICKUP.M65 and flasher/mflash.prg are not copied to the card.
Package fileid
Release package (mega65r3) no ROM 8d295d12-4422-4dc4-9553-64bf424e860e
Release package (mega65r6) no ROM 764642f7-83bc-4162-9911-99a0a6283d08
mega65-tools Windows release 06c55815-7826-4ad6-be0e-b8dc5e721b6d
mega65-tools Windows development 658322fd-e586-4b4f-a991-89470b269b4a

The release packages themselves are discovered dynamically. Only the two tools fileids are pinned.

Restricted (owner-only) content and sign-in

  • What is restricted: only the closed MEGA65 ROM, and packages that include it, need more than anonymous access (Filehost article "How to download closed ROM files").
  • How you get access: a registered user redeems the paper ownership code shipped with the machine, once, on the website (redeem.php).
  • How restriction shows in the data: restricted files are absent from readfilespublic. Anonymously, readfiledetail returns EMPTY for them. The public no-ROM package descriptions contain a "private link" (https://files.mega65.org?id=<fileid>) to the package with the ROM.

Sign-in (as the website does it)

  • Request: POST login.php with form fields logindata[username] and logindata[password]. This is jQuery's encoding of {"logindata": {...}}.
  • Required header: X-Requested-With: XMLHttpRequest. Without it the server answers {"state":"NOTOK","message":"Invalid request"} before checking credentials (verified). The app sends it on every Filehost POST.
  • Response: {"state":"OK"}, or {"state":"NOTOK","message":…} for bad credentials.
  • Session: held in the PHPSESSID cookie. logout.php ends it.
  • Expiry: session-aware endpoints may answer RELOGIN, TIMEOUT or LOGINERROR. The app treats these as "signed out".
  • No API token or OAuth exists.

What MEGA65 GUI does

  • You sign in with your own account, in the app's Filehost page. The password goes only to files.mega65.org over HTTPS, and is never logged.
    • By default only the user name is remembered.
    • "Remember my password" stores it encrypted with Windows DPAPI, readable only by your Windows account on that PC.
    • Signing out deletes the saved password.
  • The server decides access. A non-public file ID is only queried when you are signed in, and the app only lists its versions after readfiledetail returns OK for your session. CatalogueService throws otherwise.
  • Owner-only metadata is never written to the disk cache. Downloaded packages are stored in your local download cache like any other download.
  • Update My MEGA65 → "Include the closed ROM":
    1. Follows the private link from the public package.
    2. Uses the ROM package only if your account can see it.
    3. Otherwise falls back to the no-ROM package and says why.
  • The redeem flow is not automated. Redeem your code on the website.
  • Verified: sign-in works with a real account (2026-10-16).
  • Verified (R6 0.97.2): the with-ROM package has the same layout as the no-ROM one plus sdcard-files/MEGA65.ROM (128 KB). Its top folder is mega65r6-release-0.97.2-03b24c6, with no -norom suffix. The app checks that MEGA65.ROM is really present before reporting a with-ROM update.
  • Still to confirm: the API filename of the with-ROM version. The parser treats anything other than -norom as including the ROM. The parser accepts …-<hash>.7z or any suffix other than -norom.

My File Uploads (owner-only writes)

Read 2026-10-18 from the website's upload page (html/fileupload.php). The read endpoints were checked live with a real account; the two write endpoints have not yet been called against the live site.

Endpoint Method and params Answer
readfilelist.php GET [{id, title}]: your own uploads (verified)
readfile.php POST fileid {"0": {id, title, description, searchtags, shortlink, filetypeid, ntsc, pal, osmega65, osc65, osc64, osvixen, oswindows, osmac, oslinux, osonline, introdisk, highscore, groupname, coreversionid, romversionid, locked}, "state": "OK"} (verified)
readversionlist.php POST fileid [{version, versionid, filename, size, comment, uploaded, active, checked, location}], inactive versions included (verified)
readfiletypes.php GET [{id, name, extension, filecategory}], e.g. 58 = Core (verified)
readcoreversionsupload.php POST [{core, versionid, versiontext}] (verified)
readromversions.php POST [{state, versionid, versiontext}] (verified)
savefileupload.php POST multipart: file in field fileupload, plus the fields below {state: "OK", message, fileid}, or EXIST/ERROR with a message
savefileupdate.php POST form: fileid plus the attribute fields {state: "OK", message}
  • Attribute fields: title, type (file type id), description, searchtags, shortlink, ntsc, pal, osmega65, osc65, osc64, osvixen, oswindows, osmac, oslinux, osonline, introdisk, highscore, grouppublic, groupmega65, groupadmin, groupowner, coreversionid, romversionid. Flags are Y/N; exactly one group is Y. The DevKit button posts as groupmega65; readfile reports it as groupname: "devkit".
  • Escaping, as the page does it: backslashes are doubled in title, description, search tags and comment; &, < and > are HTML-escaped in title and search tags. readfile returns the title HTML-escaped, so it is unescaped before editing.
  • Upload-only fields: fileid (-1 for a new file), comment, version (1 to 9999.9, one decimal), mode (init for a new file, new to add a version, replace to delete the latest version and put the upload in its place). A new version becomes the active one.
  • The upload sends all attributes too, so MEGA65 GUI reads them with readfile first and sends them back, so an upload never resets them.
  • Rules copied from the page: at most 200 MB; extensions doc, docx, xls, xlsx, txt, zip, rar, tar, 7z, dmg, pdf, iso, m65, d81, d64, prg, asm, bas, lst, c65, cor, rom, bin, mcs, bit, hic, sid, mod, osx, exe, rdf, bdf, cfg, tcr, chr or none; a title, a type and at least one platform are required; a short link is letters, digits and -. Highscore is offered only for Game types, and a ROM version only for MEGA65 cores.
  • Not done in the app: previews (savemediaupload.php), deleting files or versions, and choosing the active version. Use the website for those.

GitHub releases

A file on the MEGA65 File Host Upload page can be linked to a GitHub repository (stored in upload-links.json). Sync reads the newest non-draft release from the public GitHub API, picks the release file by a pattern such as MegaST-*.zip, and uploads it as a new version unless that tag or that file name is already on the Filehost. The version comes from the tag (v1.2 becomes 1.2); tags that do not fit nnnn.n get the next free version. The app asks before every upload, also when the check runs at start-up.

Open questions

  • Would the Filehost operators welcome a desktop client? Should it call saveupdatedownload.php so download counts stay accurate? (Not called today; worth asking the operators.)
  • Do signed-in sessions return additional rows from readfilespublic?
  • Which endpoints back the Projects and Compatibility index pages?