SDL2 bindings for Rust

Related tags

Emulators rust-sdl2
Overview

Rust-SDL2 Build Status crates.io badge

Bindings for SDL2 in Rust

Changelog for 0.35.0

Overview

Rust-SDL2 is a library for talking to the new SDL2.0 libraries from Rust. Low-level C components are wrapped in Rust code to make them more idiomatic and abstract away inappropriate manual memory management.

Rust-SDL2 uses the MIT license.

If you want a library compatible with earlier versions of SDL, please see here

Documentation

The following features are enabled in the documentation:

  • gfx
  • image
  • mixer
  • ttf

The unsafe_textures feature is not documented online, you can use cargo doc to generate your own documentation with this feature enabled.

Requirements

Rust

We currently target the latest stable release of Rust.

SDL2.0 development libraries

SDL2 >= 2.0.8 is recommended to use these bindings, but note that SDL2 >= 2.0.5 is also supported. Below 2.0.5, you may experience link-time errors as some functions are used here but are not defined in SDL2. If you experience this issue because you are on a LTS machine (for instance, Ubuntu 12.04 or Ubuntu 14.04), we definitely recommend you to use the feature "bundled" which will compile the lastest stable version of SDL2 for your project.

"Bundled" Feature

Since 0.31, this crate supports a feature named "bundled" which compiles SDL2 from source and links it automatically. While this should work for any architecture, you will need a C compiler (like gcc, clang, or MS's own compiler) to use this feature properly.

By default, macOS and Linux only load libraries from system directories like /usr/lib. If you wish to distribute the newly built libSDL2.so/libSDL2.dylib alongside your executable, you will need to add rpath to your executable. Add the following line to build.rs script:

  • on macOS:
    println!("cargo:rustc-link-arg=-Wl,-rpath,@loader_path");
  • on Linux:
    println!("cargo:rustc-link-arg=-Wl,-rpath,$ORIGIN");

Linux

Install these through your favourite package management tool, or via http://www.libsdl.org/

Ubuntu example:

sudo apt-get install libsdl2-dev

Fedora example:

sudo dnf install SDL2-devel

Arch example:
(Arch doesn't have separate regular and development packages, everything goes together.)

sudo pacman -S sdl2

You might also need a C compiler (gcc).

Static linking in Linux

You can choose to link SDL2 statically instead of dynamically with the static-link feature. On Linux, you will need to additionally do one of the following:

  • use the bundled feature
  • use the feature use-pkgconfig so that rustc knows where to look for your SDL2 libraries and its dependencies for static linking. This is required because there is no built-in way to find the resources needed to link statically SDL2 from your system
  • install development libraries with vcpkg. Instructions to generate a static binary on Linux and other operating systems using vcpkg are here

macOS

Homebrew

On macOS, it's a good idea to install these via homebrew.

brew install sdl2

In recent versions of Homebrew, the installed libraries are usually linked into $(brew --prefix)/lib. If you are running an older version, the symlink for SDL might reside in /usr/local/lib.

To make linking libraries installed by Homebrew easier, do the following for your respective shell.

Add this line to your ~/.zshenv or ~/.bash_profile depending on whether you use ZSH or Bash.

export LIBRARY_PATH="$LIBRARY_PATH:$(brew --prefix)/lib"

MacPorts

You can also get sdl2 via macports.

sudo port install libsdl2

Then add the following to your ~/.bash_profile if not already present.

export LIBRARY_PATH="$LIBRARY_PATH:/opt/local/lib/"

If you're having issues with either Homebrew or MacPorts, see here.

If you are using the SDL2 framework

You can download and install the SDL2 Mac OS X framework from: https://www.libsdl.org/download-2.0.php

To make the sdl2 crate link with the SDL2 framework, you will need to enable the use_mac_framework feature. To build and test the sdl2 crate with this feature, use:

cargo test --features use_mac_framework

To depend on the sdl2 crate with this feature enabled, put the following in your project's Cargo.toml file:

[dependencies.sdl2]
features = ["use_mac_framework"]
version = ...  # Whichever version you are using

Alternatively, you can re-export the feature in your package by putting the following in your Cargo.toml file:

[features]
default = []
use_sdl2_mac_framework = ["sdl2/use_mac_framework"]

Static linking on macOS using vcpkg

Instructions to generate a static binary on macOS and other operating systems using vcpkg are here.

Windows (MSVC)

  1. Download MSVC development libraries from http://www.libsdl.org/ (SDL2-devel-2.0.x-VC.zip).

  2. Unpack SDL2-devel-2.0.x-VC.zip to a folder of your choosing (You can delete it afterwards).

  3. Copy all lib files from

    SDL2-devel-2.0.x-VC\SDL2-2.0.x\lib\x64\

    to (for Rust 1.6 and above)

    C:\Program Files\Rust\lib\rustlib\x86_64-pc-windows-msvc\lib

    or to (for Rust versions 1.5 and below)

    C:\Program Files\Rust\bin\rustlib\x86_64-pc-windows-msvc\lib

    or to your library folder of choice, and ensure you have a system environment variable of

    LIB = C:\your\rust\library\folder

    For Rustup users, this folder will be in

    C:\Users\{Your Username}\.rustup\toolchains\{current toolchain}\lib\rustlib\{current toolchain}\lib

Where current toolchain is likely stable-x86_64-pc-windows-msvc.

  1. Copy SDL2.dll from

    SDL2-devel-2.0.x-VC\SDL2-2.0.x\lib\x64\

    into your cargo project, right next to your Cargo.toml.

  2. When you're shipping your game make sure to copy SDL2.dll to the same directory that your compiled exe is in, otherwise the game won't launch.

Static linking with MSVC

The MSVC development libraries provided by http://libsdl.org/ don't include a static library. This means that if you want to use the static-link feature with the windows-msvc toolchain, you have to do one of

  • build an SDL2 static library yourself and copy it to your toolchain's lib directory; or
  • also enable the bundled feature, which will build a static library for you; or
  • use a static SDL2 library from vcpkg as described below.

Windows (MinGW)

  1. Download mingw development libraries from http://www.libsdl.org/ (SDL2-devel-2.0.x-mingw.tar.gz).

  2. Unpack to a folder of your choosing (You can delete it afterwards).

  3. Copy all lib files from

    SDL2-devel-2.0.x-mingw\SDL2-2.0.x\x86_64-w64-mingw32\lib

    to (for Rust 1.6 and above)

    C:\Program Files\Rust\lib\rustlib\x86_64-pc-windows-gnu\lib

    or to (for Rust versions 1.5 and below)

    C:\Program Files\Rust\bin\rustlib\x86_64-pc-windows-gnu\lib

    or to your library folder of choice, and ensure you have a system environment variable of

    LIBRARY_PATH = C:\your\rust\library\folder

    For Rustup users, this folder will be in

    C:\Users\{Your Username}\.rustup\toolchains\{current toolchain}\lib\rustlib\{current toolchain}\lib

Where current toolchain is likely stable-x86_64-pc-windows-gnu.

  1. Copy SDL2.dll from

    SDL2-devel-2.0.x-mingw\SDL2-2.0.x\x86_64-w64-mingw32\bin

    into your cargo project, right next to your Cargo.toml.

  2. When you're shipping your game make sure to copy SDL2.dll to the same directory that your compiled exe is in, otherwise the game won't launch.

Static linking with MinGW

If you want to use the static-link feature with the windows-gnu toolchain, then you will also need the following libraries:

libimm32.a
libversion.a
libdinput8.a
libdxguid.a

These files are not currently included with the windows-gnu toolchain, but can be downloaded here. For the x86_64 toolchain, you want the x86_64-win32-seh package, and for i686 you want the i686-win32-dwarf one.

You will find the aforementioned libraries under mingw64/x86_64-w64-mingw32/lib/ (for x86_64) or mingw32/i686-w64-mingw32/lib/ (for i686). Copy them to your toolchain's lib directory (the same one you copied the SDL .a files to).

Windows with build script

  1. Download mingw and msvc development libraries from http://www.libsdl.org/ (SDL2-devel-2.0.x-mingw.tar.gz & SDL2-devel-2.0.x-VC.zip).
  2. Unpack to folders of your choosing (You can delete it afterwards).
  3. Create the following folder structure in the same folder as your Cargo.toml:
gnu-mingw\dll\32
gnu-mingw\dll\64
gnu-mingw\lib\32
gnu-mingw\lib\64
msvc\dll\32
msvc\dll\64
msvc\lib\32
msvc\lib\64
  1. Copy the lib and dll files from the source archive to the directories we created in step 3 like so:
SDL2-devel-2.0.x-mingw.tar.gz\SDL2-2.0.x\i686-w64-mingw32\bin 		-> 	gnu-mingw\dll\32
SDL2-devel-2.0.x-mingw.tar.gz\SDL2-2.0.x\x86_64-w64-mingw32\bin 	-> 	gnu-mingw\dll\64
SDL2-devel-2.0.x-mingw.tar.gz\SDL2-2.0.x\i686-w64-mingw32\lib 		-> 	gnu-mingw\lib\32
SDL2-devel-2.0.x-mingw.tar.gz\SDL2-2.0.x\x86_64-w64-mingw32\lib 	-> 	gnu-mingw\lib\64
SDL2-devel-2.0.8-VC.zip\SDL2-2.0.x\lib\x86\*.dll	 		-> 	msvc\dll\32
SDL2-devel-2.0.8-VC.zip\SDL2-2.0.x\lib\x64\*.dll 			-> 	msvc\dll\64
SDL2-devel-2.0.8-VC.zip\SDL2-2.0.x\lib\x86\*.lib	 		-> 	msvc\lib\32
SDL2-devel-2.0.8-VC.zip\SDL2-2.0.x\lib\x64\*.lib	 		-> 	msvc\lib\64
  1. Create a build script, if you don't already have one put this in your Cargo.toml under [package]:

build = "build.rs"

  1. Create a file in the same directory as Cargo.toml called build.rs (if you didn't already have a build script) and paste this into it:
use std::env;
use std::path::PathBuf;

fn main() {
    let target = env::var("TARGET").unwrap();
    if target.contains("pc-windows") {
        let manifest_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
        let mut lib_dir = manifest_dir.clone();
        let mut dll_dir = manifest_dir.clone();
        if target.contains("msvc") {
            lib_dir.push("msvc");
            dll_dir.push("msvc");
        }
        else {
            lib_dir.push("gnu-mingw");
            dll_dir.push("gnu-mingw");
        }
        lib_dir.push("lib");
        dll_dir.push("dll");
        if target.contains("x86_64") {
            lib_dir.push("64");
            dll_dir.push("64");
        }
        else {
            lib_dir.push("32");
            dll_dir.push("32");
        }
        println!("cargo:rustc-link-search=all={}", lib_dir.display());
        for entry in std::fs::read_dir(dll_dir).expect("Can't read DLL dir")  {
            let entry_path = entry.expect("Invalid fs entry").path();
            let file_name_result = entry_path.file_name();
            let mut new_file_path = manifest_dir.clone();
            if let Some(file_name) = file_name_result {
                let file_name = file_name.to_str().unwrap();
                if file_name.ends_with(".dll") {
                    new_file_path.push(file_name);
                    std::fs::copy(&entry_path, new_file_path.as_path()).expect("Can't copy from DLL dir");
                }
            }
        }
    }
}
  1. On build the build script will copy the needed DLLs into the same directory as your Cargo.toml, you probably don't want to commit these to any Git repositories though so add the following line to your .gitignore file

/*.dll

  1. When you're publish your game make sure to copy the corresponding SDL2.dll to the same directory that your compiled exe is in, otherwise the game won't launch.

And now your project should build and run on any Windows computer!

Windows (MSVC with vcpkg)

  1. Install MS build tools and vcpkg
  2. Install the needed SDL2 libs: vcpkg.exe install sdl2-ttf:x64-windows sdl2:x64-windows
  3. Open a x64 native tools prompt (x64 Native Tools Command Prompt for VS 2019)
  4. set env vars:
SET PATH=%PATH%;C:\Users\my_user\dev\vcpkg\installed\x64-windows\bin
SET INCLUDE=%INCLUDE%;C:\Users\my_user\dev\vcpkg\installed\x64-windows\include
SET LIB=%LIB%;C:\Users\my_user\dev\vcpkg\installed\x64-windows\lib
  1. cargo build

Windows, Linux and macOS with vcpkg

Another method of getting the development libraries is with vcpkg. To set up a project to build a static binary on Windows (MSVC), Linux or macOS that is buildable like this:

cargo install cargo-vcpkg
cargo vcpkg build
cargo build

add the following your Cargo.toml:

[dependencies.sdl2]
version = "0.35"
default-features = false
features = ["ttf","image","gfx","mixer","static-link","use-vcpkg"]

[package.metadata.vcpkg]
dependencies = ["sdl2", "sdl2-image[libjpeg-turbo,tiff,libwebp]", "sdl2-ttf", "sdl2-gfx", "sdl2-mixer"]
git = "https://github.com/microsoft/vcpkg"
rev = "261c458af6e3eed5d099144aff95d2b5035f656b"

[package.metadata.vcpkg.target]
x86_64-pc-windows-msvc = { triplet = "x64-windows-static-md" }

More information on the cargo vcpkg tool is here.

Installation

If you're using cargo to manage your project, you can download through Crates.io:

    [dependencies]
    sdl2 = "0.35"

Alternatively, pull it from GitHub to obtain the latest version from master

    [dependencies.sdl2]
    git = "https://github.com/rust-sdl2/rust-sdl2"

Otherwise, clone this repo and run cargo

cargo build

You can enable features such as ttf, image, gfx and mixer by adding this instead:

    [dependencies.sdl2]
    version = "0.35"
    default-features = false
    features = ["ttf","image","gfx","mixer"]

Those features need their respective libraries, which can be found at these locations : (the install process is the same as SDL2)

What about sdl2_net ?

As of now, sdl2_net is meaningless compared to what other crates such as serde and bincode can offer. We highly recommend using those to develop anything UDP or TCP related (along with futures or TCP/UDP from the standard library).

If you still want an implementation of sdl2_net, you can try to add it in this repo as a feature via a Pull Request. A somewhat outdated version of this binding can be found here

Demo

We have several simple example projects included:

cargo run --example demo

You can see the full list in the examples/ folder. Some examples require some features, you can enable them like so:

cargo run --example gfx-demo --features "gfx"

Replace "gfx" by the feature(s) needed for the example you want.

About the unsafe_textures feature

In the sdl2::render module, Texture has by default lifetimes to prevent it from out-living its parent TextureCreator. These lifetimes are sometimes too hard to deal with in Rust, and so you have the option to enable the unsafe_textures feature.

This removes the lifetimes on the Textures, at the cost of optional manual memory management. If you want to manually destroy the Textures you use, you can call the destroy method of your Textures, but beware that it should not be called if none of the parents (Canvas or TextureCreator) are alive. If you do not call this method, the memory will simply be freed when the last Canvas or the last TextureCreator will be freed.

There is no online documentation for this feature, however you can build it yourself in your project by enabling the feature in your Cargo.toml, running cargo doc and accessing target/doc/sdl2/index.html via a browser.

Generating sdl2-sys with bindgen

The sdl2-sys that was generated for this crate is very generic and can be used on a lot of platforms with very few limitations. However, you may sometimes face trouble when using platform-specific features of SDL2, for instance the WindowManager category.

The feature "use-bindgen" allows you to avoid this limitation by generating the proper bindings depending on your target. It will take the headers based on what pkg-config outputs (if you enabled the feature "use-pkg-config") and generate bindings based on them. If you don't have pkg-config or disabled the feature, it will try to get the headers in SDL-2.0.8/include of this crate instead.

If somehow you have your own headers that you want to use (use a beta version, an older version, ...), you can set the environment variable "SDL2_INCLUDE_PATH" and those headers will be used by bindgen instead.

Using sdl2-sys to provide SDL2 headers/library

If you are creating a *-sys crate for a library which requires SDL2, you can use sdl2-sys to provide both the compiled library and the headers for SDL2.

Follow the following process to get the header directory. In the Cargo.toml for your crate, add sdl2-sys as a dependency (not a build-dependency). Cargo will then provide your build script with an environment variable DEP_SDL2_INCLUDE which is populated with the include directory for SDL2. If there is more than one directory, they are combined with : as a separator. Pass these directories to whatever is building your C/C++.

Once everything is linked together, there will be a single copy of SDL2 (the one provided by sdl2-sys) for all C, C++, and Rust code.

For more discussion see the corresponding issue

OpenGL

There are two ways to use OpenGL:

  • As a backend for sdl2::render, where everything is done for you by sdl2. It is the default for linux devices.
  • Manually, using only sdl2 as a "shell" for your window (akin to glutin and winit crates), and still use sdl2's joystick, events, audio, text input, ect capabilities.

If you want to use OpenGL, you also need the gl-rs package. If you're using cargo, just add these lines to your Cargo.toml:

    [dependencies.gl]
    git = "https://github.com/bjz/gl-rs"

You have two options to use OpenGL with sdl2:

  • Use OpenGL with Canvas and use sdl2::render
  • Use OpenGL directly on the Window "shell" and use manual OpenGL calls to render something

Use sdl2::render

First, find the OpenGL driver from SDL:

fn find_sdl_gl_driver() -> Option<u32> {
    for (index, item) in sdl2::render::drivers().enumerate() {
        if item.name == "opengl" {
            return Some(index as u32);
        }
    }
    None
}

fn main() {
    let sdl_context = sdl2::init().unwrap();
    let video_subsystem = sdl_context.video().unwrap();
    let window = video_subsystem.window("Window", 800, 600)
        .opengl() // this line DOES NOT enable opengl, but allows you to create/get an OpenGL context from your window.
        .build()
        .unwrap();
    let canvas = window.into_canvas()
        .index(find_sdl_gl_driver().unwrap())
        .build()
        .unwrap();

    // ...
}

If you don't plan to use OpenGL calls via the gl-rs crate, you can stop here. SDL2 will automatically use the OpenGL backend

If you plan to have your own calls intertwined with the sdl2 calls, you need to use the context of your canvas first:

// initialization
gl::load_with(|name| video_subsystem.gl_get_proc_address(name) as *const _);

// sdl::render creates a context for you, if you use a Canvas you need to use it.
canvas.window().gl_set_context_to_current();

// ... in the main loop ...
unsafe {
    gl::ClearColor(0.6, 0.0, 0.8, 1.0);
    gl::Clear(gl::COLOR_BUFFER_BIT);
}
canvas.present();

Be wary though, sdl2 has its own internal state which you should avoid messing with. Avoid using manual OpenGL in the middle of SDL2 calls, or make sure to restore the previous state.

Use OpenGL calls manually

extern crate sdl2;
extern crate gl;

use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::video::GLProfile;

fn main() {
    let sdl_context = sdl2::init().unwrap();
    let video_subsystem = sdl_context.video().unwrap();
    
    let gl_attr = video_subsystem.gl_attr();
    gl_attr.set_context_profile(GLProfile::Core);
    gl_attr.set_context_version(3, 3);

    let window = video_subsystem.window("Window", 800, 600)
        .opengl()
        .build()
        .unwrap();

    // Unlike the other example above, nobody created a context for your window, so you need to create one.
    let ctx = window.gl_create_context().unwrap();
    gl::load_with(|name| video_subsystem.gl_get_proc_address(name) as *const _);
    
    debug_assert_eq!(gl_attr.context_profile(), GLProfile::Core);
    debug_assert_eq!(gl_attr.context_version(), (3, 3));

    let mut event_pump = sdl_context.event_pump().unwrap();

    'running: loop {
        unsafe {
            gl::ClearColor(0.6, 0.0, 0.8, 1.0);
            gl::Clear(gl::COLOR_BUFFER_BIT);
        }

        window.gl_swap_window();
        for event in event_pump.poll_iter() {
            match event {
                Event::Quit {..} | Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
                    break 'running
                },
                _ => {}
            }
        }
        ::std::thread::sleep(::std::time::Duration::new(0, 1_000_000_000u32 / 60));
    }
}

As mentionned above, this method is useful when you don't care about sdl2's render capabilities, but you do care about its audio, controller and other neat features that sdl2 has.

You don't have to worry about messing with the state intertwined with sdl2 or a version you don't like: SDL2 will never call any OpenGL function outside the render module.

Vulkan

To use Vulkan, you need a Vulkan library for Rust. This example uses the Vulkano library. Other libraries may use different data types for raw Vulkan object handles. The procedure to interface SDL2's Vulkan functions with these will be different for each one.

extern crate sdl2;
extern crate vulkano;

use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::video::VkInstance;
use std::ffi::CString;
use vulkano::instance::{Instance, InstanceExtensions};
use vulkano::swapchain::Surface;
use vulkano::{Handle, Version, VulkanObject};

fn main() {
    let sdl_context = sdl2::init().unwrap();
    let video_subsystem = sdl_context.video().unwrap();

    let window = video_subsystem.window("Window", 800, 600)
        .vulkan()
        .build()
        .unwrap();

    let instance_extensions_strings: Vec<CString> = window
        .vulkan_instance_extensions()
        .unwrap()
        .iter()
        .map(|&v| CString::new(v).unwrap())
        .collect();
    let instance_extension =
        InstanceExtensions::from(instance_extensions_strings.iter().map(AsRef::as_ref));
    let instance = Instance::new(None, Version::V1_2, &instance_extension, None).unwrap();
    let surface_handle = window
        .vulkan_create_surface(instance.internal_object().as_raw() as VkInstance)
        .unwrap();
    let surface = unsafe {
        Surface::from_raw_surface(instance, Handle::from_raw(surface_handle), window.context())
    };

    let mut event_pump = sdl_context.event_pump().unwrap();

    'running: loop {
         for event in event_pump.poll_iter() {
            match event {
                Event::Quit {..} | Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
                    break 'running
                },
                _ => {}
            }
        }
        ::std::thread::sleep(::std::time::Duration::new(0, 1_000_000_000u32 / 60));
    }
}

Support for raw-window-handle

raw-window-handle can be enabled using the feature name:

[dependencies.sdl2]
version = "0.32"
features = ["raw-window-handle"]

An example working with wgpu is also available:

cargo run --example raw-window-handle-with-wgpu --features raw-window-handle

sdl2 with raw-window-handle on macOS:

On macOS the RawWindowHandle.ns_view field is returned null. Libraries consuming the RawWindowHandle (such as wgpu) should determine a sane default for ns_view. If they do not, please file an issue with the associated project.

raw-window-handle on Android

On some platforms, including Android, SDL2 tries to create the OpenGL context by itself even without creating a renderer. This can manifest in errors like VK_ERROR_NATIVE_WINDOW_IN_USE_KHR when initializing Vulkan or GLES. Add the following code before creating a window to fix the errors:

sdl2::hint::set("SDL_VIDEO_EXTERNAL_CONTEXT", "1")

When things go wrong

Rust, and Rust-SDL2, are both still heavily in development, and you may run into teething issues when using this. Before panicking, check that you're using the latest version of both Rust and Cargo, check that you've updated Rust-SDL2 to the latest version, and run cargo clean. If that fails, please let us know on the issue tracker.

Contributing

Any Pull Request is welcome, however small your contribution may be ! There are, however, conditions to contribute:

  • New features must be properly documented, be it via examples or inline documentation (via cargo doc). Documentation must be for the end user as well as your next fellow contributor.
  • Breaking changes must have a proper argumentation with it. While the pre-1.0 state of this crate allows us to be somewhat unstable, useless breaking changes will be denied.
  • Minor changes, breaking changes and new features added via Pull Request must be added in the changelog file. It is now mandatory to log your changes in the changelog. A short description with a link to your commit/pull request within GitHub is fine. Internal, documentation or meta-changes (travis build change, README instructions updates, ...) don't have to be added in the changelog.
Comments
  • Split renderer

    Split renderer

    This is my initial attempt at separating the LoadTexture (from the image feature) from the rest of the renderer. A lot of the changes are just rustfmt doing it's business as I coded away. It addresses #630

    All tests pass, and all the examples run (the only example I could not run on my machine was the audio-queue-square-wave since it requires SDL2.0.4 and I have 2.0.0 but I did not change anything on the audio feature I am confident that it works.

    Pros of my current approach:

    • The SDL image context is now required for loading images, which means that we will not accidentally try to load an image after this context has been dropped.
    • LoadImage is separate from the rendering functions which allows the user to create a ResourceManager that holds the ImageLoader (the sdl image context) without blocking the rendering functions.

    Cons:

    • Lifetimes went up. Both the Renderer and the Sdl2ImageContext hold a reference to the RenderContext which means that they now introduce a explicit lifetime.
    • The users has to explicitely keep a hold of the RenderContext since neither the Renderer nor the Sdl2ImageContext own it. An alternative would be holding an Rc<RenderContext> which would get rid of the lifetime, and it won't force the user to hold the context just to keep it alive. A con to this would be having to store it in an Rc.

    I tried to touch as little actual code as possible so the Renderer currently is still in charge of other texture creation methods. This could possibly also be moved but I wanted to get a WIP out first for review.

    I would also like to get rid of the is_alive param that exists in the Texture and the RenderContext. This could possibly be done by using a lifetime similarly to how Font Loading works? The downside would be the added complexity that explicit lifetimes entail. From my experience Font Loading and caching were also a little hard to deal with. That being said it might be worth to standardize how we handle checking that the context is alive (lifetime vs the is_alive check).

    I am open for any thoughts or nits to touch up on.

    opened by nrxus 69
  • Introducing bindgen

    Introducing bindgen

    In order to fix #694 and others I've tried to replace sdl2-sys with a bindgen dynamically generated -sys crate. In the sdl2 crate only one method has changed (data1 and data2 of event::Event::User are now ::std::os::raw::c_void instead of ::libc::c_void), so the API practically hasn't changed. The sdl2-sys crate has an almost completely new API (begin now generated by bindgen). For now I don't feel like the other sdl related libraries (TTF, Mixer, Image and GFX) should be integrated in the sdl2-sys crate with this PR; maybe this will happen with a future one. sdl2 pass all the tests, and sdl2-sys pass all the bindgen generated tests. The examples which work on master (for some reason animation.rs doesn't work on my machine) also work with this PR.

    opened by dariost 23
  • Copy SDL2_image as an optional feature

    Copy SDL2_image as an optional feature

    This adds SDL2_image as an example for #233. Enabling this in a project is as easy as adding this to your Cargo.toml:

    [dependencies.sdl2]
    features = ["image"]
    

    The extension source has been added under src/sdl2_image. This is not required but, without it there is a circular dependency and adding the crate via the path directive gets around this. If a sys or ll crate is created for all the direct ffi, then all of the primary crates could depend on this and the circle would be broken.

    My motivation for doing this would be to encourage a consistent & working API for the extensions, so moving the source is desirable from my point of view.

    opened by jdeseno 22
  • Texture and texture creator

    Texture and texture creator

    Hello, First of all I am sorry for the newbee question.

    I have some trouble to understand how I can manage the Texture and the Texture creator.

    I am stuck with the lifetime of the texture. So for the moment I do something like the code bellow to get a texture, but I have to do it at each iteration of my game loop. I have the feeling that is not the way it have to be used.

    /// Example of how I create a texture
    let map_loader = sdl2::rwops::RWops::from_file(Path::new("assets/Overworld.png"), "r").unwrap();
    let surface: Surface = map_loader.load_png().unwrap();
    let texture = self.creator.create_texture_from_surface(&surface).unwrap();
    

    So basically I wanted to have a structure that own some information (such as the texture for example) the GameScene:

    pub struct GameScene<'a> {
        creator: sdl2::render::TextureCreator<sdl2::video::WindowContext>,
        /// I would create a texture once and store it.
        texture: sdl2::render::Texture<'a>,
       /** Other objects **/
    }
    

    So here it is, the code bellow does not compile because the creator outlives the texture. I have no clue of how to do such a things, I did some attempts:

    struct TextureHolder<'a> {
        creator: &'a sdl2::render::TextureCreator<sdl2::video::WindowContext>,
        texture: sdl2::render::Texture<'a>
    }
    
    pub struct GameScene<'a> {
        creator: sdl2::render::TextureCreator<sdl2::video::WindowContext>,
        texture: TextureHolder<'a>
    }
    

    The code above would allows me to have a texture and its creator bounded to the same lifetime But when I am creating a GameScene with the following code

    
    let creator = canvas.texture_creator();
    let textureHolder = TextureHolder {
        creator: &creator,
        texture: creator.create_texture_from_surface(&surface).unwrap()
    };
    
    GameScene{
        /// I have to find someone to own my creator.
        creator: creator,
        grid: grid,
        map: map,
        /// So this 
        textureHolder : textureHolder 
    }
    

    I've got the error :

    error: `creator` does not live long enough
       --> src\scene.rs:95:23
        |
    95  |             creator: &creator,
        |                       ^^^^^^^ does not live long enough
    ...
    105 |     }
        |     - borrowed value only lives until here
        |
    note: borrowed value must be valid for the lifetime 'a as defined on the body at 62:81...
    

    I understand that the texture is bound to the creator, but I have no clue how to achieve this. I hope someone could point me to the right direction.

    By the time I'll read some documentations about the lifetime :) .

    I'm sorry for the inconvenience, Thank you very much.

    question 
    opened by adfaure 20
  • Extend travis build matrix to include bundled

    Extend travis build matrix to include bundled

    Doubles the number of builds, unfortunately, but it should cover all the common linkage scenarios, except for macos frameworks, which I'm not sure I know enough about to handle.

    Also autoformats travis.yml and splits the SDL archive extraction and installation out to a shell script.

    Travis build result: https://travis-ci.org/reynisdrangar/rust-sdl2/builds/401276819

    H-OSX-Support-Needed 
    opened by reynisdrangar 19
  • rust no longer accepts comparison between byte and i8 in event.rs, expects u8

    rust no longer accepts comparison between byte and i8 in event.rs, expects u8

    just here and a couple lines down in the case for TextInput as well. thx.

    (hopefully irrelevant but I'll mention it just in case: I'm compiling for arm, with a very recently compiled rustc)

    opened by makoConstruct 19
  • Upgraded `Timer` API and fix `Timer` tests...

    Upgraded `Timer` API and fix `Timer` tests...

    This PR is based on the feedback from issue #320 ... it introduces a more Rust-like interface for the Timer wrapper that is much less error-prone, and also memory safe!

    To summarize how it works:

    • The user passes a boxed closure to the timer, e.g: let t = Timer::new(Box::new(move|| { ... }));
    • The timer runs until that closure returns a 0-interval OR ...
    • The timer is forcibly cancelled when it is dropped, this is because the closure will go out of scope, so further invocations would point to freed memory.

    This also improves thread safety over the previous API(s), from the SDL2 documentation:

    Use this function to set up a callback function to be run on a separate thread after the specified number of milliseconds has elapsed.

    Since the callback might be run on a separate thread: the closure's environment must satisfy Send so that it can be moved to the thread the timer will run on.

    Knowing this: it would also be unsafe to allow the closure to freely mutate its environment, so the closure does not allow for a mutable environment. In practice this simply means you have to protect mutable data w/ a Mutex or RwLock, and shared data w/ an Arc.


    The tests have been improved so they hopefully don't fail spuriously anymore. I accomplished this by simply adding an upper-bound to the timer's callback so it stops trying to acquire the mutex after a certain number of iterations.


    The whole thing is marked unstable for a number of reasons:

    1. ... well, we've changed it 3 times now, so it really isn't stable
    2. Since we're forcing the caller to wrap the closure in a Box<T> we may ~~need~~ want to change the API based on how the placement-new syntax (#![feature(box)]) pans out in rust-1.0.0
    3. We may want some sugar so the caller doesn't have to wrap the closure in a Box<T> themselves?
    opened by drbawb 18
  • Allows compiling with emscripten

    Allows compiling with emscripten

    This PR simply allows compiling any project using SDL2 with cargo web. It's just a matter of avoiding linking the SDL2 library as the port from emscripten will be used instead.

    opened by tanis2000 17
  • Move sdl2_ttf, sdl2_image, sdl2_gfx, sdl2_mixer in features

    Move sdl2_ttf, sdl2_image, sdl2_gfx, sdl2_mixer in features

    Related to #233, but I'm creating a new issue for this cause I don't want to bump everyone in the other (chances are that after a year without any discussion, they wouldn't be as interested anymore)

    cc @AngryLawyer for your approval

    Why ?

    When a release / a version bump is published in this crate (rust-sdl2), breaking changes sometimes have to be updated in sdl2 modules as well. Moving everything here as optional features would allow propagating the changes to the modules directly in a single commit, instead of having an awkward period where the modules (sdl2-ttf, sdl2-image, ...) would be stuck as a deprecated version of sdl2 because the modules weren't updated as the same time as the commit.

    Another problem is that any version bump requires a PR / a change from the modules crates, which is starting to become cumbersome for such inactive crates.

    This change would be planned before 1.0.0, and would allow this crate to have all these modules as optional and disabled by default features.

    How ?

    This part raises some questions, and I must say I am rather inexperienced with such git manipulations, but subtrees would probably be the best choice here. As I said, I have never user anything like that, so any help is appreciated.

    These sdl2 modules would then be converted as features (Rust-wise) and made disabled by default. Updates to the documentation will be required as well.

    We already have the approval from @xsleonard, but ideally it would be best to have the approval of @andelf as well. Technically, we could do without it and proceed without its consent, since its crates are under MIT and we can use them as we please as long as we keep the licenses and the authors, but it would obviously be best if we could have its approval and its opinion on the topic as well.

    What about sdl2-net ?

    Rust offers a very nice API for close to metal tcp and udp protocol; in addition with other crates such as serde and bincode, tcp / udp transmissions can be a breeze, and thus sdl2-net is not required in any Rust adaptation of one's code.

    License

    This crate and every module mentioned is licensed under MIT. @cmr opened an issue on sdl2_ttf to relicense the crate under MIT/Apache-2.0, and if needed we can license only the subtree sdl2_ttf under MIT/Apache-2.0 while licensing the main crate under MIT only.

    meta issue 
    opened by Cobrand 17
  • Upgrade to SDL 2.0.9

    Upgrade to SDL 2.0.9

    Among many other things, this fixes an annoying bug on MacOS (where all new SDL windows are full black until moved), and adds Vulkan support.

    Fixes #808

    Closes #816

    As explained in https://github.com/Rust-SDL2/rust-sdl2/issues/808#issuecomment-443780784, SDL 2.0.9 contains the patch that fixes build on Mac. Verified that I can run cargo build --features=bundled,static-link on Mac.

    opened by rasky 16
  • Vulkan support

    Vulkan support

    This includes Rust wrappers for SDL's Vulkan functions. I've also included an example program in the readme, much like the existing one for OpenGL.

    edit by @Cobrand: Closes #784

    opened by Rua 16
  • CI Cross-building

    CI Cross-building

    This may be out of scope for this project, but I am having a heck of a time getting a rust SDL2 project to build in Github CI for linux/mac for arm64, and hope that someone has some experience with this.

    Here is what I tried:

    For my first pass, I just download SDL for each platform and build it normally. Here is a complete x86-64 build, that seems to work ok.

    I tried running the outputted mac x86-64 build on an M1, and although it will start (I think because mac triggers an emulator on incorrect platform) it fails trying to link against my system-installed (via brew) SDL2.

    dyld[17465]: Library not loaded: /usr/local/opt/sdl2/lib/libSDL2-2.0.0.dylib
      Referenced from: <874CD34A-B1B6-3194-94BD-85C4C8CE2FCE> /Users/konsumer/Desktop/rm8/rm8-mac-x86_64/rm8
      Reason: tried: '/Users/konsumer/VulkanSDK/1.3.216.0/macOS//lib/libSDL2-2.0.0.dylib' (no such file), '/libSDL2-2.0.0.dylib' (no such file), '/usr/local/opt/sdl2/lib/libSDL2-2.0.0.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/usr/local/opt/sdl2/lib/libSDL2-2.0.0.dylib' (no such file), '/usr/local/opt/sdl2/lib/libSDL2-2.0.0.dylib' (no such file), '/usr/local/lib/libSDL2-2.0.0.dylib' (no such file), '/usr/lib/libSDL2-2.0.0.dylib' (no such file, not in dyld cache)
    [1]    17465 abort      ./rm8
    

    If I understand the system correctly, I need to use lipo to make a universal binary for both platforms, in a single executable.

    The next step is trying to cross-build for arm64 on mac/linux.

    On linux, this fails:

    error: failed to run custom build command for `libc v0.2.139`
    
    Caused by:
      process didn't exit successfully: `/target/release/build/libc-553f84[96](https://github.com/konsumer/rm8/actions/runs/3783838112/jobs/6432688520#step:6:97)44afbfd2/build-script-build` (exit status: 1)
      --- stderr
      /target/release/build/libc-553f849644afbfd2/build-script-build: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.33' not found (required by /target/release/build/libc-553f849644afbfd2/build-script-build)
      /target/release/build/libc-553f849644afbfd2/build-script-build: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.32' not found (required by /target/release/build/libc-553f849644afbfd2/build-script-build)
      /target/release/build/libc-553f849644afbfd2/build-script-build: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found (required by /target/release/build/libc-553f849644afbfd2/build-script-build)
    

    Which seems like an issue with cross, but I can't really tell.

    Mac has a similar fail:

    error[E0463]: can't find crate for `core`
      |
      = note: the `aarch64-apple-darwin` target may not be installed
      = help: consider downloading the target with `rustup target add aarch64-apple-darwin`
    
    error[E0463]: can't find crate for `compiler_builtins`
    
    error[E0463]: can't find crate for `core`
       --> /Users/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/bitflags-1.3.2/src/lib.rs:282:1
        |
    282 | pub extern crate core as _core;
        | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't find crate
        |
        = note: the `aarch64-apple-darwin` target may not be installed
        = help: consider downloading the target with `rustup target add aarch64-apple-darwin`
    

    I think this may be related to cross not correctly installing the targets it needs, so I add rustup target add aarch64-unknown-linux-gnu and rustup target add aarch64-apple-darwin to linux/mac. That fails the same on linux and has an SDL2 linkage error on Mac.

    This may be an entirely different issue, but on my M1, I tried to simulate building (in docker) the other way (linux arm64 building for linux x86-64) without cross, and that didn't work either (I get a pkg-config error):

    # uname -a
    Linux 46b739d74d77 5.10.76-linuxkit #1 SMP PREEMPT Mon Nov 8 11:22:26 UTC 2021 aarch64 GNU/Linux
    
    # apt install -y libsdl2-dev libudev-dev
    libsdl2-dev is already the newest version (2.0.14+dfsg2-3+deb11u1).
    libudev-dev is already the newest version (247.3-7+deb11u1).
    
    # rustup target add x86_64-unknown-linux-gnu
    info: downloading component 'rust-std' for 'x86_64-unknown-linux-gnu'
    info: installing component 'rust-std' for 'x86_64-unknown-linux-gnu'
     29.7 MiB /  29.7 MiB (100 %)  19.1 MiB/s in  1s ETA:  0s
    
    # cargo build --release --target x86_64-unknown-linux-gnu
        Updating crates.io index
      Downloaded bitflags v1.3.2
      Downloaded proc-macro2 v1.0.49
      Downloaded ryu v1.0.12
      Downloaded syn v1.0.107
      Downloaded unicode-ident v1.0.6
      Downloaded serialport v4.2.0
      Downloaded version-compare v0.1.1
      Downloaded static_assertions v1.1.0
      Downloaded serde_derive v1.0.151
      Downloaded serde v1.0.151
      Downloaded serde_json v1.0.91
      Downloaded nix v0.26.1
      Downloaded itoa v1.0.5
      Downloaded nix v0.24.3
      Downloaded lazy_static v1.4.0
      Downloaded libudev-sys v0.1.4
      Downloaded sdl2 v0.35.2
      Downloaded libc v0.2.139
      Downloaded pkg-config v0.3.26
      Downloaded libudev v0.3.0
      Downloaded ctrlc v3.2.4
      Downloaded cfg-if v1.0.0
      Downloaded quote v1.0.23
      Downloaded sdl2-sys v0.35.2
      Downloaded 24 crates (9.6 MB) in 0.92s (largest was `sdl2-sys` at 7.4 MB)
       Compiling libc v0.2.139
       Compiling bitflags v1.3.2
       Compiling cfg-if v1.0.0
       Compiling libudev-sys v0.1.4
    error: failed to run custom build command for `libudev-sys v0.1.4`
    
    Caused by:
      process didn't exit successfully: `/src/target/release/build/libudev-sys-ed6dac626792d036/build-script-build` (exit status: 101)
      --- stdout
      cargo:rerun-if-env-changed=LIBUDEV_NO_PKG_CONFIG
      cargo:rerun-if-env-changed=PKG_CONFIG_ALLOW_CROSS_x86_64-unknown-linux-gnu
      cargo:rerun-if-env-changed=PKG_CONFIG_ALLOW_CROSS_x86_64_unknown_linux_gnu
      cargo:rerun-if-env-changed=TARGET_PKG_CONFIG_ALLOW_CROSS
      cargo:rerun-if-env-changed=PKG_CONFIG_ALLOW_CROSS
      cargo:rerun-if-env-changed=PKG_CONFIG_x86_64-unknown-linux-gnu
      cargo:rerun-if-env-changed=PKG_CONFIG_x86_64_unknown_linux_gnu
      cargo:rerun-if-env-changed=TARGET_PKG_CONFIG
      cargo:rerun-if-env-changed=PKG_CONFIG
      cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_x86_64-unknown-linux-gnu
      cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_x86_64_unknown_linux_gnu
      cargo:rerun-if-env-changed=TARGET_PKG_CONFIG_SYSROOT_DIR
      cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR
    
      --- stderr
      thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: "pkg-config has not been configured to support cross-compilation.\n\nInstall a sysroot for the target platform and configure it via\nPKG_CONFIG_SYSROOT_DIR and PKG_CONFIG_PATH, or install a\ncross-compiling wrapper for pkg-config and set it via\nPKG_CONFIG environment variable."', /usr/local/cargo/registry/src/github.com-1ecc6299db9ec823/libudev-sys-0.1.4/build.rs:38:41
      note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
    warning: build failed, waiting for other jobs to finish..
    

    Does anyone know any tricks to getting this to work?

    opened by konsumer 1
  • Push new minor version to crates.io with most recent version of `raw-window-handle`.

    Push new minor version to crates.io with most recent version of `raw-window-handle`.

    Currently, the most recent version of sdl on crates.io depends on 0.4.2, however, lots of new libraries require more recent versions of raw-window-handle (e.g. most recent version of wgpu). I see that the repository has the most recent version.

    Perhaps a branch can be created and the new version of raw-window-handle be the only difference, then have it pushed to crates.io? It's currently a breaking issue in a project where I use sdl2.

    opened by grantshandy 1
  • add serde feature and derives for various types

    add serde feature and derives for various types

    This adds a serde feature as well as Serialize and Deserialize implementations for the following types:

    • Axis
    • Button
    • HatState
    • Keycode
    • Scancode
    • MouseWheelDirection
    • MouseButton
    • FullscreenType

    I chose these types because I can see them all being used in a game settings struct that gets saved to a file.

    There are some reasons given against adding a serde feature in the discussion for #1065, but I disagree with those reasons for the following reasons:

    • Yes, it's another dependency, but it's an optional one, and a pretty standard one across the Rust ecosystem. Also, the code changes needed to add serde support are minimal.
    • 8 types isn't that small of a number.
    • All of the workarounds are a pain (in my opinion):
      • Manually implementing Serialize and Deserialize for a wrapper struct requires knowledge of serde that many people won't have.
      • While Keycodes and Scancodes can be converted to and from i32s, gamepad axes and buttons can only be converted to Strings or sdl2_sys enums, which don't implement Serialize or Deserialize. Strings are usable, but it's a weird inconsistency.
      • Using serde's remote derive feature requires duplicating the enums that already exist in the sdl2 crate.

    Implementing input remapping in my game would be a lot easier if sdl2 had a serde feature. Please consider adding it!

    opened by tesselode 6
  • `wgpu-hal` unable to create adapter on Emscripten + SDL2

    `wgpu-hal` unable to create adapter on Emscripten + SDL2

    The browser main thread will hang on <hal::api::Gles as hal::Api>::Adapter::new_external() and video.gl_get_proc_address(name) as *const _ despite making it to the last GL command glWaitSync, without returning an error.

    extern crate wgpu_hal as hal;
    
    fn main() {
        env_logger::init();
    
        println!("Initializing external GL context and SDL");
        let sdl = sdl2::init().unwrap();
        let video = sdl.video().unwrap();
        let window = video.window("Legend Of Worlds", 640, 400)
            .opengl()
            .resizable()
            .build()
            .unwrap();
        window.gl_create_context().unwrap();
    
        println!("Hooking up to wgpu-hal");
        let exposed = unsafe {
            <hal::api::Gles as hal::Api>::Adapter::new_external(|name| {
                video.gl_get_proc_address(name) as *const _
            })
            .expect("GL adapter can't be initialized")
        };
        
        use hal::{Adapter as _, CommandEncoder as _, Device as _, Queue as _};
    
        let mut od = unsafe {
            exposed
                .adapter
                .open(wgt::Features::empty(), &wgt::Limits::downlevel_defaults())
        }
        .unwrap();
    
        let format = wgt::TextureFormat::Rgba8UnormSrgb;
        let texture = <hal::api::Gles as hal::Api>::Texture::default_framebuffer(format);
        let view = unsafe {
            od.device
                .create_texture_view(
                    &texture,
                    &hal::TextureViewDescriptor {
                        label: None,
                        format,
                        dimension: wgt::TextureViewDimension::D2,
                        usage: hal::TextureUses::COLOR_TARGET,
                        range: wgt::ImageSubresourceRange::default(),
                    },
                )
                .unwrap()
        };
    
        println!("Filling the screen");
        let mut encoder = unsafe {
            od.device
                .create_command_encoder(&hal::CommandEncoderDescriptor {
                    label: None,
                    queue: &od.queue,
                })
                .unwrap()
        };
        let rp_desc = hal::RenderPassDescriptor {
            label: None,
            extent: wgt::Extent3d {
                width: 640,
                height: 400,
                depth_or_array_layers: 1,
            },
            sample_count: 1,
            color_attachments: &[Some(hal::ColorAttachment {
                target: hal::Attachment {
                    view: &view,
                    usage: hal::TextureUses::COLOR_TARGET,
                },
                resolve_target: None,
                ops: hal::AttachmentOps::STORE,
                clear_value: wgt::Color::BLUE,
            })],
            depth_stencil_attachment: None,
            multiview: None,
        };
        unsafe {
            encoder.begin_encoding(None).unwrap();
            encoder.begin_render_pass(&rp_desc);
            encoder.end_render_pass();
            let cmd_buf = encoder.end_encoding().unwrap();
            od.queue.submit(&[&cmd_buf], None).unwrap();
        }
    }
    

    Cargo.toml

    [dependencies]
    sdl2 = { version="0.35.2", default-features = false, features = ["unsafe_textures", "image"] }
    wgpu = { version="0.13", features = ["webgl", "emscripten"] }
    wgpu-hal = { version="0.13", features = ["emscripten"] }
    env_logger = "0.8"
    
    [dependencies.wgt]
    package = "wgpu-types"
    version = "0.13"
    
    opened by Zentendo 0
  • Support for FP render functions

    Support for FP render functions

    SDL2, as of now, has documented functions for rendering at floating-point coordinates. Integer coordinates can be quite troublesome at times and often is not desirable.

    It surfaced in a commit of 2018 and was undocumented for a long time according to this. However the changelogs apprarently seem to record it. As none usually talks about it, it slipped through notice easily.

    It is so useful that, in fact I had to use unsafe FFI in my program to use this interface.

    https://github.com/xsbee/rvsp/blob/d1f8ea3091fadd45e8e3b8237db842545c51fdb2/src/main.rs#L159-L162

    So kindly consider adding this inteface. Thank you.

    functionality 
    opened by xsbee 1
