1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
//! gc_nes_web wraps the public functions exposed by my gc_nes_core crate for use //! in the browser through Web Assembly - Javascript interop. It provides an interface //! to load and run NES ROMs, provide input, and extract rendered image data. //! Audio is currently unsupported. //! //! ### Install in an NPM Project //! `npm install gc_nes_web` //! //! ### Using the NES Emulator with Javascript //! ```javascript //! // Import the package //! const wasm = await import ("gc_nes_web"); //! // Create the NES object //! let nes = this.state.wasm.nes(romArrayOfBytes); //! // Run the emulator to the completion of the next frame and retrieve it //! let frame = nes.frame(); //! // Or run just one cycle and get the frame separately //! nes.cycle(); //! let frame = nes.get_screen(); //! // Drawing to a Canvas //! let offscreenCanvas = new OffscreenCanvas(256, 240); //! let offscreenCanvasContext = offscreenCanvas.getContext("2d"); //! let imageData = offscreenCanvasContext?.createImageData(256, 240); //! imageData.data.set(frame); //! offscreenCanvasContext.putImageData(imageData, 0, 0); //! // mainCanvasContext is the 2D context for the Canvas you actually want to draw to. //! mainCanvasContext.drawImage(offscreenCanvas, 0, 0); //! ``` //! //! Through [wasm-pack](https://github.com/rustwasm/wasm-pack), gc_nes_web has full Typescript support //! //! ### Try it Now //! //! You can try out gc_nes_emulator on my website, at https://garettcooper.com/#/nes-emulator mod utils; use gc_nes_core::cartridge::Cartridge; use gc_nes_core::nes::{Nes, NES_SCREEN_DIMENSIONS}; use wasm_bindgen::prelude::*; // When the `wee_alloc` feature is enabled, use `wee_alloc` as the global // allocator. #[cfg(feature = "wee_alloc")] #[global_allocator] static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; #[wasm_bindgen] /// Structure used the represent the NES itself in WASM. pub struct WebNes { nes: Nes, } #[wasm_bindgen] impl WebNes { /// Creates a new NES instance with no connected controllers. pub fn new(cartridge: WebCartridge) -> WebNes { WebNes { nes: Nes::new(cartridge.cartridge), } } /// Runs a single cycle on the NES pub fn cycle(&mut self) { self.nes.cycle(); } /// Runs as many cycles as necessary to complete the current frame. /// Returns the frame as a Vector of bytes, with each pixel of the /// NES screen represented by four bytes in RGBA order. pub fn frame(&mut self) -> Vec<u8> { self.nes.frame().to_vec() } /// Gets the current state of the screen from the PPU's screen buffer. /// Returns the frame as a Vector of bytes, with each pixel of the /// NES screen represented by four bytes in RGBA order. pub fn get_screen(&mut self) -> Vec<u8> { self.nes.get_screen().to_vec() } /// Updates the state of the input device connected to the first port. pub fn update_controller_one(&mut self, controller_state: u8) { self.nes.update_controller_one(Some(controller_state)); } /// Updates the state of the input device connected to the first port. pub fn update_controller_two(&mut self, controller_state: u8) { self.nes.update_controller_one(Some(controller_state)); } /// Resets the state of the NES. pub fn reset(&mut self) { self.nes.reset(); } } #[wasm_bindgen] /// Structure used to represent a NES Cartridge in WASM. pub struct WebCartridge { cartridge: Cartridge, } #[wasm_bindgen] impl WebCartridge { /// Loads a NES ROM from an array of bytes into a WebCartridge struct pub fn load(rom: &[u8]) -> WebCartridge { WebCartridge { cartridge: Cartridge::load_from_reader(rom).unwrap(), } } } #[wasm_bindgen] /// Creates a new NES instance, loading the passed array of bytes as the ROM pub fn nes(rom: &[u8]) -> WebNes { WebNes::new(WebCartridge::load(rom)) } #[wasm_bindgen] /// Gets the screen dimensions of the NES pub fn get_screen_dimensions() -> usize { NES_SCREEN_DIMENSIONS } #[wasm_bindgen] /// Enables the panic hook that logs panic messages to the browser console pub fn set_panic_hook() { utils::set_panic_hook() }