Browse Source

#alias type declarations; core library additions; `_global` import name for the global scope

gingerBill 7 years ago
parent
commit
a43b89f36e

+ 8 - 2
core/math.odin

@@ -37,6 +37,13 @@ foreign __llvm_core {
 	cos     :: proc(θ: f32) -> f32        #link_name "llvm.cos.f32" ---;
 	cos     :: proc(θ: f64) -> f64        #link_name "llvm.cos.f64" ---;
 
+	// asin     :: proc(x: f32) -> f32       #link_name "llvm.asin.f32" ---;
+	// asin     :: proc(x: f64) -> f64       #link_name "llvm.asin.f64" ---;
+
+	// acos     :: proc(x: f32) -> f32       #link_name "llvm.acos.f32" ---;
+	// acos     :: proc(x: f64) -> f64       #link_name "llvm.acos.f64" ---;
+
+
 	pow     :: proc(x, power: f32) -> f32 #link_name "llvm.pow.f32" ---;
 	pow     :: proc(x, power: f64) -> f64 #link_name "llvm.pow.f64" ---;
 
@@ -47,9 +54,8 @@ foreign __llvm_core {
 tan    :: proc(θ: f32) -> f32 #inline do return sin(θ)/cos(θ);
 tan    :: proc(θ: f64) -> f64 #inline do return sin(θ)/cos(θ);
 
+lerp   :: proc(a, b: $T, t: $E) -> (x: T) do return a*(1-t) + b*t;
 
-lerp   :: proc(a, b, t: f32) -> (x: f32) do return a*(1-t) + b*t;
-lerp   :: proc(a, b, t: f64) -> (x: f64) do return a*(1-t) + b*t;
 unlerp :: proc(a, b, x: f32) -> (t: f32) do return (x-a)/(b-a);
 unlerp :: proc(a, b, x: f64) -> (t: f64) do return (x-a)/(b-a);
 

+ 24 - 0
core/opengl_constants.odin

@@ -1381,3 +1381,27 @@ DEBUG_LOGGED_MESSAGES_ARB      :: 0x9145;
 DEBUG_SEVERITY_HIGH_ARB        :: 0x9146;
 DEBUG_SEVERITY_MEDIUM_ARB      :: 0x9147;
 DEBUG_SEVERITY_LOW_ARB         :: 0x9148;
+
+
+SHADER_BINARY_FORMAT_SPIR_V    :: 0x9551;
+SPIR_V_BINARY                  :: 0x9552;
+PARAMETER_BUFFER               :: 0x80EE;
+PARAMETER_BUFFER_BINDING       :: 0x80EF;
+CONTEXT_FLAG_NO_ERROR_BIT      :: 0x00000008;
+VERTICES_SUBMITTED             :: 0x82EE;
+PRIMITIVES_SUBMITTED           :: 0x82EF;
+VERTEX_SHADER_INVOCATIONS      :: 0x82F0;
+TESS_CONTROL_SHADER_PATCHES    :: 0x82F1;
+TESS_EVALUATION_SHADER_INVOCATIONS :: 0x82F2;
+GEOMETRY_SHADER_PRIMITIVES_EMITTED :: 0x82F3;
+FRAGMENT_SHADER_INVOCATIONS    :: 0x82F4;
+COMPUTE_SHADER_INVOCATIONS     :: 0x82F5;
+CLIPPING_INPUT_PRIMITIVES      :: 0x82F6;
+CLIPPING_OUTPUT_PRIMITIVES     :: 0x82F7;
+POLYGON_OFFSET_CLAMP           :: 0x8E1B;
+SPIR_V_EXTENSIONS              :: 0x9553;
+NUM_SPIR_V_EXTENSIONS          :: 0x9554;
+TEXTURE_MAX_ANISOTROPY         :: 0x84FE;
+MAX_TEXTURE_MAX_ANISOTROPY     :: 0x84FF;
+TRANSFORM_FEEDBACK_OVERFLOW    :: 0x82EC;
+TRANSFORM_FEEDBACK_STREAM_OVERFLOW :: 0x82ED;

+ 12 - 2
core/os.odin

@@ -2,6 +2,8 @@ when ODIN_OS == "windows" do export "core:os_windows.odin";
 when ODIN_OS == "osx"     do export "core:os_x.odin";
 when ODIN_OS == "linux"   do export "core:os_linux.odin";
 
+import "mem.odin";
+
 write_string :: proc(fd: Handle, str: string) -> (int, Errno) {
 	return write(fd, cast([]u8)str);
 }
@@ -35,8 +37,8 @@ read_entire_file :: proc(name: string) -> (data: []u8, success: bool) {
 	return data[0..bytes_read], true;
 }
 
-write_entire_file :: proc(name: string, data: []u8) -> (sucess: bool) {
-	fd, err := open(name, O_WRONLY|O_CREAT, 0);
+write_entire_file :: proc(name: string, data: []u8) -> (success: bool) {
+	fd, err := open(name, O_WRONLY|O_CREATE, 0);
 	if err != 0 {
 		return false;
 	}
@@ -45,3 +47,11 @@ write_entire_file :: proc(name: string, data: []u8) -> (sucess: bool) {
 	bytes_written, write_err := write(fd, data);
 	return write_err != 0;
 }
+
+write :: proc(fd: Handle, data: rawptr, len: int) -> (int, Errno) {
+	return write(fd, mem.slice_ptr(cast(^u8)data, len));
+}
+
+read :: proc(fd: Handle, data: rawptr, len: int) -> (int, Errno) {
+	return read(fd, mem.slice_ptr(cast(^u8)data, len));
+}

+ 1 - 1
core/os_linux.odin

@@ -12,7 +12,7 @@ Errno     :: i32;
 O_RDONLY   :: 0x00000;
 O_WRONLY   :: 0x00001;
 O_RDWR     :: 0x00002;
-O_CREAT    :: 0x00040;
+O_CREATE   :: 0x00040;
 O_EXCL     :: 0x00080;
 O_NOCTTY   :: 0x00100;
 O_TRUNC    :: 0x00200;

+ 5 - 5
core/os_windows.odin

@@ -12,7 +12,7 @@ INVALID_HANDLE: Handle : -1;
 O_RDONLY   :: 0x00000;
 O_WRONLY   :: 0x00001;
 O_RDWR     :: 0x00002;
-O_CREAT    :: 0x00040;
+O_CREATE   :: 0x00040;
 O_EXCL     :: 0x00080;
 O_NOCTTY   :: 0x00100;
 O_TRUNC    :: 0x00200;
@@ -66,7 +66,7 @@ open :: proc(path: string, mode: int = O_RDONLY, perm: u32 = 0) -> (Handle, Errn
 	case O_RDWR:   access = win32.FILE_GENERIC_READ | win32.FILE_GENERIC_WRITE;
 	}
 
-	if mode&O_CREAT != 0 {
+	if mode&O_CREATE != 0 {
 		access |= win32.FILE_GENERIC_WRITE;
 	}
 	if mode&O_APPEND != 0 {
@@ -83,11 +83,11 @@ open :: proc(path: string, mode: int = O_RDONLY, perm: u32 = 0) -> (Handle, Errn
 
 	create_mode: u32;
 	switch {
-	case mode&(O_CREAT|O_EXCL) == (O_CREAT | O_EXCL):
+	case mode&(O_CREATE|O_EXCL) == (O_CREATE | O_EXCL):
 		create_mode = win32.CREATE_NEW;
-	case mode&(O_CREAT|O_TRUNC) == (O_CREAT | O_TRUNC):
+	case mode&(O_CREATE|O_TRUNC) == (O_CREATE | O_TRUNC):
 		create_mode = win32.CREATE_ALWAYS;
-	case mode&O_CREAT == O_CREAT:
+	case mode&O_CREATE == O_CREATE:
 		create_mode = win32.OPEN_ALWAYS;
 	case mode&O_TRUNC == O_TRUNC:
 		create_mode = win32.TRUNCATE_EXISTING;

+ 1 - 1
core/os_x.odin

@@ -12,7 +12,7 @@ Errno     :: int;
 O_RDONLY   :: 0x00000;
 O_WRONLY   :: 0x00001;
 O_RDWR     :: 0x00002;
-O_CREAT    :: 0x00040;
+O_CREATE   :: 0x00040;
 O_EXCL     :: 0x00080;
 O_NOCTTY   :: 0x00100;
 O_TRUNC    :: 0x00200;

+ 5 - 5
core/strings.odin

@@ -14,9 +14,9 @@ new_c_string :: proc(s: string) -> ^u8 {
 	return &c[0];
 }
 
-to_odin_string :: proc(c: ^u8) -> string {
-	if c == nil do return "";
-	len := 0;
-	for (c+len)^ != 0 do len+=1;
-	return string(mem.slice_ptr(c, len));
+to_odin_string :: proc(str: ^u8) -> string {
+	if str == nil do return "";
+	end := str;
+	for end^ != 0 do end+=1;
+	return string(mem.slice_ptr(str, end-str));
 }

+ 184 - 17
core/sys/windows.odin

@@ -17,11 +17,15 @@ Hbrush    :: Handle;
 Hgdiobj   :: Handle;
 Hmodule   :: Handle;
 Hmonitor  :: Handle;
+Hrawinput :: Handle;
+HKL       :: Handle;
 Wparam    :: uint;
 Lparam    :: int;
 Lresult   :: int;
 Wnd_Proc  :: proc(Hwnd, u32, Wparam, Lparam) -> Lresult #cc_c;
 
+Long_Ptr :: int;
+
 Bool :: i32;
 FALSE: Bool : 0;
 TRUE:  Bool : 1;
@@ -42,6 +46,19 @@ Wnd_Class_Ex_A :: struct #ordered {
 	sm:                    Hicon,
 }
 
+Wnd_Class_Ex_W :: struct #ordered {
+	size, style:           u32,
+	wnd_proc:              Wnd_Proc,
+	cls_extra, wnd_extra:  i32,
+	instance:              Hinstance,
+	icon:                  Hicon,
+	cursor:                Hcursor,
+	background:            Hbrush,
+	menu_name, class_name: ^u16,
+	sm:                    Hicon,
+}
+
+
 Msg :: struct #ordered {
 	hwnd:    Hwnd,
 	message: u32,
@@ -167,6 +184,59 @@ Critical_Section_Debug :: struct #ordered {
 List_Entry :: struct #ordered {flink, blink: ^List_Entry};
 
 
+Raw_Input_Device :: struct #ordered {
+	usage_page: u16,
+	usage:      u16,
+	flags:      u32,
+	wnd_target: Hwnd,
+}
+
+Raw_Input_Header :: struct #ordered {
+	kind:   u32,
+	size:   u32,
+	device: Handle,
+	wparam: Wparam,
+}
+
+Raw_HID :: struct #ordered {
+	size_hid: u32,
+	count:    u32,
+	raw_data: [1]u8,
+}
+
+Raw_Keyboard :: struct #ordered {
+	make_code:         u16,
+	flags:             u16,
+	reserved:          u16,
+	vkey:              u16,
+	message:           u32,
+	extra_information: u32,
+}
+
+Raw_Mouse :: struct #ordered {
+	flags: u16,
+	using data: struct #raw_union {
+		buttons: u32,
+		using _: struct #ordered {
+			button_flags: u16,
+			button_data:  u16,
+		},
+	},
+	raw_buttons:       u32,
+	last_x:            i32,
+	last_y:            i32,
+	extra_information: u32,
+}
+
+Raw_Input :: struct #ordered {
+	using header: Raw_Input_Header,
+	data: struct #raw_union {
+		mouse:    Raw_Mouse,
+		keyboard: Raw_Keyboard,
+		hid:      Raw_HID,
+	},
+}
+
 
 MAPVK_VK_TO_VSC    :: 0;
 MAPVK_VSC_TO_VK    :: 1;
