Better using; foreign system libraries; optional semicolons

This commit is contained in:
Ginger Bill
2016-08-30 18:39:29 +01:00
parent 0eaf7bd830
commit a06f70d5d9
17 changed files with 1136 additions and 1629 deletions
+81 -81
View File
@@ -3,166 +3,166 @@
#load "file.odin"
print_string :: proc(s: string) {
file_write(file_get_standard(FileStandard.OUTPUT), s as []byte);
file_write(file_get_standard(FileStandard.OUTPUT), s as []byte)
}
byte_reverse :: proc(b: []byte) {
n := len(b);
n := len(b)
for i := 0; i < n/2; i++ {
b[i], b[n-1-i] = b[n-1-i], b[i];
b[i], b[n-1-i] = b[n-1-i], b[i]
}
}
encode_rune :: proc(r: rune) -> ([4]byte, int) {
buf: [4]byte;
i := r as u32;
mask: byte : 0x3f;
buf: [4]byte
i := r as u32
mask: byte : 0x3f
if i <= 1<<7-1 {
buf[0] = r as byte;
return buf, 1;
buf[0] = r as byte
return buf, 1
}
if i <= 1<<11-1 {
buf[0] = 0xc0 | (r>>6) as byte;
buf[1] = 0x80 | (r) as byte & mask;
return buf, 2;
buf[0] = 0xc0 | (r>>6) as byte
buf[1] = 0x80 | (r) as byte & mask
return buf, 2
}
// Invalid or Surrogate range
if i > 0x0010ffff ||
(i >= 0xd800 && i <= 0xdfff) {
r = 0xfffd;
r = 0xfffd
}
if i <= 1<<16-1 {
buf[0] = 0xe0 | (r>>12) as byte;
buf[1] = 0x80 | (r>>6) as byte & mask;
buf[2] = 0x80 | (r) as byte & mask;
return buf, 3;
buf[0] = 0xe0 | (r>>12) as byte
buf[1] = 0x80 | (r>>6) as byte & mask
buf[2] = 0x80 | (r) as byte & mask
return buf, 3
}
buf[0] = 0xf0 | (r>>18) as byte;
buf[1] = 0x80 | (r>>12) as byte & mask;
buf[2] = 0x80 | (r>>6) as byte & mask;
buf[3] = 0x80 | (r) as byte & mask;
return buf, 4;
buf[0] = 0xf0 | (r>>18) as byte
buf[1] = 0x80 | (r>>12) as byte & mask
buf[2] = 0x80 | (r>>6) as byte & mask
buf[3] = 0x80 | (r) as byte & mask
return buf, 4
}
print_rune :: proc(r: rune) {
buf, n := encode_rune(r);
str := buf[:n] as string;
print_string(str);
buf, n := encode_rune(r)
str := buf[:n] as string
print_string(str)
}
print_space :: proc() { print_rune(#rune " "); }
print_nl :: proc() { print_rune(#rune "\n"); }
print_space :: proc() { print_rune(#rune " ") }
print_nl :: proc() { print_rune(#rune "\n") }
print_int :: proc(i: int) {
print_int_base(i, 10);
}
print_int_base :: proc(i, base: int) {
NUM_TO_CHAR_TABLE :: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@$";
NUM_TO_CHAR_TABLE :: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@$"
buf: [65]byte;
len := 0;
negative := false;
buf: [65]byte
len := 0
negative := false
if i < 0 {
negative = true;
i = -i;
negative = true
i = -i
}
if i == 0 {
buf[len] = #rune "0";
len++;
buf[len] = #rune "0"
len++
}
for i > 0 {
buf[len] = NUM_TO_CHAR_TABLE[i % base];
buf[len] = NUM_TO_CHAR_TABLE[i % base]
len++;
i /= base;
i /= base
}
if negative {
buf[len] = #rune "-";
len++;
buf[len] = #rune "-"
len++
}
byte_reverse(buf[:len]);
print_string(buf[:len] as string);
byte_reverse(buf[:len])
print_string(buf[:len] as string)
}
print_uint :: proc(i: uint) {
print__uint(i, 10, 0, #rune " ");
print__uint(i, 10, 0, #rune " ")
}
print__uint :: proc(i, base: uint, min_width: int, pad_char: byte) {
NUM_TO_CHAR_TABLE :: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@$";
NUM_TO_CHAR_TABLE :: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@$"
buf: [65]byte;
len := 0;
buf: [65]byte
len := 0
if i == 0 {
buf[len] = #rune "0";
len++;
buf[len] = #rune "0"
len++
}
for i > 0 {
buf[len] = NUM_TO_CHAR_TABLE[i % base];
len++;
i /= base;
buf[len] = NUM_TO_CHAR_TABLE[i % base]
len++
i /= base
}
for len < min_width {
buf[len] = pad_char;
len++;
buf[len] = pad_char
len++
}
byte_reverse(buf[:len]);
print_string(buf[:len] as string);
byte_reverse(buf[:len])
print_string(buf[:len] as string)
}
print_bool :: proc(b : bool) {
if b { print_string("true"); }
else { print_string("false"); }
if b { print_string("true") }
else { print_string("false") }
}
print_pointer :: proc(p: rawptr) #inline { print__uint(p as uint, 16, 0, #rune " "); }
print_pointer :: proc(p: rawptr) #inline { print__uint(p as uint, 16, 0, #rune " ") }
print_f32 :: proc(f: f32) #inline { print__f64(f as f64, 7); }
print_f64 :: proc(f: f64) #inline { print__f64(f, 10); }
print_f32 :: proc(f: f32) #inline { print__f64(f as f64, 7) }
print_f64 :: proc(f: f64) #inline { print__f64(f, 10) }
print__f64 :: proc(f: f64, decimal_places: int) {
if f == 0 {
print_rune(#rune "0");
return;
print_rune(#rune "0")
return
}
if f < 0 {
print_rune(#rune "-");
f = -f;
print_rune(#rune "-")
f = -f
}
print_u64 :: proc(i: u64) {
NUM_TO_CHAR_TABLE :: "0123456789";
NUM_TO_CHAR_TABLE :: "0123456789"
buf: [22]byte;
len := 0;
buf: [22]byte
len := 0
if i == 0 {
buf[len] = #rune "0";
len++;
buf[len] = #rune "0"
len++
}
for i > 0 {
buf[len] = NUM_TO_CHAR_TABLE[i % 10];
len++;
i /= 10;
buf[len] = NUM_TO_CHAR_TABLE[i % 10]
len++
i /= 10
}
byte_reverse(buf[:len]);
print_string(buf[:len] as string);
byte_reverse(buf[:len])
print_string(buf[:len] as string)
}
i := f as u64;
print_u64(i);
f -= i as f64;
i := f as u64
print_u64(i)
f -= i as f64
print_rune(#rune ".");
print_rune(#rune ".")
mult := 10.0;
mult := 10.0
for decimal_places := 6; decimal_places >= 0; decimal_places-- {
i = (f * mult) as u64;
print_u64(i as u64);
f -= i as f64 / mult;
mult *= 10;
i = (f * mult) as u64
print_u64(i as u64)
f -= i as f64 / mult
mult *= 10
}
}
+13 -745
View File
@@ -3,760 +3,28 @@
#load "game.odin"
main :: proc() {
// _ = hellope();
// variables();
// procedures();
// constants();
// types();
// data_control();
// using_fields();
Entity :: type struct {
guid: u64;
name: string;
}
Frog :: type struct {
using entity: Entity;
jump_height: f32;
}
e: Entity;
frog : Frog;
frog.name = "Ribbit";
a: [16]u32;
x := ^a[1];
y := ^a[5];
d := ptr_sub(y, ptr_offset(x, 1));
print_int(d); nl();
Thing :: type struct {
CONSTANT :: 123;
Thing :: type struct {
y: f32;
z: int;
w: int;
}
x: Thing;
}
test :: proc() -> int {
t_outer: Thing;
t_outer.x = Thing.Thing{};
using Thing;
t_inner: Thing;
t_inner.y = 1;
print_int(CONSTANT); nl();
return CONSTANT;
}
test__ := test();
// run_game();
}
hellope :: proc() -> int {
print_string("Hellope, 世界\n");
return 1;
}
// Line comment
/*
Block Comment
*/
/*
Nested /*
Block /*
Comment
*/
*/
*/
apple, banana, carrot: bool;
box, carboard: bool = true, false;
hellope_value: int = hellope(); // The procedure is ran just before `main`
variables :: proc() {
i: int; // initialized with zero value
j: int = 1;
x, y: int = 1, 2;
// Type inference
apple, banana, 世界 := true, 123, "world";
// Basic Types of the Language
//
// bool
//
// i8 i16 i32 i64 i128
// u8 u16 u32 u64 u128
//
// f32 f64
//
// int uint (size_of(int) == size_of(uint) == size_of(rawptr))
//
// rawptr (equivalent to void * in C/C++)
//
// string
//
// byte - alias for u8
// rune - alias for i32 // Unicode Codepoint
//
// "untyped" types can implicitly convert to any of the "typed" types
// Default Type
// untyped bool - bool
// untyped integer - int
// untyped float - f64
// untyped pointer - rawptr
// untyped string - string
// untyped rune - rune/i32
// Zero values
zero_numeric := 0;
zero_boolean := false;
zero_pointer := null;
zero_string1 := ""; // Escaped string
zero_string2 := ``; // Raw string
// Compound types have a different kind of zero value
// Unary operators
// +a
// -a
// ~a
// !a
// Binary operators
// a + b add
// a - b sub
// a ~ b xor
// a | b or
// a * b mul
// a / b quo
// a % b mod
// a & b and
// a &~ b bitclear == a & (~b)
// a << b shl
// a >> b shr
// a as Type // Type cast
// a transmute Type // Bit cast
// a == b eq
// a != b ne
// a < b lt
// a > b gt
// a <= b le
// a >= b ge
}
procedures :: proc() {
add :: proc(x: int, y: int) -> int {
return x + y;
}
print_int(add(3, 4)); // 7
print_nl();
add_v2 :: proc(x, y: int) -> int {
return x + y;
}
fibonacci :: proc(n: int) -> int {
if n < 2 {
return n;
}
return fibonacci(n-1) + fibonacci(n-2);
}
print_int(fibonacci(12)); nl();
swap_strings :: proc(x, y: string) -> (string, string) {
return y, x;
}
a, b := swap_strings("Hellope\n", "World\n");
print_string(a);
print_string(b);
a, b = b, a; // Quirk of grammar the of multiple assignments
// Swap variables
print_string(a);
print_string(b);
// Not a hint like C/C++, it's mandatory (unless it cannot do it but it will warn)
proc1 :: proc(a, b: int) #inline {
print_int(a + b);
}
proc2 :: proc(a, b: int) #no_inline {
print_int(a + b);
}
print_int(3 ''add 4); // Infix style
print_nl();
print_int(12 'fibonacci); // Postfix style
print_nl();
}
TAU :: 6.28318530718;
constants :: proc() {
TAU :: 6.28318530718; // untyped float
WORLD_JAPANESE :: "世界"; // untyped string
TAU_32 : f32 : 6.28318530718;
TAU_AS_32 :: 6.28318530718 as f32;
PI :: TAU / 2;
CLOSE_TO_PI :: 3;
DIFF :: (PI - CLOSE_TO_PI) / PI; // Evaluated at compile time
a := TAU; // the constant's value becomes typed as f64
b := CLOSE_TO_PI; // the constant's value becomes typed as int
c := DIFF;
}
nl :: proc() { print_nl(); }
types :: proc() {
x: int = 123;
y := x; // y: int = x;
// z: f32 = x; // invalid
z: f32 = x as f32;
ptr_z := ^z; // Pascal notation
ptr_z^ = 123; // Derefence Notation
w: f32 = ptr_z^; // 123
print_f32(z); nl();
// ^z - pointer to z
// z^ - z from pointer
// Implicit conversion to and from rawptr
r_ptr: rawptr = ptr_z;
ptr_z = r_ptr;
f32_array: [12]f32; // Array of 12 f32
f32_array[0] = 2;
f32_array[1] = 3;
// f32_array[-1] = 2; // Error - compile time check
// f32_array[13] = 2; // Error - compile time check
f32_array_len := len(f32_array); // builtin procedure
f32_array_cap := cap(f32_array); // == len(f32_array)
mda: [2][3][4]int; // Column-major
// mda[x][y][z]
api: [2]^f32;
papi: ^[2]^f32;
f32_slice: []f32; // Slice / Array reference
f32_slice = f32_array[0:5];
f32_slice = f32_array[:5];
f32_slice = f32_array[:]; // f32_array[0:len(f32_array)-1];
f32_slice = f32_array[1:5:7]; // low:1, high:5, max:7
// len: 5-1 == 4
// cap: 7-1 == 6
append_success := append(^f32_slice, 1);
_ = append(^f32_slice, 2);
_ = copy(f32_array[0:2], f32_array[2:4]); // You can use memcpy/memmove if you want
s := "Hellope World";
sub_string: string = s[5:10];
v0: {4}f32; // Vector of 4 f32
v0[0] = 1;
v0[1] = 3;
v0[2] = 6;
v0[3] = 10;
v1 := v0 + v0; // Simd Arithmetic
v1 = v1 - v0;
v1 *= v0; // i.e. hadamard product
v1 /= v0;
// builtin procedure
v2 := swizzle(v0, 3, 2, 1, 0); // {10, 6, 3, 1}
v3: {4}bool = v0 == v2;
// LLVM rant?
Vec4 :: type {4}f32;
Array3Int :: type [3]int;
Vec3 :: type struct {
x, y, z: f32;
}
BinaryNode :: type struct {
left, right: ^BinaryNode; // same format as procedure argument
data: rawptr;
}
AddProc :: type proc(a, b: int) -> int
Packed :: type struct #packed {
a: u8;
b: u16;
c: u32;
}
static_assert(size_of(Packed) == 7); // builtin procedure
{
MyInt :: type int;
x: int = 1;
y: MyInt = 2;
// z := x + y; // Failure - types cannot implicit convert*
z := x as MyInt + y; // Type cast using `as`
}
{
// From: Quake III Arena
Q_rsqrt :: proc(number: f32) -> f32 {
i: i32;
x2, y: f32;
THREE_HALFS :: 1.5;
x2 = number * 0.5;
y = number;
i = (^y as ^i32)^; // evil floating point bit level hacking
i = 0x5f3759df - i>>1; // what the fuck?
y = (^i as ^f32)^;
y = y * (THREE_HALFS - (x2 * y *y)); // 1st iteration
// y = y * (THREE_HALFS - (x2 * y *y)); // 2nd iteration, this can be removed
return y;
}
Q_rsqrt_v2 :: proc(number: f32) -> f32 {
THREE_HALFS :: 1.5;
x2 := number * 0.5;
y := number;
i := y transmute i32; // evil floating point bit level hacking
i = 0x5f3759df - i>>1; // what the fuck?
y = i transmute f32;
y = y * (THREE_HALFS - (x2 * y *y)); // 1st iteration
// y = y * (THREE_HALFS - (x2 * y *y)); // 2nd iteration, this can be removed
return y;
}
// NOTE(bill): transmute only works if the size of the types are equal
/*
// in C
union {
i32 i;
f32 y;
};
*/
}
{ // Enumeration
Thing :: type enum {
APPLE,
FROG,
TREE,
TOMB,
}
a := Thing.APPLE;
Sized :: type enum u64 {
APPLE,
FROG,
TREE,
TOMB,
}
static_assert(size_of(Sized) == size_of(u64));
Certain :: type enum {
APPLE = 3,
FROG,
TREE = 7,
TOMB,
}
static_assert(Certain.TOMB == 8);
}
{ // Untagged union
BitHack :: type union {
i: i32;
f: f32;
}
b: BitHack;
b.f = 123;
print_int_base(b.i as int, 16); print_nl();
// Manually tagged union
EntityKind :: type enum {
Invalid,
Constant,
Variable,
TypeName,
Procedure,
Builtin,
Count,
}
Entity :: type struct {
kind: EntityKind;
guid: u64;
// Other data
/*using*/
data: union {
constant: struct{};
variable: struct{
visited, is_field, used, anonymous: bool;
};
procedure: struct { used: bool; };
buitlin: struct { id: i32; };
};
}
// NOTE(bill): Tagged unions are not added yet but are planned
}
{ // Compound Literals
a := [3]int{1, 2, 3};
b := [3]int{};
c := [..]int{1, 2, 3};
d := []int{1, 2, 3}; // slice
e := {4}f32{1, 2, 3, 4};
f := {4}f32{1}; // broadcasts to all
// g := {4}f32{1, 2}; // require either 1 or 4 elements
Vec2 :: type {2}f32;
h := Vec2{1, 2};
i := Vec2{5} * h; // For strong type safety
// FORENOTE: 5 * h was originally allowed but it was an edge case in the
// compiler I didn't think it was enough to justify have it it.
print_f32(i[0]); print_rune(#rune ",");
print_f32(i[1]); print_nl();
}
{ // First class procedures
do_thing :: proc(p: proc(a, b: int) -> int) {
print_int(p(3, 4)); nl();
}
add :: proc(a, b: int) -> int {
return a + b;
}
add_lambda := proc(a, b: int) -> int {
return a - b;
}; // note semicolon
do_thing(add);
do_thing(add_lambda);
do_thing(proc(a, b: int) -> int { // Anonymous
return a * b;
});
}
{ // strings and runes
escaped := "Hellope World\n";
raw := `Hellope World\n`;
print_string(escaped);
print_string(raw); nl();
// Crap shader example
shader_string :=
`#version 410
layout (location = 0) in vec3 a_position;
layout (location = 1) in vec3 a_normal;
layout (location = 2) in vec2 a_tex_coord;
out vec3 v_position;
out vec3 v_normal;
out vec2 v_tex_coord;
uniform mat4 u_model_view;
uniform mat3 u_normal;
uniform mat4 u_proj;
uniform mat4 u_mvp;
void main() {
v_tex_coord = a_tex_coord;
v_normal = normalize(u_normal * a_normal);
v_position = vec3(u_model_view * vec4(a_position, 1.0));
gl_Position = u_mvp * vec4(a_position, 1.0);
}`;
hearts1 := #rune "💕";
hearts2 := #rune "\U0001f495"; // 32 bit
hearts3 := #rune "\xf0\x9f\x92\x95";
:= #rune "㐒";
㐒16 := #rune "\u4db5"; // 16 bit but will be `rune`
// String ideas "nicked" from Go, so far. I think I might change how some of it works later.
}
{ // size, align, offset
Thing :: type struct {
a: u8;
b: u16;
c, d, e: u32;
}
s := size_of(Thing);
a := align_of(Thing);
o := offset_of(Thing, b);
t: Thing;
sv := size_of_val(t);
av := align_of_val(t);
ov := offset_of_val(t.b);
}
}
data_control :: proc() {
sum := 0;
for i := 0; i < 12; i++ {
sum += 1;
}
print_string("sum = "); print_int(sum); nl();
sum = 1;
for ; sum < 1000000; {
sum += sum;
}
print_string("sum = "); print_int(sum); nl();
sum = 1;
for sum < 1000000 {
sum += sum;
}
print_string("sum = "); print_int(sum); nl();
// loop
// for { } == for true {}
// Question: Should I separate all these concepts and rename it?
//
// range - iterable
// for - c style
// while
// loop - while true
// Notes:
// conditions _must_ a boolean expression
// i++ and i-- are statements, not expressions
x := 2;
if x < 3 {
print_string("x < 2\n");
}
// Unified initializer syntax - same as for statements
if x := 2; x < 3 {
print_string("x < 2\n");
}
if x := 4; x < 3 {
print_string("Never called\n");
} else {
print_string("This is called\n");
}
{ // String comparison
a := "Hellope";
b := "World";
if a < b {
print_string("a < b\n");
}
if a != b {
print_string("a != b\n");
}
}
{ // Defer statement
defer print_string("日本語\n");
print_string("Japanese\n");
using x: struct { a, b: int }
}
{
defer print_string("1\n");
defer print_string("2\n");
defer print_string("3\n");
using t := new(Thing)
defer delete(t)
a = 321
print_int(a); nl()
}
{
prev_allocator := context.allocator;
context.allocator = __default_allocator();
defer context.allocator = prev_allocator;
// {
// using t := new(Thing)
// defer delete(t)
// a = 1337
// print_int(a); nl()
// }
File :: type struct { filename: string; };
FileError :: type int;
open_file :: proc(filename: string) -> (File, FileError) {
return File{}, 0;
}
close_file :: proc(f: ^File) {}
f, err := open_file("Test");
if err != 0 {
// handle error
}
defer close_file(^f);
// Rest of code!!!
}
for i := 0; i < 100; i++ {
blah := new(int);
defer {
defer print_string("!");
defer print_int(i);
defer print_string("dealloc");
delete(blah);
}
if i == 3 {
// defers called
continue;
}
if i == 5 {
// defers called
return; // End of procedure
}
if i == 8 {
// defers called
break; // never happens
}
}
defer print_string("It'll never happen, mate 1");
print_string("It'll never happen, mate 2");
print_string("It'll never happen, mate 3");
// run_game()
}
using_fields :: proc() {
{ // Everyday stuff
Vec3 :: type struct { x, y, z: f32; }
Entity :: type struct {
name: string;
using pos: Vec3;
vel: Vec3;
}
t: Entity;
t.y = 456;
print_f32(t.y); print_nl();
print_f32(t.pos.y); print_nl();
print_f32(t.vel.y); print_nl();
Frog :: type struct { // Subtype (kind of)
using entity: Entity;
colour: u32;
jump_height: f32;
}
f: Frog;
f.y = 1337;
print_f32(f.y); print_nl();
print_f32(f.pos.y); print_nl();
print_f32(f.vel.y); print_nl();
Buffalo :: type struct {
using entity: Entity;
speed: f32;
noise_level: f32;
}
}
{ // Crazy Shit
Vec2 :: type union {
using _xy: struct { x, y: f32; };
e: [2]f32;
v: {2}f32;
}
Entity :: type struct {
using pos: ^Vec2;
name: string;
}
t: Entity;
t.pos = new(Vec2);
defer delete(t.pos);
t.x = 123;
print_f32(t._xy.x); print_nl();
print_f32(t.pos.x); print_nl();
print_f32(t.pos._xy.x); print_nl();
}
}
nl :: proc() #inline { print_nl() }
+44 -44
View File
@@ -1,37 +1,37 @@
#load "win32.odin"
File :: type struct {
Handle :: type HANDLE;
handle: Handle;
Handle :: type HANDLE
handle: Handle
}
file_open :: proc(name: string) -> (File, bool) {
buf: [300]byte;
_ = copy(buf[:], name as []byte);
f := File{CreateFileA(^buf[0], FILE_GENERIC_READ, FILE_SHARE_READ, null, OPEN_EXISTING, 0, null)};
success := f.handle != INVALID_HANDLE_VALUE as File.Handle;
buf: [300]byte
_ = copy(buf[:], name as []byte)
f := File{CreateFileA(^buf[0], FILE_GENERIC_READ, FILE_SHARE_READ, null, OPEN_EXISTING, 0, null)}
success := f.handle != INVALID_HANDLE_VALUE as File.Handle
return f, success;
return f, success
}
file_create :: proc(name: string) -> (File, bool) {
buf: [300]byte;
_ = copy(buf[:], name as []byte);
buf: [300]byte
_ = copy(buf[:], name as []byte)
f := File{
handle = CreateFileA(^buf[0], FILE_GENERIC_WRITE, FILE_SHARE_READ, null, CREATE_ALWAYS, 0, null),
};
success := f.handle != INVALID_HANDLE_VALUE as File.Handle;
return f, success;
}
success := f.handle != INVALID_HANDLE_VALUE as File.Handle
return f, success
}
file_close :: proc(f: ^File) {
CloseHandle(f.handle);
CloseHandle(f.handle)
}
file_write :: proc(f: ^File, buf: []byte) -> bool {
bytes_written: i32;
return WriteFile(f.handle, ^buf[0], len(buf) as i32, ^bytes_written, null) != 0;
bytes_written: i32
return WriteFile(f.handle, ^buf[0], len(buf) as i32, ^bytes_written, null) != 0
}
FileStandard :: type enum {
@@ -47,60 +47,60 @@ __std_files: [FileStandard.COUNT as int]File;
file_get_standard :: proc(std: FileStandard) -> ^File {
// using FileStandard;
if (!__std_file_set) {
using FileStandard;
__std_files[INPUT] .handle = GetStdHandle(STD_INPUT_HANDLE);
__std_files[OUTPUT].handle = GetStdHandle(STD_OUTPUT_HANDLE);
__std_files[ERROR] .handle = GetStdHandle(STD_ERROR_HANDLE);
__std_file_set = true;
using FileStandard
__std_files[INPUT] .handle = GetStdHandle(STD_INPUT_HANDLE)
__std_files[OUTPUT].handle = GetStdHandle(STD_OUTPUT_HANDLE)
__std_files[ERROR] .handle = GetStdHandle(STD_ERROR_HANDLE)
__std_file_set = true
}
return ^__std_files[std];
return ^__std_files[std]
}
read_entire_file :: proc(name: string) -> (string, bool) {
buf: [300]byte;
_ = copy(buf[:], name as []byte);
c_string := ^buf[0];
buf: [300]byte
_ = copy(buf[:], name as []byte)
c_string := ^buf[0]
f, file_ok := file_open(name);
f, file_ok := file_open(name)
if !file_ok {
return "", false;
return "", false
}
defer file_close(^f);
defer file_close(^f)
length: i64;
file_size_ok := GetFileSizeEx(f.handle as HANDLE, ^length) != 0;
length: i64
file_size_ok := GetFileSizeEx(f.handle as HANDLE, ^length) != 0
if !file_size_ok {
return "", false;
return "", false
}
data := new_slice(u8, length);
data := new_slice(u8, length)
if ^data[0] == null {
return "", false;
return "", false
}
single_read_length: i32;
total_read: i64;
single_read_length: i32
total_read: i64
for total_read < length {
remaining := length - total_read;
to_read: u32;
MAX :: 0x7fffffff;
remaining := length - total_read
to_read: u32
MAX :: 0x7fffffff
if remaining <= MAX {
to_read = remaining as u32;
to_read = remaining as u32
} else {
to_read = MAX;
to_read = MAX
}
ReadFile(f.handle as HANDLE, ^data[total_read], to_read, ^single_read_length, null);
ReadFile(f.handle as HANDLE, ^data[total_read], to_read, ^single_read_length, null)
if single_read_length <= 0 {
delete(data);
return "", false;
delete(data)
return "", false
}
total_read += single_read_length as i64;
total_read += single_read_length as i64
}
return data as string, true;
return data as string, true
}
+89 -89
View File
@@ -2,55 +2,55 @@
#load "opengl.odin"
#load "math.odin"
TWO_HEARTS :: #rune "💕";
TWO_HEARTS :: #rune "💕"
win32_perf_count_freq := GetQueryPerformanceFrequency();
win32_perf_count_freq := GetQueryPerformanceFrequency()
time_now :: proc() -> f64 {
if win32_perf_count_freq == 0 {
debug_trap();
debug_trap()
}
counter: i64;
_ = QueryPerformanceCounter(^counter);
result := counter as f64 / win32_perf_count_freq as f64;
return result;
counter: i64
_ = QueryPerformanceCounter(^counter)
result := counter as f64 / win32_perf_count_freq as f64
return result
}
win32_print_last_error :: proc() {
err_code := GetLastError() as int;
err_code := GetLastError() as int
if err_code != 0 {
print_string("GetLastError: ");
print_int(err_code);
print_string("\n");
print_string("GetLastError: ")
print_int(err_code)
print_string("\n")
}
}
// Yuk!
to_c_string :: proc(s: string) -> ^u8 {
c_str: ^u8 = alloc(len(s)+1);
memory_copy(c_str, ^s[0], len(s));
ptr_offset(c_str, len(s))^ = 0;
return c_str;
c_str: ^u8 = alloc(len(s)+1)
memory_copy(c_str, ^s[0], len(s))
ptr_offset(c_str, len(s))^ = 0
return c_str
}
Window :: type struct {
width, height: int;
wc: WNDCLASSEXA;
dc: HDC;
hwnd: HWND;
opengl_context, rc: HGLRC;
c_title: ^u8;
width, height: int
wc: WNDCLASSEXA
dc: HDC
hwnd: HWND
opengl_context, rc: HGLRC
c_title: ^u8
}
make_window :: proc(title: string, msg, height: int, window_proc: WNDPROC) -> (Window, bool) {
w: Window;
w.width, w.height = msg, height;
w: Window
w.width, w.height = msg, height
class_name := "Win32-Odin-Window\x00";
c_class_name := ^class_name[0];
w.c_title = to_c_string(title);
class_name := "Win32-Odin-Window\x00"
c_class_name := ^class_name[0]
w.c_title = to_c_string(title)
instance := GetModuleHandleA(null);
instance := GetModuleHandleA(null)
w.wc = WNDCLASSEXA{
size = size_of(WNDCLASSEXA) as u32,
@@ -61,7 +61,7 @@ make_window :: proc(title: string, msg, height: int, window_proc: WNDPROC) -> (W
};
if RegisterClassExA(^w.wc) == 0 {
return w, false;
return w, false
}
w.hwnd = CreateWindowExA(0,
@@ -69,14 +69,14 @@ make_window :: proc(title: string, msg, height: int, window_proc: WNDPROC) -> (W
WS_VISIBLE | WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
CW_USEDEFAULT, CW_USEDEFAULT,
w.width as i32, w.height as i32,
null, null, instance, null);
null, null, instance, null)
if w.hwnd == null {
win32_print_last_error();
return w, false;
win32_print_last_error()
return w, false
}
w.dc = GetDC(w.hwnd);
w.dc = GetDC(w.hwnd)
{
pfd := PIXELFORMATDESCRIPTOR{
@@ -89,126 +89,126 @@ make_window :: proc(title: string, msg, height: int, window_proc: WNDPROC) -> (W
depth_bits = 24,
stencil_bits = 8,
layer_type = PFD_MAIN_PLANE,
};
}
SetPixelFormat(w.dc, ChoosePixelFormat(w.dc, ^pfd), null);
w.opengl_context = wglCreateContext(w.dc);
wglMakeCurrent(w.dc, w.opengl_context);
SetPixelFormat(w.dc, ChoosePixelFormat(w.dc, ^pfd), null)
w.opengl_context = wglCreateContext(w.dc)
wglMakeCurrent(w.dc, w.opengl_context)
attribs := [8]i32{
WGL_CONTEXT_MAJOR_VERSION_ARB, 2,
WGL_CONTEXT_MINOR_VERSION_ARB, 1,
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
0, // NOTE(bill): tells the proc that this is the end of attribs
};
}
wgl_string := "wglCreateContextAttribsARB\x00";
c_wgl_string := ^wgl_string[0];
wglCreateContextAttribsARB := wglGetProcAddress(c_wgl_string) as wglCreateContextAttribsARBType;
w.rc = wglCreateContextAttribsARB(w.dc, 0, ^attribs[0]);
wglMakeCurrent(w.dc, w.rc);
SwapBuffers(w.dc);
wgl_string := "wglCreateContextAttribsARB\x00"
c_wgl_string := ^wgl_string[0]
wglCreateContextAttribsARB := wglGetProcAddress(c_wgl_string) as wglCreateContextAttribsARBType
w.rc = wglCreateContextAttribsARB(w.dc, 0, ^attribs[0])
wglMakeCurrent(w.dc, w.rc)
SwapBuffers(w.dc)
}
return w, true;
return w, true
}
destroy_window :: proc(w: ^Window) {
heap_free(w.c_title);
heap_free(w.c_title)
}
display_window :: proc(w: ^Window) {
SwapBuffers(w.dc);
SwapBuffers(w.dc)
}
Entity :: type struct {
pos: Vec2;
dim: Vec2;
pos: Vec2
dim: Vec2
}
run_game :: proc() {
win32_proc :: proc(hwnd: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT #no_inline {
if msg == WM_DESTROY || msg == WM_CLOSE || msg == WM_QUIT {
ExitProcess(0);
return 0;
ExitProcess(0)
return 0
}
return DefWindowProcA(hwnd, msg, wparam, lparam);
return DefWindowProcA(hwnd, msg, wparam, lparam)
}
window, window_success := make_window("Odin Language Demo", 854, 480, win32_proc);
window, window_success := make_window("Odin Language Demo", 854, 480, win32_proc)
if !window_success {
return;
return
}
defer destroy_window(^window);
defer destroy_window(^window)
prev_time := time_now();
running := true;
prev_time := time_now()
running := true
pos := Vec2{100, 100};
pos := Vec2{100, 100}
for running {
curr_time := time_now();
dt := (curr_time - prev_time) as f32;
prev_time = curr_time;
curr_time := time_now()
dt := (curr_time - prev_time) as f32
prev_time = curr_time
msg: MSG;
msg: MSG
for PeekMessageA(^msg, null, 0, 0, PM_REMOVE) > 0 {
if msg.message == WM_QUIT {
running = false;
running = false
}
_ = TranslateMessage(^msg);
_ = DispatchMessageA(^msg);
_ = TranslateMessage(^msg)
_ = DispatchMessageA(^msg)
}
if is_key_down(VK_ESCAPE) {
running = false;
running = false
}
{
SPEED :: 500;
v: Vec2;
SPEED :: 500
v: Vec2
if is_key_down(VK_RIGHT) { v[0] += 1; }
if is_key_down(VK_LEFT) { v[0] -= 1; }
if is_key_down(VK_UP) { v[1] += 1; }
if is_key_down(VK_DOWN) { v[1] -= 1; }
if is_key_down(VK_RIGHT) { v[0] += 1 }
if is_key_down(VK_LEFT) { v[0] -= 1 }
if is_key_down(VK_UP) { v[1] += 1 }
if is_key_down(VK_DOWN) { v[1] -= 1 }
v = vec2_norm0(v);
v = vec2_norm0(v)
pos += v * Vec2{SPEED * dt};
pos += v * Vec2{SPEED * dt}
}
glClearColor(0.5, 0.7, 1.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(0.5, 0.7, 1.0, 1.0)
glClear(GL_COLOR_BUFFER_BIT)
glLoadIdentity();
glLoadIdentity()
glOrtho(0, window.width as f64,
0, window.height as f64, 0, 1);
0, window.height as f64, 0, 1)
draw_rect :: proc(x, y, w, h: f32) {
glBegin(GL_TRIANGLES);
glBegin(GL_TRIANGLES)
glColor3f(1, 0, 0); glVertex3f(x, y, 0);
glColor3f(0, 1, 0); glVertex3f(x+w, y, 0);
glColor3f(0, 0, 1); glVertex3f(x+w, y+h, 0);
glColor3f(1, 0, 0); glVertex3f(x, y, 0)
glColor3f(0, 1, 0); glVertex3f(x+w, y, 0)
glColor3f(0, 0, 1); glVertex3f(x+w, y+h, 0)
glColor3f(0, 0, 1); glVertex3f(x+w, y+h, 0);
glColor3f(1, 1, 0); glVertex3f(x, y+h, 0);
glColor3f(1, 0, 0); glVertex3f(x, y, 0);
glColor3f(0, 0, 1); glVertex3f(x+w, y+h, 0)
glColor3f(1, 1, 0); glVertex3f(x, y+h, 0)
glColor3f(1, 0, 0); glVertex3f(x, y, 0)
glEnd();
glEnd()
}
draw_rect(pos[0], pos[1], 50, 50);
draw_rect(pos[0], pos[1], 50, 50)
display_window(^window);
ms_to_sleep := (16 - 1000*dt) as i32;
display_window(^window)
ms_to_sleep := (16 - 1000*dt) as i32
if ms_to_sleep > 0 {
sleep_ms(ms_to_sleep);
sleep_ms(ms_to_sleep)
}
}
}
+91 -91
View File
@@ -1,162 +1,162 @@
MATH_TAU :: 6.28318530717958647692528676655900576;
MATH_PI :: 3.14159265358979323846264338327950288;
MATH_ONE_OVER_TAU :: 0.636619772367581343075535053490057448;
MATH_ONE_OVER_PI :: 0.159154943091895335768883763372514362;
MATH_TAU :: 6.28318530717958647692528676655900576
MATH_PI :: 3.14159265358979323846264338327950288
MATH_ONE_OVER_TAU :: 0.636619772367581343075535053490057448
MATH_ONE_OVER_PI :: 0.159154943091895335768883763372514362
MATH_E :: 2.71828182845904523536;
MATH_SQRT_TWO :: 1.41421356237309504880168872420969808;
MATH_SQRT_THREE :: 1.73205080756887729352744634150587236;
MATH_SQRT_FIVE :: 2.23606797749978969640917366873127623;
MATH_E :: 2.71828182845904523536
MATH_SQRT_TWO :: 1.41421356237309504880168872420969808
MATH_SQRT_THREE :: 1.73205080756887729352744634150587236
MATH_SQRT_FIVE :: 2.23606797749978969640917366873127623
MATH_LOG_TWO :: 0.693147180559945309417232121458176568;
MATH_LOG_TEN :: 2.30258509299404568401799145468436421;
MATH_LOG_TWO :: 0.693147180559945309417232121458176568
MATH_LOG_TEN :: 2.30258509299404568401799145468436421
MATH_EPSILON :: 1.19209290e-7;
MATH_EPSILON :: 1.19209290e-7
τ :: MATH_TAU;
π :: MATH_PI;
τ :: MATH_TAU
π :: MATH_PI
Vec2 :: type {2}f32;
Vec3 :: type {3}f32;
Vec4 :: type {4}f32;
Vec2 :: type {2}f32
Vec3 :: type {3}f32
Vec4 :: type {4}f32
Mat2 :: type {4}f32;
Mat3 :: type {9}f32;
Mat4 :: type {16}f32;
Mat2 :: type {4}f32
Mat3 :: type {9}f32
Mat4 :: type {16}f32
fsqrt :: proc(x: f32) -> f32 #foreign "llvm.sqrt.f32"
fsin :: proc(x: f32) -> f32 #foreign "llvm.sin.f32"
fcos :: proc(x: f32) -> f32 #foreign "llvm.cos.f32"
flerp :: proc(a, b, t: f32) -> f32 { return a*(1-t) + b*t; }
fclamp :: proc(x, lower, upper: f32) -> f32 { return fmin(fmax(x, lower), upper); }
fclamp01 :: proc(x: f32) -> f32 { return fclamp(x, 0, 1); }
fabs :: proc(x: f32) -> f32 { if x < 0 { x = -x; } return x; }
fsign :: proc(x: f32) -> f32 { if x >= 0 { return +1; } return -1; }
flerp :: proc(a, b, t: f32) -> f32 { return a*(1-t) + b*t }
fclamp :: proc(x, lower, upper: f32) -> f32 { return fmin(fmax(x, lower), upper) }
fclamp01 :: proc(x: f32) -> f32 { return fclamp(x, 0, 1) }
fabs :: proc(x: f32) -> f32 { if x < 0 { x = -x } return x }
fsign :: proc(x: f32) -> f32 { if x >= 0 { return +1 } return -1 }
fmin :: proc(a, b: f32) -> f32 { if a < b { return a; } return b; }
fmax :: proc(a, b: f32) -> f32 { if a > b { return a; } return b; }
fmin3 :: proc(a, b, c: f32) -> f32 { return fmin(fmin(a, b), c); }
fmax3 :: proc(a, b, c: f32) -> f32 { return fmax(fmax(a, b), c); }
fmin :: proc(a, b: f32) -> f32 { if a < b { return a } return b }
fmax :: proc(a, b: f32) -> f32 { if a > b { return a } return b }
fmin3 :: proc(a, b, c: f32) -> f32 { return fmin(fmin(a, b), c) }
fmax3 :: proc(a, b, c: f32) -> f32 { return fmax(fmax(a, b), c) }
copy_sign :: proc(x, y: f32) -> f32 {
ix := x transmute u32;
iy := y transmute u32;
ix &= 0x7fffffff;
ix |= iy & 0x80000000;
return ix transmute f32;
ix := x transmute u32
iy := y transmute u32
ix &= 0x7fffffff
ix |= iy & 0x80000000
return ix transmute f32
}
round :: proc(x: f32) -> f32 {
if x >= 0 {
return floor(x + 0.5);
return floor(x + 0.5)
}
return ceil(x - 0.5);
return ceil(x - 0.5)
}
floor :: proc(x: f32) -> f32 {
if x >= 0 {
return x as int as f32;
return x as int as f32
}
return (x-0.5) as int as f32;
return (x-0.5) as int as f32
}
ceil :: proc(x: f32) -> f32 {
if x < 0 {
return x as int as f32;
return x as int as f32
}
return ((x as int)+1) as f32;
return ((x as int)+1) as f32
}
remainder :: proc(x, y: f32) -> f32 {
return x - round(x/y) * y;
return x - round(x/y) * y
}
fmod :: proc(x, y: f32) -> f32 {
y = fabs(y);
result := remainder(fabs(x), y);
y = fabs(y)
result := remainder(fabs(x), y)
if fsign(result) < 0 {
result += y;
result += y
}
return copy_sign(result, x);
return copy_sign(result, x)
}
to_radians :: proc(degrees: f32) -> f32 { return degrees * MATH_TAU / 360; }
to_degrees :: proc(radians: f32) -> f32 { return radians * 360 / MATH_TAU; }
to_radians :: proc(degrees: f32) -> f32 { return degrees * MATH_TAU / 360 }
to_degrees :: proc(radians: f32) -> f32 { return radians * 360 / MATH_TAU }
dot2 :: proc(a, b: Vec2) -> f32 { c := a*b; return c[0] + c[1]; }
dot3 :: proc(a, b: Vec3) -> f32 { c := a*b; return c[0] + c[1] + c[2]; }
dot4 :: proc(a, b: Vec4) -> f32 { c := a*b; return c[0] + c[1] + c[2] + c[3]; }
dot2 :: proc(a, b: Vec2) -> f32 { c := a*b; return c[0] + c[1] }
dot3 :: proc(a, b: Vec3) -> f32 { c := a*b; return c[0] + c[1] + c[2] }
dot4 :: proc(a, b: Vec4) -> f32 { c := a*b; return c[0] + c[1] + c[2] + c[3] }
cross :: proc(x, y: Vec3) -> Vec3 {
a := swizzle(x, 1, 2, 0) * swizzle(y, 2, 0, 1);
b := swizzle(x, 2, 0, 1) * swizzle(y, 1, 2, 0);
return a - b;
a := swizzle(x, 1, 2, 0) * swizzle(y, 2, 0, 1)
b := swizzle(x, 2, 0, 1) * swizzle(y, 1, 2, 0)
return a - b
}
vec2_mag :: proc(v: Vec2) -> f32 { return fsqrt(v ''dot2 v); }
vec3_mag :: proc(v: Vec3) -> f32 { return fsqrt(v ''dot3 v); }
vec4_mag :: proc(v: Vec4) -> f32 { return fsqrt(v ''dot4 v); }
vec2_mag :: proc(v: Vec2) -> f32 { return fsqrt(v ''dot2 v) }
vec3_mag :: proc(v: Vec3) -> f32 { return fsqrt(v ''dot3 v) }
vec4_mag :: proc(v: Vec4) -> f32 { return fsqrt(v ''dot4 v) }
vec2_norm :: proc(v: Vec2) -> Vec2 { return v / Vec2{vec2_mag(v)}; }
vec3_norm :: proc(v: Vec3) -> Vec3 { return v / Vec3{vec3_mag(v)}; }
vec4_norm :: proc(v: Vec4) -> Vec4 { return v / Vec4{vec4_mag(v)}; }
vec2_norm :: proc(v: Vec2) -> Vec2 { return v / Vec2{vec2_mag(v)} }
vec3_norm :: proc(v: Vec3) -> Vec3 { return v / Vec3{vec3_mag(v)} }
vec4_norm :: proc(v: Vec4) -> Vec4 { return v / Vec4{vec4_mag(v)} }
vec2_norm0 :: proc(v: Vec2) -> Vec2 {
m := vec2_mag(v);
m := vec2_mag(v)
if m == 0 {
return Vec2{0};
return Vec2{0}
}
return v / Vec2{m};
return v / Vec2{m}
}
vec3_norm0 :: proc(v: Vec3) -> Vec3 {
m := vec3_mag(v);
m := vec3_mag(v)
if m == 0 {
return Vec3{0};
return Vec3{0}
}
return v / Vec3{m};
return v / Vec3{m}
}
vec4_norm0 :: proc(v: Vec4) -> Vec4 {
m := vec4_mag(v);
m := vec4_mag(v)
if m == 0 {
return Vec4{0};
return Vec4{0}
}
return v / Vec4{m};
return v / Vec4{m}
}
F32_DIG :: 6;
F32_EPSILON :: 1.192092896e-07;
F32_GUARD :: 0;
F32_MANT_DIG :: 24;
F32_MAX :: 3.402823466e+38;
F32_MAX_10_EXP :: 38;
F32_MAX_EXP :: 128;
F32_MIN :: 1.175494351e-38;
F32_MIN_10_EXP :: -37;
F32_MIN_EXP :: -125;
F32_NORMALIZE :: 0;
F32_RADIX :: 2;
F32_ROUNDS :: 1;
F32_DIG :: 6
F32_EPSILON :: 1.192092896e-07
F32_GUARD :: 0
F32_MANT_DIG :: 24
F32_MAX :: 3.402823466e+38
F32_MAX_10_EXP :: 38
F32_MAX_EXP :: 128
F32_MIN :: 1.175494351e-38
F32_MIN_10_EXP :: -37
F32_MIN_EXP :: -125
F32_NORMALIZE :: 0
F32_RADIX :: 2
F32_ROUNDS :: 1
F64_DIG :: 15; // # of decimal digits of precision
F64_EPSILON :: 2.2204460492503131e-016; // smallest such that 1.0+F64_EPSILON != 1.0
F64_MANT_DIG :: 53; // # of bits in mantissa
F64_MAX :: 1.7976931348623158e+308; // max value
F64_MAX_10_EXP :: 308; // max decimal exponent
F64_MAX_EXP :: 1024; // max binary exponent
F64_MIN :: 2.2250738585072014e-308; // min positive value
F64_MIN_10_EXP :: -307; // min decimal exponent
F64_MIN_EXP :: -1021; // min binary exponent
F64_RADIX :: 2; // exponent radix
F64_ROUNDS :: 1; // addition rounding: near
F64_DIG :: 15 // # of decimal digits of precision
F64_EPSILON :: 2.2204460492503131e-016 // smallest such that 1.0+F64_EPSILON != 1.0
F64_MANT_DIG :: 53 // # of bits in mantissa
F64_MAX :: 1.7976931348623158e+308 // max value
F64_MAX_10_EXP :: 308 // max decimal exponent
F64_MAX_EXP :: 1024 // max binary exponent
F64_MIN :: 2.2250738585072014e-308 // min positive value
F64_MIN_10_EXP :: -307 // min decimal exponent
F64_MIN_EXP :: -1021 // min binary exponent
F64_RADIX :: 2 // exponent radix
F64_ROUNDS :: 1 // addition rounding: near
+24 -22
View File
@@ -1,29 +1,31 @@
GL_ZERO :: 0x0000;
GL_ONE :: 0x0001;
GL_TRIANGLES :: 0x0004;
GL_BLEND :: 0x0BE2;
GL_SRC_ALPHA :: 0x0302;
GL_ONE_MINUS_SRC_ALPHA :: 0x0303;
GL_TEXTURE_2D :: 0x0DE1;
GL_RGBA8 :: 0x8058;
GL_UNSIGNED_BYTE :: 0x1401;
GL_BGRA_EXT :: 0x80E1;
GL_TEXTURE_MAX_LEVEL :: 0x813D;
GL_RGBA :: 0x1908;
#foreign_system_library "opengl32"
GL_NEAREST :: 0x2600;
GL_LINEAR :: 0x2601;
GL_ZERO :: 0x0000
GL_ONE :: 0x0001
GL_TRIANGLES :: 0x0004
GL_BLEND :: 0x0be2
GL_SRC_ALPHA :: 0x0302
GL_ONE_MINUS_SRC_ALPHA :: 0x0303
GL_TEXTURE_2D :: 0x0de1
GL_RGBA8 :: 0x8058
GL_UNSIGNED_BYTE :: 0x1401
GL_BGRA_EXT :: 0x80e1
GL_TEXTURE_MAX_LEVEL :: 0x813d
GL_RGBA :: 0x1908
GL_DEPTH_BUFFER_BIT :: 0x00000100;
GL_STENCIL_BUFFER_BIT :: 0x00000400;
GL_COLOR_BUFFER_BIT :: 0x00004000;
GL_NEAREST :: 0x2600
GL_LINEAR :: 0x2601
GL_TEXTURE_MAX_ANISOTROPY_EXT :: 0x84FE;
GL_DEPTH_BUFFER_BIT :: 0x00000100
GL_STENCIL_BUFFER_BIT :: 0x00000400
GL_COLOR_BUFFER_BIT :: 0x00004000
GL_TEXTURE_MAG_FILTER :: 0x2800;
GL_TEXTURE_MIN_FILTER :: 0x2801;
GL_TEXTURE_WRAP_S :: 0x2802;
GL_TEXTURE_WRAP_T :: 0x2803;
GL_TEXTURE_MAX_ANISOTROPY_EXT :: 0x84fe
GL_TEXTURE_MAG_FILTER :: 0x2800
GL_TEXTURE_MIN_FILTER :: 0x2801
GL_TEXTURE_WRAP_S :: 0x2802
GL_TEXTURE_WRAP_T :: 0x2803
glClear :: proc(mask: u32) #foreign
glClearColor :: proc(r, g, b, a: f32) #foreign
+166 -170
View File
@@ -4,167 +4,167 @@ debug_trap :: proc() #foreign "llvm.debugtrap"
// TODO(bill): make custom heap procedures
heap_alloc :: proc(len: int) -> rawptr {
return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len)
}
heap_free :: proc(ptr: rawptr) {
_ = HeapFree(GetProcessHeap(), 0, ptr);
_ = HeapFree(GetProcessHeap(), 0, ptr)
}
memory_compare :: proc(dst, src: rawptr, len: int) -> int {
s1, s2: ^u8 = dst, src;
s1, s2: ^u8 = dst, src
for i := 0; i < len; i++ {
a := ptr_offset(s1, i)^;
b := ptr_offset(s2, i)^;
a := ptr_offset(s1, i)^
b := ptr_offset(s2, i)^
if a != b {
return (a - b) as int;
return (a - b) as int
}
}
return 0;
return 0
}
memory_copy :: proc(dst, src: rawptr, n: int) #inline {
if dst == src {
return;
return
}
v128b :: type {4}u32;
static_assert(align_of(v128b) == 16);
v128b :: type {4}u32
static_assert(align_of(v128b) == 16)
d, s: ^u8 = dst, src;
d, s: ^u8 = dst, src
for ; s as uint % 16 != 0 && n != 0; n-- {
d^ = s^;
d, s = ptr_offset(d, 1), ptr_offset(s, 1);
d^ = s^
d, s = ptr_offset(d, 1), ptr_offset(s, 1)
}
if d as uint % 16 == 0 {
for ; n >= 16; d, s, n = ptr_offset(d, 16), ptr_offset(s, 16), n-16 {
(d as ^v128b)^ = (s as ^v128b)^;
(d as ^v128b)^ = (s as ^v128b)^
}
if n&8 != 0 {
(d as ^u64)^ = (s as ^u64)^;
d, s = ptr_offset(d, 8), ptr_offset(s, 8);
(d as ^u64)^ = (s as ^u64)^
d, s = ptr_offset(d, 8), ptr_offset(s, 8)
}
if n&4 != 0 {
(d as ^u32)^ = (s as ^u32)^;
d, s = ptr_offset(d, 4), ptr_offset(s, 4);
d, s = ptr_offset(d, 4), ptr_offset(s, 4)
}
if n&2 != 0 {
(d as ^u16)^ = (s as ^u16)^;
d, s = ptr_offset(d, 2), ptr_offset(s, 2);
(d as ^u16)^ = (s as ^u16)^
d, s = ptr_offset(d, 2), ptr_offset(s, 2)
}
if n&1 != 0 {
d^ = s^;
d, s = ptr_offset(d, 1), ptr_offset(s, 1);
d^ = s^
d, s = ptr_offset(d, 1), ptr_offset(s, 1)
}
return;
}
// IMPORTANT NOTE(bill): Little endian only
LS :: proc(a, b: u32) -> u32 #inline { return a << b; }
RS :: proc(a, b: u32) -> u32 #inline { return a >> b; }
LS :: proc(a, b: u32) -> u32 #inline { return a << b }
RS :: proc(a, b: u32) -> u32 #inline { return a >> b }
/* NOTE(bill): Big endian version
LS :: proc(a, b: u32) -> u32 #inline { return a >> b; }
RS :: proc(a, b: u32) -> u32 #inline { return a << b; }
*/
w, x: u32;
w, x: u32
if d as uint % 4 == 1 {
w = (s as ^u32)^;
d^ = s^; d = ptr_offset(d, 1); s = ptr_offset(s, 1);
d^ = s^; d = ptr_offset(d, 1); s = ptr_offset(s, 1);
d^ = s^; d = ptr_offset(d, 1); s = ptr_offset(s, 1);
n -= 3;
w = (s as ^u32)^
d^ = s^; d = ptr_offset(d, 1); s = ptr_offset(s, 1)
d^ = s^; d = ptr_offset(d, 1); s = ptr_offset(s, 1)
d^ = s^; d = ptr_offset(d, 1); s = ptr_offset(s, 1)
n -= 3
for n > 16 {
d32 := d as ^u32;
s32 := ptr_offset(s, 1) as ^u32;
x = s32^; d32^ = LS(w, 24) | RS(x, 8);
d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1);
w = s32^; d32^ = LS(x, 24) | RS(w, 8);
d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1);
x = s32^; d32^ = LS(w, 24) | RS(x, 8);
d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1);
w = s32^; d32^ = LS(x, 24) | RS(w, 8);
d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1);
d32 := d as ^u32
s32 := ptr_offset(s, 1) as ^u32
x = s32^; d32^ = LS(w, 24) | RS(x, 8)
d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1)
w = s32^; d32^ = LS(x, 24) | RS(w, 8)
d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1)
x = s32^; d32^ = LS(w, 24) | RS(x, 8)
d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1)
w = s32^; d32^ = LS(x, 24) | RS(w, 8)
d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1)
d, s, n = ptr_offset(d, 16), ptr_offset(s, 16), n-16;
d, s, n = ptr_offset(d, 16), ptr_offset(s, 16), n-16
}
} else if d as uint % 4 == 2 {
w = (s as ^u32)^;
d^ = s^; d = ptr_offset(d, 1); s = ptr_offset(s, 1);
d^ = s^; d = ptr_offset(d, 1); s = ptr_offset(s, 1);
n -= 2;
w = (s as ^u32)^
d^ = s^; d = ptr_offset(d, 1); s = ptr_offset(s, 1)
d^ = s^; d = ptr_offset(d, 1); s = ptr_offset(s, 1)
n -= 2
for n > 17 {
d32 := d as ^u32;
s32 := ptr_offset(s, 2) as ^u32;
x = s32^; d32^ = LS(w, 16) | RS(x, 16);
d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1);
w = s32^; d32^ = LS(x, 16) | RS(w, 16);
d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1);
x = s32^; d32^ = LS(w, 16) | RS(x, 16);
d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1);
w = s32^; d32^ = LS(x, 16) | RS(w, 16);
d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1);
d32 := d as ^u32
s32 := ptr_offset(s, 2) as ^u32
x = s32^; d32^ = LS(w, 16) | RS(x, 16)
d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1)
w = s32^; d32^ = LS(x, 16) | RS(w, 16)
d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1)
x = s32^; d32^ = LS(w, 16) | RS(x, 16)
d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1)
w = s32^; d32^ = LS(x, 16) | RS(w, 16)
d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1)
d, s, n = ptr_offset(d, 16), ptr_offset(s, 16), n-16;
d, s, n = ptr_offset(d, 16), ptr_offset(s, 16), n-16
}
} else if d as uint % 4 == 3 {
w = (s as ^u32)^;
d^ = s^;
n -= 1;
w = (s as ^u32)^
d^ = s^
n -= 1
for n > 18 {
d32 := d as ^u32;
s32 := ptr_offset(s, 3) as ^u32;
x = s32^; d32^ = LS(w, 8) | RS(x, 24);
d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1);
w = s32^; d32^ = LS(x, 8) | RS(w, 24);
d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1);
x = s32^; d32^ = LS(w, 8) | RS(x, 24);
d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1);
w = s32^; d32^ = LS(x, 8) | RS(w, 24);
d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1);
d32 := d as ^u32
s32 := ptr_offset(s, 3) as ^u32
x = s32^; d32^ = LS(w, 8) | RS(x, 24)
d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1)
w = s32^; d32^ = LS(x, 8) | RS(w, 24)
d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1)
x = s32^; d32^ = LS(w, 8) | RS(x, 24)
d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1)
w = s32^; d32^ = LS(x, 8) | RS(w, 24)
d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1)
d, s, n = ptr_offset(d, 16), ptr_offset(s, 16), n-16;
d, s, n = ptr_offset(d, 16), ptr_offset(s, 16), n-16
}
}
if n&16 != 0 {
(d as ^v128b)^ = (s as ^v128b)^;
d, s = ptr_offset(d, 16), ptr_offset(s, 16);
(d as ^v128b)^ = (s as ^v128b)^
d, s = ptr_offset(d, 16), ptr_offset(s, 16)
}
if n&8 != 0 {
(d as ^u64)^ = (s as ^u64)^;
d, s = ptr_offset(d, 8), ptr_offset(s, 8);
(d as ^u64)^ = (s as ^u64)^
d, s = ptr_offset(d, 8), ptr_offset(s, 8)
}
if n&4 != 0 {
(d as ^u32)^ = (s as ^u32)^;
d, s = ptr_offset(d, 4), ptr_offset(s, 4);
d, s = ptr_offset(d, 4), ptr_offset(s, 4)
}
if n&2 != 0 {
(d as ^u16)^ = (s as ^u16)^;
d, s = ptr_offset(d, 2), ptr_offset(s, 2);
(d as ^u16)^ = (s as ^u16)^
d, s = ptr_offset(d, 2), ptr_offset(s, 2)
}
if n&1 != 0 {
d^ = s^;
d^ = s^
}
}
memory_move :: proc(dst, src: rawptr, n: int) #inline {
d, s: ^u8 = dst, src;
d, s: ^u8 = dst, src
if d == s {
return;
return
}
if d >= ptr_offset(s, n) || ptr_offset(d, n) <= s {
memory_copy(d, s, n);
return;
memory_copy(d, s, n)
return
}
// TODO(bill): Vectorize the shit out of this
@@ -172,94 +172,94 @@ memory_move :: proc(dst, src: rawptr, n: int) #inline {
if s as int % size_of(int) == d as int % size_of(int) {
for d as int % size_of(int) != 0 {
if n == 0 {
return;
return
}
n--;
d^ = s^;
d, s = ptr_offset(d, 1), ptr_offset(s, 1);
n--
d^ = s^
d, s = ptr_offset(d, 1), ptr_offset(s, 1)
}
di, si := d as ^int, s as ^int;
di, si := d as ^int, s as ^int
for n >= size_of(int) {
di^ = si^;
di, si = ptr_offset(di, 1), ptr_offset(si, 1);
n -= size_of(int);
di^ = si^
di, si = ptr_offset(di, 1), ptr_offset(si, 1)
n -= size_of(int)
}
}
for ; n > 0; n-- {
d^ = s^;
d, s = ptr_offset(d, 1), ptr_offset(s, 1);
d^ = s^
d, s = ptr_offset(d, 1), ptr_offset(s, 1)
}
} else {
if s as int % size_of(int) == d as int % size_of(int) {
for ptr_offset(d, n) as int % size_of(int) != 0 {
if n == 0 {
return;
return
}
n--;
d^ = s^;
d, s = ptr_offset(d, 1), ptr_offset(s, 1);
n--
d^ = s^
d, s = ptr_offset(d, 1), ptr_offset(s, 1)
}
for n >= size_of(int) {
n -= size_of(int);
di := ptr_offset(d, n) as ^int;
si := ptr_offset(s, n) as ^int;
di^ = si^;
n -= size_of(int)
di := ptr_offset(d, n) as ^int
si := ptr_offset(s, n) as ^int
di^ = si^
}
for ; n > 0; n-- {
d^ = s^;
d, s = ptr_offset(d, 1), ptr_offset(s, 1);
d^ = s^
d, s = ptr_offset(d, 1), ptr_offset(s, 1)
}
}
for n > 0 {
n--;
dn := ptr_offset(d, n);
sn := ptr_offset(s, n);
dn^ = sn^;
n--
dn := ptr_offset(d, n)
sn := ptr_offset(s, n)
dn^ = sn^
}
}
}
__string_eq :: proc(a, b : string) -> bool {
__string_eq :: proc(a, b: string) -> bool {
if len(a) != len(b) {
return false;
return false
}
if ^a[0] == ^b[0] {
return true;
return true
}
return memory_compare(^a[0], ^b[0], len(a)) == 0;
return memory_compare(^a[0], ^b[0], len(a)) == 0
}
__string_ne :: proc(a, b : string) -> bool #inline {
return !__string_eq(a, b);
return !__string_eq(a, b)
}
__string_cmp :: proc(a, b : string) -> int {
min_len := len(a);
min_len := len(a)
if len(b) < min_len {
min_len = len(b);
min_len = len(b)
}
for i := 0; i < min_len; i++ {
x := a[i];
y := b[i];
x := a[i]
y := b[i]
if x < y {
return -1;
return -1
} else if x > y {
return +1;
return +1
}
}
if len(a) < len(b) {
return -1;
return -1
} else if len(a) > len(b) {
return +1;
return +1
}
return 0;
return 0
}
__string_lt :: proc(a, b : string) -> bool #inline { return __string_cmp(a, b) < 0; }
__string_gt :: proc(a, b : string) -> bool #inline { return __string_cmp(a, b) > 0; }
__string_le :: proc(a, b : string) -> bool #inline { return __string_cmp(a, b) <= 0; }
__string_ge :: proc(a, b : string) -> bool #inline { return __string_cmp(a, b) >= 0; }
__string_lt :: proc(a, b : string) -> bool #inline { return __string_cmp(a, b) < 0 }
__string_gt :: proc(a, b : string) -> bool #inline { return __string_cmp(a, b) > 0 }
__string_le :: proc(a, b : string) -> bool #inline { return __string_cmp(a, b) <= 0 }
__string_ge :: proc(a, b : string) -> bool #inline { return __string_cmp(a, b) >= 0 }
@@ -275,117 +275,113 @@ AllocationMode :: type enum {
AllocatorProc :: type proc(allocator_data: rawptr, mode: AllocationMode,
size, alignment: int,
old_memory: rawptr, old_size: int, flags: u64) -> rawptr;
old_memory: rawptr, old_size: int, flags: u64) -> rawptr
Allocator :: type struct {
procedure: AllocatorProc;
data: rawptr;
data: rawptr
}
Context :: type struct {
thread_id: i32;
thread_id: i32
user_index: i32;
user_data: rawptr;
user_index: i32
user_data: rawptr
allocator: Allocator;
allocator: Allocator
}
#thread_local context: Context;
#thread_local context: Context
DEFAULT_ALIGNMENT :: 2*size_of(int);
DEFAULT_ALIGNMENT :: 2*size_of(int)
__check_context :: proc() {
static_assert(AllocationMode.ALLOC == 0);
static_assert(AllocationMode.DEALLOC == 1);
static_assert(AllocationMode.DEALLOC_ALL == 2);
static_assert(AllocationMode.RESIZE == 3);
if context.allocator.procedure == null {
context.allocator = __default_allocator();
context.allocator = __default_allocator()
}
}
alloc :: proc(size: int) -> rawptr #inline { return alloc_align(size, DEFAULT_ALIGNMENT); }
alloc :: proc(size: int) -> rawptr #inline { return alloc_align(size, DEFAULT_ALIGNMENT) }
alloc_align :: proc(size, alignment: int) -> rawptr #inline {
__check_context();
a := context.allocator;
return a.procedure(a.data, AllocationMode.ALLOC, size, alignment, null, 0, 0);
__check_context()
a := context.allocator
return a.procedure(a.data, AllocationMode.ALLOC, size, alignment, null, 0, 0)
}
dealloc :: proc(ptr: rawptr) #inline {
__check_context();
a := context.allocator;
_ = a.procedure(a.data, AllocationMode.DEALLOC, 0, 0, ptr, 0, 0);
__check_context()
a := context.allocator
_ = a.procedure(a.data, AllocationMode.DEALLOC, 0, 0, ptr, 0, 0)
}
dealloc_all :: proc(ptr: rawptr) #inline {
__check_context();
a := context.allocator;
_ = a.procedure(a.data, AllocationMode.DEALLOC_ALL, 0, 0, ptr, 0, 0);
__check_context()
a := context.allocator
_ = a.procedure(a.data, AllocationMode.DEALLOC_ALL, 0, 0, ptr, 0, 0)
}
resize :: proc(ptr: rawptr, old_size, new_size: int) -> rawptr #inline { return resize_align(ptr, old_size, new_size, DEFAULT_ALIGNMENT); }
resize :: proc(ptr: rawptr, old_size, new_size: int) -> rawptr #inline { return resize_align(ptr, old_size, new_size, DEFAULT_ALIGNMENT) }
resize_align :: proc(ptr: rawptr, old_size, new_size, alignment: int) -> rawptr #inline {
__check_context();
a := context.allocator;
return a.procedure(a.data, AllocationMode.RESIZE, new_size, alignment, ptr, old_size, 0);
__check_context()
a := context.allocator
return a.procedure(a.data, AllocationMode.RESIZE, new_size, alignment, ptr, old_size, 0)
}
default_resize_align :: proc(old_memory: rawptr, old_size, new_size, alignment: int) -> rawptr {
if old_memory == null {
return alloc_align(new_size, alignment);
return alloc_align(new_size, alignment)
}
if new_size == 0 {
dealloc(old_memory);
return null;
dealloc(old_memory)
return null
}
if new_size < old_size {
new_size = old_size;
new_size = old_size
}
if old_size == new_size {
return old_memory;
return old_memory
}
new_memory := alloc_align(new_size, alignment);
new_memory := alloc_align(new_size, alignment)
if new_memory == null {
return null;
return null
}
_ = copy(slice_ptr(new_memory as ^u8, new_size), slice_ptr(old_memory as ^u8, old_size));
dealloc(old_memory);
return new_memory;
_ = copy(slice_ptr(new_memory as ^u8, new_size), slice_ptr(old_memory as ^u8, old_size))
dealloc(old_memory)
return new_memory
}
__default_allocator_proc :: proc(allocator_data: rawptr, mode: AllocationMode,
size, alignment: int,
old_memory: rawptr, old_size: int, flags: u64) -> rawptr {
if mode == AllocationMode.ALLOC {
return heap_alloc(size);
} else if mode == AllocationMode.RESIZE {
return default_resize_align(old_memory, old_size, size, alignment);
} else if mode == AllocationMode.DEALLOC {
heap_free(old_memory);
} else if mode == AllocationMode.DEALLOC_ALL {
using AllocationMode
if mode == ALLOC {
return heap_alloc(size)
} else if mode == RESIZE {
return default_resize_align(old_memory, old_size, size, alignment)
} else if mode == DEALLOC {
heap_free(old_memory)
} else if mode == DEALLOC_ALL {
// NOTE(bill): Does nothing
}
return null;
return null
}
__default_allocator :: proc() -> Allocator {
return Allocator{
__default_allocator_proc,
null,
};
}
}
+13 -13
View File
@@ -7,24 +7,24 @@ type Bitmap: struct {
make_bitmap :: proc(filename: string) -> Bitmap {
stbi_load :: proc(filename: ^u8, x, y, comp: ^i32, req_comp: i32) -> ^u8 #foreign
c_buf: [1024]u8;
bytes := filename as []byte;
str_len := copy(c_buf[:], bytes);
c_buf: [1024]u8
bytes := filename as []byte
str_len := copy(c_buf[:], bytes)
b: Bitmap;
pixels := stbi_load(^c_buf[0], ^b.width, ^b.height, ^b.comp, 4);
len := (b.width*b.height*b.comp) as int;
b.data = pixels[:len];
b: Bitmap
pixels := stbi_load(^c_buf[0], ^b.width, ^b.height, ^b.comp, 4)
len := (b.width*b.height*b.comp) as int
b.data = slice_ptr(pixels, len)
return b;
return b
}
destroy_bitmap :: proc(b: ^Bitmap) {
stbi_image_free :: proc(retval_from_stbi_load: rawptr) #foreign
stbi_image_free(^b.data[0]);
b.data = b.data[:0];
b.width = 0;
b.height = 0;
b.comp = 0;
stbi_image_free(^b.data[0])
b.data = b.data[:0]
b.width = 0
b.height = 0
b.comp = 0
}
+239 -236
View File
@@ -1,63 +1,66 @@
CS_VREDRAW :: 1;
CS_HREDRAW :: 2;
CW_USEDEFAULT :: 0x80000000;
#foreign_system_library "user32"
#foreign_system_library "gdi32"
WS_OVERLAPPED :: 0;
WS_MAXIMIZEBOX :: 0x00010000;
WS_MINIMIZEBOX :: 0x00020000;
WS_THICKFRAME :: 0x00040000;
WS_SYSMENU :: 0x00080000;
WS_CAPTION :: 0x00C00000;
WS_VISIBLE :: 0x10000000;
WS_OVERLAPPEDWINDOW :: WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX;
CS_VREDRAW :: 1
CS_HREDRAW :: 2
CW_USEDEFAULT :: 0x80000000
WM_DESTROY :: 0x02;
WM_CLOSE :: 0x10;
WM_QUIT :: 0x12;
WS_OVERLAPPED :: 0
WS_MAXIMIZEBOX :: 0x00010000
WS_MINIMIZEBOX :: 0x00020000
WS_THICKFRAME :: 0x00040000
WS_SYSMENU :: 0x00080000
WS_CAPTION :: 0x00C00000
WS_VISIBLE :: 0x10000000
WS_OVERLAPPEDWINDOW :: WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX
PM_REMOVE :: 1;
WM_DESTROY :: 0x02
WM_CLOSE :: 0x10
WM_QUIT :: 0x12
COLOR_BACKGROUND :: 1 as HBRUSH;
PM_REMOVE :: 1
COLOR_BACKGROUND :: 1 as HBRUSH
HANDLE :: type rawptr;
HWND :: type HANDLE;
HDC :: type HANDLE;
HINSTANCE :: type HANDLE;
HICON :: type HANDLE;
HCURSOR :: type HANDLE;
HMENU :: type HANDLE;
HBRUSH :: type HANDLE;
WPARAM :: type uint;
LPARAM :: type int;
LRESULT :: type int;
ATOM :: type i16;
BOOL :: type i32;
POINT :: type struct { x, y: i32; };
HANDLE :: type rawptr
HWND :: type HANDLE
HDC :: type HANDLE
HINSTANCE :: type HANDLE
HICON :: type HANDLE
HCURSOR :: type HANDLE
HMENU :: type HANDLE
HBRUSH :: type HANDLE
WPARAM :: type uint
LPARAM :: type int
LRESULT :: type int
ATOM :: type i16
BOOL :: type i32
POINT :: type struct { x, y: i32 }
INVALID_HANDLE_VALUE :: (-1 as int) as HANDLE;
INVALID_HANDLE_VALUE :: (-1 as int) as HANDLE
WNDPROC :: type proc(hwnd: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT
WNDCLASSEXA :: type struct {
size, style: u32;
wnd_proc: WNDPROC;
cls_extra, wnd_extra: i32;
instance: HINSTANCE;
icon: HICON;
cursor: HCURSOR;
background: HBRUSH;
menu_name, class_name: ^u8;
sm: HICON;
size, style: u32
wnd_proc: WNDPROC
cls_extra, wnd_extra: i32
instance: HINSTANCE
icon: HICON
cursor: HCURSOR
background: HBRUSH
menu_name, class_name: ^u8
sm: HICON
}
MSG :: type struct {
hwnd: HWND;
message: u32;
wparam: WPARAM;
lparam: LPARAM;
time: u32;
pt: POINT;
hwnd: HWND
message: u32
wparam: WPARAM
lparam: LPARAM
time: u32
pt: POINT
}
@@ -75,7 +78,7 @@ QueryPerformanceCounter :: proc(result: ^i64) -> i32 #foreign
sleep_ms :: proc(ms: i32) {
Sleep :: proc(ms: i32) -> i32 #foreign
Sleep(ms);
Sleep(ms)
}
OutputDebugStringA :: proc(c_str: ^u8) #foreign
@@ -102,9 +105,9 @@ DefWindowProcA :: proc(hwnd: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM) -
GetQueryPerformanceFrequency :: proc() -> i64 {
r: i64;
_ = QueryPerformanceFrequency(^r);
return r;
r: i64
_ = QueryPerformanceFrequency(^r)
return r
}
@@ -121,30 +124,30 @@ WriteFile :: proc(h: HANDLE, buf: rawptr, len: i32, written_result: ^i32, ove
GetFileSizeEx :: proc(file_handle: HANDLE, file_size: ^i64) -> BOOL #foreign
FILE_SHARE_READ :: 0x00000001;
FILE_SHARE_WRITE :: 0x00000002;
FILE_SHARE_DELETE :: 0x00000004;
FILE_GENERIC_ALL :: 0x10000000;
FILE_GENERIC_EXECUTE :: 0x20000000;
FILE_GENERIC_WRITE :: 0x40000000;
FILE_GENERIC_READ :: 0x80000000;
FILE_SHARE_READ :: 0x00000001
FILE_SHARE_WRITE :: 0x00000002
FILE_SHARE_DELETE :: 0x00000004
FILE_GENERIC_ALL :: 0x10000000
FILE_GENERIC_EXECUTE :: 0x20000000
FILE_GENERIC_WRITE :: 0x40000000
FILE_GENERIC_READ :: 0x80000000
STD_INPUT_HANDLE :: -10;
STD_OUTPUT_HANDLE :: -11;
STD_ERROR_HANDLE :: -12;
STD_INPUT_HANDLE :: -10
STD_OUTPUT_HANDLE :: -11
STD_ERROR_HANDLE :: -12
CREATE_NEW :: 1;
CREATE_ALWAYS :: 2;
OPEN_EXISTING :: 3;
OPEN_ALWAYS :: 4;
TRUNCATE_EXISTING :: 5;
CREATE_NEW :: 1
CREATE_ALWAYS :: 2
OPEN_EXISTING :: 3
OPEN_ALWAYS :: 4
TRUNCATE_EXISTING :: 5
HeapAlloc :: proc(h: HANDLE, flags: u32, bytes: int) -> rawptr #foreign
HeapFree :: proc(h: HANDLE, flags: u32, memory: rawptr) -> BOOL #foreign
GetProcessHeap :: proc() -> HANDLE #foreign
HEAP_ZERO_MEMORY :: 0x00000008;
HEAP_ZERO_MEMORY :: 0x00000008
@@ -159,37 +162,37 @@ HEAP_ZERO_MEMORY :: 0x00000008;
// Windows OpenGL
PFD_TYPE_RGBA :: 0;
PFD_TYPE_COLORINDEX :: 1;
PFD_MAIN_PLANE :: 0;
PFD_OVERLAY_PLANE :: 1;
PFD_UNDERLAY_PLANE :: -1;
PFD_DOUBLEBUFFER :: 1;
PFD_STEREO :: 2;
PFD_DRAW_TO_WINDOW :: 4;
PFD_DRAW_TO_BITMAP :: 8;
PFD_SUPPORT_GDI :: 16;
PFD_SUPPORT_OPENGL :: 32;
PFD_GENERIC_FORMAT :: 64;
PFD_NEED_PALETTE :: 128;
PFD_NEED_SYSTEM_PALETTE :: 0x00000100;
PFD_SWAP_EXCHANGE :: 0x00000200;
PFD_SWAP_COPY :: 0x00000400;
PFD_SWAP_LAYER_BUFFERS :: 0x00000800;
PFD_GENERIC_ACCELERATED :: 0x00001000;
PFD_DEPTH_DONTCARE :: 0x20000000;
PFD_DOUBLEBUFFER_DONTCARE :: 0x40000000;
PFD_STEREO_DONTCARE :: 0x80000000;
PFD_TYPE_RGBA :: 0
PFD_TYPE_COLORINDEX :: 1
PFD_MAIN_PLANE :: 0
PFD_OVERLAY_PLANE :: 1
PFD_UNDERLAY_PLANE :: -1
PFD_DOUBLEBUFFER :: 1
PFD_STEREO :: 2
PFD_DRAW_TO_WINDOW :: 4
PFD_DRAW_TO_BITMAP :: 8
PFD_SUPPORT_GDI :: 16
PFD_SUPPORT_OPENGL :: 32
PFD_GENERIC_FORMAT :: 64
PFD_NEED_PALETTE :: 128
PFD_NEED_SYSTEM_PALETTE :: 0x00000100
PFD_SWAP_EXCHANGE :: 0x00000200
PFD_SWAP_COPY :: 0x00000400
PFD_SWAP_LAYER_BUFFERS :: 0x00000800
PFD_GENERIC_ACCELERATED :: 0x00001000
PFD_DEPTH_DONTCARE :: 0x20000000
PFD_DOUBLEBUFFER_DONTCARE :: 0x40000000
PFD_STEREO_DONTCARE :: 0x80000000
HGLRC :: type HANDLE;
PROC :: type proc();
wglCreateContextAttribsARBType :: type proc(hdc: HDC, hshareContext: rawptr, attribList: ^i32) -> HGLRC;
HGLRC :: type HANDLE
PROC :: type proc()
wglCreateContextAttribsARBType :: type proc(hdc: HDC, hshareContext: rawptr, attribList: ^i32) -> HGLRC
PIXELFORMATDESCRIPTOR :: type struct {
size,
version,
flags: u32;
flags: u32
pixel_type,
color_bits,
@@ -210,11 +213,11 @@ PIXELFORMATDESCRIPTOR :: type struct {
stencil_bits,
aux_buffers,
layer_type,
reserved: byte;
reserved: byte
layer_mask,
visible_mask,
damage_mask: u32;
damage_mask: u32
}
GetDC :: proc(h: HANDLE) -> HDC #foreign
@@ -223,10 +226,10 @@ ChoosePixelFormat :: proc(hdc: HDC, pfd: ^PIXELFORMATDESCRIPTOR) -> i32 #foreign
SwapBuffers :: proc(hdc: HDC) -> BOOL #foreign
WGL_CONTEXT_MAJOR_VERSION_ARB :: 0x2091;
WGL_CONTEXT_MINOR_VERSION_ARB :: 0x2092;
WGL_CONTEXT_PROFILE_MASK_ARB :: 0x9126;
WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB :: 0x0002;
WGL_CONTEXT_MAJOR_VERSION_ARB :: 0x2091
WGL_CONTEXT_MINOR_VERSION_ARB :: 0x2092
WGL_CONTEXT_PROFILE_MASK_ARB :: 0x9126
WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB :: 0x0002
wglCreateContext :: proc(hdc: HDC) -> HGLRC #foreign
wglMakeCurrent :: proc(hdc: HDC, hglrc: HGLRC) -> BOOL #foreign
@@ -238,159 +241,159 @@ wglDeleteContext :: proc(hglrc: HGLRC) -> BOOL #foreign
GetAsyncKeyState :: proc(v_key: i32) -> i16 #foreign
is_key_down :: proc(key: int) -> bool {
return GetAsyncKeyState(key as i32) < 0;
return GetAsyncKeyState(key as i32) < 0
}
VK_LBUTTON :: 0x01;
VK_RBUTTON :: 0x02;
VK_CANCEL :: 0x03;
VK_MBUTTON :: 0x04;
VK_LBUTTON :: 0x01
VK_RBUTTON :: 0x02
VK_CANCEL :: 0x03
VK_MBUTTON :: 0x04
VK_BACK :: 0x08;
VK_TAB :: 0x09;
VK_BACK :: 0x08
VK_TAB :: 0x09
VK_CLEAR :: 0x0C;
VK_RETURN :: 0x0D;
VK_CLEAR :: 0x0C
VK_RETURN :: 0x0D
VK_SHIFT :: 0x10;
VK_CONTROL :: 0x11;
VK_MENU :: 0x12;
VK_PAUSE :: 0x13;
VK_CAPITAL :: 0x14;
VK_SHIFT :: 0x10
VK_CONTROL :: 0x11
VK_MENU :: 0x12
VK_PAUSE :: 0x13
VK_CAPITAL :: 0x14
VK_KANA :: 0x15;
VK_HANGEUL :: 0x15;
VK_HANGUL :: 0x15;
VK_JUNJA :: 0x17;
VK_FINAL :: 0x18;
VK_HANJA :: 0x19;
VK_KANJI :: 0x19;
VK_KANA :: 0x15
VK_HANGEUL :: 0x15
VK_HANGUL :: 0x15
VK_JUNJA :: 0x17
VK_FINAL :: 0x18
VK_HANJA :: 0x19
VK_KANJI :: 0x19
VK_ESCAPE :: 0x1B;
VK_ESCAPE :: 0x1B
VK_CONVERT :: 0x1C;
VK_NONCONVERT :: 0x1D;
VK_ACCEPT :: 0x1E;
VK_MODECHANGE :: 0x1F;
VK_CONVERT :: 0x1C
VK_NONCONVERT :: 0x1D
VK_ACCEPT :: 0x1E
VK_MODECHANGE :: 0x1F
VK_SPACE :: 0x20;
VK_PRIOR :: 0x21;
VK_NEXT :: 0x22;
VK_END :: 0x23;
VK_HOME :: 0x24;
VK_LEFT :: 0x25;
VK_UP :: 0x26;
VK_RIGHT :: 0x27;
VK_DOWN :: 0x28;
VK_SELECT :: 0x29;
VK_PRINT :: 0x2A;
VK_EXECUTE :: 0x2B;
VK_SNAPSHOT :: 0x2C;
VK_INSERT :: 0x2D;
VK_DELETE :: 0x2E;
VK_HELP :: 0x2F;
VK_SPACE :: 0x20
VK_PRIOR :: 0x21
VK_NEXT :: 0x22
VK_END :: 0x23
VK_HOME :: 0x24
VK_LEFT :: 0x25
VK_UP :: 0x26
VK_RIGHT :: 0x27
VK_DOWN :: 0x28
VK_SELECT :: 0x29
VK_PRINT :: 0x2A
VK_EXECUTE :: 0x2B
VK_SNAPSHOT :: 0x2C
VK_INSERT :: 0x2D
VK_DELETE :: 0x2E
VK_HELP :: 0x2F
VK_0 :: #rune "0";
VK_1 :: #rune "1";
VK_2 :: #rune "2";
VK_3 :: #rune "3";
VK_4 :: #rune "4";
VK_5 :: #rune "5";
VK_6 :: #rune "6";
VK_7 :: #rune "7";
VK_8 :: #rune "8";
VK_9 :: #rune "9";
VK_0 :: #rune "0"
VK_1 :: #rune "1"
VK_2 :: #rune "2"
VK_3 :: #rune "3"
VK_4 :: #rune "4"
VK_5 :: #rune "5"
VK_6 :: #rune "6"
VK_7 :: #rune "7"
VK_8 :: #rune "8"
VK_9 :: #rune "9"
VK_A :: #rune "A";
VK_B :: #rune "B";
VK_C :: #rune "C";
VK_D :: #rune "D";
VK_E :: #rune "E";
VK_F :: #rune "F";
VK_G :: #rune "G";
VK_H :: #rune "H";
VK_I :: #rune "I";
VK_J :: #rune "J";
VK_K :: #rune "K";
VK_L :: #rune "L";
VK_M :: #rune "M";
VK_N :: #rune "N";
VK_O :: #rune "O";
VK_P :: #rune "P";
VK_Q :: #rune "Q";
VK_R :: #rune "R";
VK_S :: #rune "S";
VK_T :: #rune "T";
VK_U :: #rune "U";
VK_V :: #rune "V";
VK_W :: #rune "W";
VK_X :: #rune "X";
VK_Y :: #rune "Y";
VK_Z :: #rune "Z";
VK_A :: #rune "A"
VK_B :: #rune "B"
VK_C :: #rune "C"
VK_D :: #rune "D"
VK_E :: #rune "E"
VK_F :: #rune "F"
VK_G :: #rune "G"
VK_H :: #rune "H"
VK_I :: #rune "I"
VK_J :: #rune "J"
VK_K :: #rune "K"
VK_L :: #rune "L"
VK_M :: #rune "M"
VK_N :: #rune "N"
VK_O :: #rune "O"
VK_P :: #rune "P"
VK_Q :: #rune "Q"
VK_R :: #rune "R"
VK_S :: #rune "S"
VK_T :: #rune "T"
VK_U :: #rune "U"
VK_V :: #rune "V"
VK_W :: #rune "W"
VK_X :: #rune "X"
VK_Y :: #rune "Y"
VK_Z :: #rune "Z"
VK_LWIN :: 0x5B;
VK_RWIN :: 0x5C;
VK_APPS :: 0x5D;
VK_LWIN :: 0x5B
VK_RWIN :: 0x5C
VK_APPS :: 0x5D
VK_NUMPAD0 :: 0x60;
VK_NUMPAD1 :: 0x61;
VK_NUMPAD2 :: 0x62;
VK_NUMPAD3 :: 0x63;
VK_NUMPAD4 :: 0x64;
VK_NUMPAD5 :: 0x65;
VK_NUMPAD6 :: 0x66;
VK_NUMPAD7 :: 0x67;
VK_NUMPAD8 :: 0x68;
VK_NUMPAD9 :: 0x69;
VK_MULTIPLY :: 0x6A;
VK_ADD :: 0x6B;
VK_SEPARATOR :: 0x6C;
VK_SUBTRACT :: 0x6D;
VK_DECIMAL :: 0x6E;
VK_DIVIDE :: 0x6F;
VK_F1 :: 0x70;
VK_F2 :: 0x71;
VK_F3 :: 0x72;
VK_F4 :: 0x73;
VK_F5 :: 0x74;
VK_F6 :: 0x75;
VK_F7 :: 0x76;
VK_F8 :: 0x77;
VK_F9 :: 0x78;
VK_F10 :: 0x79;
VK_F11 :: 0x7A;
VK_F12 :: 0x7B;
VK_F13 :: 0x7C;
VK_F14 :: 0x7D;
VK_F15 :: 0x7E;
VK_F16 :: 0x7F;
VK_F17 :: 0x80;
VK_F18 :: 0x81;
VK_F19 :: 0x82;
VK_F20 :: 0x83;
VK_F21 :: 0x84;
VK_F22 :: 0x85;
VK_F23 :: 0x86;
VK_F24 :: 0x87;
VK_NUMPAD0 :: 0x60
VK_NUMPAD1 :: 0x61
VK_NUMPAD2 :: 0x62
VK_NUMPAD3 :: 0x63
VK_NUMPAD4 :: 0x64
VK_NUMPAD5 :: 0x65
VK_NUMPAD6 :: 0x66
VK_NUMPAD7 :: 0x67
VK_NUMPAD8 :: 0x68
VK_NUMPAD9 :: 0x69
VK_MULTIPLY :: 0x6A
VK_ADD :: 0x6B
VK_SEPARATOR :: 0x6C
VK_SUBTRACT :: 0x6D
VK_DECIMAL :: 0x6E
VK_DIVIDE :: 0x6F
VK_F1 :: 0x70
VK_F2 :: 0x71
VK_F3 :: 0x72
VK_F4 :: 0x73
VK_F5 :: 0x74
VK_F6 :: 0x75
VK_F7 :: 0x76
VK_F8 :: 0x77
VK_F9 :: 0x78
VK_F10 :: 0x79
VK_F11 :: 0x7A
VK_F12 :: 0x7B
VK_F13 :: 0x7C
VK_F14 :: 0x7D
VK_F15 :: 0x7E
VK_F16 :: 0x7F
VK_F17 :: 0x80
VK_F18 :: 0x81
VK_F19 :: 0x82
VK_F20 :: 0x83
VK_F21 :: 0x84
VK_F22 :: 0x85
VK_F23 :: 0x86
VK_F24 :: 0x87
VK_NUMLOCK :: 0x90;
VK_SCROLL :: 0x91;
VK_NUMLOCK :: 0x90
VK_SCROLL :: 0x91
VK_LSHIFT :: 0xA0;
VK_RSHIFT :: 0xA1;
VK_LCONTROL :: 0xA2;
VK_RCONTROL :: 0xA3;
VK_LMENU :: 0xA4;
VK_RMENU :: 0xA5;
VK_PROCESSKEY :: 0xE5;
VK_ATTN :: 0xF6;
VK_CRSEL :: 0xF7;
VK_EXSEL :: 0xF8;
VK_EREOF :: 0xF9;
VK_PLAY :: 0xFA;
VK_ZOOM :: 0xFB;
VK_NONAME :: 0xFC;
VK_PA1 :: 0xFD;
VK_OEM_CLEAR :: 0xFE;
VK_LSHIFT :: 0xA0
VK_RSHIFT :: 0xA1
VK_LCONTROL :: 0xA2
VK_RCONTROL :: 0xA3
VK_LMENU :: 0xA4
VK_RMENU :: 0xA5
VK_PROCESSKEY :: 0xE5
VK_ATTN :: 0xF6
VK_CRSEL :: 0xF7
VK_EXSEL :: 0xF8
VK_EREOF :: 0xF9
VK_PLAY :: 0xFA
VK_ZOOM :: 0xFB
VK_NONAME :: 0xFC
VK_PA1 :: 0xFD
VK_OEM_CLEAR :: 0xFE