{"id":18085473,"url":"https://github.com/xe/gamebridge","last_synced_at":"2025-07-17T06:07:20.810Z","repository":{"id":144741099,"uuid":"262613796","full_name":"Xe/gamebridge","owner":"Xe","description":"A simple bridge into games that use N64-style controller input","archived":false,"fork":false,"pushed_at":"2020-05-09T17:32:34.000Z","size":16,"stargazers_count":12,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-04T11:52:11.787Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","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/Xe.png","metadata":{"files":{"readme":"README.org","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,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-05-09T16:36:51.000Z","updated_at":"2022-09-14T11:35:50.000Z","dependencies_parsed_at":null,"dependency_job_id":"a73a2509-008a-43b4-b7ef-f6ecb5a383ee","html_url":"https://github.com/Xe/gamebridge","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Xe%2Fgamebridge","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Xe%2Fgamebridge/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Xe%2Fgamebridge/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Xe%2Fgamebridge/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Xe","download_url":"https://codeload.github.com/Xe/gamebridge/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248626903,"owners_count":21135758,"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-10-31T15:11:38.488Z","updated_at":"2025-04-12T20:24:20.054Z","avatar_url":"https://github.com/Xe.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"#+TITLE: gamebridge\n\nAn interface between games that take Nintendo 64 controller input and just about\nanything else your heart desires. \n\n* High level ideas\n\nThe Rust program has two threads, one is getting the inputs from (in this case\nTwitch chat) and the other is doing the file I/O to the game. The game bridge\nthread has two file descriptors open, a fifo for feeding inputs to the game and\na fifo opened by the game for signaling vblanks. The game will then write a\nreadiness signal to the rust program and read the button data fifo. Then things\nwill progress normally.\n\n** Future considerations for streaming games to a browser\n\nThe getting the input thread of the rust program *SHOULD* have some logic for\ntelling how long ago it got liveness of the input source (explicitly vaguely\ndefined to allow a controller to sit there and do nothing as long as it still\nexists), and then \"sticking\" it until, say, 10 frames have passed and then it\nwill block infinitely, freezing the game in place until the other end comes\nback.\n\n** Goals\n\n+ Use blocking I/O to have the kernel help with this\n+ Use threads to their fullest potential\n+ Unix fifos are great, let's use them\n+ Understand linear interpolation better\n+ Create a surreal demo on Twitch\n\n* Protocol\n\nThe protocol between the game and the bridge will be as follows (with input data\nbased on the [[http://tasvideos.org/EmulatorResources/Mupen/M64.html][Mupen64 demo format]]). Two unix fifos will be created by the game:\n\n+ =vblank=\n+ =input=\n\nThe game and the bridge will both need to take care that the files are opened in\n*unbuffered I/O modes*. This can be done with \n=setvbuf(f, (char *)NULL, _IONBF, 0);= in C and is the default in Rust.\n\nThe first one will be called =vblank= and will then be opened by the game in\nwrite mode when it starts. The bridge will open this fifo in read mode. \n\nThe second one will be called =input= and will be opened by the game in read\nmode. The bridge will open this fifo in write mode.\n\nOn every frame, the game *MUST* write the text =OK\\n= to the vblank fifo. This\nwill signal the bridge that it *MUST* write four bytes of data to the input\nfifo, conforming to the [[http://tasvideos.org/EmulatorResources/Mupen/M64.html#ControllerData][Controller Data]] specification of the Mupen64 format.\nThis data will be interpreted by the game as actions for Mario to take.\n\nThe bridge *MUST* block on waiting for the vblank fifo to be written to by the\ngame and the game *MUST* block on the input fifo being written to by the bridge.\n\nWhen the game is exiting, the game *SHOULD* write =BYE= to the vblank fifo.\nWhen the bridge recieves a =BYE= message, it *MUST* exit.\n\nIf the bridge recieves any message other than =OK\\n= or =BYE=, then the bridge\n*MUST* log this, as it is a bug. The bridge *MAY* crash if it is desired.\n\n* Usage instructions\n\nCurrently this is implemented with a fork of the [[https://github.com/sm64pc/sm64pc][Super Mario 64 PC Port]]. The\nneeded input bridge is implemented as a controller. You will need to get a copy\nof the git repo of the Super Mario 64 PC port and copy =controller_gamebridge.c=\nand =controller_gamebridge.h= from =contrib/sm64pc= to =src/pc/controller=. Then\napply =gamebridge_config.patch= to the source code with =git apply=. You may\nalso want to apply =gamebridge_no_lives.patch=, as this disables the extra life\nsystem. Removing the number of lives on the screen is currently a work in\nprogress.\n\n** Configuring gamebridge\n\nYou will require the following things:\n\n+ A [[https://twitch.tv][Twitch.tv]] account for this bot\n+ An [[https://twitchapps.com/tmi/][OAuth token]] for the bot to log into chat\n+ The twitch channel chatroom to listen for commands in\n\nYou will need to copy the gamebridge binary to somewhere in your =$PATH=. You\nwill also need to create a file called =.env= with the following variables:\n\n#+BEGIN_SRC sh\nTWITCH_NICK=yourbotnamehere\nTWITCH_PASS=oauth:foofoobutslol\nTWITCH_CHANNEL=yourchannelnamehere\n#+END_SRC\n\nRun the Super Mario 64 PC port at least once. This will create =sm64config.txt=\nin your current working directory (if it doesn't already exist). Open that file\nwith your favorite text editor and replace:\n\n#+BEGIN_SRC\ngamebridge false\n#+END_SRC\n\nwith:\n\n#+BEGIN_SRC\ngamebridge true\n#+END_SRC\n\nNow you will be able to run the game as normal and inputs to the game will be\nhandled by Twitch chat.\n\n** Chat commands\n\ngamebridge emulates an analog stick with chat commands. The commands that are\ncurrently recognized are:\n\n| Command  | Meaning                          |\n|----------+----------------------------------|\n| =a=      | Press the A button               |\n| =b=      | Press the B button               |\n| =z=      | Press the Z button               |\n| =r=      | Press the R button               |\n| =cup=    | Press the C-up button            |\n| =cdown=  | Press the C-down button          |\n| =cleft=  | Press the C-left button          |\n| =cright= | Press the C-right button         |\n| =start=  | Press the start button           |\n| =up=     | Press up on the analog stick     |\n| =down=   | Press down on the analog stick   |\n| =left=   | Press left on the analog stick   |\n| =stop=   | Reset the analog stick to center |\n\nChat messages, joins and parts are shown on standard error. The output of this\nprogram is safe to show on stream.\n\n** Analog stick considerations\n\nCurrently analog stick inputs will stick for about 270 frames and button inputs\nwill stick for about 20 frames before drifting back to neutral. The start button\nis special however. Inputs to the start button will stick for 5 frames at most. \n\n** Logging Levels\n\nTo change the logging detail of gamebridge, set the =RUST_LOG= environment\nvariable [[https://docs.rs/env_logger/0.7.1/env_logger/#example][according to the =env_logger= crate's documentation]].\n=RUST_LOG=gamebridge=debug= will dump all of the input data (in hex format) as\nwell as details about some of the linear interpolation (lerp) math.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxe%2Fgamebridge","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxe%2Fgamebridge","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxe%2Fgamebridge/lists"}