Improving multimedia, trying to add a single c library mode

This commit is contained in:
Krzosa Karol
2022-10-02 12:53:29 +02:00
parent 5baff3585e
commit e098663d82
9 changed files with 152 additions and 100 deletions

View File

@@ -63,7 +63,7 @@ get_ctype_name_for_type(Ast_Type *type){
switch(type->kind){
case TYPE_VOID: return "void";
case TYPE_BOOL: return "bool";
case TYPE_STRING: return "String";
case TYPE_STRING: return "CORE_String";
case TYPE_CHAR: return "char";
case TYPE_F32: return "float";
case TYPE_F64: return "double";
@@ -224,7 +224,7 @@ gen_value(Token *pos, Value a){
}break;
case TYPE_STRING:{
int length = 0;
gen("(String){(uint8_t *)\"");
gen("(CORE_String){(uint8_t *)\"");
for(int i = 0; i < a.intern_val.len; i++){
if(a.intern_val.str[i] == '\n'){length += 2; gen("\\n");}
else if(a.intern_val.str[i] == '\r'){length += 2; gen("\\r");}
@@ -789,10 +789,10 @@ compile_to_c_code(){
#define CORE_AssertMessage(x,...) CORE_Assert(x)
#define CORE_BufferSize(x) (sizeof(x)/sizeof((x)[0]))
typedef struct String{
typedef struct CORE_String{
uint8_t *str;
int64_t len;
}String;
}CORE_String;
static void
CORE_MemoryCopy(void *dst, void *src, size_t size){
@@ -873,55 +873,59 @@ CORE_MemoryCopy(void *dst, void *src, size_t size){
compiler_error(0, "Entry point is not defined! Try main or WinMain");
}
// Generate language.core
for(S32 i = 0; i < pctx->base_language_ordered_decl_len; i++){
Ast_Decl *it = get(&pctx->ordered_decls, i);
genln("");
gen_ast(it);
}
// Generate type info
genln("int64_t type_infos_len = %d;", length(&pctx->all_types));
genln("Type_Info *type_infos = (Type_Info[]){");
global_indent++;
Iter(&pctx->all_types){
Ast_Type *t = it.item[0];
genln("{/*%Q*/.kind = %d, .size = %d, .align = %d, .is_unsigned = %s, .type = %d, ", typestring(t),
(S32)t->kind, (S32)t->size, (S32)t->align, t->is_unsigned ? "true" : "false", t->type_id);
switch(t->kind){
case TYPE_POINTER:
case TYPE_SLICE: {
gen(".base_type = %d", t->base->type_id);
} break;
case TYPE_ARRAY: {
gen(".base_type = %d, ", t->base->type_id);
gen(".array_size = %d", t->arr.size);
}break;
case TYPE_LAMBDA: {
gen(".lambda_return = %d, ", t->func.ret->type_id);
gen(".lambda_argument_count = %d, ", t->func.args.len);
gen(".lambda_arguments = (Type_Info[%d]){", t->func.args.len);
For_Named(t->func.args, arg){
gen("{.type = %d}, ", arg->type_id);
}
gen("}");
} break;
case TYPE_STRUCT:{
gen(".struct_member_count = %d, ", t->agg.members.len);
gen(".struct_members = (Type_Info_Struct_Member[]){");
For_Named(t->agg.members, m){
gen("{.name = (String){(uint8_t *)\"%Q\", %d}, .type = %d, .offset = %d}, ", m.name, m.name.len, m.type->type_id, m.offset);
}
gen("}");
}break;
default: {}
// invalid_default_case;
if(emit_type_info){
// Generate language.core
for(S32 i = 0; i < pctx->base_language_ordered_decl_len; i++){
Ast_Decl *it = get(&pctx->ordered_decls, i);
genln("");
gen_ast(it);
}
gen("},");
// Generate type info
genln("int64_t type_infos_len = %d;", length(&pctx->all_types));
genln("Type_Info *type_infos = (Type_Info[]){");
global_indent++;
Iter(&pctx->all_types){
Ast_Type *t = it.item[0];
genln("{/*%Q*/.kind = %d, .size = %d, .align = %d, .is_unsigned = %s, .type = %d, ", typestring(t),
(S32)t->kind, (S32)t->size, (S32)t->align, t->is_unsigned ? "true" : "false", t->type_id);
switch(t->kind){
case TYPE_POINTER:
case TYPE_SLICE: {
gen(".base_type = %d", t->base->type_id);
} break;
case TYPE_ARRAY: {
gen(".base_type = %d, ", t->base->type_id);
gen(".array_size = %d", t->arr.size);
}break;
case TYPE_LAMBDA: {
gen(".lambda_return = %d, ", t->func.ret->type_id);
gen(".lambda_argument_count = %d, ", t->func.args.len);
gen(".lambda_arguments = (Type_Info[%d]){", t->func.args.len);
For_Named(t->func.args, arg){
gen("{.type = %d}, ", arg->type_id);
}
gen("}");
} break;
case TYPE_STRUCT:{
gen(".struct_member_count = %d, ", t->agg.members.len);
gen(".struct_members = (Type_Info_Struct_Member[]){");
For_Named(t->agg.members, m){
gen("{.name = (CORE_String){(uint8_t *)\"%Q\", %d}, .type = %d, .offset = %d}, ", m.name, m.name.len, m.type->type_id, m.offset);
}
gen("}");
}break;
default: {}
// invalid_default_case;
}
gen("},");
}
global_indent--;
gen("};");
}
global_indent--;
gen("};");
// Generate actual code
Iter(&pctx->ordered_decls){

View File

@@ -1,5 +1,10 @@
global B32 emit_line_directives = true;
global B32 emit_type_info = true;
global String symbol_prefix = ""_s;
thread_local Parse_Ctx *pctx;
thread_local B32 emit_line_directives;
Allocator *bigint_allocator;
global S64 bigint_allocation_count;

View File

@@ -13,6 +13,8 @@ In the future
- [ ] Complicated c declaration generation
- [ ] The fact that symbols from main file get introduced to the loaded files
might be kind of confusing, need to watch out for that
- [ ] Define some pragama that forces lambda evaluation in module #force_evaluate
- [ ]
- [ ] Conditional compilation
- [ ] Expand macros
@@ -291,7 +293,9 @@ int main(int argument_count, char **arguments){
test_string_builder();
test_intern_table();
emit_line_directives = true;
emit_line_directives = false;
emit_type_info = false;
symbol_prefix = "Ray_"_s;
if(argument_count > 1){
String program_name = string_from_cstring(arguments[1]);
compile_file(program_name, COMPILE_PRINT_STATS);

View File

@@ -8,14 +8,14 @@ AnyArguments :: (values: []Any)
Assert(*(values[0].data->*S64) == 10)
Assert(*(values[1].data->*S64) == 20)
printf :: #foreign (string: *char, args: ..): int
// printf :: #foreign (string: *char, args: ..): int
main :: (): int
a := 10
b := 20
values := []Any{a, b}
printf("Test %d", {a})
// printf("Test %d", {a})
for values
Assert(it.type == S64)

View File

@@ -1,11 +1,12 @@
// We can bind module to a name
M :: #import "Multimedia.core"
// We can bind a struct to a name
Mu :: M.Mu
// You can bind struct to a name
MU :: M.MU
// We can bind a lambda to a name
Start :: M.StartMultimedia
Update :: M.UpdateMultimedia
// Other example of binding a lambda to a name
SomeOtherLambda :: () ;; pass
@@ -33,7 +34,7 @@ main :: (): int
#Assert(NewInt == int)
#Assert(StrictInt != int)
mu: Mu = Start(x = 1280, y = 720)
Assert(mu.x == 1280 && mu.y == 720)
Start(x = 1280, y = 720)
Update()
return 0

View File

@@ -3,9 +3,8 @@
WinMain :: (hInstance: HINSTANCE, hPrevInstance: HINSTANCE, lpCmdLine: LPSTR, nShowCmd: int): int
StartMultimedia(title = "Hello, people!")
for UpdateMultimedia()
if Mu.key[Key.Escape].is_down
Mu.quit = true
if Mu.key[Key.Escape].down ;; Mu.quit = true
for y := 0, y < Mu.y, y+=1
for x := 0, x < Mu.x, x+=1
Mu.scrn[x + y*Mu.x] = 0xFFFFFF00
for y := 0, y < Mu.window.y, y+=1
for x := 0, x < Mu.window.x, x+=1
Mu.screen[x + y*Mu.window.x] = 0xFFFFFF00

View File

@@ -1,20 +1,25 @@
#import "Base.core"
#import "Math.core"
#import "Arena.core"
W32 :: #load "win32_multimedia.core"
/*
Library for making games/graphical applications
* The api is very simple, very few function calls
* You retrieve information about the state of application from "Mu" struct
* Data is available in many different formats to avoid format conversions in user code
API and name inspired by one of Per Vognsen streams
https://www.youtube.com/watch?v=NG_mUhc8LRw&list=PLU94OURih-CjrtFuazwZ5GYzTrupOMDL7&index=19
All of his channel is recommended watch for programmers.
*/
StartMultimedia :: W32.StartMultimedia
UpdateMultimedia :: W32.UpdateMultimedia
Mu: MU
MU :: struct
scrn: *U32
x : S64
y : S64
screen: *U32
window: MUWindow
key: [Key.Count]KeyState
mouse: Mouse
frame_count: U64
time: MUTime
quit: Bool
@@ -22,6 +27,12 @@ MU :: struct
frame_arena: Arena
os: W32.OS
MUWindow :: struct
x: S64
y: S64
sizef: Vec2
MUTime :: struct
total : F64
delta : F64 // @modifiable
@@ -29,7 +40,7 @@ MUTime :: struct
frame_start: F64
KeyState :: struct
is_down: Bool
down: Bool
Key :: enum
Nil
@@ -41,5 +52,13 @@ Key :: enum
K2;K3;K4;K5;K6;K7;K8;K9
Count
StartMultimedia :: W32.StartMultimedia
UpdateMultimedia :: W32.UpdateMultimedia
Mouse :: struct
left: KeyState
right: KeyState
middle: KeyState
wheel: S64
#import "Base.core"
#import "Math.core"
#import "Arena.core"
W32 :: #load "win32_multimedia.core"

View File

@@ -103,21 +103,24 @@ WM_SYSKEYUP :: 0x0105
WM_SYSCHAR :: 0x0106
WM_SYSDEADCHAR :: 0x0107
WM_MOUSEFIRST :: 0x0200
WM_MOUSEMOVE :: 0x0200
WM_LBUTTONDOWN :: 0x0201
WM_LBUTTONUP :: 0x0202
WM_LBUTTONDBLCLK :: 0x0203
WM_RBUTTONDOWN :: 0x0204
WM_RBUTTONUP :: 0x0205
WM_RBUTTONDBLCLK :: 0x0206
WM_MBUTTONDOWN :: 0x0207
WM_MBUTTONUP :: 0x0208
WM_MBUTTONDBLCLK :: 0x0209
WM_MOUSEWHEEL :: 0x020A
VK_BACK :: 0x08
VK_TAB :: 0x09
/*
* 0x0A - 0x0B : reserved
*/
VK_CLEAR :: 0x0C
VK_RETURN :: 0x0D
/*
* 0x0E - 0x0F : unassigned
*/
VK_SHIFT :: 0x10
VK_CONTROL :: 0x11
VK_MENU :: 0x12
@@ -135,12 +138,10 @@ VK_KANJI :: 0x19
VK_IME_OFF :: 0x1A
VK_ESCAPE :: 0x1B
VK_CONVERT :: 0x1C
VK_NONCONVERT :: 0x1D
VK_ACCEPT :: 0x1E
VK_MODECHANGE :: 0x1F
VK_SPACE :: 0x20
VK_PRIOR :: 0x21
VK_NEXT :: 0x22
@@ -167,13 +168,7 @@ VK_HELP :: 0x2F
VK_LWIN :: 0x5B
VK_RWIN :: 0x5C
VK_APPS :: 0x5D
/*
* 0x5E : reserved
*/
VK_SLEEP :: 0x5F
VK_NUMPAD0 :: 0x60
VK_NUMPAD1 :: 0x61
VK_NUMPAD2 :: 0x62

View File

@@ -132,9 +132,11 @@ StartMultimedia :: (x: S64 = 1280, y: S64 = 720, title: String = "Hello people!"
Mu.os.window_dc = GetDC(Mu.os.window)
Mu.os.bitmap = W32.CreateBitmap(Mu.os.window_dc, size)
Mu.scrn = Mu.os.bitmap.data
Mu.x = size.x
Mu.y = size.y
Mu.screen = Mu.os.bitmap.data
Mu.window.x = size.x
Mu.window.y = size.y
Mu.window.sizef.x = Mu.window.x->F32
Mu.window.sizef.y = Mu.window.y->F32
UpdateMultimedia :: (): Bool
DrawBitmapInCompatibleDC(&Mu.os.bitmap)
@@ -145,12 +147,16 @@ UpdateMultimedia :: (): Bool
DispatchMessageW(&msg)
size := GetWindowSize(Mu.os.window)
if size.x != Mu.x || size.y != Mu.y
if size.x != Mu.window.x || size.y != Mu.window.y
DestroyBitmap(&Mu.os.bitmap)
CreateBitmap(Mu.os.window_dc, size)
Mu.x = size.x
Mu.y = size.y
Mu.screen = Mu.os.bitmap.data
Mu.window.x = size.x
Mu.window.y = size.y
Mu.window.sizef.x = Mu.window.x->F32
Mu.window.sizef.y = Mu.window.y->F32
Mu.frame_count += 1
frame_time := Time() - Mu.time.frame_start
@@ -177,10 +183,29 @@ WindowProc :: (hwnd: HWND, msg: UINT, wparam: WPARAM, lparam: LPARAM): LRESULT
return 0
elif msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN
key := MapVKToKey(wparam)
Mu.key[key].is_down = true
Mu.key[key].down = true
elif msg == WM_KEYUP || msg == WM_SYSKEYUP
key := MapVKToKey(wparam)
Mu.key[key].is_down = false
Mu.key[key].down = false
elif msg == WM_LBUTTONDOWN ;; Mu.mouse.left.down = true
elif msg == WM_LBUTTONUP ;; Mu.mouse.left.down = false
elif msg == WM_RBUTTONDOWN ;; Mu.mouse.right.down = true
elif msg == WM_RBUTTONUP ;; Mu.mouse.right.down = false
elif msg == WM_MBUTTONDOWN ;; Mu.mouse.middle.down = true
elif msg == WM_MBUTTONUP ;; Mu.mouse.middle.down = false
elif msg == WM_MOUSEWHEEL
if wparam->int > 0
Mu.mouse.wheel = 1
else
Mu.mouse.wheel = -1
// Case(WM_CHAR){
// Utf32Result utf32 = Utf16ToUtf32((u16 *)&wparam, 1);
// if(!utf32.error){
// int index = OS->input_count;
// OS->input_count = ClampTop(OS->input_count + 1, (int)(ArrayCount(OS->input) - 1));
// OS->input[index] = utf32.out_str;
// }
// }Break;
else;; result = DefWindowProcW(hwnd, msg, wparam, lparam)