{"id":18627264,"url":"https://github.com/kazhuu/spc-player","last_synced_at":"2026-03-04T22:31:47.859Z","repository":{"id":53462274,"uuid":"174884386","full_name":"Kazhuu/spc-player","owner":"Kazhuu","description":"SNES music player in your browser with original hardware and Arduino.","archived":false,"fork":false,"pushed_at":"2023-07-21T16:39:18.000Z","size":3325,"stargazers_count":50,"open_issues_count":6,"forks_count":3,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-11T13:56:18.455Z","etag":null,"topics":["apu","arduino","hardware","music","player","snes","sound","spc","spc-player","spc700","webusb"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Kazhuu.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-03-10T21:40:03.000Z","updated_at":"2025-01-11T14:59:33.000Z","dependencies_parsed_at":"2024-11-07T04:42:03.455Z","dependency_job_id":"1eaebcea-c431-4c1a-b669-a4a3523dad50","html_url":"https://github.com/Kazhuu/spc-player","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Kazhuu/spc-player","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kazhuu%2Fspc-player","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kazhuu%2Fspc-player/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kazhuu%2Fspc-player/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kazhuu%2Fspc-player/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Kazhuu","download_url":"https://codeload.github.com/Kazhuu/spc-player/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kazhuu%2Fspc-player/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266087790,"owners_count":23874519,"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":["apu","arduino","hardware","music","player","snes","sound","spc","spc-player","spc700","webusb"],"created_at":"2024-11-07T04:41:46.087Z","updated_at":"2026-03-04T22:31:47.832Z","avatar_url":"https://github.com/Kazhuu.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# SPC Player\n\nSNES music player in your browser with original hardware and Arduino.\n\n![arduino-spc](./images/readme-image.png?raw=true \"APU and Arduino connected\")\n\n## Table of Contents\n\n\u003c!-- vim-markdown-toc GFM --\u003e\n\n* [What is this?](#what-is-this)\n* [Structure of the Project](#structure-of-the-project)\n* [How to Use](#how-to-use)\n  * [Connecting APU to Arduino](#connecting-apu-to-arduino)\n  * [Uploading Arduino Code](#uploading-arduino-code)\n  * [Python Frontend](#python-frontend)\n  * [Browser Frontend](#browser-frontend)\n* [Debugging APU Connections](#debugging-apu-connections)\n* [How it Works?](#how-it-works)\n* [Using Other Arduino Boads](#using-other-arduino-boads)\n* [Resources](#resources)\n* [Future Work](#future-work)\n* [Deploying GitHub Pages](#deploying-github-pages)\n\n\u003c!-- vim-markdown-toc --\u003e\n\n## What is this?\n\nVideo in action [here](https://www.youtube.com/watch?v=2sleZUMQwSA).\n\nWith this project you are able to play original SNES SPC audio files from your\nbrowser with original hardware. All you need is Arduino Micro and original SNES\nAudio Processing Unit (APU). Deployed browser player can be found\n[here](https://www.mauri.codes/spc-player). Playing songs also works from\nPython command-line tool. If you are interested how this project works check\nsections [How it Works?](#how-it-works) and [Resources](#resources).\n\nFor playing you also need to download your favorite SNES SPC music tracks. These\ncan be downloaded from [Zophar's](https://www.zophar.net/music) website. Search\nfor a game and download original music files. Files will end with `.spc` ending.\nI've included one Donkey Kong Country 2 song in root of the project that you can\nuse for quick testing.\n\nProject is develop on Linux machine and not tested on other platforms. Although\nit should work because of multiplatform tools used. If you stumble upon bugs,\nplease file an issue here in GitHub.\n\nThis project was also featured in\n[hackaday](https://hackaday.com/2021/08/08/a-snes-music-player-you-can-control-with-a-browser/).\n\n## Structure of the Project\n\nProject consist of two music track uploading frontend tools (browser and Python)\nand Arduino code for communicating with APU and with your computer. Browser\nbased frontend code lives under `frontend-web` folder and Python code under\n`frontend-python` folder. Arduino code lives under `backend` folder.\n\nProject also contains InkScape SVG image files under `images` folder and KiCad\nschemas under `schemas` folder.\n\n## How to Use\n\n### Connecting APU to Arduino\n\nFirst you need to connect APU to Arduino. Here is APU pinout looking from the\ntop side of the unit:\n\n![api-pinout](./images/apu-pinout.png?raw=true \"APU Pinout\")\n\nSignal and symbol explanations:\n* **~** means an active low signal.\n* **PA7** is port address bit 7, connected to active low chip select (~CS) pin on\n    the SPC700 chip. Pull this low to GND to enable the chip.\n* **PA6** is port address bit 6, connected to chip select (CS) pin on the SPC700 chip.\n    Pull this high to 5V to enable the chip.\n* **PA0** and **PA1** are port address bits 0 and 1. Used to select which port from 0 to\n    3 to write or read.\n* From **D0** to **D7** are bidirectional data lines for input and output a single byte.\n* **RD** is active low read, APU will write data to lines D0 to D7 when pulled low.\n* **WR** is active low write, APU will read data from lines D0 to D7 when pulled low.\n* **RESET** is active low reset line. When held low SPC is in reset mode.\n* **SMPCK** is a clock output from DSP with average clock rate of 2.23 MHz.\n* **MUTE** is active low mute output from DSP, it's 0V when DSP is muted and 5V when\n    not.\n\nHere is how you need to connect APU to Arduino:\n\n![scema](./images/schema.png?raw=true \"Schema\")\n\n### Uploading Arduino Code\n\nArduino based backend code uses [PlatformIO CLI](https://platformio.org/) tool\nfor managing the project and its dependencies instead of Arduino IDE. So to\ncompile and upload the code you need to download PlatformIO and build the\nproject using it. First download and install it from aforementioned website.\nInstalling either IDE or CLI is fine. Generally I prefer CLI over IDE, so the\nfollowing instructions are written with CLI.\n\n\nAfter installing PlatformIO go to `backend` folder. If you are using browser\nfrontend, you can simply run:\n\n```\npio run\n```\n\nThis will download needed tool and libraries. Compile the code and upload it to\nthe board. Also you should see popup window from Chrome pointing to deployed\nbrowser player. If not, then it can be found\n[here](https://kazhuu.github.io/spc-player).\n\nBy default code uses WebUSB serial to communicate with the browser. Both WebUSB\nand normal serial cannot be used at the same time. If you are using Python\nfrontend or normal serial, then you need to use following command instead and\nread the section [Python Frontend](#python-frontend).\n\n```\npio run --environment serial\n```\n\n### Python Frontend\n\nPython frontend can only upload one song at the time. If you want more player\nlike experience with automatically playing the next song. Have a look at browser\nbased frontend instead. Python frontend lives under `frontend-python` folder.\nGo to that folder and run following commands inside it.\n\nProject uses version 3.x of Python and uses pySerial library to talk to Arduino\nover USB serial line. First install pySerial with pip by running following\ncommand. Remember to use `pip3` and `python3` commands if you are using Debian\nbased system like Ubuntu.\n\n```\npip install pyserial\n```\n\nTo upload the song with Python you need to know your serial port to which\nArduino is connected to. In Linux it will be something similar like\n`/dev/ttyACM0` and on Windows `COM4`. To list available serial ports run:\n\n```\npython main.py -l\n```\n\nCopy the serial port and replace the following command `\u003cserial-port\u003e` with it.\nNow upload the song with:\n\n```\npython main.py \u003cserial-port\u003e ../dkc2-stickerbrush-symphony.spc\n```\n\nIf everything is working correctly Python should print following and song will\nstart playing.\n\n```\nopened port /dev/ttyACM0\nwrite CPU registers successful\nwrite DSP registers successful\nwrite first page RAM successful\nwrite second page RAM successful\n100%\nwrite rest of the RAM successful\nSPC execution started successfully, uploading took 9.22s\n```\n\nEnjoy some awesome SNES music! If you have some problems. Make sure APU is\nconnected to Arduino correctly. For this check [Debugging APU\nConnections](#debugging-apu-connections).\n\n### Browser Frontend\n\nBrowser based code uses WebUSB for communicating with Arduino. So check your\nbrowser compatibility for it\n[here](https://developer.mozilla.org/en-US/docs/Web/API/USB#browser_compatibility).\nFor example Chrome and supports it but Firefox does not at time of writing.\nDeployed player can be found [here](https://kazhuu.github.io/spc-player).\n\nBrowser player can play multiple songs more like a real player compared to the\nPython frontend which only can play one song at the time. Browser frontend lives\nunder `frontend-web` folder. Go to that folder and run following commands under\nit.\n\nApplication is developed with React and packages are managed with Yarn. So\ninstall yarn first for your system from\n[here](https://yarnpkg.com/getting-started/install). After installing install\nall required packages with:\n\n```\nyarn install\n```\n\nAfter installing run the application with\n\n```\nyarn start\n```\n\nand go to `localhost:3000` with your browser.\n\nWith the player you first need to give permission to your use your USB devices\nand select the correct one to connect to. After connecting successfully you are\npresented with the player. Player contains some buttons to debug your setup and\nthen button to upload SPC files. Multiple files can be uploaded at the same\ntime. One DKC2 track is include in the project root for testing purposes. When\nyou've uploaded some songs, then just click on any table line to start uploading\nthe song and it should start playing. After the song ends the next song will be\nplayed automatically. UI could be better but that is the task for the future...\n\nEnjoy some awesome SNES music! If you have some problems. Make sure APU is\nconnected to Arduino correctly. For this check section below.\n\n## Debugging APU Connections\n\nYou can test that APU is connected to Arduino correctly. You need to use normal\nserial line, not WebUSB serial. After uploading the code go to backend folder\nand run:\n\n```\npio run --target monitor\n```\n\nThis will open serial monitor. Press `R` to send R character. Arduino should\nrespond with `1` if it's able to reset the APU successfully and `0` when it\nfails. In that case check your connections and try again.\n\n## How it Works?\n\nAPU itself is a standalone CPU with it's own RAM and DSP for producing sound.\nUsually referred as SCP700 CPU\n([wiki](https://en.wikipedia.org/wiki/Super_Nintendo_Entertainment_System#Audio)).\nThen SPC music file is a snapshot of the state of that system just before the\nsong starts to play. The snapshot includes details like values of all CPU and\nDSP register and whole RAM content.\n\nWhen SPC700 boots up it will run it's Initial Program Loader (IPL) code. This\ncode is responsible for communicating over parallel lines with SNES main CPU and\ntransferring bytes to SCP700 RAM. It's also responsible of starting execution of\nuploaded code. In other words meaning when song should start playing.\n\nIn this project's case Arduino is talking with IPL program instead of SNES main\nCPU. Frontend program on PC (Python or browser) is reading SPC700 RAM bytes from\nSPC file, transferring them to Arduino over USB serial and Arduino then\ntransferring them with IPL program to SPC700 CPU RAM over it's parallel lines.\nThat's in a nutshell how the whole process works. After all RAM bytes and\nregister values have been transferred. Arduino will inject small custom bootcode\nto SPC700 RAM and tell IPL to start execution from there. The bootcode is\nresponsible for restoring last register and timer values and then jump to actual\nsong program execution. Bootcode can be found from this file\n`backend/src/SpcPlayer.cpp`.  Bootcode is filled up with details when whole RAM\ntransferring is in progress.  After the song starts playing the parallel line\ncommunication is dependant on the song and game. Only way to stop the song at\nthis point is just to reset whole APU itself with the reset line.\n\nOne interesting detail which change from game to game. When program is running\nand music is playing. Program is still reading for values from parallel lines.\nIf something is written there from SNES CPU side, then some sound effects are\nplayed. For example in Super Mario World Mario's jumping sound is played while\nthe song is playing.\n\n## Using Other Arduino Boads\n\nYou can also port this code to work on other Arduino boards. Keep in mind that\nWebUSB serial cannot be used with all boards. For WebUSB serial support check\n[this](https://github.com/webusb/arduino).\n\nFor porting the code to different Arduino board. Take a look at file\n`backend/src/SpcHal.cpp`. Which is Hardware Abstraction Layer (HAL) for the\nplatform. Here you can find the low level data communication functions.\nFunctions are directly using pin IO registers for speed purposes. But the\nequivalent Arduino code is also there commented out which uses `digitalRead` and\n`digitalWrite` functions. Which is much easier to understand. Note that using\n`digitalRead` and `digitalWrite` functions the song upload will be a lot slower!\n\n## Resources\n\nHere are the most important resources what I've collected over time when studying\nfor this project. I put them here in hope that someone else working on the same\nissues find them useful and don't have to waste time finding them.\n\nMost important source of information being original SNES development manual part\n1 which can be downloaded from this link:\nhttp://folk.uio.no/sigurdkn/snes/snes_manual1.pdf.\nSNES development manual most important pages include:\n* 153-179 for general sound system and DSP,\n* 180-188 for SPC700 CPU and\n* 237-240 for IPL ROM boot code procedure.\n\nDevelopment manual can be quite hard to read for the first time so that's why\nit's recommended to read following resources alongside with the manual to put\nbeef around the bones:\n\n* SPC700 reference: https://wiki.superfamicom.org/spc700-reference\n* SPC file ID666 file format: http://www.snesmusic.org/files/spc_file_format.txt\n* SPC2 v1.1 format: http://blog.kevtris.org/blogfiles/spc2_file_specification_v1.txt\n* SPC2 v1.3 format: https://www.caitsith2.com/snes/spc2_file_specification_v1.3.txt\n* ASCII based APU manual: https://web.archive.org/web/20090106230547/http://www.alpha-ii.com/snesmusic/files/spc700_apu_manual.txt\n* SPC 700 Documentation by Gau of the Veldt: http://emureview.ztnet.com/developerscorner/SoundCPU/spc.htm\n* SPC 700 programming tutorial: https://en.wikibooks.org/wiki/Super_NES_Programming/Loading_SPC700_programs\n* APU hardware: http://www.snesmusic.org/files/spc700.html\n* Anomie's in depth SPC700 documentation: http://www.romhacking.net/documents/197/\n* SNES schematics: https://wiki.superfamicom.org/schematics-ports-and-pinouts\n\nAlso when I studied for this project I used following project source code for\nstudying purposes https://www.caitsith2.com/snes/apu.htm. Which can also be\nfound from GitHub: https://github.com/emukidid/SNES_APU_SD.\n\n## Future Work\n\nCan play all songs that I've tested but most likely not all SPC files work. At\nthe moment only supports SPC file format v0.30. In future more formats could be\nsupported.\n\nIf you stumble upon anything please file an issue about it. PRs are also\nwelcome, thanks!\n\n## Deploying GitHub Pages\n\nUnder `frontend-web` run:\n\n```\nyarn build\nyarn deploy\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkazhuu%2Fspc-player","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkazhuu%2Fspc-player","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkazhuu%2Fspc-player/lists"}