WIP on Windows version

This commit is contained in:
Daniel Collin 2015-12-08 18:49:03 +01:00
parent 3415eb269d
commit b66fbe709a
2 changed files with 180 additions and 36 deletions

View file

@ -1,5 +1,4 @@
extern crate libc; extern crate libc;
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
#[macro_use] #[macro_use]
extern crate objc; extern crate objc;
@ -34,6 +33,7 @@ pub enum Scale {
} }
/// Vsync will allow syncronized rendering with the screen refresh rate. /// Vsync will allow syncronized rendering with the screen refresh rate.
/// Currently Vsync isn't implemented so nothing will change regardless of given value right now
pub enum Vsync { pub enum Vsync {
/// No vsync /// No vsync
No, No,
@ -48,26 +48,15 @@ pub enum Vsync {
/// ///
pub enum Key { pub enum Key {
Space,
/// The '1' key over the letters.
Key1, Key1,
/// The '2' key over the letters.
Key2, Key2,
/// The '3' key over the letters.
Key3, Key3,
/// The '4' key over the letters.
Key4, Key4,
/// The '5' key over the letters.
Key5, Key5,
/// The '6' key over the letters.
Key6, Key6,
/// The '7' key over the letters.
Key7, Key7,
/// The '8' key over the letters.
Key8, Key8,
/// The '9' key over the letters.
Key9, Key9,
/// The '0' key over the 'O' and 'P' keys.
Key0, Key0,
A, A,
@ -97,8 +86,6 @@ pub enum Key {
Y, Y,
Z, Z,
Escape,
F1, F1,
F2, F2,
F3, F3,
@ -115,15 +102,42 @@ pub enum Key {
F14, F14,
F15, F15,
ArrowLeft, Down,
ArrowRight, Left,
ArrowUp, Right,
ArrowDown, Up,
Apostrophe,
Backslash,
Comma,
Equal,
LeftBracket,
Minus,
Period,
RightBracket,
Semicolon,
Slash,
Backspace, Backspace,
Delete, Delete,
Comma, End,
Semicollon Enter,
Escape,
Home,
Insert,
Menu,
PageDown,
PageUp,
Pause,
Space,
Tab,
CapsLock,
Count = 80,
} }
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
@ -133,7 +147,6 @@ pub use windows::*;
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
pub mod macos; pub mod macos;
#[cfg(target_os = "mac")] #[cfg(target_os = "macos")]
pub use macos::*; pub use macos::*;

View file

@ -1,8 +1,14 @@
#![cfg(target_os = "windows")]
extern crate user32; extern crate user32;
extern crate kernel32; extern crate kernel32;
extern crate winapi; extern crate winapi;
extern crate gdi32; extern crate gdi32;
use Scale;
use Vsync;
use Key;
use std::ffi::CString; use std::ffi::CString;
use std::ptr; use std::ptr;
use std::os::windows::ffi::OsStrExt; use std::os::windows::ffi::OsStrExt;
@ -24,21 +30,120 @@ struct BitmapInfo {
pub bmi_colors: [RGBQUAD; 3], pub bmi_colors: [RGBQUAD; 3],
} }
fn update_key_state(window: &mut Window, wparam: u32, bool state) {
match wparam & 0x1ff {
0x00B => window.keys[Key::Key0] = state,
0x00B => window.keys[Key::Key0] = state,
0x002 => window.keys[Key::Key1] = state,
0x003 => window.keys[Key::Key2] = state,
0x004 => window.keys[Key::Key3] = state,
0x005 => window.keys[Key::Key4] = state,
0x006 => window.keys[Key::Key5] = state,
0x007 => window.keys[Key::Key6] = state,
0x008 => window.keys[Key::Key7] = state,
0x009 => window.keys[Key::Key8] = state,
0x00A => window.keys[Key::Key9] = state,
0x01E => window.keys[Key::A] = state,
0x030 => window.keys[Key::B] = state,
0x02E => window.keys[Key::C] = state,
0x020 => window.keys[Key::D] = state,
0x012 => window.keys[Key::E] = state,
0x021 => window.keys[Key::F] = state,
0x022 => window.keys[Key::G] = state,
0x023 => window.keys[Key::H] = state,
0x017 => window.keys[Key::I] = state,
0x024 => window.keys[Key::J] = state,
0x025 => window.keys[Key::K] = state,
0x026 => window.keys[Key::L] = state,
0x032 => window.keys[Key::M] = state,
0x031 => window.keys[Key::N] = state,
0x018 => window.keys[Key::O] = state,
0x019 => window.keys[Key::P] = state,
0x010 => window.keys[Key::Q] = state,
0x013 => window.keys[Key::R] = state,
0x01F => window.keys[Key::S] = state,
0x014 => window.keys[Key::T] = state,
0x016 => window.keys[Key::U] = state,
0x02F => window.keys[Key::V] = state,
0x011 => window.keys[Key::W] = state,
0x02D => window.keys[Key::X] = state,
0x015 => window.keys[Key::Y] = state,
0x02C => window.keys[Key::Z] = state,
0x03B => window.keys[Key::F1] = state,
0x03C => window.keys[Key::F2] = state,
0x03D => window.keys[Key::F3] = state,
0x03E => window.keys[Key::F4] = state,
0x03F => window.keys[Key::F5] = state,
0x040 => window.keys[Key::F6] = state,
0x041 => window.keys[Key::F7] = state,
0x042 => window.keys[Key::F8] = state,
0x043 => window.keys[Key::F9] = state,
0x042 => window.keys[Key::F8] = state,
0x043 => window.keys[Key::F9] = state,
0x044 => window.keys[Key::F10] = state,
0x057 => window.keys[Key::F11] = state,
0x058 => window.keys[Key::F12] = state,
0x150 => window.keys[Key::Down] = state,
0x14B => window.keys[Key::Left] = state,
0x14D => window.keys[Key::Right] = state,
0x148 => window.keys[Key::Up] = state,
0x028 => window.keys[Key::Apostrophe] = state,
0x02B => window.keys[Key::Backslash] = state,
0x033 => window.keys[Key::Comma] = state,
0x00D => window.keys[Key::Equal] = state,
0x01A => window.keys[Key::LeftBracket] = state,
0x00C => window.keys[Key::Minus] = state,
0x034 => window.keys[Key::Period] = state,
0x01B => window.keys[Key::RightBracket] = state,
0x027 => window.keys[Key::Semicolon] = state,
0x035 => window.keys[Key::Slash] = state,
0x00E => window.keys[Key::Backspace] = state,
0x153 => window.keys[Key::Delete] = state,
0x14F => window.keys[Key::End] = state,
0x01C => window.keys[Key::Enter] = state,
0x001 => window.keys[Key::Escape] = state,
0x147 => window.keys[Key::Home] = state,
0x152 => window.keys[Key::Insert] = state,
0x15D => window.keys[Key::Menu] = state,
0x151 => window.keys[Key::PageDown] = state,
0x149 => window.keys[Key::PageUp] = state,
0x045 => window.keys[Key::Pause] = state,
0x039 => window.keys[Key::Space] = state,
0x00F => window.keys[Key::Tab] = state,
0x03A => window.keys[Key::CapsLock] = state,
}
}
unsafe extern "system" fn wnd_proc(window: winapi::HWND, unsafe extern "system" fn wnd_proc(window: winapi::HWND,
msg: winapi::UINT, msg: winapi::UINT,
wparam: winapi::WPARAM, wparam: winapi::WPARAM,
lparam: winapi::LPARAM) lparam: winapi::LPARAM)
-> winapi::LRESULT { -> winapi::LRESULT {
// This make sure we actually don't do anything before the user data has been setup for the
// window
let user_data = user32::GetWindowLongPtrW(window, winapi::winuser::GWLP_USERDATA);
if user_data == 0
return user32::DefWindowProcW(window, msg, wparam, lparam);
let mut self = user_data as &mut Window;
match msg { match msg {
winapi::winuser::WM_KEYDOWN => { winapi::winuser::WM_KEYDOWN => {
if (wparam & 0xff) == 27 { update_key_state(self, wparam as u32, true);
if (wparam & 0x1ff) == 27 {
CLOSE_APP = true; CLOSE_APP = true;
} }
} }
winapi::winuser::WM_KEYUP => {
update_key_state(self, wparam as u32, false);
}
winapi::winuser::WM_PAINT => { winapi::winuser::WM_PAINT => {
let mut rect: winapi::RECT = mem::uninitialized(); let mut rect: winapi::RECT = mem::uninitialized();
let buffer = user32::GetWindowLongPtrW(window, winapi::winuser::GWLP_USERDATA);
user32::GetClientRect(window, &mut rect); user32::GetClientRect(window, &mut rect);
@ -56,9 +161,7 @@ unsafe extern "system" fn wnd_proc(window: winapi::HWND,
bitmap_info.bmi_colors[1].rgbGreen = 0xff; bitmap_info.bmi_colors[1].rgbGreen = 0xff;
bitmap_info.bmi_colors[2].rgbBlue = 0xff; bitmap_info.bmi_colors[2].rgbBlue = 0xff;
let dc = user32::GetDC(window); gdi32::StretchDIBits(self.dc,
gdi32::StretchDIBits(dc,
0, 0,
0, 0,
width, width,
@ -67,14 +170,12 @@ unsafe extern "system" fn wnd_proc(window: winapi::HWND,
0, 0,
width, width,
height, height,
mem::transmute(buffer), mem::transmute(self.buffer),
mem::transmute(&bitmap_info), mem::transmute(&bitmap_info),
winapi::wingdi::DIB_RGB_COLORS, winapi::wingdi::DIB_RGB_COLORS,
winapi::wingdi::SRCCOPY); winapi::wingdi::SRCCOPY);
user32::ValidateRect(window, ptr::null_mut()); user32::ValidateRect(window, ptr::null_mut());
user32::ReleaseDC(window, dc);
} }
_ => (), _ => (),
} }
@ -91,12 +192,15 @@ fn to_wstring(str: &str) -> *const u16 {
v.as_ptr() v.as_ptr()
} }
pub struct Minifb { pub struct Window {
dc: DC,
window: HWND, window: HWND,
bool keys_down: [bool; 512],
buffer: &[u32],
} }
impl Minifb { impl Window {
fn open_window(name: &str, width: usize, height: usize) -> HWND { fn open_window(name: &str, width: usize, height: usize, _: Scale, _: Vsync) -> Result<Window, &str> {
unsafe { unsafe {
let class_name = to_wstring("minifb_window"); let class_name = to_wstring("minifb_window");
let s = CString::new(name).unwrap(); let s = CString::new(name).unwrap();
@ -162,13 +266,26 @@ impl Minifb {
} }
} }
pub fn get_keys(&self -> Vec<Key> {
let index = 0;
let mut keys: Vec<Key> = Vec::new();
for i in self.keys {
if *i {
keys.push(index as Key);
}
index += 1;
}
keys
}
pub fn update(&mut self, buffer: &[u32]) -> bool { pub fn update(&mut self, buffer: &[u32]) -> bool {
unsafe { unsafe {
let mut msg = mem::uninitialized(); let mut msg = mem::uninitialized();
user32::SetWindowLongPtrW(self.window, user32::SetWindowLongPtrW(self.window, winapi::winuser::GWLP_USERDATA, self as i64);
winapi::winuser::GWLP_USERDATA,
buffer.as_ptr() as i64);
user32::InvalidateRect(self.window, ptr::null_mut(), winapi::TRUE); user32::InvalidateRect(self.window, ptr::null_mut(), winapi::TRUE);
while user32::PeekMessageW(&mut msg, self.window, 0, 0, winapi::winuser::PM_REMOVE) != 0 { while user32::PeekMessageW(&mut msg, self.window, 0, 0, winapi::winuser::PM_REMOVE) != 0 {
@ -182,3 +299,17 @@ impl Minifb {
} }
} }
} }
impl Drop for Window {
fn drop(&mut self) {
unsafe {
if self.dc.is_valid() {
user32::ReleaseDC(self.window, self.dc);
}
if self.hwnd.is_valid() {
user32::CloseWindow(self.hwnd);
}
}
}
}