Owner
null
A Chip-8 Emulator written in Rust & SDL2

Crab-8 A fully featured Chip-8 Emulator written in Rust. This project was written as a learning & development project in rust, and as such the code ma

Harry Smith 3 Dec 1, 2022
SFML bindings for Rust

rust-sfml Rust bindings for SFML, the Simple and Fast Multimedia Library. Requirements Linux, Windows, or OS X Rust 1.56 or later SFML 2.5 A C++ compi

Jeremy Letang 566 Dec 31, 2022
Unicorn Emulator Debug Server - Written in Rust, with bindings of C, Go, Java and Python

udbserver - Unicorn Emulator Debug Server When you do emulation with Unicorn Engine, do you want to inspect the inner state during every step? udbserv

Bet4 246 Dec 27, 2022
NES emulator written in Rust to learn Rust

OxideNES A NES emulator in Rust. CPU should be accurate, PPU is mostly accurate, timing between the 2 is off for some corner cases and hardware qui

null 37 Nov 7, 2022
Commodore 64 emulator written in Rust

Rust64 - a C64 emulator written in Rust This is my attempt to study the Rust programming language and have fun at the same time. The goal is to presen

Krzysztof Kondrak 214 Dec 27, 2022
A Flash Player emulator written in Rust

website | demo | nightly builds | wiki Ruffle Ruffle is an Adobe Flash Player emulator written in the Rust programming language. Ruffle targets both t

