diff --git a/rpcs3/Emu/Cell/Modules/cellKb.cpp b/rpcs3/Emu/Cell/Modules/cellKb.cpp index cb9b98ac75..206f06222a 100644 --- a/rpcs3/Emu/Cell/Modules/cellKb.cpp +++ b/rpcs3/Emu/Cell/Modules/cellKb.cpp @@ -35,11 +35,15 @@ error_code cellKbInit(u32 max_connect) { sys_io.warning("cellKbInit(max_connect=%d)", max_connect); - const auto handler = fxm::import(Emu.GetCallbacks().get_kb_handler); + auto handler = fxm::get(); - if (!handler) + if (handler) return CELL_KB_ERROR_ALREADY_INITIALIZED; + if (max_connect == 0 || max_connect > CELL_KB_MAX_KEYBOARDS) + return CELL_KB_ERROR_INVALID_PARAMETER; + + handler = fxm::import(Emu.GetCallbacks().get_kb_handler); handler->Init(std::min(max_connect, 7u)); return CELL_OK; @@ -64,10 +68,23 @@ error_code cellKbClearBuf(u32 port_no) if (!handler) return CELL_KB_ERROR_UNINITIALIZED; - if (port_no >= handler->GetKeyboards().size()) + if (port_no >= CELL_KB_MAX_KEYBOARDS) return CELL_KB_ERROR_INVALID_PARAMETER; - //? + const KbInfo& current_info = handler->GetInfo(); + + if (port_no >= handler->GetKeyboards().size() || current_info.status[port_no] != CELL_KB_STATUS_CONNECTED) + return CELL_KB_ERROR_NO_DEVICE; + + KbData& current_data = handler->GetData(port_no); + current_data.len = 0; + current_data.led = 0; + current_data.mkey = 0; + + for (int i = 0; i < CELL_KB_MAX_KEYCODES; i++) + { + current_data.keycode[i] = 0; + } return CELL_OK; } @@ -127,12 +144,15 @@ error_code cellKbGetInfo(vm::ptr info) if (!handler) return CELL_KB_ERROR_UNINITIALIZED; + if (!info) + return CELL_KB_ERROR_INVALID_PARAMETER; + const KbInfo& current_info = handler->GetInfo(); info->max_connect = current_info.max_connect; info->now_connect = current_info.now_connect; info->info = current_info.info; - for (u32 i=0; istatus[i] = current_info.status[i]; } @@ -149,17 +169,20 @@ error_code cellKbRead(u32 port_no, vm::ptr data) if (!handler) return CELL_KB_ERROR_UNINITIALIZED; - const std::vector& keyboards = handler->GetKeyboards(); - - if (port_no >= keyboards.size()) + if (port_no >= CELL_KB_MAX_KEYBOARDS || !data) return CELL_KB_ERROR_INVALID_PARAMETER; + const KbInfo& current_info = handler->GetInfo(); + + if (port_no >= handler->GetKeyboards().size() || current_info.status[port_no] != CELL_KB_STATUS_CONNECTED) + return CELL_KB_ERROR_NO_DEVICE; + KbData& current_data = handler->GetData(port_no); data->led = current_data.led; data->mkey = current_data.mkey; - data->len = std::min((u32)current_data.len, CELL_KB_MAX_KEYCODES); + data->len = std::min((s32)CELL_KB_MAX_KEYCODES, current_data.len); - for (s32 i=0; ikeycode[i] = current_data.keycode[i]; } @@ -178,17 +201,41 @@ error_code cellKbSetCodeType(u32 port_no, u32 type) if (!handler) return CELL_KB_ERROR_UNINITIALIZED; - if (port_no >= handler->GetKeyboards().size()) + if (port_no >= CELL_KB_MAX_KEYBOARDS || type > CELL_KB_CODETYPE_ASCII) return CELL_KB_ERROR_INVALID_PARAMETER; + if (port_no >= handler->GetKeyboards().size()) + return CELL_OK; + KbConfig& current_config = handler->GetConfig(port_no); current_config.code_type = type; + + // can also return CELL_KB_ERROR_SYS_SETTING_FAILED + return CELL_OK; } error_code cellKbSetLEDStatus(u32 port_no, u8 led) { - sys_io.todo("cellKbSetLEDStatus(port_no=%d, led=%d)", port_no, led); + sys_io.trace("cellKbSetLEDStatus(port_no=%d, led=%d)", port_no, led); + + const auto handler = fxm::get(); + + if (!handler) + return CELL_KB_ERROR_UNINITIALIZED; + + if (port_no >= CELL_KB_MAX_KEYBOARDS) + return CELL_KB_ERROR_INVALID_PARAMETER; + + if (led > 7) + return CELL_KB_ERROR_SYS_SETTING_FAILED; + + if (port_no >= handler->GetKeyboards().size() || handler->GetInfo().status[port_no] != CELL_KB_STATUS_CONNECTED) + return CELL_KB_ERROR_FATAL; + + KbData& current_data = handler->GetData(port_no); + current_data.led = static_cast(led); + return CELL_OK; } @@ -201,12 +248,17 @@ error_code cellKbSetReadMode(u32 port_no, u32 rmode) if (!handler) return CELL_KB_ERROR_UNINITIALIZED; - if (port_no >= handler->GetKeyboards().size()) + if (port_no >= CELL_KB_MAX_KEYBOARDS || rmode > CELL_KB_RMODE_PACKET) return CELL_KB_ERROR_INVALID_PARAMETER; + if (port_no >= handler->GetKeyboards().size()) + return CELL_OK; + KbConfig& current_config = handler->GetConfig(port_no); current_config.read_mode = rmode; + // can also return CELL_KB_ERROR_SYS_SETTING_FAILED + return CELL_OK; } @@ -219,7 +271,16 @@ error_code cellKbGetConfiguration(u32 port_no, vm::ptr config) if (!handler) return CELL_KB_ERROR_UNINITIALIZED; - if (port_no >= handler->GetKeyboards().size()) + if (port_no >= CELL_KB_MAX_KEYBOARDS) + return CELL_KB_ERROR_INVALID_PARAMETER; + + const KbInfo& current_info = handler->GetInfo(); + + if (port_no >= handler->GetKeyboards().size() || current_info.status[port_no] != CELL_KB_STATUS_CONNECTED) + return CELL_KB_ERROR_NO_DEVICE; + + // tests show that config is checked only after the device's status + if (!config) return CELL_KB_ERROR_INVALID_PARAMETER; const KbConfig& current_config = handler->GetConfig(port_no); @@ -227,6 +288,8 @@ error_code cellKbGetConfiguration(u32 port_no, vm::ptr config) config->read_mode = current_config.read_mode; config->code_type = current_config.code_type; + // can also return CELL_KB_ERROR_SYS_SETTING_FAILED + return CELL_OK; } diff --git a/rpcs3/Emu/Cell/Modules/cellKb.h b/rpcs3/Emu/Cell/Modules/cellKb.h index ad4efdc884..1698a0a1e2 100644 --- a/rpcs3/Emu/Cell/Modules/cellKb.h +++ b/rpcs3/Emu/Cell/Modules/cellKb.h @@ -12,7 +12,11 @@ enum CellKbError : u32 CELL_KB_ERROR_SYS_SETTING_FAILED = 0x80121008, }; -static const u32 CELL_KB_MAX_KEYBOARDS = 127; +enum +{ + CELL_KB_MAX_KEYCODES = 62, + CELL_KB_MAX_KEYBOARDS = 127, +}; struct CellKbInfo { @@ -22,8 +26,6 @@ struct CellKbInfo u8 status[CELL_KB_MAX_KEYBOARDS]; }; -static const u32 CELL_KB_MAX_KEYCODES = 62; - struct CellKbData { be_t led;