| 580 | } |
| 581 | |
| 582 | void Game_Config::LoadFromStream(Filesystem_Stream::InputStream& is) { |
| 583 | lcf::INIReader ini(is); |
| 584 | |
| 585 | if (ini.ParseError()) { |
| 586 | Output::Debug("Failed to parse ini config file {}", is.GetName()); |
| 587 | return; |
| 588 | } |
| 589 | |
| 590 | /** VIDEO SECTION */ |
| 591 | video.vsync.FromIni(ini); |
| 592 | video.fullscreen.FromIni(ini); |
| 593 | video.fps.FromIni(ini); |
| 594 | video.fps_limit.FromIni(ini); |
| 595 | video.window_zoom.FromIni(ini); |
| 596 | video.scaling_mode.FromIni(ini); |
| 597 | video.stretch.FromIni(ini); |
| 598 | video.touch_ui.FromIni(ini); |
| 599 | video.pause_when_focus_lost.FromIni(ini); |
| 600 | video.game_resolution.FromIni(ini); |
| 601 | |
| 602 | if (ini.HasValue("Video", "WindowX") && ini.HasValue("Video", "WindowY") && ini.HasValue("Video", "WindowWidth") && ini.HasValue("Video", "WindowHeight")) { |
| 603 | video.window_x.FromIni(ini); |
| 604 | video.window_y.FromIni(ini); |
| 605 | video.window_width.FromIni(ini); |
| 606 | video.window_height.FromIni(ini); |
| 607 | } |
| 608 | |
| 609 | /** AUDIO SECTION */ |
| 610 | audio.music_volume.FromIni(ini); |
| 611 | audio.sound_volume.FromIni(ini); |
| 612 | audio.fluidsynth_midi.FromIni(ini); |
| 613 | audio.wildmidi_midi.FromIni(ini); |
| 614 | audio.native_midi.FromIni(ini); |
| 615 | audio.soundfont.FromIni(ini); |
| 616 | |
| 617 | /** INPUT SECTION */ |
| 618 | input.buttons = Input::GetDefaultButtonMappings(); |
| 619 | auto& mappings = input.buttons; |
| 620 | |
| 621 | for (int i = 0; i < Input::BUTTON_COUNT; ++i) { |
| 622 | auto button = static_cast<Input::InputButton>(i); |
| 623 | |
| 624 | auto name = Input::kInputButtonNames.tag(button); |
| 625 | if (ini.HasValue("input", name)) { |
| 626 | auto values = ini.GetString("input", name, ""); |
| 627 | mappings.RemoveAll(button); |
| 628 | |
| 629 | auto keys = Utils::Tokenize(values, [](char32_t c) { return c == ','; }); |
| 630 | |
| 631 | // When it is a protected (important) button with zero mappings keep the default |
| 632 | // For all other buttons having no mapping is fine |
| 633 | bool has_mapping = false; |
| 634 | if (Input::IsProtectedButton(button)) { |
| 635 | // Check for protected (important) buttons if they have more than zero mappings |
| 636 | for (const auto& key: keys) { |
| 637 | Input::Keys::InputKey k; |
| 638 | if (Input::Keys::kInputKeyNames.etag(key.c_str(), k)) { |
| 639 | has_mapping = true; |