@@ -1118,10 +1118,35 @@ error_code sceNpBasicSetPresenceDetails2(vm::cptr<SceNpBasicPresenceDetails2> pr
11181118 return CELL_OK;
11191119}
11201120
1121- error_code sceNpBasicSendMessage (vm::cptr<SceNpId> to, vm::cptr<void > data, u32 size)
1121+ u64 sys_time_get_system_time ();
1122+
1123+ error_code acquire_time_slot (u64 * time_array, usz array_size, u64 slot_duration)
11221124{
1123- sceNp.warning (" sceNpBasicSendMessage(to=*0x%x, data=*0x%x, size=%d)" , to, data, size);
1125+ static shared_mutex mutex;
1126+ std::lock_guard lock (mutex);
11241127
1128+ const u64 current_time = sys_time_get_system_time ();
1129+
1130+ for (usz index = 0 ; index < array_size; index++)
1131+ {
1132+ if (time_array[index] == 0 )
1133+ {
1134+ time_array[index] = current_time;
1135+ return CELL_OK;
1136+ }
1137+
1138+ if (current_time > (time_array[index] + slot_duration))
1139+ {
1140+ time_array[index] = current_time;
1141+ return CELL_OK;
1142+ }
1143+ }
1144+
1145+ return SCE_NP_BASIC_ERROR_BUSY;
1146+ }
1147+
1148+ error_code _sceNpBasicSendMessage (vm::cptr<SceNpId> to, vm::cptr<void > data, u32 size, bool rate_limited)
1149+ {
11251150 auto & nph = g_fxo->get <named_thread<np::np_handler>>();
11261151
11271152 if (!nph.is_NP_init )
@@ -1144,6 +1169,22 @@ error_code sceNpBasicSendMessage(vm::cptr<SceNpId> to, vm::cptr<void> data, u32
11441169 return SCE_NP_BASIC_ERROR_EXCEEDS_MAX;
11451170 }
11461171
1172+ if (rate_limited)
1173+ {
1174+ struct sceNpBasicSendMessage_time_slots
1175+ {
1176+ sceNpBasicSendMessage_time_slots (sceNpBasicSendMessage_time_slots&&) = delete ;
1177+ std::array<u64 , 20 > data{};
1178+ };
1179+
1180+ auto & time_slots = g_fxo->get <sceNpBasicSendMessage_time_slots>();
1181+
1182+ if (auto error = acquire_time_slot (time_slots.data .data (), time_slots.data .size (), 60000000 ); error != CELL_OK)
1183+ {
1184+ return error;
1185+ }
1186+ }
1187+
11471188 if (nph.get_psn_status () != SCE_NP_MANAGER_STATUS_ONLINE)
11481189 {
11491190 return not_an_error (SCE_NP_BASIC_ERROR_NOT_CONNECTED);
@@ -1164,6 +1205,19 @@ error_code sceNpBasicSendMessage(vm::cptr<SceNpId> to, vm::cptr<void> data, u32
11641205 return CELL_OK;
11651206}
11661207
1208+ error_code sceNpBasicSendMessage (vm::cptr<SceNpId> to, vm::cptr<void > data, u32 size)
1209+ {
1210+ sceNp.warning (" sceNpBasicSendMessage(to=*0x%x, data=*0x%x, size=%d)" , to, data, size);
1211+ return _sceNpBasicSendMessage (to, data, size, false );
1212+ }
1213+
1214+ // This function is sceNpBasicSendMessage + a rate limiter that will return SCE_NP_BASIC_ERROR_BUSY if it too many messages have been sent
1215+ error_code sceNpBasicLimited_0xEB42E2E6 (vm::cptr<SceNpId> to, vm::cptr<void > data, u32 size)
1216+ {
1217+ sceNp.warning (" sceNpBasicLimited_0xEB42E2E6(to=*0x%x, data=*0x%x, size=%d)" , to, data, size);
1218+ return _sceNpBasicSendMessage (to, data, size, true );
1219+ }
1220+
11671221error_code sceNpBasicSendMessageGui (ppu_thread& ppu, vm::cptr<SceNpBasicMessageDetails> msg, sys_memory_container_t containerId)
11681222{
11691223 sceNp.warning (" sceNpBasicSendMessageGui(msg=*0x%x, containerId=%d)" , msg, containerId);
@@ -7289,6 +7343,11 @@ s32 _Z32_sce_np_sysutil_cxml_prepare_docPN16sysutil_cxmlutil11FixedMemoryERN4cxm
72897343 return CELL_OK;
72907344}
72917345
7346+ DECLARE (ppu_module_manager::sceNpBasicLimited)
7347+ (" sceNpBasicLimited" , []() {
7348+ ppu_module_manager::register_static_function<&sceNpBasicLimited_0xEB42E2E6>(" sceNpBasicLimited" , ppu_select_name (" sceNpBasicLimited" , " sceNpBasicLimited_0xEB42E2E6" ), BIND_FUNC_WITH_BLR (sceNpBasicLimited_0xEB42E2E6, " sceNpBasicLimited" ), 0xEB42E2E6 );
7349+ });
7350+
72927351DECLARE (ppu_module_manager::sceNp)
72937352(" sceNp" , []() {
72947353 REG_FUNC (sceNp, sceNpInit);
0 commit comments