@@ -199,26 +269,30 @@ WS_BORDER           :: 0x00800000;
 WS_CAPTION          :: 0x00C00000;
 WS_VISIBLE          :: 0x10000000;
 WS_POPUP            :: 0x80000000;
+WS_MAXIMIZE         :: 0x01000000;
+WS_MINIMIZE         :: 0x20000000;
 WS_OVERLAPPEDWINDOW :: WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX;
 WS_POPUPWINDOW      :: WS_POPUP | WS_BORDER | WS_SYSMENU;
 
-WM_DESTROY           :: 0x0002;
-WM_SIZE	             :: 0x0005;
-WM_CLOSE             :: 0x0010;
+WM_ACTIVATE          :: 0x0006;
 WM_ACTIVATEAPP       :: 0x001C;
-WM_QUIT              :: 0x0012;
+WM_CHAR              :: 0x0102;
+WM_CLOSE             :: 0x0010;
+WM_CREATE            :: 0x0001;
+WM_DESTROY           :: 0x0002;
+WM_INPUT             :: 0x00ff;
 WM_KEYDOWN           :: 0x0100;
 WM_KEYUP             :: 0x0101;
+WM_KILLFOCUS         :: 0x0008;
+WM_QUIT              :: 0x0012;
+WM_SETCURSOR         :: 0x0020;
+WM_SETFOCUS          :: 0x0007;
+WM_SIZE	             :: 0x0005;
 WM_SIZING            :: 0x0214;
 WM_SYSKEYDOWN        :: 0x0104;
 WM_SYSKEYUP          :: 0x0105;
