-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
68 additions
and
131 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} |