{"id":13546715,"url":"https://github.com/whitlockjc/m8-js","last_synced_at":"2025-10-29T00:02:04.182Z","repository":{"id":50276208,"uuid":"518616301","full_name":"whitlockjc/m8-js","owner":"whitlockjc","description":"JavaScript library for parsing Dirtywave M8 files, complete with a CLI for interacting with M8 files.","archived":false,"fork":false,"pushed_at":"2023-03-23T21:28:33.000Z","size":552,"stargazers_count":46,"open_issues_count":7,"forks_count":4,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-02-25T08:51:19.598Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/whitlockjc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2022-07-27T21:28:26.000Z","updated_at":"2024-11-29T01:58:33.000Z","dependencies_parsed_at":"2024-01-14T02:39:49.372Z","dependency_job_id":"f4386f74-1cd0-4e48-a27b-a88c3accb157","html_url":"https://github.com/whitlockjc/m8-js","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/whitlockjc%2Fm8-js","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/whitlockjc%2Fm8-js/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/whitlockjc%2Fm8-js/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/whitlockjc%2Fm8-js/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/whitlockjc","download_url":"https://codeload.github.com/whitlockjc/m8-js/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":242667466,"owners_count":20166296,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T12:00:43.620Z","updated_at":"2025-10-29T00:02:04.174Z","avatar_url":"https://github.com/whitlockjc.png","language":"JavaScript","funding_links":[],"categories":["Tools"],"sub_categories":[],"readme":"# m8-js\n\nThis repository contains a JavaScript library for parsing [Dirtywave][dirtywave] M8 files, as well as a CLI for\ninteracting with M8 files.  The hopes are not to provide yet another UI for M8 files, or to create any sort of\ncompeting product, but to provide programmatic access to the M8 resources stored in the M8 files for things like\nthird-party features _(things that maybe M8 doesn't support itself, but you find useful)_ and utilities.\n\n## Current Status\n\nAs of version `v0.1.0`, `m8-js` has the ability to read and write all known M8 file types. The API and its object model\nare pretty solid, complete with unit test over 99% code coverage. The CLI is equally solid, also unit tested with over\n99% code coverage.\n\n## Installation\n\n### Global\n\nInstallation is performed by issuing the following command:\n\n```\nnpm install m8-js --global\n```\n\nOnce you do this, `m8` should be available.\n\n## CLI Usage\n\n`m8 --help` or `m8 help` should give you enough of a starting point for now.  Just know that all commands support the\n`--help` flag for command-specific help.\n\nIn `0.2.1`, the `m8` command itself is now equivalent to the newly added `view` command which will let you print an M8\nfile without specifying the M8 file type. _(For example, if you have an M8 song file, you can run `m8 PATH` instead of\n`m8 song view PATH`.)_\n\n## API\n\n`m8-js` provides an API for both reading/writing M8 files, but it also provides an object model for programmatically\ncreating and updating M8 files. Below are some examples to help expedite your `m8-js` usage.\n\n**Note:** For an API Reference, please refer to [docs/API.md](https://github.com/whitlockjc/m8-js/blob/main/docs/API.md).\n\n### API Basics\n\nThe objects in `m8-js` were modeled based on my own interpretation of the raw M8 file data as represented in the M8 UI.\n**EVERY** object in `m8-js` will mirror M8's unaltered equivalent when created. For example, if you create a new `Song`\nobject, its representation is identical to a newly created `Song` in M8. The same goes for `Instrument` types, all\nsettings, etc. If you programmatically create anything, just know that if its constructor takes values, the default\nvalues mirror the M8 default values.\n\n### Object/JSON Representation\n\nEvery type in `lib/types` has an `asObject` instance method that will return a JavaScript `Object` representation of\nitself. Also, every type in `lib/types` has a static `fromObject` that will allow you to create an instance of itself\nbased on the JavaScript `Object` provided.\n\n### Reading an M8 file\n\nM8 files are binary files are binary in format, and `m8-js` provides an API for reading all supported M8 files\n_(Instruments, Scales, Songs and Themes)_. Here is an exmaple that hows how to read a file from disk:\n\n```js\nconst fs = require('fs')\nconst M8 = require('..')\n\nconst m8File = M8.loadM8File(Uint8Array.from(fs.readFileSync(m8FilePath))\n```\n\nAt this point, `m8File` will either be a `lib/types/Scale`, `lib/types/Song`, `lib/types/Theme` or one of the instrument\ntypes in `lib/types/instruments/`.\n\n### Writing an M8 file\n\nHere is an exmaple that hows how to write an M8 type to disk:\n\n```js\nconst fs = require('fs')\nconst M8 = require('..')\n\nfs.writeFileSync(M8.dumpM8File(m8File))\n```\n\nSo long as `m8File` is either a `lib/types/Scale`, `lib/types/Song`, `lib/types/Theme` or one of the instrument\ntypes in `lib/types/instruments/`, `M8.dumpM8File` will return a `Uint8Array` corresponding to the raw bytes for the M8\nfile.\n\n### Caveats\n\nWhile the `m8-js` API allows for programmatically creating M8 types, and writing them to files, there is data in the M8\nfiles that are unknown. While creating M8 file types complete via the API should work without issue, the safest way to\nensure complete binary accuracy, use `M8.loadM8File` to load the type you want and after you've manipulated it\nprogrammatically, use `M8.writeM8File` to write it back. If you do not use `M8.loadM8File`, the unknown bytes are\nwritten using known default values for the regions in question instead of the original values loaded from disk.\n\n### Development/Local\n\nOr you can use a local development installation by cloning this repository and installing its dependencies via\n`npm install`.\n\nOnce you do this, `./bin/m8` should be available.\n\n## Thanks\n\nWhen I initially started this effort, the only resource I could find to start this journey was this:\n\u003chttps://gist.github.com/ftsf/223b0fc761339b3c23dda7dd891514d9\u003e  Using this, a hex editor and some time on the\n[Dirtywave M8 Discord](https://discord.gg/WEavjFNYHh), this project came to life.  Thanks @impbox!\n\n[dirtywave]: https://dirtywave.com/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwhitlockjc%2Fm8-js","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwhitlockjc%2Fm8-js","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwhitlockjc%2Fm8-js/lists"}