-WM_WINDOWPOSCHANGED  :: 0x0047;
-WM_SETCURSOR         :: 0x0020;
-WM_CHAR              :: 0x0102;
-WM_ACTIVATE          :: 0x0006;
-WM_SETFOCUS          :: 0x0007;
-WM_KILLFOCUS         :: 0x0008;
 WM_USER              :: 0x0400;
+WM_WINDOWPOSCHANGED  :: 0x0047;
 
 WM_MOUSEWHEEL    :: 0x020A;
 WM_MOUSEMOVE     :: 0x0200;
@@ -248,7 +322,12 @@ COLOR_BACKGROUND :: Hbrush(int(1));
 INVALID_SET_FILE_POINTER :: ~u32(0);
 HEAP_ZERO_MEMORY         :: 0x00000008;
 INFINITE                 :: 0xffffffff;
+GWL_EXSTYLE              :: -20;
+GWLP_HINSTANCE           :: -6;
+GWLP_ID                  :: -12;
 GWL_STYLE                :: -16;
+GWLP_USERDATA            :: -21;
+GWLP_WNDPROC             :: -4;
 Hwnd_TOP                 :: Hwnd(uint(0));
 
 BI_RGB         :: 0;
@@ -267,7 +346,62 @@ SWP_NOSIZE        :: 0x0001;
 SWP_NOMOVE        :: 0x0002;
 
 
+// Raw Input
+
+
+RID_HEADER :: 0x10000005;
+RID_INPUT  :: 0x10000003;
+
+
+RIDEV_APPKEYS      :: 0x00000400;
+RIDEV_CAPTUREMOUSE :: 0x00000200;
+RIDEV_DEVNOTIFY    :: 0x00002000;
+RIDEV_EXCLUDE      :: 0x00000010;
+RIDEV_EXINPUTSINK  :: 0x00001000;
+RIDEV_INPUTSINK    :: 0x00000100;
+RIDEV_NOHOTKEYS    :: 0x00000200;
+RIDEV_NOLEGACY     :: 0x00000030;
+RIDEV_PAGEONLY     :: 0x00000020;
+RIDEV_REMOVE       :: 0x00000001;
+
+
+RIM_TYPEMOUSE    :: 0;
+RIM_TYPEKEYBOARD :: 1;
+RIM_TYPEHID      :: 2;
+
 
