/** ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ #include "xenia/kernel/xboxkrnl/xboxkrnl_xconfig.h" #include "xenia/base/logging.h" #include "xenia/cpu/processor.h" #include "xenia/kernel/kernel_state.h" #include "xenia/kernel/user_module.h" #include "xenia/kernel/util/shim_utils.h" #include "xenia/kernel/xboxkrnl/xboxkrnl_private.h" #include "xenia/xbox.h" DEFINE_int32(user_language, 1, "User language ID.\n" " 1=en 2=ja 3=de 4=fr 5=es 6=it 7=ko 8=zh\n" " 9=pt 11=pl 12=ru 13=sv 14=tr 15=nb 16=nl 17=zh", "XConfig"); DEFINE_int32(user_country, 103, "User country ID.\n" " 1=AE 2=AL 3=AM 4=AR 5=AT 6=AU 7=AZ 8=BE 9=BG\n" " 10=BH 11=BN 12=BO 13=BR 14=BY 15=BZ 16=CA 18=CH 19=CL\n" " 20=CN 21=CO 22=CR 23=CZ 24=DE 25=DK 26=DO 27=DZ 28=EC\n" " 29=EE 30=EG 31=ES 32=FI 33=FO 34=FR 35=GB 36=GE 37=GR\n" " 38=GT 39=HK 40=HN 41=HR 42=HU 43=ID 44=IE 45=IL 46=IN\n" " 47=IQ 48=IR 49=IS 50=IT 51=JM 52=JO 53=JP 54=KE 55=KG\n" " 56=KR 57=KW 58=KZ 59=LB 60=LI 61=LT 62=LU 63=LV 64=LY\n" " 65=MA 66=MC 67=MK 68=MN 69=MO 70=MV 71=MX 72=MY 73=NI\n" " 74=NL 75=NO 76=NZ 77=OM 78=PA 79=PE 80=PH 81=PK 82=PL\n" " 83=PR 84=PT 85=PY 86=QA 87=RO 88=RU 89=SA 90=SE 91=SG\n" " 92=SI 93=SK 95=SV 96=SY 97=TH 98=TN 99=TR 100=TT 101=TW\n" " 102=UA 103=US 104=UY 105=UZ 106=VE 107=VN 108=YE 109=ZA\n", "XConfig"); DEFINE_uint32( audio_flag, 0x00010001, "Audio Mode Analog.\n" " 0x00000001 = Dolby Pro Logic\n" " 0x00000002 = Analog Mono\n" "Audio Mode Digital.\n" " 0x00000000 = Digital Stereo (choose one of the above by itself)\n" " 0x00010000 = Dolby Digital\n" " 0x00030000 = Dolby Digital with WMA PRO\n" "Special Flags.\n" " 0x00000003 = Stereo Bypass\n" " 0x80000000 = Low Latency\n" " This Config requires you to pair an analog and digitial flag together\n" " while digital stereo only requires an analog flag. Bonus flags are\n" " optional. Ex) 0x00010001\n", "XConfig"); DECLARE_bool(widescreen); DECLARE_bool(use_50Hz_mode); DECLARE_int32(video_standard); DECLARE_uint32(internal_display_resolution); namespace xe { namespace kernel { namespace xboxkrnl { X_STATUS xeExGetXConfigSetting(X_CONFIG_CATEGORY category, uint16_t setting, void* buffer, uint16_t buffer_size, uint16_t* required_size) { uint16_t setting_size = 0; alignas(uint32_t) uint8_t value[4]; // TODO(benvanik): have real structs here that just get copied from. // https://free60project.github.io/wiki/XConfig.html // https://github.com/oukiar/freestyledash/blob/master/Freestyle/Tools/Generic/ExConfig.h switch (category) { case XCONFIG_SECURED_CATEGORY: switch (setting) { case 0x0002: // XCONFIG_SECURED_AV_REGION setting_size = 4; switch (cvars::video_standard) { case 1: // NTSCM xe::store_and_swap(value, X_AV_REGION::NTSCM); break; case 2: // NTSCJ xe::store_and_swap(value, X_AV_REGION::NTSCJ); break; case 3: // PAL xe::store_and_swap(value, cvars::use_50Hz_mode ? X_AV_REGION::PAL_50 : X_AV_REGION::PAL); break; default: xe::store_and_swap(value, 0); break; } break; default: XELOGW( "An unimplemented setting 0x{:04X} in XCONFIG SECURED CATEGORY", static_cast(setting)); assert_unhandled_case(setting); return X_STATUS_INVALID_PARAMETER_2; } break; case XCONFIG_USER_CATEGORY: switch (setting) { case 0x0001: // XCONFIG_USER_TIME_ZONE_BIAS case 0x0002: // XCONFIG_USER_TIME_ZONE_STD_NAME case 0x0003: // XCONFIG_USER_TIME_ZONE_DLT_NAME case 0x0004: // XCONFIG_USER_TIME_ZONE_STD_DATE case 0x0005: // XCONFIG_USER_TIME_ZONE_DLT_DATE case 0x0006: // XCONFIG_USER_TIME_ZONE_STD_BIAS case 0x0007: // XCONFIG_USER_TIME_ZONE_DLT_BIAS setting_size = 4; // TODO(benvanik): get this value. xe::store_and_swap(value, 0); break; case 0x0009: // XCONFIG_USER_LANGUAGE setting_size = 4; xe::store_and_swap(value, cvars::user_language); break; case 0x000A: // XCONFIG_USER_VIDEO_FLAGS setting_size = 4; xe::store_and_swap(value, cvars::widescreen ? X_VIDEO_FLAGS::Widescreen : X_VIDEO_FLAGS::RatioNormal); break; case 0x000B: // XCONFIG_USER_AUDIO_FLAGS setting_size = 4; xe::store_and_swap(value, cvars::audio_flag); break; case 0x000C: // XCONFIG_USER_RETAIL_FLAGS setting_size = 4; // TODO(benvanik): get this value. xe::store_and_swap(value, 0x40); break; case 0x000E: // XCONFIG_USER_COUNTRY setting_size = 1; value[0] = static_cast(cvars::user_country); break; case 0x000F: // XCONFIG_USER_PC_FLAGS setting_size = 1; value[0] = static_cast(0); break; case 0x0014: // XCONFIG_USER_AV_COMPONENT_SCREENSZ setting_size = 4; // int16_t* value[2]; if (XHDTVResolution.find(cvars::internal_display_resolution) != XHDTVResolution.cend()) { xe::store_and_swap( value, XHDTVResolution.at(cvars::internal_display_resolution)); } else { XELOGW("Resolution not supported for AV Component"); xe::store_and_swap(value, 0); } break; case 0x0015: // XCONFIG_USER_AV_VGA_SCREENSZ setting_size = 4; // int16_t* value[2]; if (XVGAResolution.find(cvars::internal_display_resolution) != XVGAResolution.cend()) { xe::store_and_swap( value, XVGAResolution.at(cvars::internal_display_resolution)); } else { XELOGW("Resolution not supported for VGA"); xe::store_and_swap(value, 0); } break; case 0x001B: // XCONFIG_USER_PC_HINT setting_size = 1; value[0] = static_cast(0); break; case 0x0029: // XCONFIG_USER_VIDEO_OUTPUT_BLACK_LEVELS setting_size = 4; xe::store_and_swap(value, X_BLACK_LEVEL::LevelNormal); break; default: XELOGW("An unimplemented setting 0x{:04X} in XCONFIG USER CATEGORY", static_cast(setting)); assert_unhandled_case(setting); return X_STATUS_INVALID_PARAMETER_2; } break; case XCONFIG_CONSOLE_CATEGORY: switch (setting) { case 0x0001: // XCONFIG_CONSOLE_SCREENSAVER setting_size = 2; xe::store_and_swap(value, X_SCREENSAVER::ScreensaverOff); break; case 0x0002: // XCONFIG_CONSOLE_AUTO_SHUTDOWN setting_size = 2; xe::store_and_swap(value, X_AUTO_SHUTDOWN::AutoShutdownOff); break; case 0x0004: // XCONFIG_CONSOLE_CAMERA_SETTINGS // Camera Flags are added together and last byte is always 0x1 setting_size = 4; xe::store_and_swap(value, X_CAMERA_FLAGS::AutoAll); break; case 0x0007: // XCONFIG_CONSOLE_KEYBOARD_LAYOUT setting_size = 2; xe::store_and_swap(value, X_KEYBOARD_LAYOUT::KeyboardDefault); break; default: XELOGW( "An unimplemented setting 0x{:04X} in XCONFIG CONSOLE CATEGORY", static_cast(setting)); assert_unhandled_case(setting); return X_STATUS_INVALID_PARAMETER_2; } break; default: XELOGW("An unimplemented category 0x{:04X}", static_cast(category)); assert_unhandled_case(category); return X_STATUS_INVALID_PARAMETER_1; } if (buffer) { if (buffer_size < setting_size) { return X_STATUS_BUFFER_TOO_SMALL; } std::memcpy(buffer, value, setting_size); } else { if (buffer_size) { return X_STATUS_INVALID_PARAMETER_3; } } if (required_size) { *required_size = setting_size; } return X_STATUS_SUCCESS; } dword_result_t ExGetXConfigSetting_entry(word_t category, word_t setting, lpvoid_t buffer_ptr, word_t buffer_size, lpword_t required_size_ptr) { uint16_t required_size = 0; X_STATUS result = xeExGetXConfigSetting(static_cast(category.value()), setting, buffer_ptr, buffer_size, &required_size); if (required_size_ptr) { *required_size_ptr = required_size; } return result; } DECLARE_XBOXKRNL_EXPORT1(ExGetXConfigSetting, kModules, kImplemented); dword_result_t ExSetXConfigSetting_entry(word_t category, word_t setting, lpvoid_t buffer_ptr, dword_t buffer_size) { /* Notes: Handles settings the only have a single flag/value like XCONFIG_USER_VIDEO_FLAGS to swap */ XELOGI("ExSetXConfigSetting: category: 0X{:04x}, setting: 0X{:04x}", static_cast(category), static_cast(setting)); return X_STATUS_SUCCESS; } DECLARE_XBOXKRNL_EXPORT1(ExSetXConfigSetting, kModules, kStub); dword_result_t ExReadModifyWriteXConfigSettingUlong_entry(word_t category, word_t setting, dword_t bit_affected, dword_t flag) { /* Notes: Handles settings with multiple flags like XCONFIG_USER_RETAIL_FLAGS and XCONFIG_CONSOLE_RETAIL_EX_FLAGS */ XELOGI( "ExReadModifyWriteXConfigSettingUlong: category: 0x{:04x}, setting: " "{:04x}, changed bits: 0X{:08x}, setting flag 0X{:08x}", static_cast(category), static_cast(setting), static_cast(bit_affected), static_cast(flag)); return X_STATUS_SUCCESS; } DECLARE_XBOXKRNL_EXPORT1(ExReadModifyWriteXConfigSettingUlong, kModules, kStub); } // namespace xboxkrnl } // namespace kernel } // namespace xe DECLARE_XBOXKRNL_EMPTY_REGISTER_EXPORTS(XConfig);