diff --git a/src/xenia/kernel/smc.h b/src/xenia/kernel/smc.h index f423f746a..0fc8d6134 100644 --- a/src/xenia/kernel/smc.h +++ b/src/xenia/kernel/smc.h @@ -57,6 +57,37 @@ enum LED_STATE : uint8_t { ORANGE = 0x88 }; +// https://free60.org/Hardware/Console/SMC_Command_0x01/#query-power-on-type +enum POWERON_TYPE : uint8_t { + POWER_BUTTON = 0x11, + EJECT_BUTTON = 0x12, + RTC_WAKEUP = 0x15, + UNKNOWN_POWERON_1 = 0x16, + REMOTE_POWER_BUTTON = 0x20, + REMOTE_EJECT_BUTTON = 0x21, + REMOTE_X_BUTTON = 0x22, + REMOTE_WIN_BUTTON = 0x24, + HARD_RESET = 0x30, // HalReturnToFirmware(1, 2, or 3) + RESET_CYCLE = 0x31, + UNKNOWN_POWERON_2 = 0x41, + KIOSK = 0x51, + WIRELESS_CONTROLLER_BUTTON = + 0x55, // controller middle button/start button (e.g. Turntable, drums, + // guitar, 360 controller) + GAME_PORT_1 = 0x56, + GAME_PORT_2 = 0x57, + EXPANSION_RESUME = 0x5A, +}; + +// https://free60.org/Hardware/Console/SMC_Command_0x82/ +enum class STANDBY_TYPE : uint16_t { + POWER_OFF = 0x0100, + POWER_OFF_RTC = 0x0132, // verify this + HARD_RESET = 0x0430, // 04 30 ?? + SOFT_RESET = 0x0431, // 04 31 ?? reset_cycle + CLEAR = 0x0433 +}; + // https://free60.org/Hardware/Console/SMC/ enum X_SMC_CMD : uint8_t { POWERON_STATE = 0x1, @@ -109,6 +140,15 @@ struct X_SMC_DATA { union { uint8_t smc_data[15]; + // POWERON_STATE + struct { + uint8_t poweron_state; + uint8_t reserved; // always 00 + uint8_t unk1; + uint8_t unk2; + uint8_t unk3; + } poweron_state; + // QUERY_TEMP_SENSOR struct { X_TEMPERATURE_DATA cpu; @@ -139,11 +179,17 @@ struct X_SMC_DATA { REMOTE_CONTROL ir_address; } ir_address; - // QUERY_TILT_STATE + // QUERY_TILT_SENSOR struct { TILT_STATE tilt_state; } tilt_state; + // SET_STANDBY + struct { + uint16_t standby_state; + uint8_t unkn; + } set_standby; + // POWER_LED_STATE struct { POWER_LED_STATE state; @@ -192,6 +238,7 @@ class SystemManagementController { void SetDriveTray(X_SMC_DATA* smc_message, X_SMC_DATA* smc_response); void SetFanSpeed(X_SMC_DATA* smc_message, X_SMC_DATA* smc_response); void SetIRAddress(X_SMC_DATA* smc_message, X_SMC_DATA* smc_response); + void SetStandby(X_SMC_DATA* smc_message, X_SMC_DATA* smc_response); void SetPowerLed(X_SMC_DATA* smc_message, X_SMC_DATA* smc_response); void SetLedState(X_SMC_DATA* smc_message, X_SMC_DATA* smc_response); diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_hal.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_hal.cc index 80a331e63..f6a3dd71b 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_hal.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_hal.cc @@ -17,16 +17,27 @@ namespace xe { namespace kernel { namespace xboxkrnl { +constexpr std::array FirmwareReentryMessage = { + "hard poweroff", + "hard reset (video error)", + "hard reset (used for dumpwritedump/frozen processor)", + "hard reset", + "power off (hard)", + "power off (nice)", + "Shut off (Lost Settings)", + "Shut off (Frozen Console)", + "Shut off", +}; + void HalReturnToFirmware_entry(dword_t routine) { - // void - // IN FIRMWARE_REENTRY Routine - - // Routine must be 1 'HalRebootRoutine' - assert_true(routine == 1); - // TODO(benvank): diediedie much more gracefully // Not sure how to blast back up the stack in LLVM without exceptions, though. - XELOGE("Game requested shutdown via HalReturnToFirmware"); + const std::string exitMessage = fmt::format( + "Game requested a {} via HalReturnToFirmware", + static_cast(routine) < FirmwareReentryMessage.size() + ? FirmwareReentryMessage[routine] + : fmt::format("Reboot (Routine Code: {})", routine.value())); + XELOGE(exitMessage); exit(0); } DECLARE_XBOXKRNL_EXPORT2(HalReturnToFirmware, kNone, kStub, kImportant); diff --git a/src/xenia/xbox.h b/src/xenia/xbox.h index 6beae4688..d4ff4209e 100644 --- a/src/xenia/xbox.h +++ b/src/xenia/xbox.h @@ -370,6 +370,18 @@ enum : XNotificationID { kXNotificationMsgrUnknown = 0x0C00000E, }; +enum FIRMWARE_REENTRY { + HalHaltRoutine = 0x0, + HalRebootRoutine = 0x1, + HalKdRebootRoutine = 0x2, + HalFatalErrorRebootRoutine = 0x3, + HalResetSMCRoutine = 0x4, + HalPowerDownRoutine = 0x5, + HalRebootQuiesceRoutine = 0x6, + HalForceShutdownRoutine = 0x7, + HalPowerCycleQuiesceRoutine = 0x8, +}; + // https://github.com/CodeAsm/ffplay360/blob/master/Common/XTLOnPC.h struct X_VIDEO_MODE { be display_width;