void save_pak(struct paki_args* args) { result_t r; struct pak_file pak; path_norm(args->pakfile, args->pakfile); path_norm(args->path, args->path); r = pak_create(&pak, mem_heap(), args->pakfile, args->compress_mode, 0); if (IS_FAIL(r)) { err_sendtolog(FALSE); return; } r = compress_directory(&pak, args, ""); if (IS_FAIL(r)) { err_sendtolog(FALSE); pak_close(&pak); return; } pak_close(&pak); // report printf(TERM_BOLDWHITE "Saved pak: '%s'\nTotal %d file(s) - %d Error(s), %d Warning(s)\n" TERM_RESET, args->pakfile, args->file_cnt, args->err_cnt, args->warn_cnt); }
void load_pak(struct paki_args* args) { result_t r; struct pak_file pak; char filename[DH_PATH_MAX]; path_norm(args->pakfile, args->pakfile); path_tounix(args->path, args->path); r = pak_open(&pak, mem_heap(), args->pakfile, 0); if (IS_FAIL(r)) { err_sendtolog(FALSE); return; } uint file_id = pak_findfile(&pak, args->path); if (file_id == INVALID_INDEX) { printf(TERM_BOLDRED "Extract failed: file '%s' not found in pak.\n" TERM_RESET, args->path); pak_close(&pak); return; } path_getfullfilename(filename, args->path); file_t f = fio_createdisk(filename); if (f == NULL) { printf(TERM_BOLDRED "Extract failed: could not create '%s' for writing.\n" TERM_RESET, filename); pak_close(&pak); err_sendtolog(FALSE); return; } file_t src_file = pak_getfile(&pak, mem_heap(), mem_heap(), file_id, 0); if (src_file == NULL) { pak_close(&pak); fio_close(f); err_sendtolog(FALSE); return; } size_t size; struct allocator* alloc; void* buffer = fio_detachmem(src_file, &size, &alloc); fio_write(f, buffer, size, 1); A_FREE(alloc, buffer); fio_close(f); pak_close(&pak); if (BIT_CHECK(args->usage, PAKI_USAGE_VERBOSE)) { printf(TERM_WHITE "%s -> %s\n" TERM_RESET, args->path, filename); } args->file_cnt ++; // report printf(TERM_BOLDWHITE "Finished: total %d file(s) - %d error(s), %d warning(s)\n" TERM_RESET, args->file_cnt, args->err_cnt, args->warn_cnt); }
result_t compress_directory(struct pak_file* pak, struct paki_args* args, const char* subdir) { result_t r; char directory[DH_PATH_MAX]; char filepath[DH_PATH_MAX]; char fullfilepath[DH_PATH_MAX]; strcpy(directory, args->path); if (subdir[0] != 0) { path_join(directory, path_norm(directory, directory), subdir, NULL); } DIR* dir = opendir(directory); if (dir == NULL) { printf(TERM_BOLDRED "Creating pak failed: directory '%s' does not exist.\n" TERM_RESET, directory); return RET_FAIL; } /* read directory recuresively, and compress files into pak */ struct dirent* ent = readdir(dir); while (ent != NULL) { if (!str_isequal(ent->d_name, ".") && !str_isequal(ent->d_name, "..")) { filepath[0] = 0; if (subdir[0] != 0) strcpy(filepath, subdir); if (ent->d_type != DT_DIR) { // put the file into the archive path_join(filepath, filepath, ent->d_name, NULL); path_join(fullfilepath, directory, ent->d_name, NULL); r = archive_put(pak, args, fullfilepath, filepath); if (IS_OK(r) && BIT_CHECK(args->usage, PAKI_USAGE_VERBOSE)) { puts(filepath); } else if (IS_FAIL(r)) { err_sendtolog(FALSE); args->err_cnt ++; } args->file_cnt ++; } else { // it's a directory, recurse path_join(filepath, filepath, ent->d_name, NULL); compress_directory(pak, args, filepath); } } ent = readdir(dir); } closedir(dir); return RET_OK; }
char* util_getexedir(char* outpath) { GetModuleFileName(NULL, outpath, DH_PATH_MAX); path_getdir(outpath, outpath); return path_norm(outpath, outpath); }
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; }