Ruffle 11.2k Jan 8, 2023
A Game Boy research project and emulator written in Rust

Mooneye GB Mooneye GB is a Game Boy research project and emulator written in Rust. The main goals of this project are accuracy and documentation. Some

Joonas Javanainen 802 Dec 28, 2022
A Gameboy Emulator in Rust

RBoy A Gameboy Color Emulator written in Rust Implemented CPU All instructions correct All timings correct Double speed mode GPU Normal mode Color mod

Mathijs van de Nes 512 Dec 23, 2022
RGB (Rust Game Boy) is a simple emulator for the original game boy

RGB RGB (Rust Game Boy) is a simple emulator for the original game boy and the color game boy. Warning: This no longer compiles in the latest versions

Niven Achenjang 18 Dec 2, 2022
Full featured Cross-platform GameBoy emulator by Rust. Forever boys!.

Gameboy Full featured Cross-platform GameBoy emulator. Forever boys!. You can start a game with the following command, here with a built-in game "Boxe

Mohanson 1.2k Jan 2, 2023
RustBoyAdvance-NG is a Nintendo™ Game Boy Advance emulator and debugger, written in the rust programming language.

RustBoyAdvance-NG Nintendo GameBoy Advance ™ emulator and debugger, written in rust. WebAssembly Demo: https://michelhe.github.io/rustboyadvance-ng/ P

