- D3D11, Image drawing & Matrix4 xform drawing

- I didn't get rotation going quite right with the xform, but it's 2am goodnight
	- Smashed my head and had bad thoughts about microsoft many times

- stuff
- lotsa example code in entry.c
This commit is contained in:
Charlie 2024-07-01 02:14:08 +02:00
parent 6879130bb0
commit b9503d8d19
24 changed files with 4167 additions and 137 deletions

BIN
berry_bush.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 556 B

View file

@ -2,7 +2,10 @@
/// ///
// Build config stuff // Build config stuff
#define RUN_TESTS 1 #define RUN_TESTS 0
// This is only for people developing oogabooga!
#define OOGABOOGA_DEV 1
// When we need very debug // When we need very debug
// #define CONFIGURATION VERY_DEBUG // #define CONFIGURATION VERY_DEBUG

View file

@ -4,6 +4,6 @@ mkdir build
pushd build pushd build
clang -g -o cgame.exe ../build.c -O0 -std=c11 -Wextra -Wno-incompatible-library-redeclaration -Wno-sign-compare -Wno-unused-parameter -Wno-builtin-requires-header -lgdi32 -luser32 -lopengl32 -lwinmm clang -g -o cgame.exe ../build.c -O0 -std=c11 -Wextra -Wno-incompatible-library-redeclaration -Wno-sign-compare -Wno-unused-parameter -Wno-builtin-requires-header -lgdi32 -luser32 -lwinmm -ld3d11 -ldxguid -ld3dcompiler
popd popd

View file

@ -7,7 +7,7 @@ pushd build
mkdir release mkdir release
pushd release pushd release
clang -o cgame.exe ../../build.c -Ofast -std=c11 -Wextra -Wno-incompatible-library-redeclaration -Wno-sign-compare -Wno-unused-parameter -Wno-builtin-requires-header -lgdi32 -luser32 -lopengl32 -lwinmm clang -o cgame.exe ../../build.c -Ofast -std=c11 -Wextra -Wno-incompatible-library-redeclaration -Wno-sign-compare -Wno-unused-parameter -Wno-builtin-requires-header -lgdi32 -luser32 -lwinmm -ld3d11 -ldxguid -ld3dcompiler
popd popd
popd popd

72
entry.c
View file

