byte win_down(byte bind) { return sys.binds[bind].pressed; } byte win_pressed(byte bind) { return sys.binds[bind].active; } void handle_int(int sig) { sys.interrupted = 1; fprintf(stderr, "\n"); } void input() { bind_t *bind; for(int z = 0; z < KEY_BINDS; z++) { bind = &sys.binds[z]; if(sys.input ^ 1) { bind->pressed = 0; } else if(bind->key >= 1 && bind->key <= KEYSYM_LAST) { bind->pressed = wcf.active && (wcf_getkey(wcf.active, bind->key) == KEY_PRESS); } else if(bind->key >= -MOUSE_BTN_C && bind->key <= -MOUSE_LEFT) { bind->pressed = wcf.active && !(wcf.active->open) && ((wcf.active->mouse >> (-MOUSE_LEFT - bind->key)) & 1); if(!sys.mouse_bind) bind->last_state = bind->pressed; } else if(bind->key >= -SCROLL_RIGHT && bind->key <= -SCROLL_UP) { bind->pressed = wcf.active && !(wcf.active->open) && ((wcf.active->scroll >> (-SCROLL_UP - bind->key)) & 1); } else { bind->pressed = 0; } bind->active = bind->pressed && !(bind->last_state); bind->last_state = bind->pressed; } sys.mouse_bind = 1; if(wcf.active) wcf.active->scroll = 0; if(win_pressed(KEY_QUIT)) { sys.interrupted = 1; } if(win_pressed(KEY_SYNC)) { cvar_setint("win_sync", sys.win_vsync ? sys.sync_limit : (sys.sync_limited ? -1 : 0)); } if(win_pressed(KEY_SCREENSHOT)) { sys.screenshot = 1; } if(win_pressed(KEY_PLAYER)) { plr_rand(); if(snd.player && snd.player->open) gui_update_text(gui_get(snd.player, 1)); } if(wcf.active && wcf.active->world) { if(win_pressed(KEY_FULLSCREEN)) { win_full(!sys.win_full); } if(win_pressed(KEY_MENU)) { gui_open(wcf.active, wcf.active->open ^ 1); } if(win_pressed(KEY_SHOW)) { if(sys.draw_debug) { sys.draw_debug = sys.draw_fps = 0; } else { sys.draw_debug = sys.draw_fps; sys.draw_fps = 1; } } } if(wcf.active && wcf.active->world && !wcf.active->open) { if(wcf.active->world->pointed && win_pressed(KEY_FLY)) { world_remove(wcf.active->world, wcf.active->world->pointed); } if(wcf.active->world->noclip) { if((!(wcf.active->world->camonly) && win_pressed(KEY_NOCLIP)) || (wcf.active->world->camonly && win_pressed(KEY_CAMERA))) { if(wcf.active->world->camonly && wcf.active->world->entity) { cam_angle_ent(&wcf.active->world->camera, wcf.active->world->entity); cam_pos_ent(&wcf.active->world->camera, wcf.active->world->entity, 0.0); } log_hud(wcf.active, wcf.active->world->camonly ? STR_CAMERA_OFF : STR_NOCLIP_OFF); wcf.active->world->noclip = wcf.active->world->camonly = 0; } } else if(wcf.active->world->entity) { if(win_pressed(KEY_NOCLIP)) { log_hud(wcf.active, STR_NOCLIP_ON); wcf.active->world->noclip = 1; } else if(win_pressed(KEY_CAMERA)) { log_hud(wcf.active, STR_CAMERA_ON); wcf.active->world->noclip = wcf.active->world->camonly = 1; } } if(win_down(KEY_ZOOM_IN)) { cam_zoom(&wcf.active->world->camera, 0.05f); } if(win_down(KEY_ZOOM_OUT)) { cam_zoom(&wcf.active->world->camera, -0.05f); } if((wcf.active->world->noclip && wcf.active->world->camonly) || !(wcf.active->world->entity)) { float speed = sys.speed * (win_down(KEY_FAST) ? 20.0f : 5.0f); if(win_down(KEY_DOWN)) { cam_move_noclip(&wcf.active->world->camera, sys.fdelta, speed, DIR_DOWN); } if(win_down(KEY_UP)) { cam_move_noclip(&wcf.active->world->camera, sys.fdelta, speed, DIR_UP); } if(win_down(KEY_FORWARD)) { cam_move_noclip(&wcf.active->world->camera, sys.fdelta, speed, DIR_FORWARD); } if(win_down(KEY_BACKWARD)) { cam_move_noclip(&wcf.active->world->camera, sys.fdelta, speed, DIR_BACKWARD); } if(win_down(KEY_LEFT)) { cam_move_noclip(&wcf.active->world->camera, sys.fdelta, speed, DIR_LEFT); } if(win_down(KEY_RIGHT)) { cam_move_noclip(&wcf.active->world->camera, sys.fdelta, speed, DIR_RIGHT); } } else { wcf.active->world->entity->speed = /* sys.speed_fixed ? 1.0f : */ sys.speed; wcf.active->world->entity->sprint = win_down(KEY_FAST); wcf.active->world->entity->sneak = win_down(KEY_DOWN); wcf.active->world->entity->jump = win_down(KEY_UP); wcf.active->world->entity->forward = (win_down(KEY_FORWARD) ? 1.0f : 0.0f) + (win_down(KEY_BACKWARD) ? -1.0f : 0.0f); wcf.active->world->entity->strafe = (win_down(KEY_LEFT) ? 1.0f : 0.0f) + (win_down(KEY_RIGHT) ? -1.0f : 0.0f); } // if(wld.entity && !(wld.camonly)) // ent_angle_cam(wld.entity, &wld.camera); } if(!(sys.keywait)) sys.input = 1; } void screenshot() { time_t t = time(0); struct tm *date = localtime(&t); struct stat statbuf; int stride = (((wcf.current->frame_x * 3) & 3) ? (4 + ((wcf.current->frame_x * 3) & ~3)) : (wcf.current->frame_x * 3)); int n = 0; byte *data = mem_alloc(stride * wcf.current->frame_y, MEM_IMAGE); mkdir(DIR_SCREENSHOTS, 0777); do { sprintf(sys.work_buf, DIR_SCREENSHOTS"/screen_%02d-%02d-%d_%02d-%02d-%02d%s%.0d.png", date->tm_mday, date->tm_mon + 1, date->tm_year + 1900, date->tm_hour, date->tm_min, date->tm_sec, n ? "_" : "", n); n++; } while(!stat(sys.work_buf, &statbuf)); glReadPixels(wcf.current->offset_x, (wcf.current->fb_y - wcf.current->frame_y) - wcf.current->offset_y, wcf.current->frame_x, wcf.current->frame_y, GL_RGB, GL_UNSIGNED_BYTE, data); if(img_save(sys.work_buf, wcf.current->frame_x, wcf.current->frame_y, 0, 1, stride, data)) logu(LOG_SYS, STR_MSG_SCREENSHOT, sys.work_buf); mem_free(data); } const char *framecode() { return (sys.tmr_framerate >= 59.0f) ? COL_GREEN : ((sys.tmr_framerate >= 29.0f) ? COL_YELLOW : ((sys.tmr_framerate >= 14.0f) ? COL_ORANGE : COL_RED)); } const char *tpscode() { return (sys.tick_tickrate >= (((float)sys.tick_target / 1000.0f) - 1.0f)) ? COL_GREEN : ((sys.tick_tickrate >= (((float)sys.tick_target / 1000.0f) / 2.0f - 1.0f)) ? COL_YELLOW : ((sys.tick_tickrate >= (((float)sys.tick_target / 1000.0f) / 4.0f - 1.0f)) ? COL_ORANGE : COL_RED)); } ulong perf_get(byte section) { return sys.tmr_profile[(sys.perf_swap ? 0 : PERF_SECTIONS) + section]; } byte gl_isdebug() { int flags; glGetIntegerv(GL_CONTEXT_FLAGS, &flags); return (flags & GL_CONTEXT_FLAG_DEBUG_BIT) == GL_CONTEXT_FLAG_DEBUG_BIT; } const char *gl_getsuffix() { int mask; glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &mask); if(mask & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT) return " compat"; else if(mask & GL_CONTEXT_CORE_PROFILE_BIT) return " core"; else return ""; } void print_debug(world_t *world) { int pos; pos = sprintf(sys.work_buf, "%s%.2f"COL_RESET" %s, @ "COL_RED"%.1f "COL_GREEN"%.1f "COL_CYAN"%.1f"COL_RESET", Y "COL_MAGENTA"%.1f"COL_RESET", P "COL_YELLOW"%.1f"COL_RESET ", H %.1f, F %.1f, Z %.1f, M "COL_RED"%.1f "COL_GREEN"%.1f "COL_CYAN"%.1f"COL_RESET , framecode(), (sys.tmr_framerate < 1.0f) ? (1.0f / sys.tmr_framerate) : sys.tmr_framerate, sys.tmr_framerate < 1.0f ? "SPF" : "FPS", world->camera.pos_x, world->camera.pos_y, world->camera.pos_z, world->camera.yaw, world->camera.pitch, (world->entity && !world->camonly) ? world->entity->eye : 0.0, gdr.fov, world->camera.zoom * (gdr.fov - 1.0f), world->entity ? world->entity->motion_x : 0.0, world->entity ? world->entity->motion_y : 0.0, world->entity ? world->entity->motion_z : 0.0 ); if(world->pointed) pos = sprintf(&sys.work_buf[pos], ", -> "COL_YELLOW"#%llu "COL_RESET"("COL_RED"%.1f "COL_GREEN"%.1f "COL_CYAN"%.1f"COL_RESET")" , world->pointed, world->look_pos X, world->look_pos Y, world->look_pos Z ); } void tick_start(world_t *world) { world->last_cx = (int)NEG_OFFSET(world->camera.pos_x, CHUNK_SIZE); world->last_cy = (int)NEG_OFFSET(world->camera.pos_y, CHUNK_SIZE); world->last_cz = (int)NEG_OFFSET(world->camera.pos_z, CHUNK_SIZE); if(world->entity && !(world->camonly)) ent_angle_cam(world->entity, &world->camera); } void tick_main(world_t *world) { ent_tick(&world->entity_base); } void tick_end(world_t *world) { if(world->entity && !(world->camonly)) cam_pos_ent(&world->camera, world->entity, sys.tick_fraction); if(world->last_cx != (int)NEG_OFFSET(world->camera.pos_x, CHUNK_SIZE) || world->last_cy != (int)NEG_OFFSET(world->camera.pos_y, CHUNK_SIZE) || world->last_cz != (int)NEG_OFFSET(world->camera.pos_z, CHUNK_SIZE)) world->light_dirty = 1; } void tick() { window_t *win; sys.tick_stime = tmr_rtime(); if((sys.tick_stime - sys.tick_update) >= 1000000ULL) { sys.tick_tickrate = ((float)sys.tick_done) * 1000000.0f / ((float)(ulong)(sys.tick_stime - sys.tick_update)); sys.tick_done = 0; sys.tick_update = sys.tick_stime; } if(sys.ticked ^ 1) { sys.tick_time = 0ULL; return; } sys.tick_torun += (((ulong)sys.tick_target) * sys.tmr_delta) / 1000ULL; sys.tick_frame = 0; for(win = wcf.window_list; win; win = win->next) { if(win->world) tick_start(win->world); } while(sys.tick_torun >= 1000000ULL) { for(win = wcf.window_list; win; win = win->next) { if(win->world) tick_main(win->world); } sys.tick_done += 1ULL; sys.tick_frame += 1; sys.tick_total += 1ULL; sys.tick_torun -= 1000000ULL; if((sys.tick_ftime = (tmr_rtime() - sys.tick_stime)) >= (((ulong)sys.tick_timeout) * 1000ULL)) { logw(LOG_TIC, STR_TICK_TIMEOUT, sys.tick_ftime / 1000ULL, sys.tick_timeout, sys.tick_torun / 1000000ULL); sys.tick_torun = 0ULL; break; } } sys.tick_fraction = ((double)sys.tick_torun) / 1000000.0; for(win = wcf.window_list; win; win = win->next) { if(win->world) tick_end(win->world); } sys.tick_ttime += sys.tick_ftime; sys.tick_time = sys.tick_frame ? (sys.tick_ftime / (ulong)sys.tick_frame) : 0ULL; } void tick_target(float tps) { sys.tick_target = (int)(tps * 1000.0f); sys.tick_torun = 0ULL; sys.tick_done = 0ULL; sys.tick_update = tmr_rtime(); sys.ticked = tps > 0.0f; } float rfloat(float min, float max) { return ((float)(int)(rand() % 1000000000)) / 1000000000.0f * (max - min) + min; } void floor_test(world_t *world, material_t *mat, int n) { for(int z = 0; z < n; z++) { world_add_floor(world, rfloat(-1800.0f, 1800.0f), rfloat(-230.0f, 230.0f), rfloat(-1800.0f, 1800.0f), rfloat(8.0f, 40.0f), rfloat(8.0f, 40.0f), mat); } } void snd_apply() { plr_debug(cvar_byte("mid_debug_events")); for(int z = 0; z < SND_VOLUMES; z++) { plr_volume(z, (ushort)(cvar_float(snd_cvar_volume[z]) * 32767.0f)); } } void save_vars() { cvar_setint("win_pos_x", sys.console->xpos); cvar_setint("win_pos_y", sys.console->ypos); cvar_setint("win_width", sys.console->xsize); cvar_setint("win_height", sys.console->ysize); } static const float lm_test[] = {20.0f, 20.0f, 40.0f, 20.0f, 20.0f, 40.0f}; float wg_test(void *p, float x, float z) { noisegen_t *gen = (noisegen_t*)p; // float n = (x * x + z * z) * // (sinf(7.57f * M_PI*2.0f*x) + 1.0f) * (sinf(16.7585f * M_PI*2.0f*z) + 1.0f) * (sinf(8.657f * M_PI*2.0f*x) + 1.0f) * (sinf(6.75485f * M_PI*2.0f*z) + 1.0f); // srand((int)(x * 16384.0f) ^ (int)(z * 16384.0f)); // n += rfloat(0.0f, n / 8.0f); double n; noise_gen(gen, &n, (double)x, 0, (double)z, 1, 1, 1, 512.0, 512.0, 512.0); return (float)(n / 512.0); } uint tex_test, tex_floor; material_t *mat_test; material_t *mat_floor; material_t *mat_grid; material_t *mat_vis; void start(char **cmds, int n_cmds) { tex_load(&tex_test, "textures/test.png", TEX_FLAG_FILTER | TEX_FLAG_MIPMAP); tex_load(&tex_floor, "textures/floor.png", TEX_FLAG_FILTER | TEX_FLAG_MIPMAP); mat_test = gfx_add_material(tex_test, 512.0f, 0xffffff, 4.0f, NULL); mat_floor = gfx_add_material(tex_floor, 512.0f, 0xffffff, 1.0f, NULL); mat_grid = gfx_add_material(0, 512.0f, 0xffffff, 1.0f, gdr.shd_grid); mat_vis = gfx_add_material(0, 512.0f, 0xffffff, 1.0f, gdr.shd_vis); // plr_play("/home/sen/Musik/midi50k/Video_Games/ff/ff2cecil.mid", 0); for(int z = 0; z < n_cmds; z++) { if(strlen(cmds[z]) >= CON_LINE) loge(LOG_SYS, STR_CON_TOOLONG, z + 1); else con_exec(cmds[z]); } } void test(window_t *win) { world_init(win, 0.0, 32.0, 0.0, 90.0f, 0.0f); noisegen_t gen; ulong rng = rng_rseed(); noise_gen_init(&gen, &rng, 16); switch(rng_zrange(&rng, 3)) { case 0: for(int z = 0; z < 10; z++) { world_add_box(win->world, 10.0f + (float)z * 2.0f, 64.0f, 20.0f, 4.0f, (float)(z + 1) * 0.5f, 6.0f, mat_test); } world_add_graph(win->world, wg_test, &gen, -1536.0f, 0.0f, -1536.0f, 3072.0f, 0.125f, 3072.0f, mat_floor, 128, 128, 0.0f, 0.0f, 512.0f, 512.0f, 1); light_b lamp; for(int z = 0; z < 256; z++) { light_init_def(&lamp, ((rand() & 0xff) | 0x40) << ((rand() % 3) << 3), 1.0f); world_add_light(win->world, &lamp, rfloat(-1250.0f, 1250.0f), rfloat(4.0f, 8.0f), rfloat(-1250.0f, 1250.0f)); } break; case 1: world_add_graph(win->world, wg_test, &gen, -1536.0f, 0.0f, -1536.0f, 3072.0f, 2.0f, 3072.0f, mat_grid, 128, 128, 0.0f, 0.0f, 512.0f, 512.0f, 1); break; case 2: world_add_graph(win->world, wg_test, &gen, -1536.0f, 0.0f, -1536.0f, 3072.0f, 1.0f, 3072.0f, mat_vis, 256, 256, 0.0f, 0.0f, 512.0f, 512.0f, 1); break; } noise_gen_free(&gen); } void run() { window_t *win; PERF_FIRST() while(sys.interrupted ^ 1) { PERF_START(PERF_TIMING) sys.tmr_current = tmr_rtime(); sys.tmr_delta = sys.tmr_current - sys.tmr_last; sys.tmr_last = sys.tmr_current; sys.fdelta = ((float)sys.tmr_delta) / 1000000.0f; if((sys.tmr_current - sys.tmr_update) >= 1000000ULL) { sys.tmr_framerate = ((float)sys.tmr_frames) * 1000000.0f / ((float)(ulong)(sys.tmr_current - sys.tmr_update)); sys.tmr_frames = 0; sys.tmr_update = sys.tmr_current; // logi(LOG_SYS, "%.3f FPS", sys.tmr_framerate); } PERF_SEC(PERF_INPUT) for(win = wcf.window_list; win; win = win->next) { gui_check(win); } input(); if(wcf.active) gui_await(wcf.active); PERF_SEC(PERF_TICK) tick(); PERF_SEC(PERF_UPDATE) plr_update(); for(win = wcf.window_list; win; win = win->next) { if(win->world) { // wcf_selcontext(wcf.active); // glViewport(0, 0, wcf.active->fb_x, wcf.active->fb_y); world_update(win->world); win->world->pointed = box_get_pointed(win->world, &win->world->camera, win->world->look_pos); } } PERF_SEC(PERF_RENDER) gdr.lists_drawn = 0; gdr.tris_drawn = 0; for(win = wcf.window_list; win; win = win->next) { if(win->world) { wcf_selcontext(win); gdr.shader = 0; glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_DEPTH_TEST); glBindFramebuffer(GL_FRAMEBUFFER, gdr.post ? win->world->fb_post : 0); glClearColor(gdr.clear_r, gdr.clear_g, gdr.clear_b, gdr.clear_a); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); if(gdr.wireframe) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glViewport(win->offset_x, (win->fb_y - win->frame_y) - win->offset_y, win->frame_x, win->frame_y); // gfx_pass_world(); // glBindTexture(GL_TEXTURE_2D, gdr.tex_test); // glDrawArrays(GL_TRIANGLES, 0, 36); // draw_floor(gdr.world); draw_world(win->world); // ... // glViewport(0, 0, wld.window->fb_x, wld.window->fb_y); if(gdr.wireframe) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } } PERF_SEC(PERF_GUI) for(win = wcf.window_list; win; win = win->next) { wcf_selcontext(win); gdr.shader = 0; glViewport(0, 0, win->fb_x, win->fb_y); glDisable(GL_DEPTH_TEST); glBindFramebuffer(GL_FRAMEBUFFER, win->fb_gui); glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); if(win->redraw) { win->redraw = 0; glClear(GL_COLOR_BUFFER_BIT); } if(win->fb_x && win->fb_y) gfx_draw_gui(win); glBindFramebuffer(GL_FRAMEBUFFER, 0); if(gdr.post && win->world) gfx_blit(win->world->fbtex_post); gfx_draw_rect(0, win->offset_y - (win->fb_x - win->frame_x) / 2, win->fb_x, win->frame_y + win->fb_x - win->frame_x, (win->fb_x - win->frame_x) / 2, 0, 0, 0, sys.style.wbrdr_top, sys.style.wbrdr_btm); if(!(win->world)) gfx_draw_rect(win->offset_x, win->offset_y, win->frame_x, win->frame_y, 0, 0, sys.style.bg_top, sys.style.bg_btm, 0, 0); else if(!win->open) gfx_draw_rect(win->offset_x + (win->frame_x / 2) - 16, win->offset_y + (win->frame_y / 2) - 16, 32, 32, 0, gdr.tex_crosshair, win->world->pointed ? 0xffffffff : 0xffcfcfcf, win->world->pointed ? 0xffffffff : 0xffcfcfcf, 0, 0); gfx_blit(win->fbtex_gui); if(win == wcf.active) gfx_draw_gui_overlay(win); if(win->drag_x || win->drag_y) { sprintf(sys.work_buf, "%d x %d", win->frame_x, win->frame_y); txt_draw(0, 0, 0, sys.font.yglyph, sys.font.yglyph, 0, 0, win->fb_x, win->fb_y, 0xffff0000, 0xff000000, &sys.font, sys.work_buf); } if(sys.hud_overlay && win->world) gfx_draw_con_overlay(win); if(sys.draw_fps && win->world) { // gfx_pass_text(); if(sys.draw_debug) { print_debug(win->world); txt_draw(win->offset_x, win->offset_y + (sys.hud_bottom ? 0 : (win->frame_y - sys.font.yglyph)), 0, sys.font.yglyph, sys.font.yglyph, win->offset_x, win->offset_y + (sys.hud_bottom ? 0 : (win->frame_y - sys.font.yglyph)), win->offset_x + win->frame_x, win->offset_y + win->frame_y, 0xffffffff, 0x40000000, &sys.font, sys.work_buf); // print_profile(); // txt_draw(win->offset_x + win->frame_x - ((sys.mono.xglyph - 1) * 28), win->offset_y, 0, sys.mono.yglyph, sys.mono.yglyph, // win->offset_x + win->frame_x - ((sys.mono.xglyph - 1) * 28), win->offset_y, win->offset_x + win->frame_x, win->offset_y + win->frame_y, // 0xffffffff, 0x40000000, &sys.mono, sys.work_buf); } else { sprintf(sys.work_buf, "%s%.2f", framecode(), sys.tmr_framerate); txt_draw(win->offset_x, win->offset_y + (sys.hud_bottom ? 0 : (win->frame_y - sys.font.yglyph)), 0, sys.font.yglyph, sys.font.yglyph, win->offset_x, win->offset_y + (sys.hud_bottom ? 0 : (win->frame_y - sys.font.yglyph)), win->offset_x + win->frame_x, win->offset_y + win->frame_y, 0xffffffff, 0x40000000, &sys.font, sys.work_buf); } } } PERF_SEC(PERF_REST) if(sys.screenshot) { sys.screenshot = 0; if(wcf.active) { wcf_selcontext(wcf.active); glViewport(0, 0, wcf.active->fb_x, wcf.active->fb_y); screenshot(); } } if(sys.cfg_dirty) { save_vars(); cvar_save(); sys.cfg_dirty = 0; } PERF_SEC(PERF_SWAP) for(win = wcf.window_list; win; win = win->next) { wcf_selcontext(win); glViewport(0, 0, win->fb_x, win->fb_y); if(sys.gl_flush) glFlush(); // glFinish(); wcf_swap(win); } PERF_SEC(PERF_EVENTS) snd_log_flush(); wcf_poll(); PERF_SEC(PERF_WAIT) while(sys.sync_limited && (tmr_rtime() - sys.tmr_current) < (1000000ULL / sys.sync_limit)) { ; } sys.tmr_frames += 1; PERF_END() } PERF_LAST() } void end() { wcf_end(); // #ifdef MEM_TRACING // logt(LOG_MEM, STR_MEM_FREE, SYS_BASE, (ulong)(&sys), sys.mem_alloc -= SYS_BASE, "base"); // #else sys.mem_alloc -= SYS_BASE; // #endif logp(LOG_MEM, STR_MEM_PEAK, sys.mem_peak); if(sys.mem_alloc) { logw(LOG_MEM, STR_MEM_LEAK, sys.mem_alloc); } logi(LOG_SYS, STR_EXIT); sys_remove_handlers(); } void finish() { logi(LOG_SYS, STR_SHUTDOWN); // world_delete(wld.world); // wld.world = NULL; plr_end(); if(snd_end()) logi(LOG_SYS, STR_SND_STOP); save_vars(); win_end(); con_end(); cvar_end(); gfx_end(); end(); } void snd_start(byte disabled) { const char *devname = snd_edevice[cvar_int("snd_device_type")]; if(!strcmp(devname, "hw") || !strcmp(devname, "plughw")) { int dev = cvar_int("snd_device_index"); int sub = cvar_int("snd_device_sub"); sprintf(sys.work_buf, dev < 0 ? "default" : (sub < 0 ? "%s:%d" : "%s:%d,%d"), devname, dev, sub); devname = sys.work_buf; } uint samplerate = snd_init(devname, cvar_int("snd_sample_rate"), cvar_byte("snd_sample_format") ? 32 : 16, cvar_int("snd_frame_size"), cvar_int("snd_buffer_size"), disabled); snd_log_flush(); if(samplerate) logi(LOG_SYS, STR_SND_START, devname, samplerate); else if(!disabled && strcmp(devname, "none")) loge(LOG_SYS, STR_SND_STARTERR, devname); } void snd_restart() { byte disabled = sgt.disabled; plr_end(); if(snd_end()) logi(LOG_SYS, STR_SND_STOP); memset(&sgt, 0, sizeof(isnd_t)); memset(&snd, 0, sizeof(snd_t)); snd_start(disabled); snd_apply(); } const char *gl_debug_source(uint src) { switch(src) { case GL_DEBUG_SOURCE_API: return "API"; case GL_DEBUG_SOURCE_WINDOW_SYSTEM: return "WIN"; case GL_DEBUG_SOURCE_SHADER_COMPILER: return "SHD"; case GL_DEBUG_SOURCE_THIRD_PARTY: return "3RD"; case GL_DEBUG_SOURCE_APPLICATION: return "PRG"; case GL_DEBUG_SOURCE_OTHER: default: return "XXX"; } } const char *gl_debug_type(uint type) { switch(type) { case GL_DEBUG_TYPE_ERROR: return "ERR!"; case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: return "DEPR"; case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: return "NDEF"; case GL_DEBUG_TYPE_PORTABILITY: return "PORT"; case GL_DEBUG_TYPE_PERFORMANCE: return "PERF"; case GL_DEBUG_TYPE_MARKER: return "MARK"; case GL_DEBUG_TYPE_PUSH_GROUP: return "GPSH"; case GL_DEBUG_TYPE_POP_GROUP: return "GPOP"; case GL_DEBUG_TYPE_OTHER: default: return "XXXX"; } } byte gl_debug_severity(uint level) { switch(level) { case GL_DEBUG_SEVERITY_HIGH: return LOG_ERROR; case GL_DEBUG_SEVERITY_MEDIUM: return LOG_WARN; case GL_DEBUG_SEVERITY_LOW: return LOG_INFO; case GL_DEBUG_SEVERITY_NOTIFICATION: default: return LOG_PERF; } } void gl_debug_callback(uint src, uint type, uint id, uint level, int len, const char *msg, const void *user) { byte lvl = gl_debug_severity(level); const char *color = log_colors[lvl]; log_str(LOG_GFX, lvl, COL_DGRAY"[%sGL:%d"COL_DGRAY"][%s%s"COL_DGRAY"][%s%s"COL_DGRAY"]%s %s", color, id, color, gl_debug_source(src), color, gl_debug_type(type), color, msg); } byte init(const char *cfgfile, const char *langfile, byte loglevel, byte gldebug, byte nosound) { clockid_t timer; sys_setup_handlers(); sys_test_handlers(getenv("ERROR_HANDLER_TEST")); timer = tmr_gettimer(); memset(&sys, 0, sizeof(sys_t)); memset(&gdr, 0, sizeof(gfx_t)); memset(&sgt, 0, sizeof(isnd_t)); memset(&snd, 0, sizeof(snd_t)); signal(SIGINT, handle_int); sys.tmr_timer = (ulong)timer; sys.tmr_start = tmr_time(); sys.log_level = loglevel == 0xff ? LOG_INFO : loglevel; sys.log_set = loglevel; sys.cfg_file = cfgfile; sys.rng_uniq = 8682522807148012L; con_reset(); loc_init(); loc_def(); if(langfile) loc_load(langfile); logi(LOG_SYS, SYS_PROGRAM_FULL); logi(LOG_SYS, STR_BUILD_COMPILER, BUILD_COMP); logi(LOG_SYS, STR_BUILD_SYSTEM, BUILD_SYS); // #ifdef MEM_TRACING // logt(LOG_MEM, STR_MEM_ALLOC, SYS_BASE, (ulong)(&sys), sys.mem_alloc = sys.mem_peak = SYS_BASE, "base"); // #else sys.mem_alloc = sys.mem_peak = SYS_BASE; // #endif if(!wcf_init(gldebug)) return 0; if(!(sys.console = wcf_create(SYS_PROGRAM, 1))) { loge(LOG_GFX, STR_WIN_CREATE_ERR); wcf_end(); return 0; } if(gl_isdebug()) { glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, 1); glDebugMessageCallback(gl_debug_callback, NULL); } logi(LOG_GFX, "OpenGL %s%s%s", glGetString(GL_VERSION), gl_getsuffix(), gl_isdebug() ? " debug" : ""); logi(LOG_GFX, "GLSL %s", glGetString(GL_SHADING_LANGUAGE_VERSION)); logi(LOG_GFX, "GL_VENDOR: %s", glGetString(GL_VENDOR)); logi(LOG_GFX, "GL_RENDERER: %s", glGetString(GL_RENDERER)); logi(LOG_SYS, STR_STARTUP); if(!gfx_init()) { gfx_end(); end(); return 0; } cvar_init(); con_init(); win_init(); win_sync(cvar_int("win_sync")); snd_start(nosound); snd_apply(); light_setup(cvar_int("gl_dynlight_max")); cvar_setdef("tic_target"); tex_load(&gdr.tex_logo, "textures/logo.png", 0); tex_load(&gdr.tex_crosshair, "textures/crosshair.png", 0); return 1; } /* txt_draw(80, 80, 0, 18, 18, 80, 80, sys.fb_x - 80, sys.fb_y - 80, 0xff1f1f1f, 0x40000000, &sys.font, " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz{|}~"STR_UNK"§°²³´µÄÖÜßäöü€"STR_WSPC"\n" COL_BLACK" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz{|}~"STR_UNK"§°²³´µÄÖÜßäöü€"STR_WSPC"\n" COL_DGRAY" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz{|}~"STR_UNK"§°²³´µÄÖÜßäöü€"STR_WSPC"\n" COL_GRAY" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz{|}~"STR_UNK"§°²³´µÄÖÜßäöü€"STR_WSPC"\n" COL_LGRAY" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz{|}~"STR_UNK"§°²³´µÄÖÜßäöü€"STR_WSPC"\n" COL_WHITE" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz{|}~"STR_UNK"§°²³´µÄÖÜßäöü€"STR_WSPC"\n" COL_RED" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz{|}~"STR_UNK"§°²³´µÄÖÜßäöü€"STR_WSPC"\n" COL_GREEN" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz{|}~"STR_UNK"§°²³´µÄÖÜßäöü€"STR_WSPC"\n" COL_BLUE" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz{|}~"STR_UNK"§°²³´µÄÖÜßäöü€"STR_WSPC"\n" COL_YELLOW" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz{|}~"STR_UNK"§°²³´µÄÖÜßäöü€"STR_WSPC"\n" COL_MAGENTA" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz{|}~"STR_UNK"§°²³´µÄÖÜßäöü€"STR_WSPC"\n" COL_CYAN" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz{|}~"STR_UNK"§°²³´µÄÖÜßäöü€"STR_WSPC"\n" COL_VIOLET" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz{|}~"STR_UNK"§°²³´µÄÖÜßäöü€"STR_WSPC"\n" COL_ORANGE" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz{|}~"STR_UNK"§°²³´µÄÖÜßäöü€"STR_WSPC"\n" COL_CRIMSON" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz{|}~"STR_UNK"§°²³´µÄÖÜßäöü€"STR_WSPC"\n" COL_MIDNIGHT" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz{|}~"STR_UNK"§°²³´µÄÖÜßäöü€"STR_WSPC"\n" COL_NEON" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz{|}~"STR_UNK"§°²³´µÄÖÜßäöü€"STR_WSPC"\n" COL_AUX1" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz{|}~"STR_UNK"§°²³´µÄÖÜßäöü€"STR_WSPC"\n" COL_AUX2" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz{|}~"STR_UNK"§°²³´µÄÖÜßäöü€"STR_WSPC"\n" COL_AUX3" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz{|}~"STR_UNK"§°²³´µÄÖÜßäöü€"STR_WSPC"\n" COL_AUX4" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz{|}~"STR_UNK"§°²³´µÄÖÜßäöü€"STR_WSPC"\n" COL_AUX5" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz{|}~"STR_UNK"§°²³´µÄÖÜßäöü€"STR_WSPC"\n" COL_AUX6" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz{|}~"STR_UNK"§°²³´µÄÖÜßäöü€"STR_WSPC"\n" COL_AUX7" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz{|}~"STR_UNK"§°²³´µÄÖÜßäöü€"STR_WSPC"\n" COL_AUX8" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz{|}~"STR_UNK"§°²³´µÄÖÜßäöü€"STR_WSPC"\n" COL_RESET"END\n" ); */