Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Basic shell example. #219

Closed
slembcke opened this issue Nov 12, 2018 · 2 comments
Closed

Basic shell example. #219

slembcke opened this issue Nov 12, 2018 · 2 comments

Comments

@slembcke
Copy link
Contributor

This came up on the NESDev forums recently here:
http://forums.nesdev.com/viewtopic.php?f=10&t=18018&p=228777#p228777

It would be really awesome to use jsnes to embed homebrew NES games in a webpage. For non-webdevs, the usage documentation is reminiscent of the "first draw a circle, then draw everything else" joke. I don't mind digging into assembly code or compute shaders, but I spent longer than I'd like to admit staring at a blank screen here. :-\

If there was a minimal example shell embedded in a single HTML file that set up a canvas and ran the IO loop that would be incredibly helpful. Otherwise the only example you have is written in a separate language, and requires installing a rather lot of tooling.

@bfirsh
Copy link
Owner

bfirsh commented Nov 12, 2018

Yes! I really want to do this, but unfortunately I haven't got the time right now. If others want to write this, it would be very welcome as a contribution.

Here is an email I actually just sent to another dev, which has some clues about how to do this:


You're right - it isn't documented clearly. I really want to make JSNES work well for homebrew devs, so I would love to document this better. Unfortunately I haven't got the time right now to write some proper documentation, but in the meantime I shall attempt to point you in the right direction.

This is the chunk of code for writing to the screen. this.canvas, is just a <canvas> element, which you can create with document.createElement("canvas") outside of React. setBuffer() is called by onFrame. In that function you can see how the buffer is converted into canvas's format. writeBuffer() actually writes the buffer to the canvas element, which is separated out in case clients aren't running at 60 FPS. For simplicity, you can assume all devices are 60 FPS (most are) and run the writeBuffer() function at the same time.

So, in short, onFrame should call something resembling the setBuffer() function, and then the writeBuffer() function.

This is the code for handling audio samples. onAudioSample points at writeSample(). There's nothing React in there so you could lift it wholesale. To keep the audio smooth and click-free, it maintains a ring buffer. You might be to do something simpler if you don't care so much about audio quality.

Then, last bit to piece it together is calling nes.frame() 60 times a second. requestAnimationFrame is the easy way to do this, if you're happy assuming clients are running at 60 FPS.

Does that help? Let me know if you need any other pointers. It would be great to have a generalised solution for embedding a simple version of JSNES for homebrew devs... let me know if you'd be interested on collaborating on something like that. :)

@bfirsh
Copy link
Owner

bfirsh commented Nov 12, 2018

Here is the entrypoint for the emulator in jsnes-web, which has lots of clues about how to do it. You can probably use this React component standalone to run the emulator: https://github.com/bfirsh/jsnes-web/blob/master/src/RunPage.js

An idea, for anyone who is interested: if the code in RunPage.js were abstracted into another component which just took the URL to a ROM (or the file in the case of an upload) then it could be embedded like this:

<div id="nes"></div>
<script>
ReactDOM.render(
  React.createElement(Emulator, {romURL: 'roms/foo.nes'}, null),
  document.getElementById('nes')
);
</script>

Still requires React, but a heck of a lot easier than implementing from scratch. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants