Files
Xenia-Canary/src/xenia/kernel/smc.h
The-Little-Wolf eed4242059 [XAM] - xcontent_type fixes & more
- added unknown smc call
- xcontent_type corrections
- add transfer cable to device type
- Select gamer type in gamercard
2025-10-30 18:37:22 +01:00

268 lines
6.9 KiB
C++

/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2025 Xenia Canary. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef XENIA_KERNEL_SMC_H_
#define XENIA_KERNEL_SMC_H_
#include <array>
#include <cstdint>
#include <functional>
#include <map>
enum X_DVD_DISC_STATE {
NO_DISC,
XBOX_360_GAME_DISC,
XBOX_GAME_DISC,
UNKNOWN_DISC,
MOVIE_DVD,
MOVIE_DVD2,
MOVIE_DVD3,
CD,
MIXED_MEDIA_DISC,
UNKNOWN_DISC2,
};
enum class X_DVD_TRAY_STATE : uint8_t {
OPEN,
UNKNOWN,
CLOSED,
OPENING,
CLOSING
};
enum REMOTE_CONTROL : uint8_t {
MEDIA_REMOTE_BOTH = 0x01,
MEDIA_REMOTE_360 = 0x0F
};
enum TILT_STATE : uint8_t { VERTICAL, HORIZONTAL };
enum POWER_LED_STATE : uint8_t {
POWER_ON = 0x01,
POWER_DEFAULT = 0x02,
POWER_OFF = 0x03,
POWER_BLINK = 0x10
};
enum LED_STATE : uint8_t {
OFF = 0x00,
RED = 0x08,
GREEN = 0x80,
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,
QUERY_RTC = 0x4,
QUERY_TEMP_SENSOR = 0x7,
QUERY_TRAY = 0xA,
QUERY_UNK_0xB =
0xB, // called on start up after VdQueryVideoMode on dash v13599
QUERY_AV_PACK = 0xF,
I2C_READ_WRITE = 0x11,
QUERY_SMC_VERSION = 0x12,
FIFO_TEST = 0x13,
QUERY_IR_ADDRESS = 0x16,
QUERY_TILT_SENSOR = 0x17,
READ_82_INTERRUPTS = 0x1E,
READ_8E_INTERRUPTS = 0x20,
SET_STANDBY = 0x82,
SET_TIME = 0x85,
SET_FAN_ALGORITHM = 0x88,
SET_FAN_SPEED_CPU = 0x89,
SET_DVD_TRAY = 0x8B,
SET_POWER_LED = 0x8C,
SET_AUDIO_MUTE = 0x8D,
ARGON_RELATED = 0x90,
SET_FAN_SPEED_GPU =
0x94, // not present on slim, not used/respected on newer fat
SET_IR_ADDRESS = 0x95,
SET_DVD_TRAY_SECURE = 0x98,
SET_LEDS = 0x99,
SET_RTC_WAKE = 0x9A,
ANA_RELATED = 0x9B,
SET_ASYNC_OPERATION = 0x9C,
SET_82_INTERRUPTS = 0x9D,
SET_9F_INTERRUPTS = 0x9F,
};
struct X_TEMPERATURE_DATA {
uint8_t integer_value_;
uint8_t fractional_value_;
void SetTemp(float celsius_temp) {
const uint16_t value = static_cast<uint16_t>(celsius_temp * 256.0f);
integer_value_ = value & 0xFF;
fractional_value_ = value >> 8;
}
};
struct X_SMC_DATA {
X_SMC_CMD command;
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;
X_TEMPERATURE_DATA gpu;
X_TEMPERATURE_DATA edram;
X_TEMPERATURE_DATA mb;
} temps;
// QUERY_TRAY
struct {
X_DVD_TRAY_STATE state;
} dvd_tray;
// QUERY_AV_PACK
struct {
uint8_t av_pack;
} av_pack;
// QUERY_SMC_VERSION
struct {
uint8_t unk;
uint8_t major;
uint8_t minor;
} smc_version;
// QUERY_IR_ADDRESS
struct {
REMOTE_CONTROL ir_address;
} ir_address;
// 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;
uint8_t animate;
} power_led_state;
// LED_STATE
struct {
LED_STATE state;
uint8_t region; // top_left >> 3 | top_right >> 2 | bottom_left >> 1 |
// bottom_right;
} led_state;
};
};
namespace xe {
namespace kernel {
// SMC = System Management Controller
// https://github.com/landaire/LaunchCode/blob/master/LaunchCode/smc.cpp
// https://github.com/XboxUnity/freestyledash/blob/master/Freestyle/Tools/SMC/smc.cpp
class SystemManagementController {
public:
SystemManagementController();
~SystemManagementController();
std::array<uint8_t, 3> GetSMCVersion() const { return smc_version; }
X_DVD_TRAY_STATE GetTrayState() const { return dvd_tray_state_; }
void SetTrayState(X_DVD_TRAY_STATE state);
void CallCommand(X_SMC_DATA* smc_message, X_SMC_DATA* smc_response);
private:
const std::array<uint8_t, 3> smc_version = {65, 2, 1};
const std::map<uint8_t, uint8_t> av_pack_to_smc_value = {
{0, 0x43}, {3, 0x4F}, {4, 0x13}, {5, 0x0F}, {6, 0x5B}, {8, 0x1F}};
void QueryTemperatureSensor(X_SMC_DATA* smc_message,
X_SMC_DATA* smc_response);
void QueryDriveTraySensor(X_SMC_DATA* smc_message, X_SMC_DATA* smc_response);
void QueryAvPack(X_SMC_DATA* smc_message, X_SMC_DATA* smc_response);
void QuerySmcVersion(X_SMC_DATA* smc_message, X_SMC_DATA* smc_response);
void QueryIRAddress(X_SMC_DATA* smc_message, X_SMC_DATA* smc_response);
void QueryTiltState(X_SMC_DATA* smc_message, X_SMC_DATA* smc_response);
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);
std::map<X_SMC_CMD, std::function<void(X_SMC_DATA* smc_message,
X_SMC_DATA* smc_response)>>
smc_commands_;
X_DVD_TRAY_STATE dvd_tray_state_ = X_DVD_TRAY_STATE::OPEN;
REMOTE_CONTROL ir_address_ = REMOTE_CONTROL::MEDIA_REMOTE_360;
TILT_STATE tilt_state_ = TILT_STATE::VERTICAL;
uint32_t cpu_fan_speed_ = 100;
uint32_t gpu_fan_speed_ = 100;
std::pair<POWER_LED_STATE, uint8_t> power_led_state_ = {
POWER_LED_STATE::POWER_ON, 0x00};
std::pair<LED_STATE, uint8_t> led_state_ = {LED_STATE::GREEN, 0x01};
};
} // namespace kernel
} // namespace xe
#endif