@ -1,5 +1,6 @@
int start(int argc, char **argv) { int start(int argc, char **argv) {
window.title = fixed_string("My epic game"); window.title = fixed_string("My epic game");
@ -8,18 +9,23 @@ int start(int argc, char **argv) {
window.x = 200; window.x = 200;
window.y = 200; window.y = 200;
Gfx_Image *bush_image = load_image_from_disk(fixed_string("berry_bush.png"));
assert(bush_image, "Failed loading berry_bush.png");
Gfx_Image *hammer_image = load_image_from_disk(fixed_string("hammer.png"));
assert(hammer_image, "Failed loading hammer.png");
seed_for_random = os_get_current_cycle_count(); seed_for_random = os_get_current_cycle_count();
const float64 fps_limit = 420; const float64 fps_limit = 69000;
const float64 min_frametime = 1.0 / fps_limit; const float64 min_frametime = 1.0 / fps_limit;
Matrix4 camera_view = m4_scalar(1.0);
float64 last_time = os_get_current_time_in_seconds(); float64 last_time = os_get_current_time_in_seconds();
while (!window.should_close) { while (!window.should_close) {
reset_temporary_storage(); reset_temporary_storage();
context.allocator = temp; context.allocator = temp;
os_update();
float64 now = os_get_current_time_in_seconds(); float64 now = os_get_current_time_in_seconds();
float64 delta = now - last_time; float64 delta = now - last_time;
if (delta < min_frametime) { if (delta < min_frametime) {
@ -28,34 +34,66 @@ int start(int argc, char **argv) {
delta = now - last_time; delta = now - last_time;
} }
last_time = now; last_time = now;
os_update();
if (is_key_just_released(KEY_ESCAPE)) { if (is_key_just_released(KEY_ESCAPE)) {
window.should_close = true; window.should_close = true;
} }
if (is_key_just_released('E')) { if (is_key_just_pressed(KEY_ARROW_LEFT)) {
print("Mouse pos: %f, %f\n", input_frame.mouse_x, input_frame.mouse_y); window.width += 10;
print("FPS: %.2f\n", 1.0 / delta); window.x -= 10;
}
if (is_key_just_pressed(KEY_ARROW_RIGHT)) {
window.width += 10;
} }
for (u64 i = 0; i < input_frame.number_of_events; i++) { if (is_key_just_released('Q')) {
Input_Event e = input_frame.events[i]; push_allocator(get_heap_allocator());
delete_image(bush_image);
switch (e.kind) { bush_image = load_image_from_disk(fixed_string("berry_bush.png"));
case INPUT_EVENT_KEY: print("Key event key code %d\n", e.key_code); break; assert(bush_image, "Failed loading berry_bush.png");
case INPUT_EVENT_SCROLL: print("Scroll event, x: %.3f, y: %.3f\n", e.xscroll, e.yscroll); break; pop_allocator();
case INPUT_EVENT_TEXT: print("Text event, utf32: %d, ascii: %c\n", e.utf32, e.ascii); break;
}
} }
const float32 cam_move_speed = 4.0;
Vector2 cam_move_axis = v2(0, 0);
if (is_key_down('A')) {
cam_move_axis.x -= 1.0;
}
if (is_key_down('D')) {
cam_move_axis.x += 1.0;
}
if (is_key_down('S')) {
cam_move_axis.y -= 1.0;
}
if (is_key_down('W')) {
cam_move_axis.y += 1.0;
}
draw_rect_rotated(v2(-.25f, -.25f), v2(.5f, .5f), COLOR_RED, v2(.25, .25), (f32)now); Vector2 cam_move = v2_mulf(cam_move_axis, delta * cam_move_speed);
Vector2 hover_position = v2_rotate_point_around_pivot(v2(-.5, -.5), v2(0, 0), -(f32)now); camera_view = m4_translate(camera_view, v3(v2_expand(cam_move), 0));
draw_frame.view = camera_view;
Matrix4 hammer_xform = m4_scalar(1.0);
hammer_xform = m4_rotate_z(hammer_xform, (f32)now);
hammer_xform = m4_translate(hammer_xform, v3(-.25f, -.25f, 0));
draw_image_xform(hammer_image, hammer_xform, v2(.5f, .5f), COLOR_RED);
Vector2 hover_position = v2_rotate_point_around_pivot(v2(-.5, -.5), v2(0, 0), (f32)now);
Vector2 local_pivot = v2(.125f, .125f); Vector2 local_pivot = v2(.125f, .125f);
draw_rect(v2_sub(hover_position, local_pivot), v2(.25f, .25f), COLOR_GREEN); draw_rect(v2_sub(hover_position, local_pivot), v2(.25f, .25f), v4((sin(now)+1.0)/2.0, 1.0, 0.0, 1.0));
draw_image(bush_image, v2(0.65, 0.65), v2(0.2*sin(now), 0.2*sin(now)), COLOR_WHITE);
gfx_update(); gfx_update();
if (is_key_just_released('E')) {
log("FPS: %.2f", 1.0 / delta);
log("ms: %.2f", delta*1000.0);
}
} }
return 0; return 0;

BIN
hammer.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 B

View file

@ -25,12 +25,15 @@ typedef u8 bool;
#define forward_global extern #define forward_global extern
#define ifnt(x) if (!(x)) // Haters gonna hate
#define If if (
#define then )
// If cond then {}
#ifdef _MSC_VER #ifdef _MSC_VER
inline void os_break() { inline void os_break() {
__debugbreak(); __debugbreak();
int *a = 0; volatile int *a = 0;
*a = 5; *a = 5;
} }
#else #else
@ -41,7 +44,7 @@ typedef u8 bool;
void printf(const char* fmt, ...); void printf(const char* fmt, ...);
#define STR_HELPER(x) #x #define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x) #define STR(x) STR_HELPER(x)
#define assert_line(line, cond, ...) if (!(cond)) { printf("Assertion failed in file " __FILE__ " on line " STR(line) "\nFailed Condition: " #cond ". Message: " __VA_ARGS__); os_break(); } #define assert_line(line, cond, ...) if(!(cond)) { printf("Assertion failed in file " __FILE__ " on line " STR(line) "\nFailed Condition: " #cond ". Message: " __VA_ARGS__); os_break(); }
#define assert(cond, ...) assert_line(__LINE__, cond, __VA_ARGS__); #define assert(cond, ...) assert_line(__LINE__, cond, __VA_ARGS__);
#if CONFIGURATION == RELEASE #if CONFIGURATION == RELEASE
@ -124,6 +127,15 @@ typedef enum Allocator_Message {
} Allocator_Message; } Allocator_Message;
typedef void*(*Allocator_Proc)(u64, void*, Allocator_Message); typedef void*(*Allocator_Proc)(u64, void*, Allocator_Message);
typedef enum Log_Level {
LOG_ERROR,
LOG_INFO,
LOG_WARNING,
LOG_VERBOSE
} Log_Level;
typedef struct Allocator { typedef struct Allocator {
Allocator_Proc proc; Allocator_Proc proc;
void *data; void *data;
@ -131,6 +143,7 @@ typedef struct Allocator {
typedef struct Context { typedef struct Context {
Allocator allocator; Allocator allocator;
void *logger; // void(*Logger_Proc)(Log_Level level, string fmt, ...)
CONTEXT_EXTRA extra; CONTEXT_EXTRA extra;
} Context; } Context;
@ -141,12 +154,9 @@ thread_local Context context;
thread_local Context context_stack[CONTEXT_STACK_MAX]; thread_local Context context_stack[CONTEXT_STACK_MAX];
thread_local u64 num_contexts = 0; thread_local u64 num_contexts = 0;
void* alloc(u64 size) { return context.allocator.proc(size, NULL, ALLOCATOR_ALLOCATE); } void* alloc(u64 size) { return context.allocator.proc(size, NULL, ALLOCATOR_ALLOCATE); }
void dealloc(void *p) { context.allocator.proc(0, p, ALLOCATOR_DEALLOCATE); } void dealloc(void *p) { context.allocator.proc(0, p, ALLOCATOR_DEALLOCATE); }
void push_context(Context c) { void push_context(Context c) {
assert(num_contexts < CONTEXT_STACK_MAX, "Context stack overflow"); assert(num_contexts < CONTEXT_STACK_MAX, "Context stack overflow");

View file

@ -0,0 +1,558 @@
/*
<<<<<< Bytecode compiled from HLSL code below: >>>>>>
struct VS_INPUT
{
float2 uv : TEXCOORD;
float4 color : COLOR;
int texture_index: TEXTURE_INDEX;
float4 position : POSITION;
};
struct PS_INPUT
{
float4 position : SV_POSITION;
float2 uv : TEXCOORD0;
float4 color : COLOR;
int texture_index: TEXTURE_INDEX;
};
PS_INPUT vs_main(VS_INPUT input)
{
PS_INPUT output;
output.position = input.position;
output.uv = input.uv;
output.color = input.color;
output.texture_index = input.texture_index;
return output;
}
// #Magicvalue
Texture2D textures[32] : register(t0);
SamplerState image_sampler : register(s0);
float4 sample_texture(int texture_index, float2 uv) {
// #Portability sigh
if (texture_index == 0) return textures[0].Sample(image_sampler, uv);
else if (texture_index == 1) return textures[1].Sample(image_sampler, uv);
else if (texture_index == 2) return textures[2].Sample(image_sampler, uv);
else if (texture_index == 3) return textures[3].Sample(image_sampler, uv);
else if (texture_index == 4) return textures[4].Sample(image_sampler, uv);
else if (texture_index == 5) return textures[5].Sample(image_sampler, uv);
else if (texture_index == 6) return textures[6].Sample(image_sampler, uv);
else if (texture_index == 7) return textures[7].Sample(image_sampler, uv);
else if (texture_index == 8) return textures[8].Sample(image_sampler, uv);
else if (texture_index == 9) return textures[9].Sample(image_sampler, uv);
else if (texture_index == 10) return textures[10].Sample(image_sampler, uv);
else if (texture_index == 11) return textures[11].Sample(image_sampler, uv);
else if (texture_index == 12) return textures[12].Sample(image_sampler, uv);
else if (texture_index == 13) return textures[13].Sample(image_sampler, uv);
else if (texture_index == 14) return textures[14].Sample(image_sampler, uv);
else if (texture_index == 15) return textures[15].Sample(image_sampler, uv);
else if (texture_index == 16) return textures[16].Sample(image_sampler, uv);
else if (texture_index == 17) return textures[17].Sample(image_sampler, uv);
else if (texture_index == 18) return textures[18].Sample(image_sampler, uv);
else if (texture_index == 19) return textures[19].Sample(image_sampler, uv);
else if (texture_index == 20) return textures[20].Sample(image_sampler, uv);
else if (texture_index == 21) return textures[21].Sample(image_sampler, uv);
else if (texture_index == 22) return textures[22].Sample(image_sampler, uv);
else if (texture_index == 23) return textures[23].Sample(image_sampler, uv);
else if (texture_index == 24) return textures[24].Sample(image_sampler, uv);
else if (texture_index == 25) return textures[25].Sample(image_sampler, uv);
else if (texture_index == 26) return textures[26].Sample(image_sampler, uv);
else if (texture_index == 27) return textures[27].Sample(image_sampler, uv);
else if (texture_index == 28) return textures[28].Sample(image_sampler, uv);
else if (texture_index == 29) return textures[29].Sample(image_sampler, uv);
else if (texture_index == 30) return textures[30].Sample(image_sampler, uv);
else if (texture_index == 31) return textures[31].Sample(image_sampler, uv);
return float4(1.0, 0.0, 0.0, 1.0);
}
float4 ps_main(PS_INPUT input) : SV_TARGET
{
if (input.texture_index >= 0) {
return sample_texture(input.texture_index, input.uv);
} else {
return input.color;
}
}
*/
const u8 IMAGE_SHADER_VERTEX_BLOB_BYTES[] = {
0x44, 0x58, 0x42, 0x43, 0xdd, 0x02, 0x55, 0xb0, 0x7b, 0x83, 0x6c, 0x34, 0x45, 0xe8, 0x51, 0xd4,
0x76, 0xbf, 0x66, 0x77, 0x01, 0x00, 0x00, 0x00, 0x3c, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00,
0x00, 0x34, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0xd4, 0x01,
0x00, 0x00, 0xa0, 0x02, 0x00, 0x00, 0x52, 0x44, 0x45, 0x46, 0x64, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x05, 0xfe, 0xff, 0x00, 0x01, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x52, 0x44, 0x31,
0x31, 0x3c, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x28, 0x00,
0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d,
0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x28, 0x52, 0x29, 0x20, 0x48, 0x4c,
0x53, 0x4c, 0x20, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69,
0x6c, 0x65, 0x72, 0x20, 0x31, 0x30, 0x2e, 0x31, 0x00, 0x49, 0x53, 0x47, 0x4e, 0x90, 0x00,
0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0x03, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x77, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02,
0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x00,
0x00, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x00, 0x43, 0x4f, 0x4c, 0x4f, 0x52,
0x00, 0x54, 0x45, 0x58, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x49, 0x4e, 0x44, 0x45, 0x58, 0x00,
0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x00, 0xab, 0xab, 0x4f, 0x53, 0x47, 0x4e,
0x94, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x0c, 0x00, 0x00,
0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
0x00, 0x02, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01,
0x0e, 0x00, 0x00, 0x53, 0x56, 0x5f, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x00,
0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x00, 0x43, 0x4f, 0x4c, 0x4f, 0x52, 0x00,
0x54, 0x45, 0x58, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x49, 0x4e, 0x44, 0x45, 0x58, 0x00, 0xab,
0xab, 0xab, 0x53, 0x48, 0x45, 0x58, 0xc4, 0x00, 0x00, 0x00, 0x50, 0x00, 0x01, 0x00, 0x31,
0x00, 0x00, 0x00, 0x6a, 0x08, 0x00, 0x01, 0x5f, 0x00, 0x00, 0x03, 0x32, 0x10, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x03, 0xf2, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00,
0x00, 0x5f, 0x00, 0x00, 0x03, 0x12, 0x10, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x5f, 0x00,
0x00, 0x03, 0xf2, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x04, 0xf2,
0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x03,
0x32, 0x20, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x03, 0xf2, 0x20, 0x10,
0x00, 0x02, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x03, 0x12, 0x20, 0x10, 0x00, 0x03, 0x00,
0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 0xf2, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46,
0x1e, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 0x32, 0x20, 0x10, 0x00,
0x01, 0x00, 0x00, 0x00, 0x46, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00,
0x05, 0xf2, 0x20, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x46, 0x1e, 0x10, 0x00, 0x01, 0x00,
0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 0x12, 0x20, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0a,
0x10, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x01, 0x53, 0x54, 0x41, 0x54,
0x94, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00
};
const u8 IMAGE_SHADER_PIXEL_BLOB_BYTES[] = {
0x44, 0x58, 0x42, 0x43, 0xa6, 0x92, 0xe1, 0x1e, 0x36, 0x1d, 0x06, 0x3b, 0xbf, 0x5b, 0xfa, 0x13,
0xd8, 0xd2, 0xd3, 0xb8, 0x01, 0x00, 0x00, 0x00, 0x74, 0x18, 0x00, 0x00, 0x05, 0x00, 0x00,
0x00, 0x34, 0x00, 0x00, 0x00, 0x64, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x34, 0x07,
0x00, 0x00, 0xd8, 0x17, 0x00, 0x00, 0x52, 0x44, 0x45, 0x46, 0x28, 0x06, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x05, 0xff, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x52, 0x44, 0x31,
0x31, 0x3c, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x28, 0x00,
0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c,
0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
0x00, 0x6a, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00,
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0d,
0x00, 0x00, 0x00, 0x76, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
0x00, 0x0d, 0x00, 0x00, 0x00, 0x82, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00,
0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x02, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x8e, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00,
0x00, 0x01, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x9a, 0x04, 0x00, 0x00, 0x02, 0x00,
0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x04,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xa6, 0x04, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
0xff, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xb2, 0x04,
0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff,
0xff, 0xff, 0xff, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
0xbe, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
0x00, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0d, 0x00,
0x00, 0x00, 0xca, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04,
0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x0d, 0x00, 0x00, 0x00, 0xd6, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x09, 0x00, 0x00, 0x00, 0x01, 0x00,
0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xe2, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05,
0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x0a, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xef, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00,
0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x0b, 0x00,
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xfc, 0x04, 0x00, 0x00, 0x02,
0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x09, 0x05, 0x00,
0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff,
0xff, 0xff, 0x0d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x16,
0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0x0e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00,
0x00, 0x23, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00,
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0d,
0x00, 0x00, 0x00, 0x30, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
0x00, 0x0d, 0x00, 0x00, 0x00, 0x3d, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00,
0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x11, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x4a, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x12, 0x00, 0x00,
0x00, 0x01, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x57, 0x05, 0x00, 0x00, 0x02, 0x00,
0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x13,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x64, 0x05, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
0xff, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x71, 0x05,
0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff,
0xff, 0xff, 0xff, 0x15, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
0x7e, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
0x00, 0xff, 0xff, 0xff, 0xff, 0x16, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0d, 0x00,
0x00, 0x00, 0x8b, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04,
0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x17, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x0d, 0x00, 0x00, 0x00, 0x98, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00,
0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xa5, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05,
0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x19, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xb2, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00,
0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x1a, 0x00,
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xbf, 0x05, 0x00, 0x00, 0x02,
0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
0x1b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xcc, 0x05, 0x00,
0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff,
0xff, 0xff, 0x1c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0xd9,
0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0x1d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00,
0x00, 0xe6, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00,
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0d,
0x00, 0x00, 0x00, 0xf3, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
0x00, 0x0d, 0x00, 0x00, 0x00, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x61, 0x6d, 0x70,
0x6c, 0x65, 0x72, 0x00, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x73, 0x5b, 0x30, 0x5d,
0x00, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x73, 0x5b, 0x31, 0x5d, 0x00, 0x74, 0x65,
0x78, 0x74, 0x75, 0x72, 0x65, 0x73, 0x5b, 0x32, 0x5d, 0x00, 0x74, 0x65, 0x78, 0x74, 0x75,
0x72, 0x65, 0x73, 0x5b, 0x33, 0x5d, 0x00, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x73,
0x5b, 0x34, 0x5d, 0x00, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x73, 0x5b, 0x35, 0x5d,
0x00, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x73, 0x5b, 0x36, 0x5d, 0x00, 0x74, 0x65,
0x78, 0x74, 0x75, 0x72, 0x65, 0x73, 0x5b, 0x37, 0x5d, 0x00, 0x74, 0x65, 0x78, 0x74, 0x75,
0x72, 0x65, 0x73, 0x5b, 0x38, 0x5d, 0x00, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x73,
0x5b, 0x39, 0x5d, 0x00, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x73, 0x5b, 0x31, 0x30,
0x5d, 0x00, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x73, 0x5b, 0x31, 0x31, 0x5d, 0x00,
0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x73, 0x5b, 0x31, 0x32, 0x5d, 0x00, 0x74, 0x65,
0x78, 0x74, 0x75, 0x72, 0x65, 0x73, 0x5b, 0x31, 0x33, 0x5d, 0x00, 0x74, 0x65, 0x78, 0x74,
0x75, 0x72, 0x65, 0x73, 0x5b, 0x31, 0x34, 0x5d, 0x00, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72,
0x65, 0x73, 0x5b, 0x31, 0x35, 0x5d, 0x00, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x73,
0x5b, 0x31, 0x36, 0x5d, 0x00, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x73, 0x5b, 0x31,
0x37, 0x5d, 0x00, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x73, 0x5b, 0x31, 0x38, 0x5d,
0x00, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x73, 0x5b, 0x31, 0x39, 0x5d, 0x00, 0x74,
0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x73, 0x5b, 0x32, 0x30, 0x5d, 0x00, 0x74, 0x65, 0x78,
0x74, 0x75, 0x72, 0x65, 0x73, 0x5b, 0x32, 0x31, 0x5d, 0x00, 0x74, 0x65, 0x78, 0x74, 0x75,
0x72, 0x65, 0x73, 0x5b, 0x32, 0x32, 0x5d, 0x00, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65,
0x73, 0x5b, 0x32, 0x33, 0x5d, 0x00, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x73, 0x5b,
0x32, 0x34, 0x5d, 0x00, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x73, 0x5b, 0x32, 0x35,
0x5d, 0x00, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x73, 0x5b, 0x32, 0x36, 0x5d, 0x00,
0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x73, 0x5b, 0x32, 0x37, 0x5d, 0x00, 0x74, 0x65,
0x78, 0x74, 0x75, 0x72, 0x65, 0x73, 0x5b, 0x32, 0x38, 0x5d, 0x00, 0x74, 0x65, 0x78, 0x74,
0x75, 0x72, 0x65, 0x73, 0x5b, 0x32, 0x39, 0x5d, 0x00, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72,
0x65, 0x73, 0x5b, 0x33, 0x30, 0x5d, 0x00, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x73,
0x5b, 0x33, 0x31, 0x5d, 0x00, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20,
0x28, 0x52, 0x29, 0x20, 0x48, 0x4c, 0x53, 0x4c, 0x20, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72,
0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x31, 0x30, 0x2e, 0x31, 0x00,
0x49, 0x53, 0x47, 0x4e, 0x94, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x03, 0x03, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x83, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03,
0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x53, 0x56, 0x5f, 0x50, 0x4f, 0x53, 0x49, 0x54,
0x49, 0x4f, 0x4e, 0x00, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x00, 0x43, 0x4f,
0x4c, 0x4f, 0x52, 0x00, 0x54, 0x45, 0x58, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x49, 0x4e, 0x44,
0x45, 0x58, 0x00, 0xab, 0xab, 0xab, 0x4f, 0x53, 0x47, 0x4e, 0x2c, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00,
0x00, 0x53, 0x56, 0x5f, 0x54, 0x41, 0x52, 0x47, 0x45, 0x54, 0x00, 0xab, 0xab, 0x53, 0x48,
0x45, 0x58, 0x9c, 0x10, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x27, 0x04, 0x00, 0x00, 0x6a,
0x08, 0x00, 0x01, 0x5a, 0x00, 0x00, 0x03, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x58, 0x18, 0x00, 0x04, 0x00, 0x70, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x00,
0x00, 0x58, 0x18, 0x00, 0x04, 0x00, 0x70, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x55, 0x55,
0x00, 0x00, 0x58, 0x18, 0x00, 0x04, 0x00, 0x70, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x55,
0x55, 0x00, 0x00, 0x58, 0x18, 0x00, 0x04, 0x00, 0x70, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00,
0x55, 0x55, 0x00, 0x00, 0x58, 0x18, 0x00, 0x04, 0x00, 0x70, 0x10, 0x00, 0x04, 0x00, 0x00,
0x00, 0x55, 0x55, 0x00, 0x00, 0x58, 0x18, 0x00, 0x04, 0x00, 0x70, 0x10, 0x00, 0x05, 0x00,
0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x58, 0x18, 0x00, 0x04, 0x00, 0x70, 0x10, 0x00, 0x06,
0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x58, 0x18, 0x00, 0x04, 0x00, 0x70, 0x10, 0x00,
0x07, 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x58, 0x18, 0x00, 0x04, 0x00, 0x70, 0x10,
0x00, 0x08, 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x58, 0x18, 0x00, 0x04, 0x00, 0x70,
0x10, 0x00, 0x09, 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x58, 0x18, 0x00, 0x04, 0x00,
0x70, 0x10, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x58, 0x18, 0x00, 0x04,
0x00, 0x70, 0x10, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x58, 0x18, 0x00,
0x04, 0x00, 0x70, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x58, 0x18,
0x00, 0x04, 0x00, 0x70, 0x10, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x58,
0x18, 0x00, 0x04, 0x00, 0x70, 0x10, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00,
0x58, 0x18, 0x00, 0x04, 0x00, 0x70, 0x10, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x55, 0x55, 0x00,
0x00, 0x58, 0x18, 0x00, 0x04, 0x00, 0x70, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x55, 0x55,
0x00, 0x00, 0x58, 0x18, 0x00, 0x04, 0x00, 0x70, 0x10, 0x00, 0x11, 0x00, 0x00, 0x00, 0x55,
0x55, 0x00, 0x00, 0x58, 0x18, 0x00, 0x04, 0x00, 0x70, 0x10, 0x00, 0x12, 0x00, 0x00, 0x00,
0x55, 0x55, 0x00, 0x00, 0x58, 0x18, 0x00, 0x04, 0x00, 0x70, 0x10, 0x00, 0x13, 0x00, 0x00,
0x00, 0x55, 0x55, 0x00, 0x00, 0x58, 0x18, 0x00, 0x04, 0x00, 0x70, 0x10, 0x00, 0x14, 0x00,
0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x58, 0x18, 0x00, 0x04, 0x00, 0x70, 0x10, 0x00, 0x15,
0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x58, 0x18, 0x00, 0x04, 0x00, 0x70, 0x10, 0x00,
0x16, 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x58, 0x18, 0x00, 0x04, 0x00, 0x70, 0x10,
0x00, 0x17, 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x58, 0x18, 0x00, 0x04, 0x00, 0x70,
0x10, 0x00, 0x18, 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x58, 0x18, 0x00, 0x04, 0x00,
0x70, 0x10, 0x00, 0x19, 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x58, 0x18, 0x00, 0x04,
0x00, 0x70, 0x10, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x58, 0x18, 0x00,
0x04, 0x00, 0x70, 0x10, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x58, 0x18,
0x00, 0x04, 0x00, 0x70, 0x10, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x58,
0x18, 0x00, 0x04, 0x00, 0x70, 0x10, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00,
0x58, 0x18, 0x00, 0x04, 0x00, 0x70, 0x10, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x55, 0x55, 0x00,
0x00, 0x58, 0x18, 0x00, 0x04, 0x00, 0x70, 0x10, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x55, 0x55,
0x00, 0x00, 0x62, 0x10, 0x00, 0x03, 0x32, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x62,
0x10, 0x00, 0x03, 0xf2, 0x10, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x62, 0x08, 0x00, 0x03,
0x12, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x03, 0xf2, 0x20, 0x10,
0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00,
0x00, 0x07, 0x12, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x10, 0x10, 0x00, 0x03,
0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x04, 0x03,
0x0a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x03, 0x0a, 0x10, 0x10,
0x00, 0x03, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x8b, 0xc2, 0x00, 0x00, 0x80, 0x43, 0x55,
0x15, 0x00, 0xf2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x10, 0x10, 0x00, 0x01,
0x00, 0x00, 0x00, 0x46, 0x7e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 0x12, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00,
0x00, 0x01, 0x40, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x12, 0x00, 0x00, 0x01, 0x20, 0x00,
0x00, 0x07, 0x22, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x10, 0x10, 0x00, 0x03,
0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x04, 0x03,
0x1a, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x8b, 0xc2, 0x00, 0x00,
0x80, 0x43, 0x55, 0x15, 0x00, 0xf2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x10,
0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x7e, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 0x12, 0x00, 0x10, 0x00,
0x01, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x12, 0x00, 0x00,
0x01, 0x20, 0x00, 0x00, 0x07, 0x22, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x10,
0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1f,
0x00, 0x04, 0x03, 0x1a, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x8b,
0xc2, 0x00, 0x00, 0x80, 0x43, 0x55, 0x15, 0x00, 0xf2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
0x00, 0x46, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x7e, 0x10, 0x00, 0x02, 0x00,
0x00, 0x00, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 0x12,
0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
0x12, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x07, 0x22, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00,
0x00, 0x0a, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x03, 0x00,
0x00, 0x00, 0x1f, 0x00, 0x04, 0x03, 0x1a, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x45,
0x00, 0x00, 0x8b, 0xc2, 0x00, 0x00, 0x80, 0x43, 0x55, 0x15, 0x00, 0xf2, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x46, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x7e, 0x10,
0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00,
0x00, 0x05, 0x12, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0xff,
0xff, 0xff, 0xff, 0x12, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x07, 0x22, 0x00, 0x10, 0x00,
0x01, 0x00, 0x00, 0x00, 0x0a, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00,
0x00, 0x04, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x04, 0x03, 0x1a, 0x00, 0x10, 0x00, 0x01, 0x00,
0x00, 0x00, 0x45, 0x00, 0x00, 0x8b, 0xc2, 0x00, 0x00, 0x80, 0x43, 0x55, 0x15, 0x00, 0xf2,
0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00,
0x46, 0x7e, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00,
0x00, 0x36, 0x00, 0x00, 0x05, 0x12, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x40,
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x12, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x07, 0x22,
0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00,
0x01, 0x40, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x04, 0x03, 0x1a, 0x00, 0x10,
0x00, 0x01, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x8b, 0xc2, 0x00, 0x00, 0x80, 0x43, 0x55,
0x15, 0x00, 0xf2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x10, 0x10, 0x00, 0x01,
0x00, 0x00, 0x00, 0x46, 0x7e, 0x10, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x60, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 0x12, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00,
0x00, 0x01, 0x40, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x12, 0x00, 0x00, 0x01, 0x20, 0x00,
0x00, 0x07, 0x22, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x10, 0x10, 0x00, 0x03,
0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x04, 0x03,
0x1a, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x8b, 0xc2, 0x00, 0x00,
0x80, 0x43, 0x55, 0x15, 0x00, 0xf2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x10,
0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x7e, 0x10, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00,
0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 0x12, 0x00, 0x10, 0x00,
0x01, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x12, 0x00, 0x00,
0x01, 0x20, 0x00, 0x00, 0x07, 0x22, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x10,
0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x1f,
0x00, 0x04, 0x03, 0x1a, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x8b,
0xc2, 0x00, 0x00, 0x80, 0x43, 0x55, 0x15, 0x00, 0xf2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
0x00, 0x46, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x7e, 0x10, 0x00, 0x07, 0x00,
0x00, 0x00, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 0x12,
0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
0x12, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x07, 0x22, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00,
0x00, 0x0a, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x08, 0x00,
0x00, 0x00, 0x1f, 0x00, 0x04, 0x03, 0x1a, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x45,
0x00, 0x00, 0x8b, 0xc2, 0x00, 0x00, 0x80, 0x43, 0x55, 0x15, 0x00, 0xf2, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x46, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x7e, 0x10,
0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00,
0x00, 0x05, 0x12, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0xff,
0xff, 0xff, 0xff, 0x12, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x07, 0x22, 0x00, 0x10, 0x00,
0x01, 0x00, 0x00, 0x00, 0x0a, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00,
0x00, 0x09, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x04, 0x03, 0x1a, 0x00, 0x10, 0x00, 0x01, 0x00,
0x00, 0x00, 0x45, 0x00, 0x00, 0x8b, 0xc2, 0x00, 0x00, 0x80, 0x43, 0x55, 0x15, 0x00, 0xf2,
0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00,
0x46, 0x7e, 0x10, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00,
0x00, 0x36, 0x00, 0x00, 0x05, 0x12, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x40,
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x12, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x07, 0x22,
0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00,
0x01, 0x40, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x04, 0x03, 0x1a, 0x00, 0x10,
0x00, 0x01, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x8b, 0xc2, 0x00, 0x00, 0x80, 0x43, 0x55,
0x15, 0x00, 0xf2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x10, 0x10, 0x00, 0x01,
0x00, 0x00, 0x00, 0x46, 0x7e, 0x10, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x60, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 0x12, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00,
0x00, 0x01, 0x40, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x12, 0x00, 0x00, 0x01, 0x20, 0x00,
0x00, 0x07, 0x22, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x10, 0x10, 0x00, 0x03,
0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x04, 0x03,
0x1a, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x8b, 0xc2, 0x00, 0x00,
0x80, 0x43, 0x55, 0x15, 0x00, 0xf2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x10,
0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x7e, 0x10, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00,
0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 0x12, 0x00, 0x10, 0x00,
0x01, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x12, 0x00, 0x00,
0x01, 0x20, 0x00, 0x00, 0x07, 0x22, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x10,
0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x1f,
0x00, 0x04, 0x03, 0x1a, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x8b,
0xc2, 0x00, 0x00, 0x80, 0x43, 0x55, 0x15, 0x00, 0xf2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
0x00, 0x46, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x7e, 0x10, 0x00, 0x0c, 0x00,
0x00, 0x00, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 0x12,
0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
0x12, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x07, 0x22, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00,
0x00, 0x0a, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x0d, 0x00,
0x00, 0x00, 0x1f, 0x00, 0x04, 0x03, 0x1a, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x45,
0x00, 0x00, 0x8b, 0xc2, 0x00, 0x00, 0x80, 0x43, 0x55, 0x15, 0x00, 0xf2, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x46, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x7e, 0x10,
0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00,
0x00, 0x05, 0x12, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0xff,
0xff, 0xff, 0xff, 0x12, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x07, 0x22, 0x00, 0x10, 0x00,
0x01, 0x00, 0x00, 0x00, 0x0a, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00,
0x00, 0x0e, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x04, 0x03, 0x1a, 0x00, 0x10, 0x00, 0x01, 0x00,
0x00, 0x00, 0x45, 0x00, 0x00, 0x8b, 0xc2, 0x00, 0x00, 0x80, 0x43, 0x55, 0x15, 0x00, 0xf2,
0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00,
0x46, 0x7e, 0x10, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00,
0x00, 0x36, 0x00, 0x00, 0x05, 0x12, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x40,
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x12, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x07, 0x22,
0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00,
0x01, 0x40, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x04, 0x03, 0x1a, 0x00, 0x10,
0x00, 0x01, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x8b, 0xc2, 0x00, 0x00, 0x80, 0x43, 0x55,
0x15, 0x00, 0xf2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x10, 0x10, 0x00, 0x01,
0x00, 0x00, 0x00, 0x46, 0x7e, 0x10, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x60, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 0x12, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00,
0x00, 0x01, 0x40, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x12, 0x00, 0x00, 0x01, 0x20, 0x00,
0x00, 0x07, 0x22, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x10, 0x10, 0x00, 0x03,
0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x04, 0x03,
0x1a, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x8b, 0xc2, 0x00, 0x00,
0x80, 0x43, 0x55, 0x15, 0x00, 0xf2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x10,
0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x7e, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 0x12, 0x00, 0x10, 0x00,
0x01, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x12, 0x00, 0x00,
0x01, 0x20, 0x00, 0x00, 0x07, 0x22, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x10,
0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x1f,
0x00, 0x04, 0x03, 0x1a, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x8b,
0xc2, 0x00, 0x00, 0x80, 0x43, 0x55, 0x15, 0x00, 0xf2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
0x00, 0x46, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x7e, 0x10, 0x00, 0x11, 0x00,
0x00, 0x00, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 0x12,
0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
0x12, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x07, 0x22, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00,
0x00, 0x0a, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x12, 0x00,
0x00, 0x00, 0x1f, 0x00, 0x04, 0x03, 0x1a, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x45,
0x00, 0x00, 0x8b, 0xc2, 0x00, 0x00, 0x80, 0x43, 0x55, 0x15, 0x00, 0xf2, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x46, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x7e, 0x10,
0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00,
0x00, 0x05, 0x12, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0xff,
0xff, 0xff, 0xff, 0x12, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x07, 0x22, 0x00, 0x10, 0x00,
0x01, 0x00, 0x00, 0x00, 0x0a, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00,
0x00, 0x13, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x04, 0x03, 0x1a, 0x00, 0x10, 0x00, 0x01, 0x00,
0x00, 0x00, 0x45, 0x00, 0x00, 0x8b, 0xc2, 0x00, 0x00, 0x80, 0x43, 0x55, 0x15, 0x00, 0xf2,
0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00,
0x46, 0x7e, 0x10, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00,
0x00, 0x36, 0x00, 0x00, 0x05, 0x12, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x40,
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x12, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x07, 0x22,
0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00,
0x01, 0x40, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x04, 0x03, 0x1a, 0x00, 0x10,
0x00, 0x01, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x8b, 0xc2, 0x00, 0x00, 0x80, 0x43, 0x55,
0x15, 0x00, 0xf2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x10, 0x10, 0x00, 0x01,
0x00, 0x00, 0x00, 0x46, 0x7e, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x60, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 0x12, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00,
0x00, 0x01, 0x40, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x12, 0x00, 0x00, 0x01, 0x20, 0x00,
0x00, 0x07, 0x22, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x10, 0x10, 0x00, 0x03,
0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x04, 0x03,
0x1a, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x8b, 0xc2, 0x00, 0x00,
0x80, 0x43, 0x55, 0x15, 0x00, 0xf2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x10,
0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x7e, 0x10, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00,
0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 0x12, 0x00, 0x10, 0x00,
0x01, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x12, 0x00, 0x00,
0x01, 0x20, 0x00, 0x00, 0x07, 0x22, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x10,
0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x1f,
0x00, 0x04, 0x03, 0x1a, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x8b,
0xc2, 0x00, 0x00, 0x80, 0x43, 0x55, 0x15, 0x00, 0xf2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
0x00, 0x46, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x7e, 0x10, 0x00, 0x16, 0x00,
0x00, 0x00, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 0x12,
0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
0x12, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x07, 0x22, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00,
0x00, 0x0a, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x17, 0x00,
0x00, 0x00, 0x1f, 0x00, 0x04, 0x03, 0x1a, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x45,
0x00, 0x00, 0x8b, 0xc2, 0x00, 0x00, 0x80, 0x43, 0x55, 0x15, 0x00, 0xf2, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x46, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x7e, 0x10,
0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00,
0x00, 0x05, 0x12, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0xff,
0xff, 0xff, 0xff, 0x12, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x07, 0x22, 0x00, 0x10, 0x00,
0x01, 0x00, 0x00, 0x00, 0x0a, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00,
0x00, 0x18, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x04, 0x03, 0x1a, 0x00, 0x10, 0x00, 0x01, 0x00,
0x00, 0x00, 0x45, 0x00, 0x00, 0x8b, 0xc2, 0x00, 0x00, 0x80, 0x43, 0x55, 0x15, 0x00, 0xf2,
0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00,
0x46, 0x7e, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00,
0x00, 0x36, 0x00, 0x00, 0x05, 0x12, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x40,
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x12, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x07, 0x22,
0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00,
0x01, 0x40, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x04, 0x03, 0x1a, 0x00, 0x10,
0x00, 0x01, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x8b, 0xc2, 0x00, 0x00, 0x80, 0x43, 0x55,
0x15, 0x00, 0xf2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x10, 0x10, 0x00, 0x01,
0x00, 0x00, 0x00, 0x46, 0x7e, 0x10, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x60, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 0x12, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00,
0x00, 0x01, 0x40, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x12, 0x00, 0x00, 0x01, 0x20, 0x00,
0x00, 0x07, 0x22, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x10, 0x10, 0x00, 0x03,
0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x04, 0x03,
0x1a, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x8b, 0xc2, 0x00, 0x00,
0x80, 0x43, 0x55, 0x15, 0x00, 0xf2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x10,
0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x7e, 0x10, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00,
0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 0x12, 0x00, 0x10, 0x00,
0x01, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x12, 0x00, 0x00,
0x01, 0x20, 0x00, 0x00, 0x07, 0x22, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x10,
0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x1f,
0x00, 0x04, 0x03, 0x1a, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x8b,
0xc2, 0x00, 0x00, 0x80, 0x43, 0x55, 0x15, 0x00, 0xf2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
0x00, 0x46, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x7e, 0x10, 0x00, 0x1b, 0x00,
0x00, 0x00, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 0x12,
0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
0x12, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x07, 0x22, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00,
0x00, 0x0a, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x1c, 0x00,
0x00, 0x00, 0x1f, 0x00, 0x04, 0x03, 0x1a, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x45,
0x00, 0x00, 0x8b, 0xc2, 0x00, 0x00, 0x80, 0x43, 0x55, 0x15, 0x00, 0xf2, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x46, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x7e, 0x10,
0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00,
0x00, 0x05, 0x12, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0xff,
0xff, 0xff, 0xff, 0x12, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x07, 0x22, 0x00, 0x10, 0x00,
0x01, 0x00, 0x00, 0x00, 0x0a, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00,
0x00, 0x1d, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x04, 0x03, 0x1a, 0x00, 0x10, 0x00, 0x01, 0x00,
0x00, 0x00, 0x45, 0x00, 0x00, 0x8b, 0xc2, 0x00, 0x00, 0x80, 0x43, 0x55, 0x15, 0x00, 0xf2,
0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00,
0x46, 0x7e, 0x10, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00,
0x00, 0x36, 0x00, 0x00, 0x05, 0x12, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x40,
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x12, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x07, 0x22,
0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00,
0x01, 0x40, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x04, 0x03, 0x1a, 0x00, 0x10,
0x00, 0x01, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x8b, 0xc2, 0x00, 0x00, 0x80, 0x43, 0x55,
0x15, 0x00, 0xf2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x10, 0x10, 0x00, 0x01,
0x00, 0x00, 0x00, 0x46, 0x7e, 0x10, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x60, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 0x12, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00,
0x00, 0x01, 0x40, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x12, 0x00, 0x00, 0x01, 0x20, 0x00,
0x00, 0x07, 0x12, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x10, 0x10, 0x00, 0x03,
0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x04, 0x03,
0x0a, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x8b, 0xc2, 0x00, 0x00,
0x80, 0x43, 0x55, 0x15, 0x00, 0xf2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x10,
0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x7e, 0x10, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00,
0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x01, 0x15, 0x00, 0x00, 0x01,
0x15, 0x00, 0x00, 0x01, 0x15, 0x00, 0x00, 0x01, 0x15, 0x00, 0x00, 0x01, 0x15, 0x00, 0x00,
0x01, 0x15, 0x00, 0x00, 0x01, 0x15, 0x00, 0x00, 0x01, 0x15, 0x00, 0x00, 0x01, 0x15, 0x00,
0x00, 0x01, 0x15, 0x00, 0x00, 0x01, 0x15, 0x00, 0x00, 0x01, 0x15, 0x00, 0x00, 0x01, 0x15,
0x00, 0x00, 0x01, 0x15, 0x00, 0x00, 0x01, 0x15, 0x00, 0x00, 0x01, 0x15, 0x00, 0x00, 0x01,
0x15, 0x00, 0x00, 0x01, 0x15, 0x00, 0x00, 0x01, 0x15, 0x00, 0x00, 0x01, 0x15, 0x00, 0x00,
0x01, 0x15, 0x00, 0x00, 0x01, 0x15, 0x00, 0x00, 0x01, 0x15, 0x00, 0x00, 0x01, 0x15, 0x00,
0x00, 0x01, 0x15, 0x00, 0x00, 0x01, 0x15, 0x00, 0x00, 0x01, 0x15, 0x00, 0x00, 0x01, 0x15,
0x00, 0x00, 0x01, 0x15, 0x00, 0x00, 0x01, 0x15, 0x00, 0x00, 0x01, 0x15, 0x00, 0x00, 0x01,
0x37, 0x00, 0x00, 0x0c, 0xf2, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x10,
0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x0e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x40,
0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x80, 0x3f, 0x3e, 0x00, 0x00, 0x01, 0x12, 0x00, 0x00, 0x01, 0x36, 0x00, 0x00, 0x05,
0xf2, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x1e, 0x10, 0x00, 0x02, 0x00, 0x00,
0x00, 0x3e, 0x00, 0x00, 0x01, 0x15, 0x00, 0x00, 0x01, 0x3e, 0x00, 0x00, 0x01, 0x53, 0x54,
0x41, 0x54, 0x94, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
};

View file

@ -0,0 +1,75 @@
struct VS_INPUT
{
float2 uv : TEXCOORD;
float4 color : COLOR;
int texture_index: TEXTURE_INDEX;
float4 position : POSITION;
};
struct PS_INPUT
{
float4 position : SV_POSITION;
float2 uv : TEXCOORD0;
float4 color : COLOR;
int texture_index: TEXTURE_INDEX;
};
PS_INPUT vs_main(VS_INPUT input)
{
PS_INPUT output;
output.position = input.position;
output.uv = input.uv;
output.color = input.color;
output.texture_index = input.texture_index;
return output;
}
// #Magicvalue
Texture2D textures[32] : register(t0);
SamplerState image_sampler : register(s0);
float4 sample_texture(int texture_index, float2 uv) {
// #Portability sigh
if (texture_index == 0) return textures[0].Sample(image_sampler, uv);
else if (texture_index == 1) return textures[1].Sample(image_sampler, uv);
else if (texture_index == 2) return textures[2].Sample(image_sampler, uv);
else if (texture_index == 3) return textures[3].Sample(image_sampler, uv);
else if (texture_index == 4) return textures[4].Sample(image_sampler, uv);
else if (texture_index == 5) return textures[5].Sample(image_sampler, uv);
else if (texture_index == 6) return textures[6].Sample(image_sampler, uv);
else if (texture_index == 7) return textures[7].Sample(image_sampler, uv);
else if (texture_index == 8) return textures[8].Sample(image_sampler, uv);
else if (texture_index == 9) return textures[9].Sample(image_sampler, uv);
else if (texture_index == 10) return textures[10].Sample(image_sampler, uv);
else if (texture_index == 11) return textures[11].Sample(image_sampler, uv);
else if (texture_index == 12) return textures[12].Sample(image_sampler, uv);
else if (texture_index == 13) return textures[13].Sample(image_sampler, uv);
else if (texture_index == 14) return textures[14].Sample(image_sampler, uv);
else if (texture_index == 15) return textures[15].Sample(image_sampler, uv);
else if (texture_index == 16) return textures[16].Sample(image_sampler, uv);
else if (texture_index == 17) return textures[17].Sample(image_sampler, uv);
else if (texture_index == 18) return textures[18].Sample(image_sampler, uv);
else if (texture_index == 19) return textures[19].Sample(image_sampler, uv);
else if (texture_index == 20) return textures[20].Sample(image_sampler, uv);
else if (texture_index == 21) return textures[21].Sample(image_sampler, uv);
else if (texture_index == 22) return textures[22].Sample(image_sampler, uv);
else if (texture_index == 23) return textures[23].Sample(image_sampler, uv);
else if (texture_index == 24) return textures[24].Sample(image_sampler, uv);
else if (texture_index == 25) return textures[25].Sample(image_sampler, uv);
else if (texture_index == 26) return textures[26].Sample(image_sampler, uv);
else if (texture_index == 27) return textures[27].Sample(image_sampler, uv);
else if (texture_index == 28) return textures[28].Sample(image_sampler, uv);
else if (texture_index == 29) return textures[29].Sample(image_sampler, uv);
else if (texture_index == 30) return textures[30].Sample(image_sampler, uv);
else if (texture_index == 31) return textures[31].Sample(image_sampler, uv);
return float4(1.0, 0.0, 0.0, 1.0);
}
float4 ps_main(PS_INPUT input) : SV_TARGET
{
if (input.texture_index >= 0) {
return sample_texture(input.texture_index, input.uv);
} else {
return input.color;
}
}

View file

@ -13,8 +13,9 @@ Usage:
quad.top_left = v2(x, y); quad.top_left = v2(x, y);
quad.top_right = v2(x, y); quad.top_right = v2(x, y);
quad.bottom_right = v2(x, y); quad.bottom_right = v2(x, y);
quad.color = v4(r, g, b, a);
quad.color = v4(r, g, b, a); quad.image = my_image; // ZERO(Gfx_Image) To draw a plain color
quad.uv = v4(0, 0, 1, 1);
draw_quad(quad); draw_quad(quad);
@ -26,15 +27,41 @@ Usage:
// With a centered pivot (half size) and a rotation of 2.4 radians // With a centered pivot (half size) and a rotation of 2.4 radians
// If pivot is v2(0, 0), the rectangle will rotate around it's bottom left. // If pivot is v2(0, 0), the rectangle will rotate around it's bottom left.
draw_rect_rotated(v2(-0.25, -0.5), v2(0.5, 0.5), COLOR_GREEN, v2(0.25, 0.25), 2.4f); draw_rect_rotated(v2(-0.25, -0.5), v2(0.5, 0.5), COLOR_GREEN, v2(0.25, 0.25), 2.4f);
// Basic image. Bottom left at X=-0.25, Y=-0.5 with a size of W=0.5, H=0.5
draw_image(v2(-0.25, -0.5), v2(0.5, 0.5), COLOR_GREEN);
// Rotated image. Bottom left at X=-0.25, Y=-0.5 with a size of W=0.5, H=0.5
// With a centered pivot (half size) and a rotation of 2.4 radians
// If pivot is v2(0, 0), the rectangle will rotate around it's bottom left.
draw_image_rotated(v2(-0.25, -0.5), v2(0.5, 0.5), COLOR_GREEN, v2(0.25, 0.25), 2.4f);
// Loading an image (png only)
Gfx_Image image = load_image_from_disk("my_image.png");
if (!image.data) {
// We failed loading the image.
}
// If you ever need to free the image:
delete_image(image);
*/ */
#define QUADS_PER_BLOCK 1024
#define QUADS_PER_BLOCK 1024
typedef struct Draw_Quad { typedef struct Draw_Quad {
Vector2 bottom_left, top_left, top_right, bottom_right; Vector2 bottom_left, top_left, top_right, bottom_right;
// r, g, b, a // r, g, b, a
Vector4 color; Vector4 color;
Gfx_Image *image;
// x1, y1, x2, y2
Vector4 uv;
} Draw_Quad; } Draw_Quad;
typedef struct Draw_Quad_Block { typedef struct Draw_Quad_Block {
@ -47,15 +74,37 @@ typedef struct Draw_Quad_Block {
typedef struct Draw_Frame { typedef struct Draw_Frame {
Draw_Quad_Block first_block; Draw_Quad_Block first_block;
Draw_Quad_Block *current; Draw_Quad_Block *current;
} Draw_Frame; u64 num_blocks;
Matrix4 projection;
Matrix4 view;
Gfx_Handle garbage_stack[4096];
u64 garbage_stack_count;
} Draw_Frame;
// This frame is passed to the platform layer and rendered in os_update. // This frame is passed to the platform layer and rendered in os_update.
// Resets every frame. // Resets every frame.
Draw_Frame draw_frame = ZERO(Draw_Frame); Draw_Frame draw_frame = ZERO(Draw_Frame);
void draw_quad(Draw_Quad quad) { void reset_draw_frame(Draw_Frame *frame) {
*frame = (Draw_Frame){0};
float32 aspect = (float32)window.width/(float32)window.height;
frame->projection = m4_make_orthographic_projection(-aspect, aspect, -1, 1, -1, 10);
frame->view = m4_scalar(1.0);
}
Draw_Quad *draw_quad_projected(Draw_Quad quad, Matrix4 world_to_clip) {
quad.bottom_left = m4_transform(world_to_clip, v4(v2_expand(quad.bottom_left), 0, 1)).xy;
quad.top_left = m4_transform(world_to_clip, v4(v2_expand(quad.top_left), 0, 1)).xy;
quad.top_right = m4_transform(world_to_clip, v4(v2_expand(quad.top_right), 0, 1)).xy;
quad.bottom_right = m4_transform(world_to_clip, v4(v2_expand(quad.bottom_right), 0, 1)).xy;
if (!draw_frame.current) draw_frame.current = &draw_frame.first_block; if (!draw_frame.current) draw_frame.current = &draw_frame.first_block;
if (draw_frame.current == &draw_frame.first_block) draw_frame.num_blocks = 1;
assert(draw_frame.current->num_quads <= QUADS_PER_BLOCK); assert(draw_frame.current->num_quads <= QUADS_PER_BLOCK);
if (draw_frame.current->num_quads == QUADS_PER_BLOCK) { if (draw_frame.current->num_quads == QUADS_PER_BLOCK) {
@ -64,13 +113,26 @@ void draw_quad(Draw_Quad quad) {
draw_frame.current->next = 0; draw_frame.current->next = 0;
draw_frame.current->num_quads = 0; draw_frame.current->num_quads = 0;
draw_frame.num_blocks += 1;
} }
draw_frame.current->quad_buffer[draw_frame.current->num_quads] = quad; draw_frame.current->quad_buffer[draw_frame.current->num_quads] = quad;
draw_frame.current->num_quads += 1; draw_frame.current->num_quads += 1;
return &draw_frame.current->quad_buffer[draw_frame.current->num_quads-1];
}
Draw_Quad *draw_quad(Draw_Quad quad) {
return draw_quad_projected(quad, m4_multiply(m4_inverse(draw_frame.view), draw_frame.projection));
} }
void draw_rect(Vector2 position, Vector2 size, Vector4 color) { Draw_Quad *draw_quad_xform(Draw_Quad quad, Matrix4 xform) {
Matrix4 world_to_clip = m4_multiply(m4_inverse(draw_frame.view), xform);
world_to_clip = m4_multiply(world_to_clip, draw_frame.projection);
return draw_quad_projected(quad, world_to_clip);
}
Draw_Quad *draw_rect(Vector2 position, Vector2 size, Vector4 color) {
const float32 left = position.x; const float32 left = position.x;
const float32 right = position.x + size.x; const float32 right = position.x + size.x;
const float32 bottom = position.y; const float32 bottom = position.y;
@ -82,34 +144,103 @@ void draw_rect(Vector2 position, Vector2 size, Vector4 color) {
q.top_right = v2(right, top); q.top_right = v2(right, top);
q.bottom_right = v2(right, bottom); q.bottom_right = v2(right, bottom);
q.color = color; q.color = color;
q.image = 0;
draw_quad(q); return draw_quad(q);
} }
void draw_rect_rotated(Vector2 position, Vector2 size, Vector4 color, Vector2 local_pivot, float32 rotation) { Draw_Quad *draw_rect_xform(Matrix4 xform, Vector2 size, Vector4 color) {
Draw_Quad q = ZERO(Draw_Quad);
q.bottom_left = v2(0, 0);
q.top_left = v2(0, size.y);
q.top_right = v2(size.x, size.y);
q.bottom_right = v2(size.x, 0);
q.color = color;
q.image = 0;
const float32 left = position.x; return draw_quad_xform(q, xform);
const float32 right = position.x + size.x; }
const float32 bottom = position.y; Draw_Quad *draw_image(Gfx_Image *image, Vector2 position, Vector2 size, Vector4 color) {
const float32 top = position.y+size.y; Draw_Quad *q = draw_rect(position, size, color);
Vector2 bottom_left = v2(left, bottom); q->image = image;
Vector2 top_left = v2(left, top); q->uv = v4(0, 0, 1, 1);
Vector2 top_right = v2(right, top);
Vector2 bottom_right = v2(right, bottom);
Vector2 pivot = v2(position.x + local_pivot.x, position.y + local_pivot.y); return q;
}
Draw_Quad *draw_image_xform(Gfx_Image *image, Matrix4 xform, Vector2 size, Vector4 color) {
Draw_Quad *q = draw_rect_xform(xform, size, color);
Draw_Quad q; q->image = image;
q.bottom_left = v2_rotate_point_around_pivot(bottom_left, pivot, rotation); q->uv = v4(0, 0, 1, 1);
q.top_left = v2_rotate_point_around_pivot(top_left, pivot, rotation);
q.top_right = v2_rotate_point_around_pivot(top_right, pivot, rotation);
q.bottom_right = v2_rotate_point_around_pivot(bottom_right, pivot, rotation);
q.color = color;
draw_quad(q); return q;
} }
#define COLOR_RED ((Vector4){1.0, 0.0, 0.0, 1.0}) #define COLOR_RED ((Vector4){1.0, 0.0, 0.0, 1.0})
#define COLOR_GREEN ((Vector4){0.0, 1.0, 0.0, 1.0}) #define COLOR_GREEN ((Vector4){0.0, 1.0, 0.0, 1.0})
#define COLOR_BLUE ((Vector4){0.0, 0.0, 1.0, 1.0}) #define COLOR_BLUE ((Vector4){0.0, 0.0, 1.0, 1.0})
#define COLOR_WHITE ((Vector4){1.0, 1.0, 1.0, 1.0})
#define COLOR_BLACK ((Vector4){0.0, 0.0, 0.0, 1.0})
// context.allocator
Gfx_Image *load_image_from_disk(string path) {
string png;
bool ok = os_read_entire_file(path, &png);
if (!ok) return 0;
Gfx_Image *image = alloc(sizeof(Gfx_Image));
// This is fucking terrible I gotta write my own decoder
LodePNGState state;
lodepng_state_init(&state);
u32 error = lodepng_inspect(&image->width, &image->height, &state, png.data, png.count);
if (error) {
return 0;
}
// 5 lines of code to say "ignore_adler32 = true" (because it's broken and gives me an error)
// I JUST WANT TO LOAD A PNG
LodePNGDecoderSettings decoder;
lodepng_decoder_settings_init(&decoder);
lodepng_decompress_settings_init(&decoder.zlibsettings);
decoder.zlibsettings.ignore_adler32 = true;
state.decoder = decoder;
error = lodepng_decode(&image->data, &image->width, &image->height, &state, png.data, png.count);
lodepng_state_cleanup(&state);
dealloc_string(png);
if (error) {
return 0;
}
// We need to flip the image
u32 row_bytes = image->width * 4; // #Magicvalue assuming 4 bytes
u8* temp_row = (u8*)alloc(row_bytes);
for (u32 i = 0; i < image->height / 2; i++) {
u8* top_row = image->data + i * row_bytes;
u8* bottom_row = image->data + (image->height - i - 1) * row_bytes;
// Swap the top row with the bottom row
memcpy(temp_row, top_row, row_bytes);
memcpy(top_row, bottom_row, row_bytes);
memcpy(bottom_row, temp_row, row_bytes);
}
dealloc(temp_row);
image->gfx_handle = GFX_INVALID_HANDLE; // This is handled in gfx
return image;
}
void delete_image(Gfx_Image *image) {
dealloc(image->data);
image->width = 0;
image->height = 0;
draw_frame.garbage_stack[draw_frame.garbage_stack_count] = image->gfx_handle;
draw_frame.garbage_stack_count += 1;
dealloc(image);
}

View file

@ -0,0 +1,637 @@
#if !OOGABOOGA_DEV
#include "d3d11_image_shader_bytecode.c"
#endif
#define D3D11Release(x) x->lpVtbl->Release(x)
#define VTABLE(proc, ...) FIRST_ARG(__VA_ARGS__)->lpVtbl->proc(__VA_ARGS__)
const Gfx_Handle GFX_INVALID_HANDLE = 0;
string temp_win32_null_terminated_wide_to_fixed_utf8(const u16 *utf16);
typedef struct D3D11_Vertex {
Vector4 position;
Vector2 uv;
Vector4 color;
int texture_index;
} D3D11_Vertex;
ID3D11Debug *d3d11_debug = 0;
ID3D11Device* d3d11_device = 0;
ID3D11DeviceContext* d3d11_context = 0;
ID3D11RenderTargetView *d3d11_window_render_target_view = 0;
ID3D11Texture2D *d3d11_back_buffer = 0;
D3D_DRIVER_TYPE d3d11_driver_type = 0;
D3D_FEATURE_LEVEL d3d11_feature_level = 0;
IDXGISwapChain1 *d3d11_swap_chain = 0;
DXGI_SWAP_CHAIN_DESC1 d3d11_swap_chain_desc = ZERO(DXGI_SWAP_CHAIN_DESC1);
u32 d3d11_swap_chain_width = 0;
u32 d3d11_swap_chain_height = 0;
ID3D11BlendState *d3d11_blend_state = 0;
ID3D11RasterizerState *d3d11_rasterizer = 0;
ID3D11SamplerState *d3d11_image_sampler = 0;
ID3D11VertexShader *d3d11_image_vertex_shader = 0;
ID3D11PixelShader *d3d11_image_pixel_shader = 0;
ID3D11InputLayout *d3d11_image_vertex_layout = 0;
ID3D11Buffer *d3d11_quad_vbo = 0;
u32 d3d11_quad_vbo_size = 0;
#define win32_check_hr(hr) win32_check_hr_impl(hr, __LINE__, __FILE__);
void win32_check_hr_impl(HRESULT hr, u32 line, const char* file_name) {
if (FAILED(hr)) {
LPVOID errorMsg;
DWORD dwFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS;
DWORD messageLength = FormatMessage(
dwFlags,
NULL,
hr,
MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
(LPTSTR) &errorMsg,
0,
NULL );
if (messageLength > 0) {
MessageBox(NULL, (LPCTSTR)errorMsg, TEXT("Error"), MB_OK | MB_ICONERROR);
} else {
MessageBox(NULL, TEXT("Failed to retrieve error message."), TEXT("Error"), MB_OK | MB_ICONERROR);
}
panic("win32 hr failed in file %cs on line %d", file_name, line);
}
}
void d3d11_update_swapchain() {
HRESULT hr;
bool create = !d3d11_swap_chain;
if (create) {
DXGI_SWAP_CHAIN_DESC1 scd = ZERO(DXGI_SWAP_CHAIN_DESC1);
scd.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
//scd.BufferDesc.RefreshRate.Numerator = xx st.refresh_rate;
//scd.BufferDesc.RefreshRate.Denominator = 1;
scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
scd.SampleDesc.Count = 1;
scd.SampleDesc.Quality = 0;
if (d3d11_feature_level < D3D_FEATURE_LEVEL_11_0) {
scd.Scaling = DXGI_SCALING_STRETCH; // for compatability with 7
}
// Windows 10 allows to use DXGI_SWAP_EFFECT_FLIP_DISCARD
// for Windows 8 compatibility use DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
// for Windows 7 compatibility use DXGI_SWAP_EFFECT_DISCARD
if (d3d11_feature_level >= D3D_FEATURE_LEVEL_11_0) {
// this is supported only on FLIP presentation model
scd.Scaling = DXGI_SCALING_NONE;
scd.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
scd.BufferCount = 3;
gfx._can_vsync = false;
log_verbose("Present mode is flip discard, 3 buffers");
} else {
scd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
scd.BufferCount = 2;
gfx._can_vsync = true;
log_verbose("Present mode is discard, 2 buffers");
}
// Obtain DXGI factory from device
IDXGIDevice *dxgi_device;
hr = VTABLE(QueryInterface, d3d11_device, &IID_IDXGIDevice, cast(void**)&dxgi_device);
win32_check_hr(hr);
IDXGIAdapter *adapter;
hr = VTABLE(GetAdapter, dxgi_device, &adapter);
win32_check_hr(hr);
IDXGIFactory2 *dxgi_factory;
hr = VTABLE(GetParent, adapter, &IID_IDXGIFactory2, cast(void**)&dxgi_factory);
win32_check_hr(hr);
hr = VTABLE(CreateSwapChainForHwnd, dxgi_factory, (IUnknown*)d3d11_device, window._os_handle, &scd, 0, 0, &d3d11_swap_chain);
win32_check_hr(hr);
RECT client_rect;
bool ok = GetClientRect(window._os_handle, &client_rect);
assert(ok, "GetClientRect failed with error code %lu", GetLastError());
d3d11_swap_chain_width = client_rect.right-client_rect.left;
d3d11_swap_chain_height = client_rect.bottom-client_rect.top;
// store the swap chain description, as created by CreateSwapChainForHwnd
hr = VTABLE(GetDesc1, d3d11_swap_chain, &d3d11_swap_chain_desc);
win32_check_hr(hr);
// disable alt enter
VTABLE(MakeWindowAssociation, dxgi_factory, window._os_handle, cast (u32) DXGI_MWA_NO_ALT_ENTER);
D3D11Release(dxgi_device);
D3D11Release(adapter);
D3D11Release(dxgi_factory);
log("Created swap chain of size %dx%d", d3d11_swap_chain_width, d3d11_swap_chain_height);
} else {
if (d3d11_window_render_target_view) D3D11Release(d3d11_window_render_target_view);
if (d3d11_back_buffer) D3D11Release(d3d11_back_buffer);
RECT client_rect;
bool ok = GetClientRect(window._os_handle, &client_rect);
assert(ok, "GetClientRect failed with error code %lu", GetLastError());
u32 window_width = client_rect.right-client_rect.left;
u32 window_height = client_rect.bottom-client_rect.top;
hr = VTABLE(ResizeBuffers, d3d11_swap_chain, d3d11_swap_chain_desc.BufferCount, window_width, window_height, d3d11_swap_chain_desc.Format, d3d11_swap_chain_desc.Flags);
win32_check_hr(hr);
// update swap chain description
hr = VTABLE(GetDesc1, d3d11_swap_chain, &d3d11_swap_chain_desc);
win32_check_hr(hr);
log("Resized swap chain from %dx%d to %dx%d", d3d11_swap_chain_width, d3d11_swap_chain_height, window_width, window_height);
d3d11_swap_chain_width = window_width;
d3d11_swap_chain_height = window_height;
}
hr = VTABLE(GetBuffer, d3d11_swap_chain, 0, &IID_ID3D11Texture2D, (void**)&d3d11_back_buffer);
win32_check_hr(hr);
hr = VTABLE(CreateRenderTargetView, d3d11_device, (ID3D11Resource*)d3d11_back_buffer, 0, &d3d11_window_render_target_view);
win32_check_hr(hr);
}
void gfx_init() {
gfx.enable_vsync = false;
log_verbose("d3d11 gfx_init");
HWND hwnd = window._os_handle;
HRESULT hr = S_OK;
D3D11_CREATE_DEVICE_FLAG flags = 0;
#if CONFIGURATION == DEBUG
flags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
D3D_DRIVER_TYPE driver_types[] = {
D3D_DRIVER_TYPE_HARDWARE,
D3D_DRIVER_TYPE_WARP,
D3D_DRIVER_TYPE_REFERENCE
};
s64 num_drivers = sizeof(driver_types)/sizeof(D3D_DRIVER_TYPE);
D3D_FEATURE_LEVEL feature_levels[] = {
D3D_FEATURE_LEVEL_11_1,
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0
};
s64 num_feature_levels = sizeof(feature_levels)/sizeof(D3D_FEATURE_LEVEL);
for (s64 i = 0; i < num_drivers; i++) {
d3d11_driver_type = driver_types[i];
hr = D3D11CreateDevice(0, d3d11_driver_type, 0, flags, feature_levels, num_feature_levels, D3D11_SDK_VERSION, &d3d11_device, &d3d11_feature_level, &d3d11_context);
if (hr == E_INVALIDARG) {
// 11_1 not recognized in 11.0
hr = D3D11CreateDevice(0, d3d11_driver_type, 0, flags, feature_levels+1, num_feature_levels-1, D3D11_SDK_VERSION, &d3d11_device, &d3d11_feature_level, &d3d11_context);
}
if (SUCCEEDED(hr)) break;
log_verbose("Failed driver type number %d (%d)", i, driver_types[i]);
}
win32_check_hr(hr);
assert(d3d11_device != 0, "D3D11CreateDevice failed");
#if CONFIGURATION == DEBUG
hr = VTABLE(QueryInterface, d3d11_device, &IID_ID3D11Debug, (void**)&d3d11_debug);
if (SUCCEEDED(hr)) {
log_verbose("D3D11 debug is active");
}
#endif
log_verbose("Created D3D11 device");
IDXGIDevice *dxgi_device = 0;
IDXGIAdapter *target_adapter = 0;
hr = VTABLE(QueryInterface, d3d11_device, &IID_IDXGIDevice, (void **)&dxgi_device);
hr = VTABLE(GetAdapter, dxgi_device, &target_adapter);
if (SUCCEEDED(hr)) {
DXGI_ADAPTER_DESC adapter_desc = ZERO(DXGI_ADAPTER_DESC);
hr = VTABLE(GetDesc, target_adapter, &adapter_desc);
if (SUCCEEDED(hr)) {
string desc = temp_win32_null_terminated_wide_to_fixed_utf8(adapter_desc.Description);
log("D3D11 adapter is: %s", desc);
} else {
log_error("Failed to get adapter description");
}
} else {
log_error("Failed querying targeted d3d11_ adapter");
}
d3d11_update_swapchain();
{
D3D11_BLEND_DESC bd = ZERO(D3D11_BLEND_DESC);
bd.RenderTarget[0].BlendEnable = TRUE;
bd.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
bd.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
bd.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
bd.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
bd.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
bd.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
bd.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
hr = VTABLE(CreateBlendState, d3d11_device, &bd, &d3d11_blend_state);
win32_check_hr(hr);
VTABLE(OMSetBlendState, d3d11_context, d3d11_blend_state, NULL, 0xffffffff);
}
{
D3D11_RASTERIZER_DESC desc = ZERO(D3D11_RASTERIZER_DESC);
desc.FillMode = D3D11_FILL_SOLID;
//desc.CullMode = D3D11_CULL_BACK;
desc.FrontCounterClockwise = FALSE;
desc.DepthClipEnable = FALSE;
desc.CullMode = D3D11_CULL_NONE;
hr = VTABLE(CreateRasterizerState, d3d11_device, &desc, &d3d11_rasterizer);
win32_check_hr(hr);
VTABLE(RSSetState, d3d11_context, d3d11_rasterizer);
}
// COnst buffer
/*{
D3D11_BUFFER_DESC bd;
bd.ByteWidth = align_forward(sizeof(GlobalConstBuffer), 16);
bd.Usage = D3D11_USAGE_DYNAMIC;
bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
ID3D11Device_CreateBuffer(dx_state.d3d_device, &bd, NULL, &dx_state.const_buffer_resource);
}*/
/*{
D3D11_BUFFER_DESC bd;
bd.ByteWidth = align_forward(sizeof(BatchUniforms), 16);
bd.Usage = D3D11_USAGE_DYNAMIC;
bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
ID3D11Device_CreateBuffer(dx_state.d3d_device, &bd, NULL, &render_st.batch.ubo);
}*/
{
D3D11_SAMPLER_DESC sd = ZERO(D3D11_SAMPLER_DESC);
sd.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
sd.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
sd.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
sd.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
sd.ComparisonFunc = D3D11_COMPARISON_NEVER;
hr = VTABLE(CreateSamplerState, d3d11_device, &sd, &d3d11_image_sampler);
win32_check_hr(hr);
}
// We are ooga booga devs so we read the file and compile
#if OOGABOOGA_DEV
string source;
bool source_ok = os_read_entire_file(fxstr("oogabooga/dev/d3d11_image_shader.hlsl"), &source);
assert(source_ok, "Could not open d3d11_image_shader source");
// Compile vertex shader
ID3DBlob* vs_blob = NULL;
ID3DBlob* err_blob = NULL;
hr = D3DCompile((char*)source.data, source.count, 0, 0, 0, "vs_main", "vs_5_0", 0, 0, &vs_blob, &err_blob);
assert(SUCCEEDED(hr), "Vertex Shader Compilation Error: %cs\n", (char*)VTABLE(GetBufferPointer, err_blob));
// Compile pixel shader
ID3DBlob* ps_blob = NULL;
hr = D3DCompile((char*)source.data, source.count, 0, 0, 0, "ps_main", "ps_5_0", 0, 0, &ps_blob, &err_blob);
assert(SUCCEEDED(hr), "Vertex Shader Compilation Error: %cs\n", (char*)VTABLE(GetBufferPointer, err_blob));
void *vs_buffer = VTABLE(GetBufferPointer, vs_blob);
u64 vs_size = VTABLE(GetBufferSize, vs_blob);
void *ps_buffer = VTABLE(GetBufferPointer, ps_blob);
u64 ps_size = VTABLE(GetBufferSize, ps_blob);
log_verbose("Shaders compiled");
///
// Dump blobs to the .c
File blob_file = os_file_open(fxstr("oogabooga/d3d11_image_shader_bytecode.c"), O_WRITE | O_CREATE);
os_file_write_string(blob_file, fxstr("/*\n"));
os_file_write_string(blob_file, fxstr("<<<<<< Bytecode compiled from HLSL code below: >>>>>>\n\n"));
os_file_write_string(blob_file, source);
os_file_write_string(blob_file, fxstr("\n*/\n\n"));
os_file_write_string(blob_file, fxstr("const u8 IMAGE_SHADER_VERTEX_BLOB_BYTES[] = {\n"));
for (u64 i = 0; i < vs_size; i++) {
os_file_write_string(blob_file, tprint("0x%02x", (int)((u8*)vs_buffer)[i]));
if (i < vs_size-1) os_file_write_string(blob_file, fxstr(", "));
if (i % 15 == 0 && i != 0) os_file_write_string(blob_file, fxstr("\n"));
}
os_file_write_string(blob_file, fxstr("\n};\n"));
os_file_write_string(blob_file, fxstr("const u8 IMAGE_SHADER_PIXEL_BLOB_BYTES[] = {\n"));
for (u64 i = 0; i < ps_size; i++) {
os_file_write_string(blob_file, tprint("0x%02x", (int)((u8*)ps_buffer)[i]));
if (i < ps_size-1) os_file_write_string(blob_file, fxstr(", "));
if (i % 15 == 0 && i != 0) os_file_write_string(blob_file, fxstr("\n"));
}
os_file_write_string(blob_file, fxstr("\n};\n"));
os_file_close(blob_file);
#else
const void *vs_buffer = IMAGE_SHADER_VERTEX_BLOB_BYTES;
u64 vs_size = sizeof(IMAGE_SHADER_VERTEX_BLOB_BYTES);
const void *ps_buffer = IMAGE_SHADER_PIXEL_BLOB_BYTES;
u64 ps_size = sizeof(IMAGE_SHADER_PIXEL_BLOB_BYTES);
log_verbose("Cached shaders loaded");
#endif
// Create the shaders
hr = VTABLE(CreateVertexShader, d3d11_device, vs_buffer, vs_size, NULL, &d3d11_image_vertex_shader);
win32_check_hr(hr);
hr = VTABLE(CreatePixelShader, d3d11_device, ps_buffer, ps_size, NULL, &d3d11_image_pixel_shader);
win32_check_hr(hr);
log_verbose("Shaders created");
#if OOGABOOGA_DEV
D3D11Release(vs_blob);
D3D11Release(ps_blob);
#endif
D3D11_INPUT_ELEMENT_DESC layout[4];
memset(layout, 0, sizeof(layout));
layout[0] = (D3D11_INPUT_ELEMENT_DESC){
"POSITION", 0,
DXGI_FORMAT_R32G32B32A32_FLOAT, 0,
offsetof(D3D11_Vertex, position),
D3D11_INPUT_PER_VERTEX_DATA, 0
};
layout[1] = (D3D11_INPUT_ELEMENT_DESC){
"TEXCOORD", 0,
DXGI_FORMAT_R32G32_FLOAT, 0,
offsetof(D3D11_Vertex, uv),
D3D11_INPUT_PER_VERTEX_DATA, 0
};
layout[2] = (D3D11_INPUT_ELEMENT_DESC){
"COLOR", 0,
DXGI_FORMAT_R32G32B32A32_FLOAT, 0,
offsetof(D3D11_Vertex, color),
D3D11_INPUT_PER_VERTEX_DATA, 0
};
layout[3] = (D3D11_INPUT_ELEMENT_DESC){
"TEXTURE_INDEX", 0,
DXGI_FORMAT_R32_SINT, 0,
offsetof(D3D11_Vertex, texture_index),
D3D11_INPUT_PER_VERTEX_DATA, 0
};
hr = VTABLE(CreateInputLayout, d3d11_device, layout, 4, vs_buffer, vs_size, &d3d11_image_vertex_layout);
log_info("D3D11 init done");
}
void d3d11_draw_call(int number_of_rendered_quads, ID3D11ShaderResourceView **textures, u64 num_textures) {
VTABLE(OMSetBlendState, d3d11_context, d3d11_blend_state, 0, 0xffffffff);
VTABLE(OMSetRenderTargets, d3d11_context, 1, &d3d11_window_render_target_view, 0);
VTABLE(RSSetState, d3d11_context, d3d11_rasterizer);
D3D11_VIEWPORT viewport = ZERO(D3D11_VIEWPORT);
viewport.Width = d3d11_swap_chain_width;
viewport.Height = d3d11_swap_chain_height;
viewport.MaxDepth = 1.0;
VTABLE(RSSetViewports, d3d11_context, 1, &viewport);
UINT stride = sizeof(D3D11_Vertex);
UINT offset = 0;
VTABLE(IASetInputLayout, d3d11_context, d3d11_image_vertex_layout);
VTABLE(IASetVertexBuffers, d3d11_context, 0, 1, &d3d11_quad_vbo, &stride, &offset);
VTABLE(IASetPrimitiveTopology, d3d11_context, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
VTABLE(VSSetShader, d3d11_context, d3d11_image_vertex_shader, NULL, 0);
VTABLE(PSSetShader, d3d11_context, d3d11_image_pixel_shader, NULL, 0);
VTABLE(PSSetSamplers, d3d11_context, 0, 1, &d3d11_image_sampler);
VTABLE(PSSetShaderResources, d3d11_context, 0, num_textures, textures);
VTABLE(ClearRenderTargetView, d3d11_context, d3d11_window_render_target_view, (float*)&window.clear_color);
VTABLE(Draw, d3d11_context, number_of_rendered_quads * 6, 0);
}
void gfx_update() {
if (window.should_close) return;
VTABLE(ClearRenderTargetView, d3d11_context, d3d11_window_render_target_view, (float*)&window.clear_color);
f64 rest_before = os_get_current_time_in_seconds();
HRESULT hr;
///
// purge garbage
for (u64 i = 0; i < draw_frame.garbage_stack_count; i++) {
ID3D11ShaderResourceView *view = draw_frame.garbage_stack[i];
ID3D11Resource *resource = 0;
VTABLE(GetResource, view, &resource);
ID3D11Texture2D *texture = 0;
hr = VTABLE(QueryInterface, resource, &IID_ID3D11Texture2D, (void**)&texture);
if (SUCCEEDED(hr)) {
D3D11Release(view);
D3D11Release(texture);
log("Destroyed an image");
} else {
panic("Unhandled D3D11 resource deletion");
}
}
///
// Maybe resize swap chain
RECT client_rect;
bool ok = GetClientRect(window._os_handle, &client_rect);
assert(ok, "GetClientRect failed with error code %lu", GetLastError());
u32 window_width = client_rect.right-client_rect.left;
u32 window_height = client_rect.bottom-client_rect.top;
if (window_width != d3d11_swap_chain_width || window_height != d3d11_swap_chain_height) {
d3d11_update_swapchain();
}
///
// Maybe grow quad vbo
u32 required_size = sizeof(D3D11_Vertex) * draw_frame.num_blocks*QUADS_PER_BLOCK*6;
if (required_size > d3d11_quad_vbo_size) {
if (d3d11_quad_vbo) {
D3D11Release(d3d11_quad_vbo);
}
D3D11_BUFFER_DESC desc = ZERO(D3D11_BUFFER_DESC);
desc.Usage = D3D11_USAGE_DYNAMIC;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
desc.ByteWidth = required_size;
desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
HRESULT hr = VTABLE(CreateBuffer, d3d11_device, &desc, 0, &d3d11_quad_vbo);
assert(SUCCEEDED(hr), "CreateBuffer failed");
d3d11_quad_vbo_size = required_size;
log_verbose("Grew quad vbo to %d bytes.", d3d11_quad_vbo_size);
}
if (draw_frame.num_blocks > 0) {
///
// Render geometry from into vbo quad list
D3D11_MAPPED_SUBRESOURCE buffer_mapping;
VTABLE(Map, d3d11_context, (ID3D11Resource*)d3d11_quad_vbo, 0, D3D11_MAP_WRITE_DISCARD, 0, &buffer_mapping);
ID3D11ShaderResourceView *textures[32];
ID3D11ShaderResourceView *last_texture = 0;
u64 num_textures = 0;
D3D11_Vertex* head = buffer_mapping.pData;
D3D11_Vertex* pointer = head;
u64 number_of_rendered_quads = 0;
Draw_Quad_Block *block = &draw_frame.first_block;
while (block != 0) {
for (u64 i = 0; i < block->num_quads; i++) {
Draw_Quad *q = &block->quad_buffer[i];
int texture_index = -1;
if (q->image) {
if (!q->image->gfx_handle) {
D3D11_TEXTURE2D_DESC desc = ZERO(D3D11_TEXTURE2D_DESC);
desc.Width = q->image->width;
desc.Height = q->image->height;
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
desc.CPUAccessFlags = 0;
desc.MiscFlags = 0;
D3D11_SUBRESOURCE_DATA data = ZERO(D3D11_SUBRESOURCE_DATA);
data.pSysMem = q->image->data;
data.SysMemPitch = q->image->width * 4; // #Magicvalue assuming 4 channels
ID3D11Texture2D* texture = 0;
HRESULT hr = VTABLE(CreateTexture2D, d3d11_device, &desc, &data, &texture);
win32_check_hr(hr);
hr = VTABLE(CreateShaderResourceView, d3d11_device, (ID3D11Resource*)texture, 0, &q->image->gfx_handle);
win32_check_hr(hr);
log_verbose("Created an image of width %d and height %d.", q->image->width, q->image->height);
}
if (last_texture == q->image->gfx_handle) {
texture_index = (int)(num_textures-1);
} else {
// First look if texture is already bound
for (u64 j = 0; j < num_textures; j++) {
if (textures[j] == q->image->gfx_handle) {
texture_index = (int)j;
break;
}
}
// Otherwise use a new slot
if (texture_index <= -1) {
if (num_textures >= 32) {
// If max textures reached, make a draw call and start over
d3d11_draw_call(number_of_rendered_quads, textures, num_textures);
num_textures = 0;
texture_index = 0;
number_of_rendered_quads = 0;
pointer = head;
} else {
texture_index = (int)num_textures;
num_textures += 1;
}
}
}
textures[texture_index] = q->image->gfx_handle;
last_texture = q->image->gfx_handle;
}
// We will write to 6 vertices for the one quad (two tris)
D3D11_Vertex* BL = pointer + 0;
D3D11_Vertex* TL = pointer + 1;
D3D11_Vertex* TR = pointer + 2;
D3D11_Vertex* BL2 = pointer + 3;
D3D11_Vertex* TR2 = pointer + 4;
D3D11_Vertex* BR = pointer + 5;
pointer += 6;
BL->position = v4(q->bottom_left.x, q->bottom_left.y, 0, 1);
TL->position = v4(q->top_left.x, q->top_left.y, 0, 1);
TR->position = v4(q->top_right.x, q->top_right.y, 0, 1);
BR->position = v4(q->bottom_right.x, q->bottom_right.y, 0, 1);
BL->uv = v2(q->uv.x1, q->uv.y1);
TL->uv = v2(q->uv.x1, q->uv.y2);
TR->uv = v2(q->uv.x2, q->uv.y2);
BR->uv = v2(q->uv.x2, q->uv.y1);
BL->color = TL->color = TR->color = BR->color = q->color;
BL->texture_index=TL->texture_index=TR->texture_index=BR->texture_index = texture_index;
*BL2 = *BL;
*TR2 = *TR;
number_of_rendered_quads += 1;
}
block = block->next;
}
VTABLE(Unmap, d3d11_context, (ID3D11Resource*)d3d11_quad_vbo, 0);
///
// Draw call
d3d11_draw_call(number_of_rendered_quads, textures, num_textures);
}
f64 rest_after = os_get_current_time_in_seconds();
if (is_key_just_pressed('E'))
log("The rest took %.2fms", (rest_after-rest_before)*1000.0);
f64 before_present = os_get_current_time_in_seconds();
hr = VTABLE(Present, d3d11_swap_chain, gfx._can_vsync && gfx.enable_vsync, 0);
f64 after = os_get_current_time_in_seconds();
if (is_key_just_pressed('E'))
log("Present took %.2fms", (after-before_present)*1000.0);
win32_check_hr(hr);
reset_draw_frame(&draw_frame);
}

View file

@ -7,6 +7,8 @@
HDC hdc; HDC hdc;
typedef BOOL (APIENTRY *PFNWGLSWAPINTERVALEXTPROC) (int interval); typedef BOOL (APIENTRY *PFNWGLSWAPINTERVALEXTPROC) (int interval);
const Gfx_Handle GFX_INVALID_HANDLE = 0;
void gfx_init() { void gfx_init() {
// #Temporary #Cleanup // #Temporary #Cleanup
// #Temporary #Cleanup // #Temporary #Cleanup
@ -56,11 +58,13 @@ void gfx_update() {
for (u64 i = 0; i < block->num_quads; i++) { for (u64 i = 0; i < block->num_quads; i++) {
Draw_Quad q = block->quad_buffer[i]; Draw_Quad q = block->quad_buffer[i];
glColor4f(q.color.r, q.color.g, q.color.b, q.color.a);
glColor4f(v4_expand(q.color));
glVertex2f(v2_expand(q.bottom_left)); glVertex2f(v2_expand(q.bottom_left));
glVertex2f(v2_expand(q.top_left)); glVertex2f(v2_expand(q.top_left));
glVertex2f(v2_expand(q.top_right)); glVertex2f(v2_expand(q.top_right));
glVertex2f(v2_expand(q.bottom_right)); glVertex2f(v2_expand(q.bottom_right));
} }
block = block->next; block = block->next;

37
oogabooga/gfx_interface.c Normal file
View file

@ -0,0 +1,37 @@
#if GFX_RENDERER == GFX_RENDERER_D3D11
#include <d3d11.h>
#include <dxgi.h>
#include <dxgi1_2.h>
#include <d3dcompiler.h>
#include <dxgidebug.h>
#include <d3dcommon.h>
typedef ID3D11ShaderResourceView * Gfx_Handle;
#elif GFX_RENDERER == GFX_RENDERER_VULKAN
#error "We only have a D3D11 renderer at the moment"
#elif GFX_RENDERER == GFX_RENDERER_METAL
#error "We only have a D3D11 renderer at the moment"
#else
#error "Unknown renderer GFX_RENDERER defined"
#endif
typedef struct Gfx_State {
// config
bool enable_vsync;
// readonly
bool _can_vsync;
} Gfx_State;
Gfx_State gfx;
forward_global const Gfx_Handle GFX_INVALID_HANDLE;
typedef struct Gfx_Image {
u32 width, height;
u8 *data;
Gfx_Handle gfx_handle;
} Gfx_Image;

View file

@ -6,89 +6,345 @@
#define RAD_PER_DEG (PI64 / 180.0) #define RAD_PER_DEG (PI64 / 180.0)
#define DEG_PER_RAD (180.0 / PI64) #define DEG_PER_RAD (180.0 / PI64)
#define to_radians (degrees) (((float32)degrees)*(float32)RAD_PER_DEG) #define to_radians (degrees) (((float)degrees)*(float)RAD_PER_DEG)
#define to_degrees (radians) (((float32)radians)*(float32)DEG_PER_RAD) #define to_degrees (radians) (((float)radians)*(float)DEG_PER_RAD)
#define to_radians64(degrees) (((float64)degrees)*(float64)RAD_PER_DEG) #define to_radians64(degrees) (((float64)degrees)*(float64)RAD_PER_DEG)
#define to_degrees64(radians) (((float64)radians)*(float64)DEG_PER_RAD) #define to_degrees64(radians) (((float64)radians)*(float64)DEG_PER_RAD)
#define to_radians32 to_radians #define to_radians32 to_radians
#define to_degrees32 to_degrees #define to_degrees32 to_degrees
typedef struct Vector2 { typedef union Vector2 {
union {float32 x, r;}; struct {float x, y;};
union {float32 y, g;};
} Vector2; } Vector2;
inline Vector2 v2(float32 x, float32 y) { return (Vector2){x, y}; } inline Vector2 v2(float x, float y) { return (Vector2){x, y}; }
#define v2_expand(v) (v).x, (v).y #define v2_expand(v) (v).x, (v).y
typedef struct Vector3 { typedef union Vector3 {
union {float32 x, r;}; struct {float x, y, z;};
union {float32 y, g;}; struct {float r, g, b;};
union {float32 z, b;}; struct {Vector2 xy;};
struct {float _x; Vector2 yz;};
} Vector3; } Vector3;
inline Vector3 v3(float32 x, float32 y, float32 z) { return (Vector3){x, y, z}; } inline Vector3 v3(float x, float y, float z) { return (Vector3){x, y, z}; }
#define v3_expand(v) (v).x, (v).y, (v).z #define v3_expand(v) (v).x, (v).y, (v).z
typedef struct Vector4 { typedef union Vector4 {
union {float32 x, r, left; }; struct {float x, y, z, w;};
union {float32 y, g, bottom;}; struct {float x1, y1, x2, y2;};
union {float32 z, b, right; }; struct {float r, g, b, a;};
union {float32 w, a, top; }; struct {float left, bottom, right, top;};
struct {Vector2 xy; Vector2 zw;};
struct {Vector3 xyz;};
struct {float _x; Vector3 yzw;};
} Vector4; } Vector4;
inline Vector4 v4(float32 x, float32 y, float32 z, float32 w) { return (Vector4){x, y, z, w}; } inline Vector4 v4(float x, float y, float z, float w) { return (Vector4){x, y, z, w}; }
#define v4_expand(v) (v).x, (v).y, (v).z, (v).w #define v4_expand(v) (v).x, (v).y, (v).z, (v).w
// #Simd #Speed // #Simd #Speed
Vector2 v2_add(Vector2 a, Vector2 b) { inline Vector2 v2_add(Vector2 a, Vector2 b) {
return v2(a.x + b.x, a.y + b.y); return v2(a.x + b.x, a.y + b.y);
} }
Vector3 v3_add(Vector3 a, Vector3 b) { inline Vector3 v3_add(Vector3 a, Vector3 b) {
return v3(a.x + b.x, a.y + b.y, a.z + b.z); return v3(a.x + b.x, a.y + b.y, a.z + b.z);
} }
Vector4 v4_add(Vector4 a, Vector4 b) { inline Vector4 v4_add(Vector4 a, Vector4 b) {
return v4(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w); return v4(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w);
} }
Vector2 v2_sub(Vector2 a, Vector2 b) { inline Vector2 v2_sub(Vector2 a, Vector2 b) {
return v2(a.x - b.x, a.y - b.y); return v2(a.x - b.x, a.y - b.y);
} }
Vector3 v3_sub(Vector3 a, Vector3 b) { inline Vector3 v3_sub(Vector3 a, Vector3 b) {
return v3(a.x - b.x, a.y - b.y, a.z - b.z); return v3(a.x - b.x, a.y - b.y, a.z - b.z);
} }
Vector4 v4_sub(Vector4 a, Vector4 b) { inline Vector4 v4_sub(Vector4 a, Vector4 b) {
return v4(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w); return v4(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w);
} }
Vector2 v2_mul(Vector2 a, Vector2 b) { inline Vector2 v2_mul(Vector2 a, Vector2 b) {
return v2(a.x * b.x, a.y * b.y); return v2(a.x * b.x, a.y * b.y);
} }
Vector3 v3_mul(Vector3 a, Vector3 b) { inline Vector2 v2_mulf(Vector2 a, float b) {
return v2(a.x * b, a.y * b);
}
inline Vector3 v3_mul(Vector3 a, Vector3 b) {
return v3(a.x * b.x, a.y * b.y, a.z * b.z); return v3(a.x * b.x, a.y * b.y, a.z * b.z);
} }
Vector4 v4_mul(Vector4 a, Vector4 b) { inline Vector4 v4_mul(Vector4 a, Vector4 b) {
return v4(a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w); return v4(a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w);
} }
Vector2 v2_div(Vector2 a, Vector2 b) { inline Vector2 v2_div(Vector2 a, Vector2 b) {
return v2(a.x / b.x, a.y / b.y); return v2(a.x / b.x, a.y / b.y);
} }
Vector3 v3_div(Vector3 a, Vector3 b) { inline Vector3 v3_div(Vector3 a, Vector3 b) {
return v3(a.x / b.x, a.y / b.y, a.z / b.z); return v3(a.x / b.x, a.y / b.y, a.z / b.z);
} }
Vector4 v4_div(Vector4 a, Vector4 b) { inline Vector4 v4_div(Vector4 a, Vector4 b) {
return v4(a.x / b.x, a.y / b.y, a.z / b.z, a.w / b.w); return v4(a.x / b.x, a.y / b.y, a.z / b.z, a.w / b.w);
} }
Vector2 v2_rotate_point_around_pivot(Vector2 point, Vector2 pivot, float32 rotation_radians) { Vector2 v2_rotate_point_around_pivot(Vector2 point, Vector2 pivot, float rotation_radians) {
float32 s = sin(rotation_radians); float s = sin(rotation_radians);
float32 c = cos(rotation_radians); float c = cos(rotation_radians);
point.x -= pivot.x; point.x -= pivot.x;
point.y -= pivot.y; point.y -= pivot.y;
float32 x_new = point.x * c - point.y * s; float x_new = point.x * c - point.y * s;
float32 y_new = point.x * s + point.y * c; float y_new = point.x * s + point.y * c;
point.x = x_new + pivot.x; point.x = x_new + pivot.x;
point.y = y_new + pivot.y; point.y = y_new + pivot.y;
return point; return point;
} }
typedef struct Matrix4 {
union {float m[4][4]; float data[16]; };
} Matrix4;
Matrix4 m4_scalar(float scalar) {
Matrix4 m;
for (int i = 0; i < 16; i++) {
m.data[i] = 0.0f;
}
m.data[0] = scalar;
m.data[5] = scalar;
m.data[10] = scalar;
m.data[15] = scalar;
return m;
}
Matrix4 m4_make_translation(Vector3 translation) {
Matrix4 m = m4_scalar(1.0);
m.m[0][0] = 1.0f; m.m[1][1] = 1.0f; m.m[2][2] = 1.0f; m.m[3][3] = 1.0f;
m.m[0][3] = translation.x;
m.m[1][3] = translation.y;
m.m[2][3] = translation.z;
return m;
}
Matrix4 m4_make_rotation(Vector3 axis, float radians) {
Matrix4 m = m4_scalar(1.0);
float c = cosf(radians);
float s = sinf(radians);
float t = 1.0f - c;
m.m[0][0] = c + axis.x * axis.x * t;
m.m[0][1] = axis.x * axis.y * t + axis.z * s;
m.m[0][2] = axis.x * axis.z * t - axis.y * s;
m.m[1][0] = axis.y * axis.x * t - axis.z * s;
m.m[1][1] = c + axis.y * axis.y * t;
m.m[1][2] = axis.y * axis.z * t + axis.x * s;
m.m[2][0] = axis.z * axis.x * t + axis.y * s;
m.m[2][1] = axis.z * axis.y * t - axis.x * s;
m.m[2][2] = c + axis.z * axis.z * t;
m.m[3][3] = 1.0f;
return m;
}
inline Matrix4 m4_make_rotation_z(float radians) {
return m4_make_rotation(v3(0, 0, 1), radians);
}
Matrix4 m4_make_scale(Vector3 scale) {
Matrix4 m = m4_scalar(1.0);
m.m[0][0] = scale.x;
m.m[1][1] = scale.y;
m.m[2][2] = scale.z;
m.m[3][3] = 1.0f;
return m;
}
Matrix4 m4_multiply(Matrix4 a, Matrix4 b) {
Matrix4 result;
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
result.m[i][j] = a.m[i][0] * b.m[0][j] +
a.m[i][1] * b.m[1][j] +
a.m[i][2] * b.m[2][j] +
a.m[i][3] * b.m[3][j];
}
}
return result;
}
inline Matrix4 m4_translate(Matrix4 m, Vector3 translation) {
Matrix4 translation_matrix = m4_make_translation(translation);
return m4_multiply(m, translation_matrix);
}
inline Matrix4 m4_rotate(Matrix4 m, Vector3 axis, float radians) {
Matrix4 rotation_matrix = m4_make_rotation(axis, radians);
return m4_multiply(m, rotation_matrix);
}
inline Matrix4 m4_rotate_z(Matrix4 m, float radians) {
Matrix4 rotation_matrix = m4_make_rotation(v3(0, 0, 1), radians);
return m4_multiply(m, rotation_matrix);
}
inline Matrix4 m4_scale(Matrix4 m, Vector3 scale) {
Matrix4 scale_matrix = m4_make_scale(scale);
return m4_multiply(m, scale_matrix);
}
Matrix4 m4_make_orthographic_projection(float left, float right, float bottom, float top, float near, float far) {
Matrix4 m = m4_scalar(1.0f);
m.m[0][0] = 2.0f / (right - left);
m.m[1][1] = 2.0f / (top - bottom);
m.m[2][2] = -2.0f / (far - near);
m.m[0][3] = -(right + left) / (right - left);
m.m[1][3] = -(top + bottom) / (top - bottom);
m.m[2][3] = -(far + near) / (far - near);
m.m[3][3] = 1.0f;
return m;
}
Vector4 m4_transform(Matrix4 m, Vector4 v) {
Vector4 result;
result.x = m.m[0][0] * v.x + m.m[0][1] * v.y + m.m[0][2] * v.z + m.m[0][3] * v.w;
result.y = m.m[1][0] * v.x + m.m[1][1] * v.y + m.m[1][2] * v.z + m.m[1][3] * v.w;
result.z = m.m[2][0] * v.x + m.m[2][1] * v.y + m.m[2][2] * v.z + m.m[2][3] * v.w;
result.w = m.m[3][0] * v.x + m.m[3][1] * v.y + m.m[3][2] * v.z + m.m[3][3] * v.w;
return result;
}
Matrix4 m4_inverse(Matrix4 m) {
Matrix4 inv;
float det;
inv.m[0][0] = m.m[1][1] * m.m[2][2] * m.m[3][3] -
m.m[1][1] * m.m[2][3] * m.m[3][2] -
m.m[2][1] * m.m[1][2] * m.m[3][3] +
m.m[2][1] * m.m[1][3] * m.m[3][2] +
m.m[3][1] * m.m[1][2] * m.m[2][3] -
m.m[3][1] * m.m[1][3] * m.m[2][2];
inv.m[1][0] = -m.m[1][0] * m.m[2][2] * m.m[3][3] +
m.m[1][0] * m.m[2][3] * m.m[3][2] +
m.m[2][0] * m.m[1][2] * m.m[3][3] -
m.m[2][0] * m.m[1][3] * m.m[3][2] -
m.m[3][0] * m.m[1][2] * m.m[2][3] +
m.m[3][0] * m.m[1][3] * m.m[2][2];
inv.m[2][0] = m.m[1][0] * m.m[2][1] * m.m[3][3] -
m.m[1][0] * m.m[2][3] * m.m[3][1] -
m.m[2][0] * m.m[1][1] * m.m[3][3] +
m.m[2][0] * m.m[1][3] * m.m[3][1] +
m.m[3][0] * m.m[1][1] * m.m[2][3] -
m.m[3][0] * m.m[1][3] * m.m[2][1];
inv.m[3][0] = -m.m[1][0] * m.m[2][1] * m.m[3][2] +
m.m[1][0] * m.m[2][2] * m.m[3][1] +
m.m[2][0] * m.m[1][1] * m.m[3][2] -
m.m[2][0] * m.m[1][2] * m.m[3][1] -
m.m[3][0] * m.m[1][1] * m.m[2][2] +
m.m[3][0] * m.m[1][2] * m.m[2][1];
inv.m[0][1] = -m.m[0][1] * m.m[2][2] * m.m[3][3] +
m.m[0][1] * m.m[2][3] * m.m[3][2] +
m.m[2][1] * m.m[0][2] * m.m[3][3] -
m.m[2][1] * m.m[0][3] * m.m[3][2] -
m.m[3][1] * m.m[0][2] * m.m[2][3] +
m.m[3][1] * m.m[0][3] * m.m[2][2];
inv.m[1][1] = m.m[0][0] * m.m[2][2] * m.m[3][3] -
m.m[0][0] * m.m[2][3] * m.m[3][2] -
m.m[2][0] * m.m[0][2] * m.m[3][3] +
m.m[2][0] * m.m[0][3] * m.m[3][2] +
m.m[3][0] * m.m[0][2] * m.m[2][3] -
m.m[3][0] * m.m[0][3] * m.m[2][2];
inv.m[2][1] = -m.m[0][0] * m.m[2][1] * m.m[3][3] +
m.m[0][0] * m.m[2][3] * m.m[3][1] +
m.m[2][0] * m.m[0][1] * m.m[3][3] -
m.m[2][0] * m.m[0][3] * m.m[3][1] -
m.m[3][0] * m.m[0][1] * m.m[2][3] +
m.m[3][0] * m.m[0][3] * m.m[2][1];
inv.m[3][1] = m.m[0][0] * m.m[2][1] * m.m[3][2] -
m.m[0][0] * m.m[2][2] * m.m[3][1] -
m.m[2][0] * m.m[0][1] * m.m[3][2] +
m.m[2][0] * m.m[0][2] * m.m[3][1] +
m.m[3][0] * m.m[0][1] * m.m[2][2] -
m.m[3][0] * m.m[0][2] * m.m[2][1];
inv.m[0][2] = m.m[0][1] * m.m[1][2] * m.m[3][3] -
m.m[0][1] * m.m[1][3] * m.m[3][2] -
m.m[1][1] * m.m[0][2] * m.m[3][3] +
m.m[1][1] * m.m[0][3] * m.m[3][2] +
m.m[3][1] * m.m[0][2] * m.m[1][3] -
m.m[3][1] * m.m[0][3] * m.m[1][2];
inv.m[1][2] = -m.m[0][0] * m.m[1][2] * m.m[3][3] +
m.m[0][0] * m.m[1][3] * m.m[3][2] +
m.m[1][0] * m.m[0][2] * m.m[3][3] -
m.m[1][0] * m.m[0][3] * m.m[3][2] -
m.m[3][0] * m.m[0][2] * m.m[1][3] +
m.m[3][0] * m.m[0][3] * m.m[1][2];
inv.m[2][2] = m.m[0][0] * m.m[1][1] * m.m[3][3] -
m.m[0][0] * m.m[1][3] * m.m[3][1] -
m.m[1][0] * m.m[0][1] * m.m[3][3] +
m.m[1][0] * m.m[0][3] * m.m[3][1] +
m.m[3][0] * m.m[0][1] * m.m[1][3] -
m.m[3][0] * m.m[0][3] * m.m[1][1];
inv.m[3][2] = -m.m[0][0] * m.m[1][1] * m.m[3][2] +
m.m[0][0] * m.m[1][2] * m.m[3][1] +
m.m[1][0] * m.m[0][1] * m.m[3][2] -
m.m[1][0] * m.m[0][2] * m.m[3][1] -
m.m[3][0] * m.m[0][1] * m.m[1][2] +
m.m[3][0] * m.m[0][2] * m.m[1][1];
inv.m[0][3] = -m.m[0][1] * m.m[1][2] * m.m[2][3] +
m.m[0][1] * m.m[1][3] * m.m[2][2] +
m.m[1][1] * m.m[0][2] * m.m[2][3] -
m.m[1][1] * m.m[0][3] * m.m[2][2] -
m.m[2][1] * m.m[0][2] * m.m[1][3] +
m.m[2][1] * m.m[0][3] * m.m[1][2];
inv.m[1][3] = m.m[0][0] * m.m[1][2] * m.m[2][3] -
m.m[0][0] * m.m[1][3] * m.m[2][2] -
m.m[1][0] * m.m[0][2] * m.m[2][3] +
m.m[1][0] * m.m[0][3] * m.m[2][2] +
m.m[2][0] * m.m[0][2] * m.m[1][3] -
m.m[2][0] * m.m[0][3] * m.m[1][2];
inv.m[2][3] = -m.m[0][0] * m.m[1][1] * m.m[2][3] +
m.m[0][0] * m.m[1][3] * m.m[2][1] +
m.m[1][0] * m.m[0][1] * m.m[2][3] -
m.m[1][0] * m.m[0][3] * m.m[2][1] -
m.m[2][0] * m.m[0][1] * m.m[1][3] +
m.m[2][0] * m.m[0][3] * m.m[1][1];
inv.m[3][3] = m.m[0][0] * m.m[1][1] * m.m[2][2] -
m.m[0][0] * m.m[1][2] * m.m[2][1] -
m.m[1][0] * m.m[0][1] * m.m[2][2] +
m.m[1][0] * m.m[0][2] * m.m[2][1] +
m.m[2][0] * m.m[0][1] * m.m[1][2] -
m.m[2][0] * m.m[0][2] * m.m[1][1];
det = m.m[0][0] * inv.m[0][0] + m.m[0][1] * inv.m[1][0] + m.m[0][2] * inv.m[2][0] + m.m[0][3] * inv.m[3][0];
if (det == 0)
return m4_scalar(0);
det = 1.0f / det;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
inv.m[i][j] *= det;
}
}
return inv;
}

View file

@ -383,11 +383,14 @@ void* heap_allocator_proc(u64 size, void *p, Allocator_Message message) {
break; break;
} }
case ALLOCATOR_DEALLOCATE: { case ALLOCATOR_DEALLOCATE: {
assert(is_pointer_valid(p), "Invalid pointer passed to heap allocator deallocate"); assert(is_pointer_valid(p), "Invalid pointer passed to heap allocator deallocate");
heap_dealloc(p); heap_dealloc(p);
return 0; return 0;
} }
case ALLOCATOR_REALLOCATE: { case ALLOCATOR_REALLOCATE: {
if (!p) {
return heap_alloc(size);
}
assert(is_pointer_valid(p), "Invalid pointer passed to heap allocator reallocate"); assert(is_pointer_valid(p), "Invalid pointer passed to heap allocator reallocate");
Heap_Allocation_Metadata *meta = (Heap_Allocation_Metadata*)((u64)p)-sizeof(Heap_Allocation_Metadata); Heap_Allocation_Metadata *meta = (Heap_Allocation_Metadata*)((u64)p)-sizeof(Heap_Allocation_Metadata);
void *new = heap_alloc(size); void *new = heap_alloc(size);
@ -399,6 +402,15 @@ void* heap_allocator_proc(u64 size, void *p, Allocator_Message message) {
return 0; return 0;
} }
Allocator get_heap_allocator() {
Allocator heap_allocator;
heap_allocator.proc = heap_allocator_proc;
heap_allocator.data = 0;
return heap_allocator;
}
/// ///
/// ///
// Temporary storage // Temporary storage

View file

@ -37,13 +37,40 @@ void* lodepng_malloc(size_t size) {
return context.allocator.proc((u64)size, 0, ALLOCATOR_ALLOCATE); return context.allocator.proc((u64)size, 0, ALLOCATOR_ALLOCATE);
} }
void* lodepng_realloc(void* ptr, size_t new_size) { void* lodepng_realloc(void* ptr, size_t new_size) {
return context.allocator.proc((u64)new_size, 0, ALLOCATOR_REALLOCATE); return context.allocator.proc((u64)new_size, ptr, ALLOCATOR_REALLOCATE);
} }
void lodepng_free(void* ptr) { void lodepng_free(void* ptr) {
if (!ptr) return;
context.allocator.proc(0, ptr, ALLOCATOR_DEALLOCATE); context.allocator.proc(0, ptr, ALLOCATOR_DEALLOCATE);
} }
#define LODEPNG_NO_COMPILE_ALLOCATORS #define LODEPNG_NO_COMPILE_ALLOCATORS
//#define LODEPNG_NO_COMPILE_ANCILLARY_CHUNKS
#define LODEPNG_NO_COMPILE_DISK
#define LODEPNG_NO_COMPILE_ERROR_TEXT
#define LODEPNG_NO_COMPILE_ENCODER
// One day I might write my own png decoder so we don't even need this
#include "third_party/lodepng.h"
#include "third_party/lodepng.c" #include "third_party/lodepng.c"
/*
To decode a png file:
// 1. Read to memory
string path = fixed_string("my_image.png");
string png;
os_read_entire_file(path, &png);
// 2. Decode
u8 *image;
u32 width;
u32 height;
u32 error = lodepng_decode32(&image, &width, &height, png.data, png.count);
// Cleanup
dealloc_string(png);
dealloc(image);
*/
///// /////
@ -52,14 +79,17 @@ void lodepng_free(void* ptr) {
#ifdef _WIN32 #ifdef _WIN32
#include <Windows.h> #include <Windows.h>
#define TARGET_OS WINDOWS #define TARGET_OS WINDOWS
#define OS_PATHS_HAVE_BACKSLASH 1
#elif defined(__linux__) #elif defined(__linux__)
// Include whatever #Incomplete #Portability // Include whatever #Incomplete #Portability
#define TARGET_OS LINUX #define TARGET_OS LINUX
#error "Linux is not supported yet"; #error "Linux is not supported yet";
#define OS_PATHS_HAVE_BACKSLASH 0
#elif defined(__APPLE__) && defined(__MACH__) #elif defined(__APPLE__) && defined(__MACH__)
// Include whatever #Incomplete #Portability // Include whatever #Incomplete #Portability
#define TARGET_OS MACOS #define TARGET_OS MACOS
#error "Mac is not supported yet"; #error "Mac is not supported yet";
#define OS_PATHS_HAVE_BACKSLASH 1
#else #else
#error "Current OS not supported!"; #error "Current OS not supported!";
#endif #endif
@ -67,11 +97,6 @@ void lodepng_free(void* ptr) {
#define GFX_RENDERER_D3D11 0 #define GFX_RENDERER_D3D11 0
#define GFX_RENDERER_VULKAN 1 #define GFX_RENDERER_VULKAN 1
#define GFX_RENDERER_METAL 2 #define GFX_RENDERER_METAL 2
#define GFX_RENDERER_LEGACY_OPENGL 3 // #Temporary #Cleanup
// #Temporary #Cleanup
#undef GFX_RENDERER
#define GFX_RENDERER GFX_RENDERER_LEGACY_OPENGL
#ifndef GFX_RENDERER #ifndef GFX_RENDERER
// #Portability // #Portability
@ -88,8 +113,18 @@ void lodepng_free(void* ptr) {
#include "string.c" #include "string.c"
#include "unicode.c" #include "unicode.c"
#include "string_format.c" #include "string_format.c"
#include "path_utils.c"
#include "os_interface.c" #include "os_interface.c"
#include "gfx_interface.c"
// I hope whoever caused this @ microsoft is fired.
#ifdef near
#undef near
#endif
#ifdef far
#undef far
#endif
#include "random.c" #include "random.c"
@ -110,7 +145,7 @@ void lodepng_free(void* ptr) {
#elif GFX_RENDERER == GFX_RENDERER_LEGACY_OPENGL #elif GFX_RENDERER == GFX_RENDERER_LEGACY_OPENGL
#include "gfx_impl_legacy_opengl.c" #include "gfx_impl_legacy_opengl.c"
#else #else
#error "Unknown renderer defined in GFX_RENDERER" #error "Unknown renderer GFX_RENDERER defined"
#endif #endif
#if TARGET_OS == WINDOWS #if TARGET_OS == WINDOWS
@ -125,6 +160,7 @@ void lodepng_free(void* ptr) {
void oogabooga_init(u64 program_memory_size) { void oogabooga_init(u64 program_memory_size) {
context.logger = default_logger;
os_init(program_memory_size); os_init(program_memory_size);
gfx_init(); gfx_init();
heap_init(); heap_init();
@ -157,3 +193,4 @@ int main(int argc, char **argv) {
return code; return code;
} }

View file

@ -160,13 +160,9 @@ void os_init(u64 program_memory_size) {
program_memory_mutex = os_make_mutex(); program_memory_mutex = os_make_mutex();
os_grow_program_memory(program_memory_size); os_grow_program_memory(program_memory_size);
Allocator heap_allocator;
heap_allocator.proc = heap_allocator_proc;
heap_allocator.data = 0;
heap_init(); heap_init();
context.allocator = heap_allocator; context.allocator = get_heap_allocator();
os.crt = os_load_dynamic_library(const_string("msvcrt.dll")); os.crt = os_load_dynamic_library(const_string("msvcrt.dll"));
assert(os.crt != 0, "Could not load win32 crt library. Might be compiled with non-msvc? #Incomplete #Portability"); assert(os.crt != 0, "Could not load win32 crt library. Might be compiled with non-msvc? #Incomplete #Portability");
@ -255,9 +251,6 @@ bool os_grow_program_memory(u64 new_size) {
u64 aligned_size = (new_size+os.granularity) & ~(os.granularity); u64 aligned_size = (new_size+os.granularity) & ~(os.granularity);
void* aligned_base = (void*)(((u64)VIRTUAL_MEMORY_BASE+os.granularity) & ~(os.granularity-1)); void* aligned_base = (void*)(((u64)VIRTUAL_MEMORY_BASE+os.granularity) & ~(os.granularity-1));
u64 m = aligned_size & os.granularity;
assert(m == 0);
program_memory = VirtualAlloc(aligned_base, aligned_size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); program_memory = VirtualAlloc(aligned_base, aligned_size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
if (program_memory == 0) { if (program_memory == 0) {
os_unlock_mutex(program_memory_mutex); // #Sync os_unlock_mutex(program_memory_mutex); // #Sync
@ -519,6 +512,31 @@ u16 *temp_win32_fixed_utf8_to_null_terminated_wide(string utf8) {
pop_allocator(); pop_allocator();
return result; return result;
} }
string win32_null_terminated_wide_to_fixed_utf8(const u16 *utf16) {
u64 utf8_length = WideCharToMultiByte(CP_UTF8, 0, (LPCWCH)utf16, -1, 0, 0, 0, 0);
u8 *utf8_str = (u8 *)alloc(utf8_length * sizeof(u8));
int result = WideCharToMultiByte(CP_UTF8, 0, (LPCWCH)utf16, -1, (LPSTR)utf8_str, (int)utf8_length, 0, 0);
if (result == 0) {
dealloc(utf8_str);
return (string){0, 0};
}
string utf8;
utf8.data = utf8_str;
utf8.count = utf8_length-1;
return utf8;
}
string temp_win32_null_terminated_wide_to_fixed_utf8(const u16 *utf16) {
push_temp_allocator();
string result = win32_null_terminated_wide_to_fixed_utf8(utf16);
pop_allocator();
return result;
}
File os_file_open(string path, Os_Io_Open_Flags flags) { File os_file_open(string path, Os_Io_Open_Flags flags) {
DWORD access = GENERIC_READ; DWORD access = GENERIC_READ;
@ -588,13 +606,18 @@ bool os_read_entire_file_handle(File f, string *result) {
return false; return false;
} }
u64 actual_read = 0;
result->data = (u8*)alloc(file_size.QuadPart); result->data = (u8*)alloc(file_size.QuadPart);
if (!result->data) {
return false;
}
result->count = file_size.QuadPart; result->count = file_size.QuadPart;
return os_file_read(f, result->data, file_size.QuadPart, NULL);
bool ok = os_file_read(f, result->data, file_size.QuadPart, &actual_read);
if (!ok) {
dealloc(result->data);
result->data = 0;
return false;
}
return actual_read == file_size.QuadPart;
} }
bool os_read_entire_file(string path, string *result) { bool os_read_entire_file(string path, string *result) {
@ -607,6 +630,38 @@ bool os_read_entire_file(string path, string *result) {
return res; return res;
} }
bool os_is_file(string path) {
u16 *path_wide = temp_win32_fixed_utf8_to_null_terminated_wide(path);
assert(path_wide, "Invalid path string");
if (path_wide == NULL) {
return false;
}
DWORD attributes = GetFileAttributesW(path_wide);
if (attributes == INVALID_FILE_ATTRIBUTES) {
return false;
}
return !(attributes & FILE_ATTRIBUTE_DIRECTORY);
}
bool os_is_directory(string path) {
u16 *path_wide = temp_win32_fixed_utf8_to_null_terminated_wide(path);
assert(path_wide, "Invalid path string");
if (path_wide == NULL) {
return false;
}
DWORD attributes = GetFileAttributesW(path_wide);
if (attributes == INVALID_FILE_ATTRIBUTES) {
return false;
}
return (attributes & FILE_ATTRIBUTE_DIRECTORY);
}
void fprints(File f, string fmt, ...) { void fprints(File f, string fmt, ...) {
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
@ -623,6 +678,10 @@ void fprintf(File f, const char* fmt, ...) {
va_end(args); va_end(args);
} }
/// ///
/// ///
// Memory // Memory

View file

@ -213,6 +213,9 @@ bool os_write_entire_file(string path, string data);
bool os_read_entire_file_handle(File f, string *result); bool os_read_entire_file_handle(File f, string *result);
bool os_read_entire_file(string path, string *result); bool os_read_entire_file(string path, string *result);
bool os_is_file(string path);
bool os_is_directory(string path);
void fprints(File f, string fmt, ...); void fprints(File f, string fmt, ...);
void fprintf(File f, const char* fmt, ...); void fprintf(File f, const char* fmt, ...);

22
oogabooga/path_utils.c Normal file
View file

@ -0,0 +1,22 @@
// in "dir/file.ext" this returns "ext". Returns an empty string if there is no extension
string get_file_extension(string path) {
if (path.count <= 0) return ZERO(string);
for (s64 i = path.count-1; i >= 0; i--) {
if (path.data[i] == '/' || path.data[i] == '\\' || path.data[i] == ':') {
return ZERO(string);
}
if (path.data[i] == '.') {
string ext = ZERO(string);
ext.count = path.count-i;
if (ext.count > 0) ext.data = path.data+i;
return ext;
}
}
return ZERO(string);
}

View file

@ -51,9 +51,10 @@ typedef struct string {
void push_temp_allocator(); void push_temp_allocator();
// Not sure what to call this lol // Not sure what to call this lol
#define fxstr fixed_string
#define fixed_string const_string #define fixed_string const_string
#define cstr const_string #define cstr const_string
#define const_string(s) ((string){ length_of_null_terminated_string(s), (u8*)s }) #define const_string(s) ((string){ length_of_null_terminated_string((const char*)s), (u8*)s })
inline u64 length_of_null_terminated_string(const char* cstring) { inline u64 length_of_null_terminated_string(const char* cstring) {
u64 len = 0; u64 len = 0;
@ -124,3 +125,24 @@ string string_view(string s, u64 start_index, u64 count) {
return result; return result;
} }
// Returns first index from left where "sub" matches in "s". Returns -1 if no match is found.
s64 string_find_from_left(string s, string sub) {
for (s64 i = 0; i <= s.count-sub.count; i++) {
if (strings_match(string_view(s, i, sub.count), sub)) {
return i;
}
}
return -1;
}
// Returns first index from right where "sub" matches in "s" Returns -1 if no match is found.
s64 string_find_from_right(string s, string sub) {
for (s64 i = s.count-sub.count; i >= 0 ; i--) {
if (strings_match(string_view(s, i, sub.count), sub)) {
return i;
}
}
return -1;
}

View file

@ -24,17 +24,16 @@ u64 format_string_to_buffer(char* buffer, u64 count, const char* fmt, va_list ar
// We extend the standard formatting and add %cs so we can format c strings if we need to // We extend the standard formatting and add %cs so we can format c strings if we need to
p += 2; p += 2;
char* s = va_arg(args, char*); char* s = va_arg(args, char*);
assert(is_pointer_valid(s), "You passed an invalid pointer to %%cs");
u64 len = 0; u64 len = 0;
while (*s != '\0' && (bufp - buffer) < count - 1) { while (*s != '\0' && (bufp - buffer) < count - 1) {
assert(is_pointer_valid(s) && len < (1024ULL*1024ULL*1024ULL*1ULL), "The argument passed to %%cs is either way too big, missing null-termination or simply not a char*."); assert(len < (1024ULL*1024ULL*1024ULL*1ULL), "The argument passed to %%cs is either way too big, missing null-termination or simply not a char*.");
if (buffer) { if (buffer) {
*bufp = *s; *bufp = *s;
} }
s += 1; s += 1;
bufp += 1; bufp += 1;
len += 1; len += 1;
assert(is_pointer_valid(s) && len < (1024ULL*1024ULL*1024ULL*1ULL), "The argument passed to %%cs is either way too big, missing null-termination or simply not a char*."); assert(len < (1024ULL*1024ULL*1024ULL*1ULL), "The argument passed to %%cs is either way too big, missing null-termination or simply not a char*.");
} }
} else { } else {
// Fallback to standard vsnprintf // Fallback to standard vsnprintf
@ -222,3 +221,25 @@ void printf(const char* fmt, ...) {
va_end(args); va_end(args);
} }
typedef void(*Logger_Proc)(Log_Level level, string s);
#define LOG_BASE(level, ...) If context.logger then ((Logger_Proc)context.logger)(level, tprint(__VA_ARGS__))
#define log_verbose(...) LOG_BASE(LOG_VERBOSE, __VA_ARGS__)
#define log_info(...) LOG_BASE(LOG_INFO, __VA_ARGS__)
#define log_warning(...) LOG_BASE(LOG_WARNING, __VA_ARGS__)
#define log_error(...) LOG_BASE(LOG_ERROR, __VA_ARGS__)
#define log(...) LOG_BASE(LOG_INFO, __VA_ARGS__)
void default_logger(Log_Level level, string s) {
switch (level) {
case LOG_VERBOSE: print("[VERBOSE]: %s\n", s); break;
case LOG_INFO: print("[INFO]: %s\n", s); break;
case LOG_WARNING: print("[WARNING]: %s\n", s); break;
case LOG_ERROR: print("[ERROR]: %s\n", s); break;
}
}

View file

@ -408,6 +408,23 @@ void test_file_io() {
assert(read_entire_result, "Failed: could not read balls.txt"); assert(read_entire_result, "Failed: could not read balls.txt");
assert(strings_match(hello_balls, fixed_string("Hello, Balls!")), "Failed: balls read/write mismatch. Expected 'Hello, Balls!', got '%s'", hello_balls); assert(strings_match(hello_balls, fixed_string("Hello, Balls!")), "Failed: balls read/write mismatch. Expected 'Hello, Balls!', got '%s'", hello_balls);
u64 integers[4096];
for (u64 i = 0; i < 4096; i++) {
integers[i] = get_random();
}
string integers_data;
integers_data.data = (u8*)integers;
integers_data.count = 4096*sizeof(u64);
bool ok = os_write_entire_file(fxstr("integers"), integers_data);
assert(ok, "write integers fail");
string integers_read;
ok = os_read_entire_file(fxstr("integers"), &integers_read);
assert(ok, "read integers fail");
u64 *new_integers = (u64*)integers_data.data;
assert(integers_read.count == integers_data.count, "Failed: big file read/write mismatch. Read was %d and written was %d", integers_read.count, integers_data.count);
assert(strings_match(integers_data, integers_read), "Failed: big file read/write mismatch");
// Clean up test files // Clean up test files
bool delete_ok = false; bool delete_ok = false;
delete_ok = os_file_delete(fixed_string("test.txt")); delete_ok = os_file_delete(fixed_string("test.txt"));

View file

@ -28,16 +28,7 @@ The manual and changelog are in the header file "lodepng.h"
Rename this file to lodepng.cpp to use it for C++, or to lodepng.c to use it for C. Rename this file to lodepng.cpp to use it for C++, or to lodepng.c to use it for C.
*/ */
/* #include "lodepng.h"
MODIFICATION NOTICE:
Commented out '#include "lodepng.h"' since we are not using the header.
- Charlie Malmqvist 2024-06-29
*/
//#include "lodepng.h"
#ifdef LODEPNG_COMPILE_DISK #ifdef LODEPNG_COMPILE_DISK
#include <limits.h> /* LONG_MAX */ #include <limits.h> /* LONG_MAX */
@ -312,7 +303,7 @@ static void string_cleanup(char** out) {
} }
/*also appends null termination character*/ /*also appends null termination character*/
static char* alloc_string_sized(const char* in, size_t insize) { static char* lodepng_alloc_string_sized(const char* in, size_t insize) {
char* out = (char*)lodepng_malloc(insize + 1); char* out = (char*)lodepng_malloc(insize + 1);
if(out) { if(out) {
lodepng_memcpy(out, in, insize); lodepng_memcpy(out, in, insize);
@ -322,8 +313,8 @@ static char* alloc_string_sized(const char* in, size_t insize) {
} }
/* dynamically allocates a new string with a copy of the null terminated input text */ /* dynamically allocates a new string with a copy of the null terminated input text */
static char* alloc_string(const char* in) { static char* lodepng_alloc_string(const char* in) {
return alloc_string_sized(in, lodepng_strlen(in)); return lodepng_alloc_string_sized(in, lodepng_strlen(in));
} }
#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ #endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
#endif /*LODEPNG_COMPILE_PNG*/ #endif /*LODEPNG_COMPILE_PNG*/
@ -3188,8 +3179,8 @@ static unsigned lodepng_add_text_sized(LodePNGInfo* info, const char* key, const
if(!new_keys || !new_strings) return 83; /*alloc fail*/ if(!new_keys || !new_strings) return 83; /*alloc fail*/
++info->text_num; ++info->text_num;
info->text_keys[info->text_num - 1] = alloc_string(key); info->text_keys[info->text_num - 1] = lodepng_alloc_string(key);
info->text_strings[info->text_num - 1] = alloc_string_sized(str, size); info->text_strings[info->text_num - 1] = lodepng_alloc_string_sized(str, size);
if(!info->text_keys[info->text_num - 1] || !info->text_strings[info->text_num - 1]) return 83; /*alloc fail*/ if(!info->text_keys[info->text_num - 1] || !info->text_strings[info->text_num - 1]) return 83; /*alloc fail*/
return 0; return 0;
@ -3261,10 +3252,10 @@ static unsigned lodepng_add_itext_sized(LodePNGInfo* info, const char* key, cons
++info->itext_num; ++info->itext_num;
info->itext_keys[info->itext_num - 1] = alloc_string(key); info->itext_keys[info->itext_num - 1] = lodepng_alloc_string(key);
info->itext_langtags[info->itext_num - 1] = alloc_string(langtag); info->itext_langtags[info->itext_num - 1] = lodepng_alloc_string(langtag);
info->itext_transkeys[info->itext_num - 1] = alloc_string(transkey); info->itext_transkeys[info->itext_num - 1] = lodepng_alloc_string(transkey);
info->itext_strings[info->itext_num - 1] = alloc_string_sized(str, size); info->itext_strings[info->itext_num - 1] = lodepng_alloc_string_sized(str, size);
return 0; return 0;
} }
@ -3278,7 +3269,7 @@ unsigned lodepng_add_itext(LodePNGInfo* info, const char* key, const char* langt
static unsigned lodepng_assign_icc(LodePNGInfo* info, const char* name, const unsigned char* profile, unsigned profile_size) { static unsigned lodepng_assign_icc(LodePNGInfo* info, const char* name, const unsigned char* profile, unsigned profile_size) {
if(profile_size == 0) return 100; /*invalid ICC profile size*/ if(profile_size == 0) return 100; /*invalid ICC profile size*/
info->iccp_name = alloc_string(name); info->iccp_name = lodepng_alloc_string(name);
info->iccp_profile = (unsigned char*)lodepng_malloc(profile_size); info->iccp_profile = (unsigned char*)lodepng_malloc(profile_size);
if(!info->iccp_name || !info->iccp_profile) return 83; /*alloc fail*/ if(!info->iccp_name || !info->iccp_profile) return 83; /*alloc fail*/

2097
oogabooga/third_party/lodepng.h vendored Normal file

File diff suppressed because it is too large Load diff