MishMish 510 Dec 30, 2022
An NES emulator written in Rust

Pinky Pinky is an NES emulator written in Rust completely from scratch based only on publicly available documentation. You can run it in your Web brow

Koute 709 Dec 23, 2022
NES emulator written in Rust

sprocketnes is an emulator for the Nintendo Entertainment System written in the Rust programming language. Its purpose is to serve as a technology dem

Patrick Walton 725 Dec 27, 2022
NES emulator in rust

NES emulator in Rust plastic is a NES emulator built from scratch using Rust. This is a personal project for fun and to experience emulating hardware

Amjad Alsharafi 27 Dec 15, 2022
ZX Spectrum emulator written in Rust

rustzx ZX Spectrum emulator which I writing in rust. I develop this project just for fun and for learning the basics of computer architecture. License

Vladislav Nikonov 162 Dec 27, 2022
Intel 8080 cpu emulator by Rust

i8080 i8080 is a emulator for Intel 8080 cpu. 8080 Programmers Manual 8080 opcodes [dependencies] i8080 = { git = "https://github.com/mohanson/i8080"

Mohanson 83 Dec 27, 2022
CHIP-8 emulator written in Rust

CHIP-8 emulator written in Rust. This is intended to be a project for gaining experience writing emulators and practice Rust.

Pedro Rodrigues 4 May 21, 2021
A CHIP-8 emulator for Rust in ~350 LOC

chip8 An implementation of the CHIP-8 for Rust in ~350 lines of code. What is CHIP-8? CHIP-8 is a virtual machine (along with a supporting programming

Daniel Gatis 8 Apr 23, 2022
Rudroid - Writing the World's worst Android Emulator in Rust 🦀

Rudroid - Writing the World's worst Android Emulator in Rust ?? Introduction Rudroid - this might arguably be one of the worst Android emulators possi

Chaithu 102 Dec 23, 2022