GameLoop::GameLoop() : m_input_devices(), m_screen_factory(), m_screen(nullptr) { const Configuration& configuration = *the_context.configuration; if(NetworkMode::SERVER == configuration.network_mode || NetworkMode::WITH_SERVER == configuration.network_mode) { auto server_backend = std::make_unique<ENetServer>(configuration.port); auto server_impl = std::make_unique<BasicServer>(std::move(server_backend)); m_server.reset(new ServerThread(std::move(server_impl))); m_screen_factory.set_server(m_server.get()); } // configure player control if(configuration.player_number.has_value()) { const int player_number = *configuration.player_number; if(2 <= player_number) { throw GameException("Cannot control player " + std::to_string(player_number) + ". More than two players are currently not yet supported."); } m_input_devices.set_player_number(player_number); } // attach joystick input if(configuration.joystick_number.has_value()) { const int joystick_number = *configuration.joystick_number; const int joysticks_count = SDL_NumJoysticks(); if(joystick_number < 0 || joystick_number >= joysticks_count) { throw GameException("Joystick " + std::to_string(joystick_number) + " not found. There are " + std::to_string(joysticks_count) + " joysticks."); } JoystickPtr joystick(SDL_JoystickOpen(joystick_number)); sdlok(joystick.get()); m_input_devices.set_joystick(std::move(joystick)); } next_screen(); }
main(int argc, char *argv[]) /* MAIN Purpose : 1 Get privilege mask 2 Setup SMG environment unless no VT or DFU$NOSMG is set 3 Get and Parse command (syntax only) 4 Dispatch to correct subroutine Inputs : Command line (if specified through foreign command) Outputs : returns last status code to DCL in case of single command processing. In interactive mode always returns SS$_NORMAL. */ { const rms_eof=98938,smg$_eof=1213442; struct { short status, count; int extra ; } iosb; static char command_line[255], *e; unsigned int out_len,ret_len,prvmask; void reset_ctrl(), clean_ctrlc(), prev_screen(), next_screen(), dump_screen(), toggle_width() ; int smg_flag, x, y, i, ttype; int cursor_on = SMG$M_CURSOR_ON; $DESCRIPTOR(input_line , command_line); $DESCRIPTOR(prompt,"DFU> "); $DESCRIPTOR(terminal,"SYS$COMMAND"); $DESCRIPTOR(top_txt,"< DFU V2.2 (Freeware) >"); $DESCRIPTOR(status_txt,"Statistics"); $DESCRIPTOR(do_key,"DO"); $DESCRIPTOR(pf2,"PF2"); $DESCRIPTOR(pf4,"PF4"); $DESCRIPTOR(prev,"PREV_SCREEN"); $DESCRIPTOR(next,"NEXT_SCREEN"); $DESCRIPTOR(select,"SELECT"); $DESCRIPTOR(help,"HELP"); /* First find out how we got called ( by RUN, or a foreign command */ ret_len = 0; #if 0 status = lib$get_foreign(&input_line,0,&ret_len,0); #else status = 1; #if 0 strcpy(command_line,argv[1]); #endif #endif out_len = ret_len; smg$enable = TRUE; key_tab = 0; disp2_id = 0; cip = 0; setvbuf(stdout, NULL, _IONBF, 0); // need this to see i/o at all #if 0 smg$enable = FALSE; vms_mm = check_vms_mm(); #else /* Now create the SMG environment */ colls=80; rows=24; SMG$CREATE_PASTEBOARD(&paste_id, 0, &rows, &colls,&SMG$M_KEEP_CONTENTS,&ttype,0); if ((e = (char *) getenv("DFU$NOSMG")) && *e) smg$enable = FALSE; else { if (ttype != SMG$K_VTTERMTABLE) smg$enable = FALSE; if (ttype != SMG$K_VTTERMTABLE) SMG$DELETE_PASTEBOARD(&paste_id,&i0); } SMG$CREATE_VIRTUAL_KEYBOARD(&keyb_id,0,0,0,0); if (smg$enable) /* Setup key table */ { SMG$ERASE_PASTEBOARD(&paste_id, 0, 0, 0, 0, 0, 0); SMG$CREATE_KEY_TABLE(&key_tab); colls -=2; orig_colls = colls; smg_flag = SMG$M_KEY_NOECHO + SMG$M_KEY_TERMINATE; SMG$ADD_KEY_DEF(&key_tab,&do_key,0, &smg_flag, &do_key,0); SMG$ADD_KEY_DEF(&key_tab,&pf4,0, &smg_flag,&pf4,0); SMG$ADD_KEY_DEF(&key_tab,&prev,0, &smg_flag, &prev,0); SMG$ADD_KEY_DEF(&key_tab,&next,0, &smg_flag, &next,0); SMG$ADD_KEY_DEF(&key_tab,&pf2,0, &smg_flag, &help,0); SMG$ADD_KEY_DEF(&key_tab,&help,0, &smg_flag, &help,0); SMG$ADD_KEY_DEF(&key_tab,&select,0, &smg_flag, &select,0); SMG$CREATE_VIRTUAL_DISPLAY(&i500, &colls , &disp1_id, &SMG$M_BORDER, 0, 0); x = 508 - rows; y = rows - 7; SMG$CREATE_VIEWPORT(&disp1_id,&x,&i1,&y,&colls); SMG$CREATE_VIRTUAL_DISPLAY(&i2, &colls, &status_id, 0 , 0, 0); SMG$CREATE_VIRTUAL_DISPLAY(&i2, &colls, &disp2_id, 0 , 0, 0); SMG$SET_BROADCAST_TRAPPING(&paste_id,brdcst_ast,0); SMG$LABEL_BORDER(&disp1_id, &top_txt, 0, 0,&SMG$M_BOLD, 0, 0); SMG$LABEL_BORDER(&status_id, &status_txt, 0, 0,&SMG$M_BOLD, 0, 0); SMG$PASTE_VIRTUAL_DISPLAY(&disp1_id, &paste_id, &i2,&i2,0); x = rows - 4; SMG$PASTE_VIRTUAL_DISPLAY(&status_id, &paste_id, &x,&i2,0); x = rows - 1; SMG$PASTE_VIRTUAL_DISPLAY(&disp2_id, &paste_id, &x,&i2,0); x = 508 - rows; SMG$SET_CURSOR_ABS(&disp1_id,&x,&i1); SMG$SET_CURSOR_ABS(&disp2_id,&i1,&i1); SMG$BEGIN_PASTEBOARD_UPDATE(&paste_id); } #endif sprintf(outbuf,"\n Disk and File Utilities for OpenVMS DFU V2.2"); put_disp(); sprintf(outbuf," Freeware version"); put_disp(); sprintf(outbuf," Copyright © 1995 Digital Equipment Corporation\n"); put_disp(); if (smg$enable) { /* Enter additional info */ sprintf(outbuf," DFU functions are : \n"); put_disp(); sprintf(outbuf," DEFRAGMENT : Defragment files"); put_disp(); sprintf(outbuf," DELETE : Delete files by File-ID; delete directory (trees)"); put_disp(); sprintf(outbuf," DIRECTORY : Manipulate directories"); put_disp(); sprintf(outbuf," REPORT : Generate a complete disk report"); put_disp(); sprintf(outbuf," SEARCH : Fast file search"); put_disp(); sprintf(outbuf," SET : Modify file attributes"); put_disp(); sprintf(outbuf," UNDELETE : Recover deleted files"); put_disp(); sprintf(outbuf," VERIFY : Check and repair disk structure"); put_disp(); SMG$END_PASTEBOARD_UPDATE(&paste_id); } prvmask = 0; status = dfu_check_access(&prvmask); /*Get the privilege mask */ /* Setup terminal channel for control purposes; get the terminal chars */ status = SYS$ASSIGN(&terminal, &tchan, 0,0); status = SYS$QIOW(0,tchan, IO$_SENSEMODE,0,0,0,&orgttchar,12,0,0,0,0); for (i = 0; i < 3; i++) ttchar[i] = orgttchar[i]; ttchar[2] &= ~TT2$M_EDITING; /* Clear line edit bit */ clean_ctrlc(); /* Enable CTRL/W if needed */ if (ret_len==0) { if (smg$enable) status = SMG$READ_COMPOSED_LINE(&keyb_id,&key_tab,&input_line,&prompt, &out_len,&disp2_id,0,0,0,0,0); else status = SMG$READ_COMPOSED_LINE(&keyb_id,0,&input_line,&prompt, &out_len,0,0,0,0,0,0); } memcpy (command_line, input_line.dsc$a_pointer, input_line.dsc$w_length); cip = 1; /* Main loop starts here. Get a command and pasre it*/ for (;;) { /* loop forever until EXIT is entered */ if(status==smg$_eof) status = exit_command(prvmask); if ((status&1) != 1) goto endfor; if (out_len == 0) goto endfor; /* First catch special screen commands */ if (smg$enable) { status = strncmp(command_line, "PREV_SCREEN", 11); if (status == 0) { prev_screen(); goto endfor; } status = strncmp(command_line, "DO",2); if (status == 0) { status = spawn_command(prvmask); goto endfor; } status = strncmp(command_line, "PF4",3); if (status == 0) { dump_screen(); goto endfor; } status = strncmp(command_line, "NEXT_SCREEN", 11); if (status == 0) { next_screen(); goto endfor; } status = strncmp(command_line, "SELECT", 6); if (status == 0) { toggle_width(); goto endfor; } SMG$ERASE_DISPLAY(&disp1_id, 0, 0, 0, 0); SMG$ERASE_DISPLAY(&status_id, 0, 0, 0, 0); SMG$CHANGE_VIEWPORT(&disp1_id,&x,&i1,&y,&colls); SMG$SET_CURSOR_ABS(&disp1_id,&x,&i1); } /* Catch the CLI errors do avoid disrupting the SMG screen... */ #if 0 VAXC$ESTABLISH(prim_hand); #endif status = CLI$DCL_PARSE(&input_line,&dfu_tables,0 /* not yet lib$get_input*/,0,&prompt); // check added & before dfu_tables #if 0 VAXC$ESTABLISH(NULL); #endif if (status == CLI$_NOCOMD) singlemsg(0,status); if ((status & 1 ) != 1) goto endfor; else /* Now dispatch if no errors */ { reset_ctrl(); CLI$DISPATCH(prvmask); clean_ctrlc(); cip = 0; status = brdcst_ast(); if (smg$enable) SMG$SET_CURSOR_MODE(&paste_id, &cursor_on); } endfor: if (ret_len !=0) { /* Single command processing , so exit here */ status += 0x10000000; /* Do not echo the error on DCL level */ if (smg$enable) { if (colls != orig_colls) toggle_width(); SMG$SET_CURSOR_ABS(&disp2_id,&i2,&i1); } exit(status); } /* Get next line */ cip = 0; #if 1 if (smg$enable) { SMG$ERASE_LINE(&disp2_id, &i1, &i1); SMG$SET_CURSOR_ABS(&disp2_id,&i1,&i1); status = SMG$READ_COMPOSED_LINE(&keyb_id,&key_tab,&input_line, &prompt,&out_len,&disp2_id,0,0,0,0,0); /*Get next command */ cip = 1; } else status = SMG$READ_COMPOSED_LINE(&keyb_id,0,&input_line, &prompt,&out_len,0,0,0,0,0,0); /*Get next command */ #else printf("%s",prompt.dsc$a_pointer); out_len = read(0,command_line,254); out_len--; command_line[out_len]=0; if (strncmp(command_line,"exit",4)==0) return 0; #endif } } /* END of MAIN */
void GameLoop::game_loop() { Uint64 t0 = SDL_GetPerformanceCounter(); // start of game time Uint64 freq = SDL_GetPerformanceFrequency(); long tick = 0; // current logic tick counter Uint64 next_logic = t0 + freq / TPS; // time for next logic update while (m_screen) { // draw frames as long as logic is up to date Uint64 now = SDL_GetPerformanceCounter(); while (now < next_logic) { float fraction = 1.0f - static_cast<float>((next_logic - now) * TPS) / freq; assert(fraction >= 0); assert(fraction <= 1); m_screen->draw(fraction); now = SDL_GetPerformanceCounter(); // yield CPU if we have the time if(now < next_logic) { Uint64 wait = (next_logic - now) * 1000L / freq; // in ms assert(wait <= std::numeric_limits<Uint32>::max()); SDL_Delay(static_cast<Uint32>(wait)); now = SDL_GetPerformanceCounter(); } } // get different sources of input const auto inputs = m_input_devices.poll(); for(auto i : inputs) { // Debug functionality: take control of a certain player. // F2 key: take control of player 0 // F3 key: take control of player 1 if(Button::DEBUG2 == i.button && ButtonAction::DOWN == i.action) m_input_devices.set_player_number(0); else if(Button::DEBUG3 == i.button && ButtonAction::DOWN == i.action) m_input_devices.set_player_number(1); m_screen->input(i); } if(m_client) m_client->poll(); // run one frame of local logic m_screen->update(); if(m_screen->done()) { next_screen(); t0 = SDL_GetPerformanceCounter(); tick = 0; next_logic = t0 + freq / TPS; } else { tick++; next_logic = t0 + (tick + 1) * freq / TPS; } } Log::info("Game exit."); }