+MOUSE_ATTRIBUTES_CHANGED :: 0x04;
+MOUSE_MOVE_RELATIVE      :: 0;
+MOUSE_MOVE_ABSOLUTE      :: 1;
+MOUSE_VIRTUAL_DESKTOP    :: 0x02;
+
+
+
+RI_MOUSE_BUTTON_1_DOWN      :: 0x0001;
+RI_MOUSE_BUTTON_1_UP        :: 0x0002;
+RI_MOUSE_BUTTON_2_DOWN      :: 0x0004;
+RI_MOUSE_BUTTON_2_UP        :: 0x0008;
+RI_MOUSE_BUTTON_3_DOWN      :: 0x0010;
+RI_MOUSE_BUTTON_3_UP        :: 0x0020;
+RI_MOUSE_BUTTON_4_DOWN      :: 0x0040;
+RI_MOUSE_BUTTON_4_UP        :: 0x0080;
+RI_MOUSE_BUTTON_5_DOWN      :: 0x0100;
+RI_MOUSE_BUTTON_5_UP        :: 0x0200;
+RI_MOUSE_LEFT_BUTTON_DOWN   :: 0x0001;
+RI_MOUSE_LEFT_BUTTON_UP     :: 0x0002;
+RI_MOUSE_MIDDLE_BUTTON_DOWN :: 0x0010;
+RI_MOUSE_MIDDLE_BUTTON_UP   :: 0x0020;
+RI_MOUSE_RIGHT_BUTTON_DOWN  :: 0x0004;
+RI_MOUSE_RIGHT_BUTTON_UP    :: 0x0008;
+RI_MOUSE_WHEEL              :: 0x0400;
+
+
+RI_KEY_MAKE            :: 0x00;
+RI_KEY_BREAK           :: 0x01;
+RI_KEY_E0              :: 0x02;
+RI_KEY_E1              :: 0x04;
+RI_KEY_TERMSRV_SET_LED :: 0x08;
+RI_KEY_TERMSRV_SHADOW  :: 0x10;
 
 // Windows OpenGL
 
