From d1f5b46568d8da4dac7fec47f6a767fbe4eaa4d6 Mon Sep 17 00:00:00 2001 From: Sigve Sebastian Farstad Date: Tue, 31 Jan 2017 22:20:08 +0100 Subject: [PATCH] Replace glium with SDL2 --- .travis.yml | 7 ++++ Cargo.toml | 6 ++- README.md | 2 + src/display.rs | 106 +++++++------------------------------------------ src/gamepad.rs | 26 ++++++------ src/main.rs | 36 ++++++++++++----- src/utils.rs | 23 ++++------- 7 files changed, 75 insertions(+), 131 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4719b8b..8310f1e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,14 @@ +dist: trusty +sudo: required + language: rust rust: - nightly +before_install: + - sudo apt-get -qq update + - sudo apt-get install -y libsdl2-dev libsdl2-gfx-dev + notifications: email: false diff --git a/Cargo.toml b/Cargo.toml index 06132bf..14b44a6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,4 +14,8 @@ nom = "2.0.1" num = "0.1.30" gl = "0.6.1" libc = "0.2.20" -glium = "0.16.0" + +[dependencies.sdl2] +version = "0.28.0" +default-features = false +features = ["gfx"] diff --git a/README.md b/README.md index 45a76df..a9de267 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,4 @@ # gba-roa Game Boy Advance: Rusty Oxidation Action - The ROA Emulator + +You need some SDL2. Follow these instructions: https://github.com/AngryLawyer/rust-sdl2 diff --git a/src/display.rs b/src/display.rs index 9d6a678..6aaea31 100644 --- a/src/display.rs +++ b/src/display.rs @@ -1,111 +1,35 @@ use interconnect::InterconnectWrite; -use glium::{self, DisplayBuild, Frame, Surface}; -use glium::texture::RawImage2d; -use glium::texture::ClientFormat; -use utils::gba_to_display_format; +use utils::B5G5R5_to_B8G8R8; +use sdl2::gfx::primitives::DrawRenderer; +use sdl2::render::Renderer; pub struct Display { - pub display: glium::backend::glutin_backend::GlutinFacade, - pub program: glium::Program, pub buf: [u16; 240 * 160], } -#[derive(Copy, Clone)] -struct Vertex { - position: [f32; 2], -} - -implement_vertex!(Vertex, position); - impl Display { pub fn new() -> Self { - let display = glium::glutin::WindowBuilder::new() - .with_dimensions(240 * 2, 160 * 2) - .with_title("Game Boy Advance: Rusty Oxidation Action - The ROA Emulator") - .build_glium() - .unwrap(); - - let width = 160; - let height = 240; - - let vertex_shader_src = r#" - #version 140 - - in vec2 position; - out vec2 vuv; - - void main() { - vuv = position; - gl_Position = vec4(position, 0.0, 1.0); - } - "#; - - let fragment_shader_src = r#" - #version 140 - - in vec2 vuv; - out vec4 color; - - uniform sampler2D tex; - - void main() { - color = texture(tex, vuv / 2.0 + 0.5); - } - "#; - - let program = - glium::Program::from_source(&display, vertex_shader_src, fragment_shader_src, None) - .unwrap(); - Display { - display: display, - program: program, buf: [0b0000_0000_0000_0000u16; 240 * 160], } } - fn vsync(&self) { - let shape = vec![Vertex { position: [-1.0, -1.0] }, - Vertex { position: [1.0, -1.0] }, - Vertex { position: [-1.0, 1.0] }, - Vertex { position: [-1.0, 1.0] }, - Vertex { position: [1.0, -1.0] }, - Vertex { position: [1.0, 1.0] }]; - - let vertex_buffer = glium::VertexBuffer::new(&self.display, &shape).unwrap(); - let indices = glium::index::NoIndices(glium::index::PrimitiveType::TrianglesList); - - use std::borrow::Cow; - let image = glium::texture::RawImage2d { - data: Cow::from(&self.buf[..]), - width: 240, - height: 160, - format: ClientFormat::U5U5U5U1, - }; - - let texture = glium::texture::Texture2d::new(&self.display, image).unwrap(); - let sampler = texture.sampled() - .magnify_filter(glium::uniforms::MagnifySamplerFilter::Nearest); - let uniforms = uniform! { - tex: sampler, - }; - - let mut target = self.display.draw(); - target.clear_color(0.0, 0.0, 0.0, 1.0); - target.draw(&vertex_buffer, - &indices, - &self.program, - &uniforms, - &Default::default()) - .unwrap(); - target.finish().unwrap(); - + pub fn draw(&self, renderer: &mut Renderer) { + renderer.clear(); + for x in 0..240 { + for y in 0..160 { + renderer.pixel( + x as i16, + y as i16, + B5G5R5_to_B8G8R8(self.buf[y * 160 + x] as u16)); + } + } + renderer.present(); } } impl InterconnectWrite for Display { fn write(&mut self, address: u32, word: u32) { - self.buf[address as usize] = gba_to_display_format(word as u16); - self.vsync(); + self.buf[address as usize] = word as u16; } } diff --git a/src/gamepad.rs b/src/gamepad.rs index 542e97e..326432c 100644 --- a/src/gamepad.rs +++ b/src/gamepad.rs @@ -1,5 +1,5 @@ -use glium::glutin::{ElementState, VirtualKeyCode}; use interconnect::InterconnectRead; +use sdl2::keyboard::Keycode; #[derive(Default, Debug)] pub struct Gamepad { @@ -16,18 +16,18 @@ pub struct Gamepad { } impl Gamepad { - pub fn update(&mut self, key_state: ElementState, virtual_key_code: VirtualKeyCode) { - match virtual_key_code { - VirtualKeyCode::W => self.up = key_state == ElementState::Pressed, - VirtualKeyCode::A => self.left = key_state == ElementState::Pressed, - VirtualKeyCode::S => self.down = key_state == ElementState::Pressed, - VirtualKeyCode::D => self.right = key_state == ElementState::Pressed, - VirtualKeyCode::J => self.a = key_state == ElementState::Pressed, - VirtualKeyCode::K => self.b = key_state == ElementState::Pressed, - VirtualKeyCode::U => self.left_bumper = key_state == ElementState::Pressed, - VirtualKeyCode::I => self.right_bumper = key_state == ElementState::Pressed, - VirtualKeyCode::Return => self.start = key_state == ElementState::Pressed, - VirtualKeyCode::P => self.select = key_state == ElementState::Pressed, + pub fn update(&mut self, pressed: bool, keycode: Keycode) { + match keycode { + Keycode::W => self.up = pressed, + Keycode::A => self.left = pressed, + Keycode::S => self.down = pressed, + Keycode::D => self.right = pressed, + Keycode::J => self.a = pressed, + Keycode::K => self.b = pressed, + Keycode::U => self.left_bumper = pressed, + Keycode::I => self.right_bumper = pressed, + Keycode::Return => self.start = pressed, + Keycode::P => self.select = pressed, _ => (), } } diff --git a/src/main.rs b/src/main.rs index d6baebc..5852cd8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,10 +7,12 @@ extern crate nom; #[macro_use] extern crate enum_primitive; +extern crate sdl2; + extern crate num; -#[macro_use] -extern crate glium; +use sdl2::event::Event; +use sdl2::keyboard::Keycode; mod cpu; mod display; @@ -28,8 +30,6 @@ mod errors { use errors::*; quick_main!(run); -use glium::glutin::Event; -use glium::{DisplayBuild, Surface}; use interconnect::InterconnectWrite; fn run() -> Result<()> { @@ -48,17 +48,31 @@ fn run() -> Result<()> { gba.interconnect.write(vram_base + 80 * 240 + 120, 0b0_00000_11111_00000); gba.interconnect.write(vram_base + 80 * 240 + 125, 0b0_11111_00000_00000); + let sdl_context = sdl2::init().unwrap(); + let video_subsys = sdl_context.video().unwrap(); + let window = video_subsys.window( + "Game Boy Advance: Rusty Oxidation Action - The ROA Emulator", 240, 160) + .position_centered() + .opengl() + .build() + .unwrap(); + + let mut renderer = window.renderer().build().unwrap(); + let mut events = sdl_context.event_pump().unwrap(); + loop { - for ev in gba.interconnect.display.display.poll_events() { - match ev { - Event::KeyboardInput(key_state, _, Some(virtual_key_code)) => { - gba.interconnect.gamepad.update(key_state, virtual_key_code) + for event in events.poll_iter() { + match event { + Event::Quit {..} => break, + Event::KeyUp {keycode: Some(keycode), ..} => { + gba.interconnect.gamepad.update(true, keycode) + } + Event::KeyDown {keycode: Some(keycode), ..} => { + gba.interconnect.gamepad.update(false, keycode) } - Event::Closed => return Ok(()), _ => (), } - - println!("Keyboard state: {:?}", gba.interconnect.gamepad); + gba.interconnect.display.draw(&mut renderer); } } } diff --git a/src/utils.rs b/src/utils.rs index e837a87..ca5f9d5 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,18 +1,11 @@ -pub fn gba_to_display_format(gba_format: u16) -> u16 { - (gba_format & 0b0_00000_00000_11111) << 11 | // Red - (gba_format & 0b0_00000_11111_00000) << 1 | // Green - (gba_format & 0b0_11111_00000_00000) >> 9 // Blue -} - -#[cfg(test)] -mod tests { - use super::gba_to_display_format; - #[test] - fn test_display_format_conversion() { - let gba_format = 0b0_10001_11111_00000; - let display_format = 0b00000_11111_10001_0; - assert_eq!(gba_to_display_format(gba_format), display_format); - } +pub fn B5G5R5_to_B8G8R8(B5G5R5: u16) -> u32 { + let upscale: [u32; 32] = [0, 8, 16, 25, 33, 41, 49, 58, 66, 74, 82, 90, 99, 107, + 115, 123, 132, 140, 148, 156, 165, 173, 181, 189, 197, 206, 214, 222, 230, 239, + 247, 255]; + upscale[(B5G5R5 & 0b0_00000_00000_11111) as usize] | + (upscale[((B5G5R5 & 0b0_00000_11111_00000) >> 5) as usize] << 8) | + (upscale[((B5G5R5 & 0b0_11111_00000_00000) >> 10) as usize] << 16) | + 0xFF000000u32 }