static void cmdline_compressmode(command_t* self, void* param) { struct paki_args* args = (struct paki_args*)self->data; if (str_isequal_nocase(self->arg, "none")) args->compress_mode = COMPRESS_NONE; else if (str_isequal_nocase(self->arg, "fast")) args->compress_mode = COMPRESS_FAST; else if (str_isequal_nocase(self->arg, "normal")) args->compress_mode = COMPRESS_NORMAL; else if (str_isequal_nocase(self->arg, "best")) args->compress_mode = COMPRESS_BEST; else args->compress_mode = COMPRESS_NORMAL; }
int parse_cmd(const char* arg) { uint test_cnt = sizeof(g_tests)/sizeof(struct unit_test_desc); for (uint i = 0; i < test_cnt; i++) { if (str_isequal_nocase(arg, g_tests[i].name)) { return i; } } return -1; }
result_t eng_console_showgraph(uint argc, const char** argv, void* param) { if (argc != 1 && argc != 2) return RET_INVALIDARG; int show = TRUE; if (argc == 2) show = str_tobool(argv[1]); struct rect2di rc; if (str_isequal_nocase(argv[0], "ft")) { if (show) { hud_add_graph("graph-ft", eng_hud_drawftgraph, ui_create_graphline("ft", 0, 16.0f, 60, *rect2di_seti(&rc, 0, 0, GRAPH_WIDTH, GRAPH_HEIGHT), FALSE), NULL); } else { hud_remove_graph("graph-ft"); } } else if (str_isequal_nocase(argv[0], "fps")) { if (show) { hud_add_graph("graph-fps", eng_hud_drawfpsgraph, ui_create_graphline("fps", 0, 60.0f, 60, *rect2di_seti(&rc, 0, 0, GRAPH_WIDTH, GRAPH_HEIGHT), TRUE),NULL); } else { hud_remove_graph("graph-fps"); } } else if (str_isequal_nocase(argv[0], "drawcalls")) { if (show) { hud_add_graph("graph-drawcall", eng_hud_drawcallgraph, ui_create_graphline("drawcalls", 0, 100.0f, 60, *rect2di_seti(&rc, 0, 0, GRAPH_WIDTH, GRAPH_HEIGHT), TRUE), NULL); } else { hud_remove_graph("graph-drawcall"); } } else { return RET_INVALIDARG; } return RET_OK; }
void cmd_gettest(command_t* cmd, void* param) { if (str_isequal_nocase(cmd->arg, "heap")) { g_testidx = 0; } else if (str_isequal_nocase(cmd->arg, "freelist")) { g_testidx = 1; } else if (str_isequal_nocase(cmd->arg, "json")) { g_testidx = 2; } else if (str_isequal_nocase(cmd->arg, "pool")) { g_testidx = 3; } else if (str_isequal_nocase(cmd->arg, "thread")) { g_testidx = 4; } else if (str_isequal_nocase(cmd->arg, "taskmgr")) { g_testidx = 5; } else if (str_isequal_nocase(cmd->arg, "hashtable")) { g_testidx = 6; } }
void gfx_parseparams(struct gfx_params* params, json_t j) { memset(params, 0x00, sizeof(struct gfx_params)); /* graphics */ json_t gfx = json_getitem(j, "gfx"); if (gfx != NULL) { if (json_getb_child(gfx, "fullscreen", FALSE)) BIT_ADD(params->flags, GFX_FLAG_FULLSCREEN); if (json_getb_child(gfx, "vsync", FALSE)) BIT_ADD(params->flags, GFX_FLAG_VSYNC); if (json_getb_child(gfx, "debug", FALSE)) BIT_ADD(params->flags, GFX_FLAG_DEBUG); if (json_getb_child(gfx, "fxaa", FALSE)) BIT_ADD(params->flags, GFX_FLAG_FXAA); if (json_getb_child(gfx, "rebuild-shaders", FALSE)) BIT_ADD(params->flags, GFX_FLAG_REBUILDSHADERS); int msaa = json_geti_child(gfx, "msaa", 0); switch (msaa) { case 2: params->msaa = MSAA_2X; break; case 4: params->msaa = MSAA_4X; break; case 8: params->msaa = MSAA_8X; break; default: params->msaa = MSAA_NONE; break; } const char* texq = json_gets_child(gfx, "texture-quality", "highest"); if (str_isequal_nocase(texq, "high")) params->tex_quality = TEXTURE_QUALITY_HIGH; else if(str_isequal_nocase(texq, "normal")) params->tex_quality = TEXTURE_QUALITY_NORMAL; else if(str_isequal_nocase(texq, "low")) params->tex_quality = TEXTURE_QUALITY_LOW; else params->tex_quality = TEXTURE_QUALITY_HIGHEST; const char* texf = json_gets_child(gfx, "texture-filter", "trilinear"); if (str_isequal_nocase(texf, "trilinear")) params->tex_filter = TEXTURE_FILTER_TRILINEAR; else if(str_isequal_nocase(texf, "bilinear")) params->tex_filter = TEXTURE_FILTER_BILINEAR; else if(str_isequal_nocase(texf, "aniso2x")) params->tex_filter = TEXTURE_FILTER_ANISO2X; else if(str_isequal_nocase(texf, "aniso4x")) params->tex_filter = TEXTURE_FILTER_ANISO4X; else if(str_isequal_nocase(texf, "aniso8x")) params->tex_filter = TEXTURE_FILTER_ANISO8X; else if(str_isequal_nocase(texf, "aniso16x")) params->tex_filter = TEXTURE_FILTER_ANISO16X; else params->tex_filter = TEXTURE_FILTER_TRILINEAR; const char* shq = json_gets_child(gfx, "shading-quality", "high"); if (str_isequal_nocase(shq, "normal")) params->shading_quality = SHADING_QUALITY_NORMAL; else if(str_isequal_nocase(shq, "low")) params->shading_quality = SHADING_QUALITY_LOW; else params->shading_quality = SHADING_QUALITY_HIGH; const char* ver = json_gets_child(gfx, "hw-version", ""); if (str_isequal_nocase(ver, "d3d10")) params->hwver = GFX_HWVER_D3D10_0; else if (str_isequal_nocase(ver, "d3d10.1")) params->hwver = GFX_HWVER_D3D10_1; else if (str_isequal_nocase(ver, "d3d11")) params->hwver = GFX_HWVER_D3D11_0; else if (str_isequal_nocase(ver, "d3d11.1")) params->hwver = GFX_HWVER_D3D11_1; else if (str_isequal_nocase(ver, "gl3.2")) params->hwver = GFX_HWVER_GL3_2; else if (str_isequal_nocase(ver, "gl3.3")) params->hwver = GFX_HWVER_GL3_3; else if (str_isequal_nocase(ver, "gl4.0")) params->hwver = GFX_HWVER_GL4_0; else if (str_isequal_nocase(ver, "gl4.1")) params->hwver = GFX_HWVER_GL4_1; else if (str_isequal_nocase(ver, "gl4.2")) params->hwver = GFX_HWVER_GL4_2; else if (str_isequal_nocase(ver, "gl4.3")) params->hwver = GFX_HWVER_GL4_3; else if (str_isequal_nocase(ver, "gl4.4")) params->hwver = GFX_HWVER_GL4_4; else params->hwver = GFX_HWVER_UNKNOWN; params->adapter_id = json_geti_child(gfx, "adapter-id", 0); params->width = json_geti_child(gfx, "width", 1280); params->height = json_geti_child(gfx, "height", 720); params->refresh_rate = json_geti_child(gfx, "refresh-rate", 60); } else { params->width = 1280; params->height = 720; } }
reshandle_t rs_load_animctrl(const char* ctrl_filepath, uint flags) { reshandle_t res_hdl = INVALID_HANDLE; reshandle_t override_hdl = res_hdl; if (!g_rs.init) return INVALID_HANDLE; struct hashtable_item_chained* item = hashtable_chained_find(&g_rs.dict, hash_str(ctrl_filepath)); if (item != NULL) { uint idx = (uint)item->value; struct rs_resource* res = (struct rs_resource*)g_rs.ress.buffer + idx; res_hdl = res->hdl; } if (res_hdl != INVALID_HANDLE && BIT_CHECK(flags, RS_LOAD_REFRESH)) { /* rs_resource already loaded, but refresh flag is set, so we reload it */ if (BIT_CHECK(g_rs.flags, RS_FLAG_BGLOADING)) { res_hdl = rs_animctrl_queueload(ctrl_filepath, res_hdl); } else { override_hdl = res_hdl; res_hdl = INVALID_HANDLE; } } else if (res_hdl != INVALID_HANDLE) { /* add ref count */ struct rs_resource* ress = (struct rs_resource*)g_rs.ress.buffer; ress[GET_INDEX(res_hdl)].ref_cnt ++; } /* rs_resource is not loaded before, so we just have to load it for the first time */ if (res_hdl == INVALID_HANDLE) { if(BIT_CHECK(g_rs.flags, RS_FLAG_BGLOADING)) { res_hdl = rs_animctrl_queueload(ctrl_filepath, INVALID_HANDLE); } else { /* determine file extension, then load the texture based on that */ char ext[128]; path_getfileext(ext, ctrl_filepath); anim_ctrl ctrl = NULL; /* model files should be valid extension */ if (str_isequal_nocase(ext, "json")) ctrl = anim_ctrl_load((struct allocator*)g_rs.alloc, ctrl_filepath, 0); if (ctrl == NULL) { log_printf(LOG_WARNING, "res-mgr: loading rs_resource '%s' failed:" " could not load anim-ctrl", ctrl_filepath); err_clear(); if (override_hdl != INVALID_HANDLE) rs_remove_fromdb(override_hdl); return INVALID_HANDLE; } res_hdl = rs_add_resource(ctrl_filepath, ctrl, override_hdl, rs_animctrl_unload); /* add to hot-loading files */ if (BIT_CHECK(g_rs.flags, RS_FLAG_HOTLOADING) && !BIT_CHECK(flags, RS_LOAD_REFRESH)) fio_mon_reg(ctrl_filepath, rs_animctrl_reload, res_hdl, 0, 0); log_printf(LOG_LOAD, "(anim-ctrl) \"%s\" - id: %d", ctrl_filepath, GET_ID(res_hdl)); } } return res_hdl; }
reshandle_t rs_load_texture(const char* tex_filepath, uint first_mipidx, int srgb, uint flags) { reshandle_t res_hdl = INVALID_HANDLE; reshandle_t override_hdl = res_hdl; if (!g_rs.init) return INVALID_HANDLE; struct hashtable_item_chained* item = hashtable_chained_find(&g_rs.dict, hash_str(tex_filepath)); if (item != NULL) { uint idx = (uint)item->value; struct rs_resource* res = (struct rs_resource*)g_rs.ress.buffer + idx; res_hdl = res->hdl; } if (res_hdl != INVALID_HANDLE && BIT_CHECK(flags, RS_LOAD_REFRESH)) { /* rs_resource already loaded, but refresh flag is set, so we reload it */ if (BIT_CHECK(g_rs.flags, RS_FLAG_BGLOADING)) { res_hdl = rs_texture_queueload(tex_filepath, first_mipidx, srgb, res_hdl); } else { override_hdl = res_hdl; res_hdl = INVALID_HANDLE; } } else if (res_hdl != INVALID_HANDLE) { /* add ref count */ struct rs_resource* ress = (struct rs_resource*)g_rs.ress.buffer; ress[GET_INDEX(res_hdl)].ref_cnt ++; } /* rs_resource is not loaded before, so we just have to load it for the first time */ if (res_hdl == INVALID_HANDLE) { if(BIT_CHECK(g_rs.flags, RS_FLAG_BGLOADING)) { res_hdl = rs_texture_queueload(tex_filepath, first_mipidx, srgb, INVALID_HANDLE); } else { /* determine file extension, then load the texture based on that */ char ext[128]; path_getfileext(ext, tex_filepath); gfx_texture tex = NULL; if (str_isequal_nocase(ext, "dds")) tex = gfx_texture_loaddds(tex_filepath, first_mipidx, srgb, 0); if (tex == NULL) { log_printf(LOG_WARNING, "res-mgr: loading rs_resource '%s' failed:" " could not load texture", tex_filepath); err_clear(); if (override_hdl != INVALID_HANDLE) rs_remove_fromdb(override_hdl); return INVALID_HANDLE; } res_hdl = rs_add_resource(tex_filepath, tex, override_hdl, rs_texture_unload); /* add to hot-loading files */ if (BIT_CHECK(g_rs.flags, RS_FLAG_HOTLOADING) && !BIT_CHECK(flags, RS_LOAD_REFRESH)) { fio_mon_reg(tex_filepath, rs_texture_reload, res_hdl, (uptr_t)first_mipidx, (uptr_t)srgb); } log_printf(LOG_LOAD, "(texture) \"%s\" - id: %d", tex_filepath, GET_ID(res_hdl)); } } return res_hdl; }
result_t eng_init(const struct init_params* params) { result_t r = RET_OK; ASSERT(g_eng == NULL); g_eng = (struct engine*)ALLOC(sizeof(struct engine), 0); if (g_eng == 0) return err_printn(__FILE__, __LINE__, RET_OUTOFMEMORY); memset(g_eng, 0x00, sizeof(struct engine)); eng_zero(); memcpy(&g_eng->params, params, sizeof(struct init_params)); hw_getinfo(&g_eng->hwinfo, HWINFO_ALL); /* console (before anything else) */ if (BIT_CHECK(params->flags, ENG_FLAG_CONSOLE)) { r |= con_init(params->console_lines_max); if (IS_FAIL(r)) return RET_FAIL; log_outputfunc(TRUE, con_log, NULL); } /* show build options */ #if !defined(FULL_VERSION) #error "must define FULL_VERSION macro" #endif time_t raw_tm; time(&raw_tm); log_printf(LOG_TEXT, "init darkhammer engine v%s build[%s, %s, %s, %s], time: %s", FULL_VERSION, #if defined(_DEBUG_) "debug" #else "release" #endif , #if defined(_PROFILE_) "profile" #else "no-profile" #endif , #if defined(_X86_) "x86" #elif defined(_X64_) "x64" #endif , #if defined(_ENABLEASSERT_) "assert" #else "no-assert" #endif , asctime(localtime(&raw_tm))); /* hardware info */ hw_printinfo(&g_eng->hwinfo, HWINFO_ALL); size_t tmp_sz = params->dev.buffsize_tmp; size_t data_sz = data_sz = params->dev.buffsize_data; tmp_sz = tmp_sz != 0 ? ((size_t)tmp_sz*1024) : FRAME_STACK_SIZE; data_sz = data_sz != 0 ? ((size_t)data_sz*1024) : DATA_SIZE; /* allocators */ /* dynamic allocator for data in dev (editor) mode, stack allocator in game (normal) mode */ if (BIT_CHECK(params->flags, ENG_FLAG_OPTIMIZEMEMORY)) { /* lsr (load-stay-resident) allocator for essential engine data */ r |= mem_stack_create(mem_heap(), &g_eng->lsr_stack, LSR_SIZE, MID_DATA); mem_stack_bindalloc(&g_eng->lsr_stack, &g_eng->lsr_alloc); r |= mem_freelist_create(mem_heap(), &g_eng->data_freelist, data_sz, MID_DATA); mem_freelist_bindalloc(&g_eng->data_freelist, &g_eng->data_alloc); } else { mem_heap_bindalloc(&g_eng->data_alloc); mem_heap_bindalloc(&g_eng->lsr_alloc); g_eng->data_alloc.alloc_fn = eng_allocfn_data; g_eng->data_alloc.alignedalloc_fn = eng_alignedallocfn_data; g_eng->lsr_alloc.alloc_fn = eng_allocfn_lsr; g_eng->lsr_alloc.alignedalloc_fn = eng_alignedallocfn_lsr; r = RET_OK; } if (IS_FAIL(r)) { err_print(__FILE__, __LINE__, "engine init failed: out of memory for allocators"); return RET_FAIL; } /* timer manager and frame timer */ g_eng->timer = timer_createinstance(TRUE); /* add engine's own data path to file-mgr */ if (params->data_path != NULL) { char data_path_ext[DH_PATH_MAX]; path_getfileext(data_path_ext, params->data_path); if (str_isequal_nocase(data_path_ext, "pak")) { if (IS_FAIL(pak_open(&g_eng->data_pak, mem_heap(), params->data_path, 0))) { err_print(__FILE__, __LINE__, "engine init: could not open data pak"); return RET_FAIL; } } else { if (!util_pathisdir(params->data_path)) { err_print(__FILE__, __LINE__, "engine init: data path is not valid"); return RET_FAIL; } fio_addvdir(params->data_path, FALSE); } /* assume that share directory is same as data dir */ path_getdir(g_eng->share_dir, params->data_path); } else { char data_path[DH_PATH_MAX]; char share_dir[DH_PATH_MAX]; #ifndef SHARE_DIR char exe_dir[DH_PATH_MAX]; path_join(share_dir, util_getexedir(exe_dir), "..", NULL); path_norm(share_dir, share_dir); #else path_norm(share_dir, SHARE_DIR); #endif path_join(data_path, share_dir, "data", NULL); if (!util_pathisdir(data_path)) { err_print(__FILE__, __LINE__, "engine init: data path is not valid"); return RET_FAIL; } fio_addvdir(data_path, FALSE); /* set default (config.h configured on build) data dir */ strcpy(g_eng->share_dir, share_dir); } uint rs_flags = 0; /* activate hot loading in DEV mode */ rs_flags |= BIT_CHECK(params->flags, ENG_FLAG_DEV) ? RS_FLAG_HOTLOADING : 0; if (!BIT_CHECK(params->flags, ENG_FLAG_DISABLEBGLOAD)) { rs_flags |= RS_FLAG_PREPARE_BGLOAD; } /* task manager */ uint thread_cnt = maxui(g_eng->hwinfo.cpu_core_cnt - 1, 1); r = tsk_initmgr(thread_cnt, 0, tmp_sz, 0); if (IS_FAIL(r)) { err_print(__FILE__, __LINE__, "engine init failed: could not init task-mgr"); return RET_FAIL; } struct allocator* tmp_alloc = tsk_get_tmpalloc(0); A_SAVE(tmp_alloc); /* resource manager (with only 1 thread for multi-thread loading) */ r = rs_initmgr(rs_flags, 1); if (IS_FAIL(r)) { err_print(__FILE__, __LINE__, "engine init failed: could not init res-mgr"); return RET_FAIL; } rs_set_dataalloc(&g_eng->lsr_alloc); /* graphics renderer */ r = gfx_init(¶ms->gfx); if (IS_FAIL(r)) { err_print(__FILE__, __LINE__, "engine init failed: could not init gfx"); return RET_FAIL; } /* debug HUD */ r = hud_init(BIT_CHECK(params->flags, ENG_FLAG_CONSOLE)); if (IS_FAIL(r)) { err_print(__FILE__, __LINE__, "engine init failed: could not init debug-hud"); return RET_FAIL; } /* Physics */ if (!BIT_CHECK(params->flags, ENG_FLAG_DISABLEPHX)) { r = phx_init(params); if (IS_FAIL(r)) { err_print(__FILE__, __LINE__, "engine init failed: could not init physics"); return RET_FAIL; } } /* component manager */ r = cmp_initmgr(); if (IS_FAIL(r)) { err_print(__FILE__, __LINE__, "engine init failed: could not init cmp-mgr"); return RET_FAIL; } cmp_set_globalalloc(&g_eng->data_alloc, tsk_get_tmpalloc(0)); /* world manager */ r = wld_initmgr(); if (IS_FAIL(r)) { err_print(__FILE__, __LINE__, "engine init failed: could not init world-mgr"); return RET_FAIL; } /* scene manager */ r = scn_initmgr(); if (IS_FAIL(r)) { err_print(__FILE__, __LINE__, "engine init failed: could not init scene-mgr"); return RET_FAIL; } /* init lua */ r = sct_init(¶ms->sct, BIT_CHECK(params->flags, ENG_FLAG_DEV) ? TRUE : FALSE); if (IS_FAIL(r)) { err_print(__FILE__, __LINE__, "engine init failed: could not init script engine"); return RET_FAIL; } /* web-server */ #if defined(_PROFILE_) r = prf_initmgr(); if (IS_FAIL(r)) { log_print(LOG_WARNING, "profiler manager init failed: service will not be available"); prf_releasemgr(); } #endif /* lod-scheme */ r = lod_initmgr(); if (IS_FAIL(r)) { err_print(__FILE__, __LINE__, "engine init failed: could not init lod-scheme"); return RET_FAIL; } /* init basic resources */ r = rs_init_resources(); if (IS_FAIL(r)) { err_print(__FILE__, __LINE__, "engine init failed: coult not init res-mgr resources"); return RET_FAIL; } /* switch back to normal data allocator */ rs_set_dataalloc(&g_eng->data_alloc); /* enable background-loading if res-mgr is prepared for (see above rs_initmgr) */ if (gfx_check_feature(GFX_FEATURE_THREADED_CREATES)) rs_add_flags(RS_FLAG_BGLOADING); log_print(LOG_TEXT, "init ok: ready."); /* init world vars */ eng_world_regvars(); /* engine specific console commnads */ con_register_cmd("showfps", eng_console_showfps, NULL, "showfps [1*/0]"); con_register_cmd("showft", eng_console_showft, NULL, "showft [1*/0]"); con_register_cmd("showgraph", eng_console_showgraph, NULL, "showgraph [ft][fps][drawcalls]"); con_register_cmd("lockfps", eng_console_lockfps, NULL, "lockfps [fps]"); /* execute console commands - should be the final stage if initialization */ if (BIT_CHECK(params->flags, ENG_FLAG_CONSOLE)) { for (uint i = 0; i < params->console_cmds_cnt; i++) { con_exec(params->console_cmds + i*128); } } A_LOAD(tmp_alloc); return RET_OK; }