diff --git a/rpcs3/Emu/Cell/lv2/sys_fs.cpp b/rpcs3/Emu/Cell/lv2/sys_fs.cpp index da5b959cd8..9bac3963c9 100644 --- a/rpcs3/Emu/Cell/lv2/sys_fs.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_fs.cpp @@ -1649,7 +1649,10 @@ error_code sys_fs_fcntl(ppu_thread& ppu, u32 fd, u32 op, vm::ptr _arg, u32 case 0xc0000007: // cellFsArcadeHddSerialNumber { - break; + const auto arg = vm::static_ptr_cast(_arg); + // TODO populate arg-> unk1+2 + arg->out_code = CELL_OK; + return CELL_OK; } case 0xc0000008: // cellFsSetDefaultContainer, cellFsSetIoBuffer, cellFsSetIoBufferFromDefaultContainer @@ -1657,9 +1660,35 @@ error_code sys_fs_fcntl(ppu_thread& ppu, u32 fd, u32 op, vm::ptr _arg, u32 break; } - case 0xc0000015: // Unknown + case 0xc0000015: // USB Vid/Pid lookup - Used by arcade games on dev_usbXXX { - break; + const auto arg = vm::static_ptr_cast(_arg); + + if (arg->size != 0x20u) + { + sys_fs.error("sys_fs_fcntl(0xc0000015): invalid size (0x%x)", arg->size); + break; + } + + if (arg->_x4 != 0x10u || arg->_x8 != 0x18u) + { + sys_fs.error("sys_fs_fcntl(0xc0000015): invalid args (0x%x, 0x%x)", arg->_x4, arg->_x8); + break; + } + + std::string_view vpath{ arg->name.get_ptr(), arg->name_size }; + if (!vpath.starts_with("/dev_usb"sv)) + { + arg->out_code = CELL_ENOTSUP; + break; + } + + // TODO hook up to config for dev_usb + // arg->vendorID = 0x0000; + // arg->productID = 0x0000; + + arg->out_code = CELL_OK; + return CELL_OK; } case 0xc0000016: // ps2disc_8160A811 @@ -1672,6 +1701,38 @@ error_code sys_fs_fcntl(ppu_thread& ppu, u32 fd, u32 op, vm::ptr _arg, u32 break; } + case 0xc000001c: // USB Vid/Pid/Serial lookup + { + const auto arg = vm::static_ptr_cast(_arg); + + if (arg->size != 0x60u) + { + sys_fs.error("sys_fs_fcntl(0xc000001c): invalid size (0x%x)", arg->size); + break; + } + + if (arg->_x4 != 0x10u || arg->_x8 != 0x18u) + { + sys_fs.error("sys_fs_fcntl(0xc000001c): invalid args (0x%x, 0x%x)", arg->_x4, arg->_x8); + break; + } + + std::string_view vpath{ arg->name.get_ptr(), arg->name_size }; + if (!vpath.starts_with("/dev_usb"sv)) + { + arg->out_code = CELL_ENOTSUP; + break; + } + + // TODO hook up to config for dev_usb + // arg->vendorID = 0x0000; + // arg->productID = 0x0000; + // arg->serial = "blabla"; // String needs to be encoded to utf-16 BE + + arg->out_code = CELL_OK; + return CELL_OK; + } + case 0xc0000021: // 9FDBBA89 { break; diff --git a/rpcs3/Emu/Cell/lv2/sys_fs.h b/rpcs3/Emu/Cell/lv2/sys_fs.h index 7399725ad3..ee8ebda2d4 100644 --- a/rpcs3/Emu/Cell/lv2/sys_fs.h +++ b/rpcs3/Emu/Cell/lv2/sys_fs.h @@ -435,6 +435,50 @@ struct lv2_file_c0000006 : lv2_file_op CHECK_SIZE(lv2_file_c0000006, 0x20); +struct lv2_file_c000007 : lv2_file_op +{ + be_t out_code; + vm::bcptr name; + be_t name_size; // 0x14 + vm::bptr unk1; + be_t unk1_size; //0x41 + vm::bptr unk2; + be_t unk2_size; //0x21 +}; + +CHECK_SIZE(lv2_file_c000007, 0x1c); + +struct lv2_file_c0000015 : lv2_file_op +{ + be_t size; // 0x20 + be_t _x4; // 0x10 + be_t _x8; // 0x18 - offset of out_code + be_t name_size; + vm::bcptr name; + be_t _x14; // + be_t vendorID; + be_t productID; + be_t out_code; // set to 0 +}; + +CHECK_SIZE(lv2_file_c0000015, 0x20); + +struct lv2_file_c000001c : lv2_file_op +{ + be_t size; // 0x20 + be_t _x4; // 0x10 + be_t _x8; // 0x18 - offset of out_code + be_t name_size; + vm::bcptr name; + be_t unk1; + be_t vendorID; + be_t productID; + be_t out_code; // set to 0 + u8 serial[64]; +}; + +CHECK_SIZE(lv2_file_c000001c, 0x60); + // sys_fs_fcntl: cellFsAllocateFileAreaWithoutZeroFill struct lv2_file_e0000017 : lv2_file_op {