@@ -302,6 +436,7 @@ foreign kernel32 {
 	get_last_error              :: proc() -> i32                                                                               #cc_std #link_name "GetLastError"                 ---;
 	exit_process                :: proc(exit_code: u32)                                                                        #cc_std #link_name "ExitProcess"                  ---;
 	get_module_handle_a         :: proc(module_name: ^u8) -> Hinstance                                                         #cc_std #link_name "GetModuleHandleA"             ---;
+	get_module_handle_w         :: proc(module_name: ^u16) -> Hinstance                                                        #cc_std #link_name "GetModuleHandleW"             ---;
 	sleep                       :: proc(ms: i32) -> i32                                                                        #cc_std #link_name "Sleep"                        ---;
 	query_performance_frequency :: proc(result: ^i64) -> i32                                                                   #cc_std #link_name "QueryPerformanceFrequency"    ---;
 	query_performance_counter   :: proc(result: ^i64) -> i32                                                                   #cc_std #link_name "QueryPerformanceCounter"      ---;
@@ -394,11 +529,14 @@ foreign kernel32 {
 foreign user32 {
 	get_desktop_window  :: proc() -> Hwnd                                                                       #cc_std #link_name "GetDesktopWindow"    ---;
 	show_cursor         :: proc(show : Bool)                                                                    #cc_std #link_name "ShowCursor"          ---;
-	get_cursor_pos      :: proc(p: ^Point) -> i32                                                               #cc_std #link_name "GetCursorPos"        ---;
-	screen_to_client    :: proc(h: Hwnd, p: ^Point) -> i32                                                      #cc_std #link_name "ScreenToClient"      ---;
+	get_cursor_pos      :: proc(p: ^Point) -> Bool                                                              #cc_std #link_name "GetCursorPos"        ---;
+	set_cursor_pos      :: proc(x, y: i32) -> Bool                                                              #cc_std #link_name "SetCursorPos"        ---;
+	screen_to_client    :: proc(h: Hwnd, p: ^Point) -> Bool                                                     #cc_std #link_name "ScreenToClient"      ---;
+	client_to_screen    :: proc(h: Hwnd, p: ^Point) -> Bool                                                     #cc_std #link_name "ClientToScreen"      ---;
 	post_quit_message   :: proc(exit_code: i32)                                                                 #cc_std #link_name "PostQuitMessage"     ---;
 	set_window_text_a   :: proc(hwnd: Hwnd, c_string: ^u8) -> Bool                                              #cc_std #link_name "SetWindowTextA"      ---;
 	register_class_ex_a :: proc(wc: ^Wnd_Class_Ex_A) -> i16                                                     #cc_std #link_name "RegisterClassExA"    ---;
+	register_class_ex_w :: proc(wc: ^Wnd_Class_Ex_W) -> i16                                                     #cc_std #link_name "RegisterClassExW"    ---;
 
 	create_window_ex_a  :: proc(ex_style: u32,
 	                            class_name, title: ^u8,
@@ -407,13 +545,24 @@ foreign user32 {
 	                            parent: Hwnd, menu: Hmenu, instance: Hinstance,
 	                            param: rawptr) -> Hwnd                                                          #cc_std #link_name "CreateWindowExA"     ---;
 
+	create_window_ex_w  :: proc(ex_style: u32,
+	                            class_name, title: ^u16,
+	                            style: u32,
+	                            x, y, w, h: i32,
+	                            parent: Hwnd, menu: Hmenu, instance: Hinstance,
+	                            param: rawptr) -> Hwnd                                                          #cc_std #link_name "CreateWindowExW"     ---;
+
 	show_window        :: proc(hwnd: Hwnd, cmd_show: i32) -> Bool                                               #cc_std #link_name "ShowWindow"          ---;
 	translate_message  :: proc(msg: ^Msg) -> Bool                                                               #cc_std #link_name "TranslateMessage"    ---;
 	dispatch_message_a :: proc(msg: ^Msg) -> Lresult                                                            #cc_std #link_name "DispatchMessageA"    ---;
+	dispatch_message_w :: proc(msg: ^Msg) -> Lresult                                                            #cc_std #link_name "DispatchMessageW"    ---;
 	update_window      :: proc(hwnd: Hwnd) -> Bool                                                              #cc_std #link_name "UpdateWindow"        ---;
 	get_message_a      :: proc(msg: ^Msg, hwnd: Hwnd, msg_filter_min, msg_filter_max : u32) -> Bool             #cc_std #link_name "GetMessageA"         ---;
+	get_message_w      :: proc(msg: ^Msg, hwnd: Hwnd, msg_filter_min, msg_filter_max : u32) -> Bool             #cc_std #link_name "GetMessageW"         ---;
 	peek_message_a     :: proc(msg: ^Msg, hwnd: Hwnd,
-		                       msg_filter_min, msg_filter_max, remove_msg: u32) -> Bool                         #cc_std #link_name "PeekMessageA"        ---;
+	                           msg_filter_min, msg_filter_max, remove_msg: u32) -> Bool                         #cc_std #link_name "PeekMessageA"        ---;
+	peek_message_w     :: proc(msg: ^Msg, hwnd: Hwnd,
+	                           msg_filter_min, msg_filter_max, remove_msg: u32) -> Bool                         #cc_std #link_name "PeekMessageW"        ---;
 
 
 	post_message          :: proc(hwnd: Hwnd, msg, wparam, lparam : u32) -> Bool                                #cc_std #link_name "PostMessageA"        ---;
@@ -435,8 +584,10 @@ foreign user32 {
 	set_window_placement  :: proc(wnd: Hwnd, wndpl: ^Window_Placement) -> Bool                                  #cc_std #link_name "SetWindowPlacement"  ---;
 	get_window_rect       :: proc(wnd: Hwnd, rect: ^Rect) -> Bool                                               #cc_std #link_name "GetWindowRect"       ---;
 
-	get_window_long_ptr_a :: proc(wnd: Hwnd, index: i32) -> i64                                                 #cc_std #link_name "GetWindowLongPtrA"   ---;
-	set_window_long_ptr_a :: proc(wnd: Hwnd, index: i32, new: i64) -> i64                                       #cc_std #link_name "SetWindowLongPtrA"   ---;
+	get_window_long_ptr_a :: proc(wnd: Hwnd, index: i32) -> Long_Ptr                                            #cc_std #link_name "GetWindowLongPtrA"   ---;
+	set_window_long_ptr_a :: proc(wnd: Hwnd, index: i32, new: Long_Ptr) -> Long_Ptr                             #cc_std #link_name "SetWindowLongPtrA"   ---;
+	get_window_long_ptr_w :: proc(wnd: Hwnd, index: i32) -> Long_Ptr                                            #cc_std #link_name "GetWindowLongPtrW"   ---;
+	set_window_long_ptr_w :: proc(wnd: Hwnd, index: i32, new: Long_Ptr) -> Long_Ptr                             #cc_std #link_name "SetWindowLongPtrW"   ---;
 
 	get_window_text       :: proc(wnd: Hwnd, str: ^u8, maxCount: i32) -> i32                                    #cc_std #link_name "GetWindowText"       ---;
 
@@ -445,10 +596,23 @@ foreign user32 {
 	get_dc                :: proc(h: Hwnd) -> Hdc                                                               #cc_std #link_name "GetDC"               ---;
 	release_dc            :: proc(wnd: Hwnd, hdc: Hdc) -> i32                                                   #cc_std #link_name "ReleaseDC"           ---;
 
-	map_virtual_key       :: proc(scancode : u32, map_type : u32) -> u32                                        #cc_std #link_name "MapVirtualKeyA"      ---;
+	map_virtual_key_a     :: proc(scancode : u32, map_type : u32) -> u32                                        #cc_std #link_name "MapVirtualKeyA"      ---;
+	map_virtual_key_w     :: proc(scancode : u32, map_type : u32) -> u32                                        #cc_std #link_name "MapVirtualKeyW"      ---;
 
 	get_key_state         :: proc(v_key: i32) -> i16                                                            #cc_std #link_name "GetKeyState"         ---;
 	get_async_key_state   :: proc(v_key: i32) -> i16                                                            #cc_std #link_name "GetAsyncKeyState"    ---;
+
+	set_foreground_window :: proc(h: Hwnd) -> Bool                                                              #cc_std #link_name "SetForegroundWindow" ---;
+	set_focus             :: proc(h: Hwnd) -> Hwnd                                                              #cc_std #link_name "SetFocus"            ---;
+
+
+
+	register_raw_input_devices :: proc(raw_input_device: ^Raw_Input_Device, num_devices, size: u32) -> Bool #cc_std #link_name "RegisterRawInputDevices" ---;
+
+	get_raw_input_data         :: proc(raw_input: Hrawinput, command: u32, data: rawptr, size: ^u32, size_header: u32) -> u32 #cc_std #link_name "GetRawInputData" ---;
+
+	map_virtual_key_ex_w       :: proc(code, map_type: u32, hkl: HKL) #cc_std #link_name "MapVirtualKeyExW" ---;
+	map_virtual_key_ex_a       :: proc(code, map_type: u32, hkl: HKL) #cc_std #link_name "MapVirtualKeyExA" ---;
 }
 
 foreign gdi32 {
@@ -493,7 +657,6 @@ is_key_down :: proc(key: Key_Code) -> bool #inline { return get_async_key_state(
 
 
 
-
 MAX_PATH :: 0x00000104;
 
 HANDLE_FLAG_INHERIT :: 1;
@@ -582,10 +745,14 @@ Rgb_Quad :: struct #ordered {blue, green, red, reserved: u8}
 
 
 Key_Code :: enum i32 {
+	Unknown    = 0x00,
+
 	Lbutton    = 0x01,
 	Rbutton    = 0x02,
 	Cancel     = 0x03,
 	Mbutton    = 0x04,
+	Xbutton1   = 0x05,
+	Xbutton2   = 0x06,
 	Back       = 0x08,
 	Tab        = 0x09,
 	Clear      = 0x0C,

+ 32 - 1
core/utf16.odin

@@ -1,3 +1,5 @@
+import "utf8.odin"
+
 REPLACEMENT_CHAR :: '\uFFFD';
 MAX_RUNE         :: '\U0010FFFF';
 
@@ -27,7 +29,7 @@ encode_surrogate_pair :: proc(r: rune) -> (r1, r2: rune) {
 	return _surr1 + (r>>10)&0x3ff, _surr2 + r&0x3ff;
 }
 
-encode :: proc(d: []u16, s: []rune) {
+encode :: proc(d: []u16, s: []rune) -> int {
 	n := len(s);
 	for r in s do if r >= _surr_self do n += 1;
 
@@ -51,4 +53,33 @@ encode :: proc(d: []u16, s: []rune) {
 			n += 1;
 		}
 	}
+	return n;
+}
+
+
+encode :: proc(d: []u16, s: string) -> int {
+	n := utf8.rune_count(s);
+	for r in s do if r >= _surr_self do n += 1;
+
+	max_n := min(len(d), n);
+	n = 0;
+
+	for r in s {
+		switch r {
+		case 0.._surr1, _surr3.._surr_self:
+			d[n] = u16(r);
+			n += 1;
+
+		case _surr_self..MAX_RUNE:
+			r1, r2 := encode_surrogate_pair(r);
+			d[n]    = u16(r1);
+			d[n+1]  = u16(r2);
+			n += 2;
+
+		case:
+			d[n] = u16(REPLACEMENT_CHAR);
+			n += 1;
+		}
+	}
+	return n;
 }

+ 28 - 8
src/check_decl.cpp

@@ -170,8 +170,26 @@ void check_init_constant(Checker *c, Entity *e, Operand *operand) {
 	e->Constant.value = operand->value;
 }
 
-void check_type_decl(Checker *c, Entity *e, AstNode *type_expr, Type *def) {
+AstNode *remove_type_alias(AstNode *node) {
+	for (;;) {
+		if (node == nullptr) {
+			return nullptr;
+		}
+		if (node->kind == AstNode_ParenExpr) {
+			node = node->ParenExpr.expr;
+		} else if (node->kind == AstNode_AliasType) {
+			node = node->AliasType.type;
+		} else {
+			return node;
+		}
+	}
+}
+
+void check_type_decl(Checker *c, Entity *e, AstNode *type_expr, Type *def, bool is_alias) {
 	GB_ASSERT(e->type == nullptr);
+	AstNode *te = remove_type_alias(type_expr);
+
+	e->type = t_invalid;
 	String name = e->token.string;
 	Type *named = make_type_named(c->allocator, name, nullptr, e);
 	named->Named.type_name = e;
@@ -180,12 +198,14 @@ void check_type_decl(Checker *c, Entity *e, AstNode *type_expr, Type *def) {
 	}
 	e->type = named;
 
-	// gb_printf_err("%.*s %p\n", LIT(e->token.string), e);
-
-	Type *bt = check_type(c, type_expr, named);
+	Type *bt = check_type(c, te, named);
 	named->Named.base = base_type(bt);
-	if (named->Named.base == t_invalid) {
-		// gb_printf("check_type_decl: %s\n", type_to_string(named));
+	if (is_alias) {
+		if (is_type_named(bt)) {
+			e->type = bt;
+		} else {
+			warning(type_expr, "Type declaration will not be an alias type");
+		}
 	}
 }
 
@@ -232,7 +252,7 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init,
 				error(e->token, "A type declaration cannot have an type parameter");
 			}
 			d->type_expr = d->init_expr;
-			check_type_decl(c, e, d->type_expr, named_type);
+			check_type_decl(c, e, d->type_expr, named_type, false);
 			return;
 		}
 
@@ -673,7 +693,7 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type) {
 		check_const_decl(c, e, d->type_expr, d->init_expr, named_type);
 		break;
 	case Entity_TypeName:
-		check_type_decl(c, e, d->type_expr, named_type);
+		check_type_decl(c, e, d->type_expr, named_type, d->type_expr->kind == AstNode_AliasType);
 		break;
 	case Entity_Procedure:
 		check_proc_decl(c, e, d);

+ 16 - 3
src/check_expr.cpp

@@ -57,7 +57,7 @@ ExprKind check_expr_base                (Checker *c, Operand *operand, AstNode *
 void     check_expr_with_type_hint      (Checker *c, Operand *o, AstNode *e, Type *t);
 Type *   check_type                     (Checker *c, AstNode *expression, Type *named_type = nullptr);
 Type *   make_optional_ok_type(gbAllocator a, Type *value);
-void     check_type_decl                (Checker *c, Entity *e, AstNode *type_expr, Type *def);
+void     check_type_decl                (Checker *c, Entity *e, AstNode *type_expr, Type *def, bool alias);
 Entity * check_selector                 (Checker *c, Operand *operand, AstNode *node, Type *type_hint);
 Entity * check_ident                    (Checker *c, Operand *o, AstNode *n, Type *named_type, Type *type_hint, bool allow_import_name);
 Entity * find_polymorphic_struct_entity(Checker *c, Type *original_type, isize param_count, Array<Operand> ordered_operands);
@@ -1421,6 +1421,14 @@ void check_unary_expr(Checker *c, Operand *o, Token op, AstNode *node) {
 		if (is_type_unsigned(type)) {
 			precision = cast(i32)(8 * type_size_of(c->allocator, type));
 		}
+		if (op.kind == Token_Xor && is_type_untyped(type)) {
+			gbString err_str = expr_to_string(node);
+			error(op, "Bitwise not cannot be applied to untyped constants `%s`", err_str);
+			gb_string_free(err_str);
+			o->mode = Addressing_Invalid;
+			return;
+		}
+
 		o->value = exact_unary_operator_value(op.kind, o->value, precision);
 
 		if (is_type_typed(type)) {
@@ -5353,7 +5361,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
 					for_array(i, cl->elems) {
 						AstNode *elem = cl->elems[i];
 						if (elem->kind != AstNode_FieldValue) {
-							error(elem, "Mixture of `field = value` and value elements in a structure literal is not allowed");
+							error(elem, "Mixture of `field = value` and value elements in a literal is not allowed");
 							continue;
 						}
 						ast_node(fv, FieldValue, elem);
@@ -5416,7 +5424,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
 					for_array(index, cl->elems) {
 						AstNode *elem = cl->elems[index];
 						if (elem->kind == AstNode_FieldValue) {
-							error(elem, "Mixture of `field = value` and value elements in a structure literal is not allowed");
+							error(elem, "Mixture of `field = value` and value elements in a literal is not allowed");
 							continue;
 						}
 						if (index >= field_count) {
@@ -6316,6 +6324,11 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
 		str = write_expr_to_string(str, ht->type);
 	case_end;
 
+	case_ast_node(ht, AliasType, node);
+		str = gb_string_appendc(str, "#alias ");
+		str = write_expr_to_string(str, ht->type);
+	case_end;
+
 
 	case_ast_node(pt, PolyType, node);
 		str = gb_string_append_rune(str, '$');

+ 6 - 0
src/check_type.cpp

@@ -2131,6 +2131,12 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type)
 		return check_type_internal(c, ht->type, type, named_type);
 	case_end;
 
+	case_ast_node(at, AliasType, e);
+		error(e, "Invalid use of `#alias`");
+		// NOTE(bill): Treat it as a HelperType to remove errors
+		return check_type_internal(c, at->type, type, named_type);
+	case_end;
+
 	case_ast_node(pt, PolyType, e);
 		AstNode *ident = pt->type;
 		if (ident->kind != AstNode_Ident) {

+ 12 - 0
src/checker.cpp

@@ -1716,7 +1716,19 @@ void init_preload(Checker *c) {
 		t_map_header = e->type;
 	}
 
+
+	{
+		String _global = str_lit("_global");
+
+		Entity *e = make_entity_import_name(c->allocator, c->global_scope->parent, make_token_ident(_global), t_invalid,
+		                                    str_lit(""), _global,
+		                                    c->global_scope);
+
+		add_entity(c, c->global_scope, nullptr, e);
+	}
+
 	c->done_preload = true;
+
 }
 
 

+ 1 - 0
src/entity.cpp

@@ -156,6 +156,7 @@ bool is_entity_exported(Entity *e) {
 	return name[0] != '_';
 }
 
+
 gb_global u64 global_entity_id = 0;
 
 Entity *alloc_entity(gbAllocator a, EntityKind kind, Scope *scope, Token token, Type *type) {

+ 1 - 1
src/gb/gb.h

@@ -7954,7 +7954,7 @@ gbFileTime gb_file_last_write_time(char const *filepath) {
 	time_t result = 0;
 	struct stat file_stat;
 
-	if (stat(filepath, &file_stat)) {
+	if (stat(filepath, &file_stat) == 0) {
 		result = file_stat.st_mtime;
 	}
 

+ 9 - 1
src/ir.cpp

@@ -119,6 +119,7 @@ struct irProcedure {
 	u64                   tags;
 	bool                  is_foreign;
 	bool                  is_export;
+	bool                  is_entry_point;
 
 	irValue *             return_ptr;
 	Array<irValue *>      params;
@@ -3743,6 +3744,12 @@ void ir_check_type_and_gen_for_proc_lit(irModule *m, String prefix_name, Type *t
 void ir_gen_global_type_name(irModule *m, Entity *e, String name) {
 	if (e->type == nullptr) return;
 
+	if (e->kind == Entity_TypeName && e->type->kind == Type_Named) {
+		if (e != e->type->Named.type_name) {
+			// NOTE(bill): Is alias
+			return;
+		}
+	}
 
 	Type *bt = base_type(e->type);
 
@@ -8267,7 +8274,6 @@ void ir_gen_tree(irGen *s) {
 
 		switch (e->kind) {
 		case Entity_TypeName:
-			GB_ASSERT(e->type->kind == Type_Named);
 			ir_gen_global_type_name(m, e, name);
 			break;
 
@@ -8374,6 +8380,7 @@ void ir_gen_tree(irGen *s) {
 
 		irProcedure *proc = &p->Proc;
 		proc->tags = ProcTag_no_inline; // TODO(bill): is no_inline a good idea?
+		proc->is_entry_point = true;
 		e->Procedure.link_name = name;
 
 		ir_begin_procedure_body(proc);
@@ -8444,6 +8451,7 @@ void ir_gen_tree(irGen *s) {
 
 		irProcedure *proc = &p->Proc;
 		proc->tags = ProcTag_no_inline; // TODO(bill): is no_inline a good idea?
+		proc->is_entry_point = true;
 		e->Procedure.link_name = name;
 
 		ir_begin_procedure_body(proc);

+ 3 - 0
src/ir_print.cpp

@@ -1678,6 +1678,9 @@ void ir_print_proc(irFileBuffer *f, irModule *m, irProcedure *proc) {
 				ir_write_string(f, "dllexport ");
 			}
 		}
+		// if (!proc->is_export && !proc->is_foreign && !proc->is_entry_point) {
+			// ir_write_string(f, "internal ");
+		// }
 	}
 
 	TypeProc *proc_type = &proc->type->Proc;

+ 19 - 2
src/parser.cpp

@@ -407,6 +407,10 @@ AST_NODE_KIND(_TypeBegin, "", i32) \
 		Token token; \
 		AstNode *type; \
 	}) \
+	AST_NODE_KIND(AliasType, "alias type", struct { \
+		Token token; \
+		AstNode *type; \
+	}) \
 	AST_NODE_KIND(PolyType, "polymorphic type", struct { \
 		Token    token; \
 		AstNode *type;  \
@@ -611,6 +615,7 @@ Token ast_node_token(AstNode *node) {
 
 	case AstNode_TypeType:         return node->TypeType.token;
 	case AstNode_HelperType:       return node->HelperType.token;
+	case AstNode_AliasType:        return node->AliasType.token;
 	case AstNode_PolyType:         return node->PolyType.token;
 	case AstNode_ProcType:         return node->ProcType.token;
 	case AstNode_PointerType:      return node->PointerType.token;
@@ -857,6 +862,9 @@ AstNode *clone_ast_node(gbAllocator a, AstNode *node) {
 	case AstNode_HelperType:
 		n->HelperType.type = clone_ast_node(a, n->HelperType.type);
 		break;
+	case AstNode_AliasType:
+		n->AliasType.type = clone_ast_node(a, n->AliasType.type);
+		break;
 	case AstNode_ProcType:
 		n->ProcType.params  = clone_ast_node(a, n->ProcType.params);
 		n->ProcType.results = clone_ast_node(a, n->ProcType.results);
@@ -1411,6 +1419,13 @@ AstNode *ast_helper_type(AstFile *f, Token token, AstNode *type) {
 	return result;
 }
 
+AstNode *ast_alias_type(AstFile *f, Token token, AstNode *type) {
+	AstNode *result = make_ast_node(f, AstNode_AliasType);
+	result->AliasType.token = token;
+	result->AliasType.type  = type;
+	return result;
+}
+
 
 AstNode *ast_poly_type(AstFile *f, Token token, AstNode *type, AstNode *specialization) {
 	AstNode *result = make_ast_node(f, AstNode_PolyType);
@@ -2256,8 +2271,10 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
 		if (allow_token(f, Token_type)) {
 			return ast_helper_type(f, token, parse_type(f));
 		}
-		Token name  = expect_token(f, Token_Ident);
-		if (name.string == "run") {
+		Token name = expect_token(f, Token_Ident);
+		if (name.string == "alias") {
+			return ast_alias_type(f, token, parse_type(f));
+		} else if (name.string == "run") {
 			AstNode *expr = parse_expr(f, false);
 			operand = ast_run_expr(f, token, name, expr);
 			if (unparen_expr(expr)->kind != AstNode_CallExpr) {