int splash_main(int argc, char **argv) { osd_surface_t *surface; int ret = -1; int c, opt_index; char *opt_p = NULL, *opt_s = NULL; av_init(); if (av_get_mode() == AV_MODE_PAL) { width = 720; height = 576; av_set_mode(AV_MODE_PAL); } else { width = 720; height = 480; } if ((surface=osd_create_surface(width, height, 0, OSD_FB)) == NULL) { goto err; } while ((c=getopt_long(argc, argv, "blp:s:", opts, &opt_index)) != -1) { switch (c) { case 'b': ret = blank(surface); break; #if defined(STANDALONE) case 'l': ret = draw_logo(surface); break; #endif /* STANDALONE */ case 'p': opt_p = strdup(optarg); break; case 's': opt_s = strdup(optarg); break; } } if (opt_p && opt_s) { ret = draw_progress(surface, atoi(opt_p), atoi(opt_s)); } err: return ret; }
int parse_command(char *string, int length) { char *command; char *origstring = string; int parsed=0; #ifdef DEBUG fprintf (logfile, "%s\n", string); fflush (logfile); #endif parsed = strlen(string)+1; if (strcmp(string,"QUIT")==0) { return 1; } command = strtok(string," "); if (strcmp(command,"TEXT")==0) { char *line = strtok(NULL,"\0"); int length = strlen(line); while (length>50) { draw_text(line,50); line+=50; length-=50; } draw_text(line,length); } else if (strcmp(command,"STATUS")==0) { draw_status(strtok(NULL,"\0"),0); } else if (strcmp(command,"SUCCESS")==0) { draw_status(strtok(NULL,"\0"),TEXT_FOREGROUND); } else if (strcmp(command,"FAILURE")==0) { draw_status(strtok(NULL,"\0"),RED); } else if (strcmp(command,"PROGRESS")==0) { draw_progress(atoi(strtok(NULL,"\0"))); } else if (strcmp(command,"CLEAR")==0) { text_clear(); } else if (strcmp(command,"TIMEOUT")==0) { timeout=(atoi(strtok(NULL,"\0"))); } else if (strcmp(command,"QUIT")==0) { return 1; } return 0; }
void dir_draw() { switch(dir_ui) { case 0: if(dir_fatalerr) fprintf(stderr, "%s.\n", dir_fatalerr); break; case 1: if(dir_fatalerr) fprintf(stderr, "\r%s.\n", dir_fatalerr); else if(dir_output.size) fprintf(stderr, "\r%-55s %8d files /%s", cropstr(dir_curpath, 55), dir_output.items, formatsize(dir_output.size)); else fprintf(stderr, "\r%-65s %8d files", cropstr(dir_curpath, 65), dir_output.items); break; case 2: browse_draw(); if(dir_fatalerr) draw_error(dir_curpath, dir_fatalerr); else draw_progress(); break; } }
void Pi::Init(const std::map<std::string,std::string> &options, bool no_gui) { #ifdef PIONEER_PROFILER Profiler::reset(); #endif Profiler::Timer timer; timer.Start(); OS::EnableBreakpad(); OS::NotifyLoadBegin(); FileSystem::Init(); FileSystem::userFiles.MakeDirectory(""); // ensure the config directory exists #ifdef PIONEER_PROFILER FileSystem::userFiles.MakeDirectory("profiler"); profilerPath = FileSystem::JoinPathBelow(FileSystem::userFiles.GetRoot(), "profiler"); #endif Pi::config = new GameConfig(options); if (config->Int("RedirectStdio")) OS::RedirectStdio(); std::string version(PIONEER_VERSION); if (strlen(PIONEER_EXTRAVERSION)) version += " (" PIONEER_EXTRAVERSION ")"; const char* platformName = SDL_GetPlatform(); if(platformName) Output("ver %s on: %s\n\n", version.c_str(), platformName); else Output("ver %s but could not detect platform name.\n\n", version.c_str()); Output("%s\n", OS::GetOSInfoString().c_str()); ModManager::Init(); Lang::Resource res(Lang::GetResource("core", config->String("Lang"))); Lang::MakeCore(res); Pi::detail.planets = config->Int("DetailPlanets"); Pi::detail.textures = config->Int("Textures"); Pi::detail.fracmult = config->Int("FractalMultiple"); Pi::detail.cities = config->Int("DetailCities"); // Initialize SDL Uint32 sdlInitFlags = SDL_INIT_VIDEO | SDL_INIT_JOYSTICK; #if defined(DEBUG) || defined(_DEBUG) sdlInitFlags |= SDL_INIT_NOPARACHUTE; #endif if (SDL_Init(sdlInitFlags) < 0) { Error("SDL initialization failed: %s\n", SDL_GetError()); } SDL_version ver; SDL_GetVersion(&ver); Output("SDL Version %d.%d.%d\n", ver.major, ver.minor, ver.patch); Graphics::RendererOGL::RegisterRenderer(); // Do rest of SDL video initialization and create Renderer Graphics::Settings videoSettings = {}; videoSettings.rendererType = Graphics::RENDERER_OPENGL; videoSettings.width = config->Int("ScrWidth"); videoSettings.height = config->Int("ScrHeight"); videoSettings.fullscreen = (config->Int("StartFullscreen") != 0); videoSettings.hidden = no_gui; videoSettings.requestedSamples = config->Int("AntiAliasingMode"); videoSettings.vsync = (config->Int("VSync") != 0); videoSettings.useTextureCompression = (config->Int("UseTextureCompression") != 0); videoSettings.enableDebugMessages = (config->Int("EnableGLDebug") != 0); videoSettings.iconFile = OS::GetIconFilename(); videoSettings.title = "Pioneer"; Pi::renderer = Graphics::Init(videoSettings); Pi::CreateRenderTarget(videoSettings.width, videoSettings.height); Pi::rng.IncRefCount(); // so nothing tries to free it Pi::rng.seed(time(0)); InitJoysticks(); // we can only do bindings once joysticks are initialised. if (!no_gui) // This re-saves the config file. With no GUI we want to allow multiple instances in parallel. KeyBindings::InitBindings(); joystickEnabled = (config->Int("EnableJoystick")) ? true : false; mouseYInvert = (config->Int("InvertMouseY")) ? true : false; compactScanner = (config->Int("CompactScanner")) ? true : false; navTunnelDisplayed = (config->Int("DisplayNavTunnel")) ? true : false; speedLinesDisplayed = (config->Int("SpeedLines")) ? true : false; hudTrailsDisplayed = (config->Int("HudTrails")) ? true : false; EnumStrings::Init(); // get threads up Uint32 numThreads = config->Int("WorkerThreads"); const int numCores = OS::GetNumCores(); assert(numCores > 0); if (numThreads == 0) numThreads = std::max(Uint32(numCores) - 1, 1U); asyncJobQueue.reset(new AsyncJobQueue(numThreads)); Output("started %d worker threads\n", numThreads); syncJobQueue.reset(new SyncJobQueue); Output("ShipType::Init()\n"); // XXX early, Lua init needs it ShipType::Init(); // XXX UI requires Lua but Pi::ui must exist before we start loading // templates. so now we have crap everywhere :/ Output("Lua::Init()\n"); Lua::Init(); Pi::ui.Reset(new UI::Context(Lua::manager, Pi::renderer, Graphics::GetScreenWidth(), Graphics::GetScreenHeight())); LuaInit(); // Gui::Init shouldn't initialise any VBOs, since we haven't tested // that the capability exists. (Gui does not use VBOs so far) Gui::Init(renderer, Graphics::GetScreenWidth(), Graphics::GetScreenHeight(), 800, 600); UI::Box *box = Pi::ui->VBox(5); UI::Label *label = Pi::ui->Label(""); label->SetFont(UI::Widget::FONT_HEADING_NORMAL); UI::Gauge *gauge = Pi::ui->Gauge(); Pi::ui->GetTopLayer()->SetInnerWidget( Pi::ui->Margin(10, UI::Margin::HORIZONTAL)->SetInnerWidget( Pi::ui->Expand()->SetInnerWidget( Pi::ui->Align(UI::Align::MIDDLE)->SetInnerWidget( box->PackEnd(UI::WidgetSet( label, gauge )) ) ) ) ); draw_progress(gauge, label, 0.0f); Output("GalaxyGenerator::Init()\n"); if (config->HasEntry("GalaxyGenerator")) GalaxyGenerator::Init(config->String("GalaxyGenerator"), config->Int("GalaxyGeneratorVersion", GalaxyGenerator::LAST_VERSION)); else GalaxyGenerator::Init(); draw_progress(gauge, label, 0.1f); Output("FaceParts::Init()\n"); FaceParts::Init(); draw_progress(gauge, label, 0.2f); Output("new ModelCache\n"); modelCache = new ModelCache(Pi::renderer); draw_progress(gauge, label, 0.3f); Output("Shields::Init\n"); Shields::Init(Pi::renderer); draw_progress(gauge, label, 0.4f); //unsigned int control_word; //_clearfp(); //_controlfp_s(&control_word, _EM_INEXACT | _EM_UNDERFLOW | _EM_ZERODIVIDE, _MCW_EM); //double fpexcept = Pi::timeAccelRates[1] / Pi::timeAccelRates[0]; Output("BaseSphere::Init\n"); BaseSphere::Init(); draw_progress(gauge, label, 0.5f); Output("CityOnPlanet::Init\n"); CityOnPlanet::Init(); draw_progress(gauge, label, 0.6f); Output("SpaceStation::Init\n"); SpaceStation::Init(); draw_progress(gauge, label, 0.7f); Output("NavLights::Init\n"); NavLights::Init(Pi::renderer); draw_progress(gauge, label, 0.75f); Output("Sfx::Init\n"); Sfx::Init(Pi::renderer); draw_progress(gauge, label, 0.8f); if (!no_gui && !config->Int("DisableSound")) { Output("Sound::Init\n"); Sound::Init(); Sound::SetMasterVolume(config->Float("MasterVolume")); Sound::SetSfxVolume(config->Float("SfxVolume")); GetMusicPlayer().SetVolume(config->Float("MusicVolume")); Sound::Pause(0); if (config->Int("MasterMuted")) Sound::Pause(1); if (config->Int("SfxMuted")) Sound::SetSfxVolume(0.f); if (config->Int("MusicMuted")) GetMusicPlayer().SetEnabled(false); } draw_progress(gauge, label, 0.9f); OS::NotifyLoadEnd(); draw_progress(gauge, label, 1.0f); #if 0 // frame test code Frame *root = new Frame(0, "root", 0); Frame *p1 = new Frame(root, "p1", Frame::FLAG_HAS_ROT); Frame *p1r = new Frame(p1, "p1r", Frame::FLAG_ROTATING); Frame *m1 = new Frame(p1, "m1", Frame::FLAG_HAS_ROT); Frame *m1r = new Frame(m1, "m1r", Frame::FLAG_ROTATING); Frame *p2 = new Frame(root, "p2", Frame::FLAG_HAS_ROT); Frame *p2r = new Frame(p2, "pr2", Frame::FLAG_ROTATING); p1->SetPosition(vector3d(1000,0,0)); p1->SetVelocity(vector3d(0,1,0)); p2->SetPosition(vector3d(0,2000,0)); p2->SetVelocity(vector3d(-2,0,0)); p1r->SetAngVelocity(vector3d(0,0,0.0001)); p1r->SetOrient(matrix3x3d::BuildRotate(M_PI/4, vector3d(0,0,1))); p2r->SetAngVelocity(vector3d(0,0,-0.0004)); p2r->SetOrient(matrix3x3d::BuildRotate(-M_PI/2, vector3d(0,0,1))); root->UpdateOrbitRails(0, 0); CargoBody *c1 = new CargoBody(Equip::Type::SLAVES); c1->SetFrame(p1r); c1->SetPosition(vector3d(0,180,0)); // c1->SetVelocity(vector3d(1,0,0)); CargoBody *c2 = new CargoBody(Equip::Type::SLAVES); c2->SetFrame(p1r); c2->SetPosition(vector3d(0,200,0)); // c2->SetVelocity(vector3d(1,0,0)); vector3d pos = c1->GetPositionRelTo(p1); vector3d vel = c1->GetVelocityRelTo(p1); double speed = vel.Length(); vector3d pos2 = c2->GetPositionRelTo(p1); vector3d vel2 = c2->GetVelocityRelTo(p1); double speed2 = vel2.Length(); double speed3 = c2->GetVelocityRelTo(c1).Length(); c2->SwitchToFrame(p1); vector3d vel4 = c2->GetVelocityRelTo(c1); double speed4 = c2->GetVelocityRelTo(c1).Length(); root->UpdateOrbitRails(0, 1.0); //buildrotate test matrix3x3d m = matrix3x3d::BuildRotate(M_PI/2, vector3d(0,0,1)); vector3d v = m * vector3d(1,0,0); /* vector3d pos = p1r->GetPositionRelTo(p2r); vector3d vel = p1r->GetVelocityRelTo(p2r); matrix3x3d o1 = p1r->GetOrientRelTo(p2r); double speed = vel.Length(); vector3d pos2 = p2r->GetPositionRelTo(p1r); vector3d vel2 = p2r->GetVelocityRelTo(p1r); matrix3x3d o2 = p2r->GetOrientRelTo(p1r); double speed2 = vel2.Length(); */ root->UpdateOrbitRails(0, 1.0/60); delete p2r; delete p2; delete m1r; delete m1; delete p1r; delete p1; delete root; delete c1; delete c2; #endif #if 0 // test code to produce list of ship stats FILE *pStatFile = fopen("shipstat.csv","wt"); if (pStatFile) { fprintf(pStatFile, "name,modelname,hullmass,capacity,fakevol,rescale,xsize,ysize,zsize,facc,racc,uacc,sacc,aacc,exvel\n"); for (auto iter : ShipType::types) { const ShipType *shipdef = &(iter.second); SceneGraph::Model *model = Pi::FindModel(shipdef->modelName, false); double hullmass = shipdef->hullMass; double capacity = shipdef->capacity; double xsize = 0.0, ysize = 0.0, zsize = 0.0, fakevol = 0.0, rescale = 0.0, brad = 0.0; if (model) { std::unique_ptr<SceneGraph::Model> inst(model->MakeInstance()); model->CreateCollisionMesh(); Aabb aabb = model->GetCollisionMesh()->GetAabb(); xsize = aabb.max.x-aabb.min.x; ysize = aabb.max.y-aabb.min.y; zsize = aabb.max.z-aabb.min.z; fakevol = xsize*ysize*zsize; brad = aabb.GetRadius(); rescale = pow(fakevol/(100 * (hullmass+capacity)), 0.3333333333); } double simass = (hullmass + capacity) * 1000.0; double angInertia = (2/5.0)*simass*brad*brad; double acc1 = shipdef->linThrust[ShipType::THRUSTER_FORWARD] / (9.81*simass); double acc2 = shipdef->linThrust[ShipType::THRUSTER_REVERSE] / (9.81*simass); double acc3 = shipdef->linThrust[ShipType::THRUSTER_UP] / (9.81*simass); double acc4 = shipdef->linThrust[ShipType::THRUSTER_RIGHT] / (9.81*simass); double acca = shipdef->angThrust/angInertia; double exvel = shipdef->effectiveExhaustVelocity; fprintf(pStatFile, "%s,%s,%.1f,%.1f,%.1f,%.3f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%f,%.1f\n", shipdef->name.c_str(), shipdef->modelName.c_str(), hullmass, capacity, fakevol, rescale, xsize, ysize, zsize, acc1, acc2, acc3, acc4, acca, exvel); } fclose(pStatFile); } #endif luaConsole = new LuaConsole(); KeyBindings::toggleLuaConsole.onPress.connect(sigc::mem_fun(Pi::luaConsole, &LuaConsole::Toggle)); planner = new TransferPlanner(); timer.Stop(); Output("\n\nLoading took: %lf milliseconds\n", timer.millicycles()); }
void Pi::Init() { config.Load(GetPiUserDir() + "config.ini"); Pi::detail.planets = config.Int("DetailPlanets"); Pi::detail.cities = config.Int("DetailCities"); int width = config.Int("ScrWidth"); int height = config.Int("ScrHeight"); const SDL_VideoInfo *info = NULL; Uint32 sdlInitFlags = SDL_INIT_VIDEO | SDL_INIT_JOYSTICK; #if defined _WIN32 && defined _DEBUG sdlInitFlags |= SDL_INIT_NOPARACHUTE; #endif if (SDL_Init(sdlInitFlags) < 0) { fprintf(stderr, "Video initialization failed: %s\n", SDL_GetError()); exit(-1); } InitJoysticks(); // no mode set, find an ok one if ((width <= 0) || (height <= 0)) { SDL_Rect **modes = SDL_ListModes(NULL, SDL_HWSURFACE | SDL_FULLSCREEN); if (modes == 0) { fprintf(stderr, "It seems no video modes are available..."); } if (modes == (SDL_Rect **)-1) { // hm. all modes available. odd. try 800x600 width = 800; height = 600; } else { width = modes[0]->w; height = modes[0]->h; } } info = SDL_GetVideoInfo(); printf("SDL_GetVideoInfo says %d bpp\n", info->vfmt->BitsPerPixel); switch (info->vfmt->BitsPerPixel) { case 16: SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5); break; case 24: case 32: SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); break; default: fprintf(stderr, "Invalid pixel depth: %d bpp\n", info->vfmt->BitsPerPixel); } SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); Uint32 flags = SDL_OPENGL; if (config.Int("StartFullscreen")) flags |= SDL_FULLSCREEN; if ((Pi::scrSurface = SDL_SetVideoMode(width, height, info->vfmt->BitsPerPixel, flags)) == 0) { // fall back on 16-bit depth buffer... SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); fprintf(stderr, "Failed to set video mode. (%s). Re-trying with 16-bit depth buffer.\n", SDL_GetError()); if ((Pi::scrSurface = SDL_SetVideoMode(width, height, info->vfmt->BitsPerPixel, flags)) == 0) { fprintf(stderr, "Failed to set video mode: %s", SDL_GetError()); } } glewInit(); SDL_WM_SetCaption("Pioneer","Pioneer"); Pi::scrWidth = width; Pi::scrHeight = height; Pi::scrAspect = width / (float)height; Pi::rng.seed(time(NULL)); InitOpenGL(); GLFTInit(); // Gui::Init shouldn't initialise any VBOs, since we haven't tested // that the capability exists. (Gui does not use VBOs so far) Gui::Init(scrWidth, scrHeight, 800, 600); if (!GLEW_ARB_vertex_buffer_object) { Error("OpenGL extension ARB_vertex_buffer_object not supported. Pioneer can not run on your graphics card."); } Render::Init(width, height); draw_progress(0.1f); Galaxy::Init(); draw_progress(0.2f); NameGenerator::Init(); if (config.Int("DisableShaders")) Render::ToggleShaders(); if (config.Int("EnableHDR")) Render::ToggleHDR(); draw_progress(0.3f); LmrModelCompilerInit(); //unsigned int control_word; //_clearfp(); //_controlfp_s(&control_word, _EM_INEXACT | _EM_UNDERFLOW, _MCW_EM); //double fpexcept = Pi::timeAccelRates[1] / Pi::timeAccelRates[0]; draw_progress(0.4f); ShipType::Init(); draw_progress(0.5f); GeoSphere::Init(); draw_progress(0.6f); Space::Init(); draw_progress(0.7f); Polit::Init(); draw_progress(0.8f); SpaceStation::Init(); draw_progress(0.9f); if (!config.Int("DisableSound")) { Sound::Init(); Sound::SetGlobalVolume(config.Float("SfxVolume")); Sound::Pause(0); } draw_progress(1.0f); // test code to produce list of ship stats FILE *pStatFile = fopen("shipstat.csv","wt"); if (pStatFile) { fprintf(pStatFile, "name,lmrname,hullmass,capacity,xsize,ysize,zsize,facc,racc,uacc,aacc\n"); for (std::map<std::string, ShipType>::iterator i = ShipType::types.begin(); i != ShipType::types.end(); ++i) { ShipType *shipdef = &(i->second); LmrModel *lmrModel = LmrLookupModelByName(shipdef->lmrModelName.c_str()); LmrObjParams lmrParams; memset(&lmrParams, 0, sizeof(LmrObjParams)); LmrCollMesh *collMesh = new LmrCollMesh(lmrModel, &lmrParams); Aabb aabb = collMesh->GetAabb(); double hullmass = shipdef->hullMass; double capacity = shipdef->capacity; double xsize = aabb.max.x-aabb.min.x; double ysize = aabb.max.y-aabb.min.y; double zsize = aabb.max.z-aabb.min.z; double brad = aabb.GetBoundingRadius(); double simass = (hullmass + capacity) * 1000.0; double angInertia = (2/5.0)*simass*brad*brad; double acc1 = shipdef->linThrust[ShipType::THRUSTER_FORWARD] / (9.81*simass); double acc2 = shipdef->linThrust[ShipType::THRUSTER_REVERSE] / (9.81*simass); double acc3 = shipdef->linThrust[ShipType::THRUSTER_UP] / (9.81*simass); double acca = shipdef->angThrust/angInertia; fprintf(pStatFile, "%s,%s,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%f\n", shipdef->name.c_str(), shipdef->lmrModelName.c_str(), hullmass, capacity, xsize, ysize, zsize, acc1, acc2, acc3, acca); } fclose(pStatFile); } gameMenuView = new GameMenuView(); config.Save(); }
static void draw_func (GtkDrawingArea *da, cairo_t *cr, int width, int height, gpointer data) { GtkWidget *widget = GTK_WIDGET (da); gint panewidth; gint x, y; panewidth = width / 2; cairo_rectangle (cr, 0, 0, width, height); cairo_set_source_rgb (cr, 0.9, 0.9, 0.9); cairo_fill (cr); x = y = 10; draw_horizontal_scrollbar (widget, cr, x, y, panewidth - 20, 30, GTK_STATE_FLAG_NORMAL, &height); y += height + 8; draw_horizontal_scrollbar (widget, cr, x, y, panewidth - 20, 40, GTK_STATE_FLAG_PRELIGHT, &height); y += height + 8; draw_horizontal_scrollbar (widget, cr, x, y, panewidth - 20, 50, GTK_STATE_FLAG_ACTIVE|GTK_STATE_FLAG_PRELIGHT, &height); y += height + 8; draw_text (widget, cr, x, y, panewidth - 20, 20, "Not selected", GTK_STATE_FLAG_NORMAL); y += 20 + 10; draw_text (widget, cr, x, y, panewidth - 20, 20, "Selected", GTK_STATE_FLAG_SELECTED); x = 10; y += 20 + 10; draw_check (widget, cr, x, y, GTK_STATE_FLAG_NORMAL, &width, &height); x += width + 10; draw_check (widget, cr, x, y, GTK_STATE_FLAG_CHECKED, &width, &height); x += width + 10; draw_radio (widget, cr, x, y, GTK_STATE_FLAG_NORMAL, &width, &height); x += width + 10; draw_radio (widget, cr, x, y, GTK_STATE_FLAG_CHECKED, &width, &height); x = 10; y += height + 10; draw_progress (widget, cr, x, y, panewidth - 20, 50, &height); y += height + 10; draw_scale (widget, cr, x, y, panewidth - 20, 75, &height); y += height + 20; draw_notebook (widget, cr, x, y, panewidth - 20, 160); /* Second column */ x += panewidth; y = 10; draw_menu (widget, cr, x, y, panewidth - 20, &height); y += height + 10; draw_menubar (widget, cr, x, y, panewidth - 20, &height); y += height + 20; draw_spinbutton (widget, cr, x, y, panewidth - 20, &height); y += height + 30; draw_combobox (widget, cr, x, y, panewidth - 20, FALSE, &height); y += height + 10; draw_combobox (widget, cr, 10 + panewidth, y, panewidth - 20, TRUE, &height); }
int journal_file_verify( JournalFile *f, const char *key, usec_t *first_contained, usec_t *last_validated, usec_t *last_contained, bool show_progress) { int r; Object *o; uint64_t p = 0, last_epoch = 0, last_tag_realtime = 0, last_sealed_realtime = 0; uint64_t entry_seqnum = 0, entry_monotonic = 0, entry_realtime = 0; sd_id128_t entry_boot_id; bool entry_seqnum_set = false, entry_monotonic_set = false, entry_realtime_set = false, found_main_entry_array = false; uint64_t n_weird = 0, n_objects = 0, n_entries = 0, n_data = 0, n_fields = 0, n_data_hash_tables = 0, n_field_hash_tables = 0, n_entry_arrays = 0, n_tags = 0; usec_t last_usec = 0; int data_fd = -1, entry_fd = -1, entry_array_fd = -1; unsigned i; bool found_last = false; #ifdef HAVE_GCRYPT uint64_t last_tag = 0; #endif assert(f); if (key) { #ifdef HAVE_GCRYPT r = journal_file_parse_verification_key(f, key); if (r < 0) { log_error("Failed to parse seed."); return r; } #else return -ENOTSUP; #endif } else if (f->seal) return -ENOKEY; data_fd = open_tmpfile("/var/tmp", O_RDWR | O_CLOEXEC); if (data_fd < 0) { log_error_errno(errno, "Failed to create data file: %m"); r = -errno; goto fail; } entry_fd = open_tmpfile("/var/tmp", O_RDWR | O_CLOEXEC); if (entry_fd < 0) { log_error_errno(errno, "Failed to create entry file: %m"); r = -errno; goto fail; } entry_array_fd = open_tmpfile("/var/tmp", O_RDWR | O_CLOEXEC); if (entry_array_fd < 0) { log_error_errno(errno, "Failed to create entry array file: %m"); r = -errno; goto fail; } if (le32toh(f->header->compatible_flags) & ~HEADER_COMPATIBLE_SUPPORTED) { log_error("Cannot verify file with unknown extensions."); r = -ENOTSUP; goto fail; } for (i = 0; i < sizeof(f->header->reserved); i++) if (f->header->reserved[i] != 0) { error(offsetof(Header, reserved[i]), "Reserved field is non-zero"); r = -EBADMSG; goto fail; } /* First iteration: we go through all objects, verify the * superficial structure, headers, hashes. */ p = le64toh(f->header->header_size); for (;;) { /* Early exit if there are no objects in the file, at all */ if (le64toh(f->header->tail_object_offset) == 0) break; if (show_progress) draw_progress(scale_progress(0x7FFF, p, le64toh(f->header->tail_object_offset)), &last_usec); r = journal_file_move_to_object(f, OBJECT_UNUSED, p, &o); if (r < 0) { error(p, "Invalid object"); goto fail; } if (p > le64toh(f->header->tail_object_offset)) { error(offsetof(Header, tail_object_offset), "Invalid tail object pointer"); r = -EBADMSG; goto fail; } n_objects ++; r = journal_file_object_verify(f, p, o); if (r < 0) { error(p, "Invalid object contents: %s", strerror(-r)); goto fail; } if ((o->object.flags & OBJECT_COMPRESSED_XZ) && (o->object.flags & OBJECT_COMPRESSED_LZ4)) { error(p, "Objected with double compression"); r = -EINVAL; goto fail; } if ((o->object.flags & OBJECT_COMPRESSED_XZ) && !JOURNAL_HEADER_COMPRESSED_XZ(f->header)) { error(p, "XZ compressed object in file without XZ compression"); r = -EBADMSG; goto fail; } if ((o->object.flags & OBJECT_COMPRESSED_LZ4) && !JOURNAL_HEADER_COMPRESSED_LZ4(f->header)) { error(p, "LZ4 compressed object in file without LZ4 compression"); r = -EBADMSG; goto fail; } switch (o->object.type) { case OBJECT_DATA: r = write_uint64(data_fd, p); if (r < 0) goto fail; n_data++; break; case OBJECT_FIELD: n_fields++; break; case OBJECT_ENTRY: if (JOURNAL_HEADER_SEALED(f->header) && n_tags <= 0) { error(p, "First entry before first tag"); r = -EBADMSG; goto fail; } r = write_uint64(entry_fd, p); if (r < 0) goto fail; if (le64toh(o->entry.realtime) < last_tag_realtime) { error(p, "Older entry after newer tag"); r = -EBADMSG; goto fail; } if (!entry_seqnum_set && le64toh(o->entry.seqnum) != le64toh(f->header->head_entry_seqnum)) { error(p, "Head entry sequence number incorrect"); r = -EBADMSG; goto fail; } if (entry_seqnum_set && entry_seqnum >= le64toh(o->entry.seqnum)) { error(p, "Entry sequence number out of synchronization"); r = -EBADMSG; goto fail; } entry_seqnum = le64toh(o->entry.seqnum); entry_seqnum_set = true; if (entry_monotonic_set && sd_id128_equal(entry_boot_id, o->entry.boot_id) && entry_monotonic > le64toh(o->entry.monotonic)) { error(p, "Entry timestamp out of synchronization"); r = -EBADMSG; goto fail; } entry_monotonic = le64toh(o->entry.monotonic); entry_boot_id = o->entry.boot_id; entry_monotonic_set = true; if (!entry_realtime_set && le64toh(o->entry.realtime) != le64toh(f->header->head_entry_realtime)) { error(p, "Head entry realtime timestamp incorrect"); r = -EBADMSG; goto fail; } entry_realtime = le64toh(o->entry.realtime); entry_realtime_set = true; n_entries ++; break; case OBJECT_DATA_HASH_TABLE: if (n_data_hash_tables > 1) { error(p, "More than one data hash table"); r = -EBADMSG; goto fail; } if (le64toh(f->header->data_hash_table_offset) != p + offsetof(HashTableObject, items) || le64toh(f->header->data_hash_table_size) != le64toh(o->object.size) - offsetof(HashTableObject, items)) { error(p, "header fields for data hash table invalid"); r = -EBADMSG; goto fail; } n_data_hash_tables++; break; case OBJECT_FIELD_HASH_TABLE: if (n_field_hash_tables > 1) { error(p, "More than one field hash table"); r = -EBADMSG; goto fail; } if (le64toh(f->header->field_hash_table_offset) != p + offsetof(HashTableObject, items) || le64toh(f->header->field_hash_table_size) != le64toh(o->object.size) - offsetof(HashTableObject, items)) { error(p, "Header fields for field hash table invalid"); r = -EBADMSG; goto fail; } n_field_hash_tables++; break; case OBJECT_ENTRY_ARRAY: r = write_uint64(entry_array_fd, p); if (r < 0) goto fail; if (p == le64toh(f->header->entry_array_offset)) { if (found_main_entry_array) { error(p, "More than one main entry array"); r = -EBADMSG; goto fail; } found_main_entry_array = true; } n_entry_arrays++; break; case OBJECT_TAG: if (!JOURNAL_HEADER_SEALED(f->header)) { error(p, "Tag object in file without sealing"); r = -EBADMSG; goto fail; } if (le64toh(o->tag.seqnum) != n_tags + 1) { error(p, "Tag sequence number out of synchronization"); r = -EBADMSG; goto fail; } if (le64toh(o->tag.epoch) < last_epoch) { error(p, "Epoch sequence out of synchronization"); r = -EBADMSG; goto fail; } #ifdef HAVE_GCRYPT if (f->seal) { uint64_t q, rt; debug(p, "Checking tag %"PRIu64"...", le64toh(o->tag.seqnum)); rt = f->fss_start_usec + o->tag.epoch * f->fss_interval_usec; if (entry_realtime_set && entry_realtime >= rt + f->fss_interval_usec) { error(p, "tag/entry realtime timestamp out of synchronization"); r = -EBADMSG; goto fail; } /* OK, now we know the epoch. So let's now set * it, and calculate the HMAC for everything * since the last tag. */ r = journal_file_fsprg_seek(f, le64toh(o->tag.epoch)); if (r < 0) goto fail; r = journal_file_hmac_start(f); if (r < 0) goto fail; if (last_tag == 0) { r = journal_file_hmac_put_header(f); if (r < 0) goto fail; q = le64toh(f->header->header_size); } else q = last_tag; while (q <= p) { r = journal_file_move_to_object(f, OBJECT_UNUSED, q, &o); if (r < 0) goto fail; r = journal_file_hmac_put_object(f, OBJECT_UNUSED, o, q); if (r < 0) goto fail; q = q + ALIGN64(le64toh(o->object.size)); } /* Position might have changed, let's reposition things */ r = journal_file_move_to_object(f, OBJECT_UNUSED, p, &o); if (r < 0) goto fail; if (memcmp(o->tag.tag, gcry_md_read(f->hmac, 0), TAG_LENGTH) != 0) { error(p, "Tag failed verification"); r = -EBADMSG; goto fail; } f->hmac_running = false; last_tag_realtime = rt; last_sealed_realtime = entry_realtime; } last_tag = p + ALIGN64(le64toh(o->object.size)); #endif last_epoch = le64toh(o->tag.epoch); n_tags ++; break; default: n_weird ++; } if (p == le64toh(f->header->tail_object_offset)) { found_last = true; break; } p = p + ALIGN64(le64toh(o->object.size)); }; if (!found_last && le64toh(f->header->tail_object_offset) != 0) { error(le64toh(f->header->tail_object_offset), "Tail object pointer dead"); r = -EBADMSG; goto fail; } if (n_objects != le64toh(f->header->n_objects)) { error(offsetof(Header, n_objects), "Object number mismatch"); r = -EBADMSG; goto fail; } if (n_entries != le64toh(f->header->n_entries)) { error(offsetof(Header, n_entries), "Entry number mismatch"); r = -EBADMSG; goto fail; } if (JOURNAL_HEADER_CONTAINS(f->header, n_data) && n_data != le64toh(f->header->n_data)) { error(offsetof(Header, n_data), "Data number mismatch"); r = -EBADMSG; goto fail; } if (JOURNAL_HEADER_CONTAINS(f->header, n_fields) && n_fields != le64toh(f->header->n_fields)) { error(offsetof(Header, n_fields), "Field number mismatch"); r = -EBADMSG; goto fail; } if (JOURNAL_HEADER_CONTAINS(f->header, n_tags) && n_tags != le64toh(f->header->n_tags)) { error(offsetof(Header, n_tags), "Tag number mismatch"); r = -EBADMSG; goto fail; } if (JOURNAL_HEADER_CONTAINS(f->header, n_entry_arrays) && n_entry_arrays != le64toh(f->header->n_entry_arrays)) { error(offsetof(Header, n_entry_arrays), "Entry array number mismatch"); r = -EBADMSG; goto fail; } if (!found_main_entry_array && le64toh(f->header->entry_array_offset) != 0) { error(0, "Missing entry array"); r = -EBADMSG; goto fail; } if (entry_seqnum_set && entry_seqnum != le64toh(f->header->tail_entry_seqnum)) { error(offsetof(Header, tail_entry_seqnum), "Invalid tail seqnum"); r = -EBADMSG; goto fail; } if (entry_monotonic_set && (!sd_id128_equal(entry_boot_id, f->header->boot_id) || entry_monotonic != le64toh(f->header->tail_entry_monotonic))) { error(0, "Invalid tail monotonic timestamp"); r = -EBADMSG; goto fail; } if (entry_realtime_set && entry_realtime != le64toh(f->header->tail_entry_realtime)) { error(0, "Invalid tail realtime timestamp"); r = -EBADMSG; goto fail; } /* Second iteration: we follow all objects referenced from the * two entry points: the object hash table and the entry * array. We also check that everything referenced (directly * or indirectly) in the data hash table also exists in the * entry array, and vice versa. Note that we do not care for * unreferenced objects. We only care that everything that is * referenced is consistent. */ r = verify_entry_array(f, data_fd, n_data, entry_fd, n_entries, entry_array_fd, n_entry_arrays, &last_usec, show_progress); if (r < 0) goto fail; r = verify_hash_table(f, data_fd, n_data, entry_fd, n_entries, entry_array_fd, n_entry_arrays, &last_usec, show_progress); if (r < 0) goto fail; if (show_progress) flush_progress(); mmap_cache_close_fd(f->mmap, data_fd); mmap_cache_close_fd(f->mmap, entry_fd); mmap_cache_close_fd(f->mmap, entry_array_fd); safe_close(data_fd); safe_close(entry_fd); safe_close(entry_array_fd); if (first_contained) *first_contained = le64toh(f->header->head_entry_realtime); if (last_validated) *last_validated = last_sealed_realtime; if (last_contained) *last_contained = le64toh(f->header->tail_entry_realtime); return 0; fail: if (show_progress) flush_progress(); log_error("File corruption detected at %s:"OFSfmt" (of %llu bytes, %"PRIu64"%%).", f->path, p, (unsigned long long) f->last_stat.st_size, 100 * p / f->last_stat.st_size); if (data_fd >= 0) { mmap_cache_close_fd(f->mmap, data_fd); safe_close(data_fd); } if (entry_fd >= 0) { mmap_cache_close_fd(f->mmap, entry_fd); safe_close(entry_fd); } if (entry_array_fd >= 0) { mmap_cache_close_fd(f->mmap, entry_array_fd); safe_close(entry_array_fd); } return r; }
static int verify_entry_array( JournalFile *f, int data_fd, uint64_t n_data, int entry_fd, uint64_t n_entries, int entry_array_fd, uint64_t n_entry_arrays, usec_t *last_usec, bool show_progress) { uint64_t i = 0, a, n, last = 0; int r; assert(f); assert(data_fd >= 0); assert(entry_fd >= 0); assert(entry_array_fd >= 0); assert(last_usec); n = le64toh(f->header->n_entries); a = le64toh(f->header->entry_array_offset); while (i < n) { uint64_t next, m, j; Object *o; if (show_progress) draw_progress(0x8000 + scale_progress(0x3FFF, i, n), last_usec); if (a == 0) { error(a, "Array chain too short at %"PRIu64" of %"PRIu64, i, n); return -EBADMSG; } if (!contains_uint64(f->mmap, entry_array_fd, n_entry_arrays, a)) { error(a, "Invalid array %"PRIu64" of %"PRIu64, i, n); return -EBADMSG; } r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o); if (r < 0) return r; next = le64toh(o->entry_array.next_entry_array_offset); if (next != 0 && next <= a) { error(a, "Array chain has cycle at %"PRIu64" of %"PRIu64" (jumps back from to "OFSfmt")", i, n, next); return -EBADMSG; } m = journal_file_entry_array_n_items(o); for (j = 0; i < n && j < m; i++, j++) { uint64_t p; p = le64toh(o->entry_array.items[j]); if (p <= last) { error(a, "Entry array not sorted at %"PRIu64" of %"PRIu64, i, n); return -EBADMSG; } last = p; if (!contains_uint64(f->mmap, entry_fd, n_entries, p)) { error(a, "Invalid array entry at %"PRIu64" of %"PRIu64, i, n); return -EBADMSG; } r = journal_file_move_to_object(f, OBJECT_ENTRY, p, &o); if (r < 0) return r; r = verify_entry(f, o, p, data_fd, n_data); if (r < 0) return r; /* Pointer might have moved, reposition */ r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o); if (r < 0) return r; } a = next; } return 0; }
static int verify_hash_table( JournalFile *f, int data_fd, uint64_t n_data, int entry_fd, uint64_t n_entries, int entry_array_fd, uint64_t n_entry_arrays, usec_t *last_usec, bool show_progress) { uint64_t i, n; int r; assert(f); assert(data_fd >= 0); assert(entry_fd >= 0); assert(entry_array_fd >= 0); assert(last_usec); n = le64toh(f->header->data_hash_table_size) / sizeof(HashItem); if (n <= 0) return 0; r = journal_file_map_data_hash_table(f); if (r < 0) return log_error_errno(r, "Failed to map data hash table: %m"); for (i = 0; i < n; i++) { uint64_t last = 0, p; if (show_progress) draw_progress(0xC000 + scale_progress(0x3FFF, i, n), last_usec); p = le64toh(f->data_hash_table[i].head_hash_offset); while (p != 0) { Object *o; uint64_t next; if (!contains_uint64(f->mmap, data_fd, n_data, p)) { error(p, "Invalid data object at hash entry %"PRIu64" of %"PRIu64, i, n); return -EBADMSG; } r = journal_file_move_to_object(f, OBJECT_DATA, p, &o); if (r < 0) return r; next = le64toh(o->data.next_hash_offset); if (next != 0 && next <= p) { error(p, "Hash chain has a cycle in hash entry %"PRIu64" of %"PRIu64, i, n); return -EBADMSG; } if (le64toh(o->data.hash) % n != i) { error(p, "Hash value mismatch in hash entry %"PRIu64" of %"PRIu64, i, n); return -EBADMSG; } r = verify_data(f, o, p, entry_fd, n_entries, entry_array_fd, n_entry_arrays); if (r < 0) return r; last = p; p = next; } if (last != le64toh(f->data_hash_table[i].tail_hash_offset)) { error(p, "Tail hash pointer mismatch in hash table"); return -EBADMSG; } } return 0; }
void Pi::Init() { OS::NotifyLoadBegin(); FileSystem::Init(); FileSystem::userFiles.MakeDirectory(""); // ensure the config directory exists Pi::config = new GameConfig(); KeyBindings::InitBindings(); if (config->Int("RedirectStdio")) OS::RedirectStdio(); ModManager::Init(); if (!Lang::LoadStrings(config->String("Lang"))) abort(); Pi::detail.planets = config->Int("DetailPlanets"); Pi::detail.textures = config->Int("Textures"); Pi::detail.fracmult = config->Int("FractalMultiple"); Pi::detail.cities = config->Int("DetailCities"); #ifdef __linux__ // there appears to be a bug in the Linux evdev input driver that stops // DGA mouse grab restoring state correctly. SDL can use an alternative // method, but its only configurable via environment variable. Here we set // that environment variable (unless the user explicitly doesn't want it // via config). // // we also enable warp-after-grab here, as the SDL alternative method // doesn't restore the mouse pointer to its pre-grab position // // XXX SDL2 uses a different mechanism entirely and this environment // variable doesn't exist there, so we can get rid of it when we go to SDL2 if (!config->Int("SDLUseDGAMouse")) { Pi::warpAfterMouseGrab = true; setenv("SDL_VIDEO_X11_DGAMOUSE", "0", 1); } #endif // Initialize SDL Uint32 sdlInitFlags = SDL_INIT_VIDEO | SDL_INIT_JOYSTICK; #if defined(DEBUG) || defined(_DEBUG) sdlInitFlags |= SDL_INIT_NOPARACHUTE; #endif if (SDL_Init(sdlInitFlags) < 0) { OS::Error("SDL initialization failed: %s\n", SDL_GetError()); } // needed for the UI SDL_EnableUNICODE(1); // Do rest of SDL video initialization and create Renderer Graphics::Settings videoSettings = {}; videoSettings.width = config->Int("ScrWidth"); videoSettings.height = config->Int("ScrHeight"); videoSettings.fullscreen = (config->Int("StartFullscreen") != 0); videoSettings.shaders = (config->Int("DisableShaders") == 0); videoSettings.requestedSamples = config->Int("AntiAliasingMode"); videoSettings.vsync = (config->Int("VSync") != 0); videoSettings.useTextureCompression = (config->Int("UseTextureCompression") != 0); Pi::renderer = Graphics::Init(videoSettings); { std::ostringstream buf; renderer->PrintDebugInfo(buf); FILE *f = FileSystem::userFiles.OpenWriteStream("opengl.txt", FileSystem::FileSourceFS::WRITE_TEXT); if (!f) fprintf(stderr, "Could not open 'opengl.txt'\n"); const std::string &s = buf.str(); fwrite(s.c_str(), 1, s.size(), f); fclose(f); } OS::LoadWindowIcon(); SDL_WM_SetCaption("Pioneer","Pioneer"); Pi::scrAspect = videoSettings.width / float(videoSettings.height); Pi::rng.seed(time(0)); InitJoysticks(); joystickEnabled = (config->Int("EnableJoystick")) ? true : false; mouseYInvert = (config->Int("InvertMouseY")) ? true : false; navTunnelDisplayed = (config->Int("DisplayNavTunnel")) ? true : false; // XXX UI requires Lua but Pi::ui must exist before we start loading // templates. so now we have crap everywhere :/ Lua::Init(); Pi::ui.Reset(new UI::Context(Lua::manager, Pi::renderer, Graphics::GetScreenWidth(), Graphics::GetScreenHeight(), Lang::GetCurrentLanguage())); LuaInit(); // Gui::Init shouldn't initialise any VBOs, since we haven't tested // that the capability exists. (Gui does not use VBOs so far) Gui::Init(renderer, Graphics::GetScreenWidth(), Graphics::GetScreenHeight(), 800, 600); draw_progress(0.1f); Galaxy::Init(); draw_progress(0.2f); Faction::Init(); draw_progress(0.3f); CustomSystem::Init(); draw_progress(0.4f); LmrModelCompilerInit(Pi::renderer); modelCache = new ModelCache(Pi::renderer); draw_progress(0.5f); //unsigned int control_word; //_clearfp(); //_controlfp_s(&control_word, _EM_INEXACT | _EM_UNDERFLOW | _EM_ZERODIVIDE, _MCW_EM); //double fpexcept = Pi::timeAccelRates[1] / Pi::timeAccelRates[0]; ShipType::Init(); draw_progress(0.6f); GeoSphere::Init(); draw_progress(0.7f); CityOnPlanet::Init(); draw_progress(0.8f); SpaceStation::Init(); draw_progress(0.9f); Sfx::Init(Pi::renderer); draw_progress(0.95f); if (!config->Int("DisableSound")) { Sound::Init(); Sound::SetMasterVolume(config->Float("MasterVolume")); Sound::SetSfxVolume(config->Float("SfxVolume")); GetMusicPlayer().SetVolume(config->Float("MusicVolume")); Sound::Pause(0); if (config->Int("MasterMuted")) Sound::Pause(1); if (config->Int("SfxMuted")) Sound::SetSfxVolume(0.f); if (config->Int("MusicMuted")) GetMusicPlayer().SetEnabled(false); } draw_progress(1.0f); OS::NotifyLoadEnd(); #if 0 // frame test code Frame *root = new Frame(0, "root", 0); Frame *p1 = new Frame(root, "p1", Frame::FLAG_HAS_ROT); Frame *p1r = new Frame(p1, "p1r", Frame::FLAG_ROTATING); Frame *m1 = new Frame(p1, "m1", Frame::FLAG_HAS_ROT); Frame *m1r = new Frame(m1, "m1r", Frame::FLAG_ROTATING); Frame *p2 = new Frame(root, "p2", Frame::FLAG_HAS_ROT); Frame *p2r = new Frame(p2, "pr2", Frame::FLAG_ROTATING); p1->SetPosition(vector3d(1000,0,0)); p1->SetVelocity(vector3d(0,1,0)); p2->SetPosition(vector3d(0,2000,0)); p2->SetVelocity(vector3d(-2,0,0)); p1r->SetAngVelocity(vector3d(0,0,0.0001)); p1r->SetOrient(matrix3x3d::BuildRotate(M_PI/4, vector3d(0,0,1))); p2r->SetAngVelocity(vector3d(0,0,-0.0004)); p2r->SetOrient(matrix3x3d::BuildRotate(-M_PI/2, vector3d(0,0,1))); root->UpdateOrbitRails(0, 0); CargoBody *c1 = new CargoBody(Equip::Type::SLAVES); c1->SetFrame(p1r); c1->SetPosition(vector3d(0,180,0)); // c1->SetVelocity(vector3d(1,0,0)); CargoBody *c2 = new CargoBody(Equip::Type::SLAVES); c2->SetFrame(p1r); c2->SetPosition(vector3d(0,200,0)); // c2->SetVelocity(vector3d(1,0,0)); vector3d pos = c1->GetPositionRelTo(p1); vector3d vel = c1->GetVelocityRelTo(p1); double speed = vel.Length(); vector3d pos2 = c2->GetPositionRelTo(p1); vector3d vel2 = c2->GetVelocityRelTo(p1); double speed2 = vel2.Length(); double speed3 = c2->GetVelocityRelTo(c1).Length(); c2->SwitchToFrame(p1); vector3d vel4 = c2->GetVelocityRelTo(c1); double speed4 = c2->GetVelocityRelTo(c1).Length(); root->UpdateOrbitRails(0, 1.0); //buildrotate test matrix3x3d m = matrix3x3d::BuildRotate(M_PI/2, vector3d(0,0,1)); vector3d v = m * vector3d(1,0,0); /* vector3d pos = p1r->GetPositionRelTo(p2r); vector3d vel = p1r->GetVelocityRelTo(p2r); matrix3x3d o1 = p1r->GetOrientRelTo(p2r); double speed = vel.Length(); vector3d pos2 = p2r->GetPositionRelTo(p1r); vector3d vel2 = p2r->GetVelocityRelTo(p1r); matrix3x3d o2 = p2r->GetOrientRelTo(p1r); double speed2 = vel2.Length(); */ root->UpdateOrbitRails(0, 1.0/60); delete p2r; delete p2; delete m1r; delete m1; delete p1r; delete p1; delete root; delete c1; delete c2; #endif #if 0 // test code to produce list of ship stats FILE *pStatFile = fopen("shipstat.csv","wt"); if (pStatFile) { fprintf(pStatFile, "name,lmrname,hullmass,capacity,fakevol,rescale,xsize,ysize,zsize,facc,racc,uacc,sacc,aacc,exvel\n"); for (std::map<std::string, ShipType>::iterator i = ShipType::types.begin(); i != ShipType::types.end(); ++i) { ShipType *shipdef = &(i->second); LmrModel *lmrModel = LmrLookupModelByName(shipdef->lmrModelName.c_str()); LmrObjParams lmrParams; memset(&lmrParams, 0, sizeof(LmrObjParams)); lmrParams.animationNamespace = "ShipAnimation"; EquipSet equip; equip.InitSlotSizes(shipdef->id); lmrParams.equipment = &equip; LmrCollMesh *collMesh = new LmrCollMesh(lmrModel, &lmrParams); Aabb aabb = collMesh->GetAabb(); double hullmass = shipdef->hullMass; double capacity = shipdef->capacity; double xsize = aabb.max.x-aabb.min.x; double ysize = aabb.max.y-aabb.min.y; double zsize = aabb.max.z-aabb.min.z; double fakevol = xsize*ysize*zsize; double rescale = pow(fakevol/(100 * (hullmass+capacity)), 0.3333333333); double brad = aabb.GetRadius(); double simass = (hullmass + capacity) * 1000.0; double angInertia = (2/5.0)*simass*brad*brad; double acc1 = shipdef->linThrust[ShipType::THRUSTER_FORWARD] / (9.81*simass); double acc2 = shipdef->linThrust[ShipType::THRUSTER_REVERSE] / (9.81*simass); double acc3 = shipdef->linThrust[ShipType::THRUSTER_UP] / (9.81*simass); double acc4 = shipdef->linThrust[ShipType::THRUSTER_RIGHT] / (9.81*simass); double acca = shipdef->angThrust/angInertia; double exvel = shipdef->linThrust[ShipType::THRUSTER_FORWARD] / (shipdef->fuelTankMass * shipdef->thrusterFuelUse * 10 * 1e6); fprintf(pStatFile, "%s,%s,%.1f,%.1f,%.1f,%.3f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%f,%.1f\n", shipdef->name.c_str(), shipdef->lmrModelName.c_str(), hullmass, capacity, fakevol, rescale, xsize, ysize, zsize, acc1, acc2, acc3, acc4, acca, exvel); delete collMesh; } fclose(pStatFile); } #endif luaConsole = new LuaConsole(10); KeyBindings::toggleLuaConsole.onPress.connect(sigc::ptr_fun(&Pi::ToggleLuaConsole)); gameMenuView = new GameMenuView(); config->Save(); }