diff --git a/src/xenia/kernel/kernel_state.cc b/src/xenia/kernel/kernel_state.cc index 565206faa..1055f6d5f 100644 --- a/src/xenia/kernel/kernel_state.cc +++ b/src/xenia/kernel/kernel_state.cc @@ -48,7 +48,8 @@ KernelState::KernelState(Emulator* emulator) memory_(emulator->memory()), object_table_(nullptr), has_notified_startup_(false), - process_type_(X_PROCTYPE_USER) { + process_type_(X_PROCTYPE_USER), + process_info_block_address_(0) { processor_ = emulator->processor(); file_system_ = emulator->file_system(); @@ -66,12 +67,29 @@ KernelState::KernelState(Emulator* emulator) assert_null(shared_kernel_state_); shared_kernel_state_ = this; + process_info_block_address_ = memory_->SystemHeapAlloc(0x60); + auto pib = + memory_->TranslateVirtual(process_info_block_address_); + // TODO(benvanik): figure out what this list is. + pib->unk_04 = pib->unk_08 = 0; + pib->unk_0C = 0x0000007F; + pib->unk_10 = 0x001F0000; + pib->thread_count = 0; + pib->unk_1B = 0x06; + pib->kernel_stack_size = 16 * 1024; + // TODO(benvanik): figure out what this list is. + pib->unk_54 = pib->unk_58 = 0; + apps::RegisterApps(this, app_manager_.get()); } KernelState::~KernelState() { SetExecutableModule(nullptr); + if (process_info_block_address_) { + memory_->SystemHeapFree(process_info_block_address_); + } + executable_module_.reset(); user_modules_.clear(); kernel_modules_.clear(); @@ -95,6 +113,18 @@ uint32_t KernelState::title_id() const { return executable_module_->xex_header()->execution_info.title_id; } +uint32_t KernelState::process_type() const { + auto pib = + memory_->TranslateVirtual(process_info_block_address_); + return pib->process_type; +} + +void KernelState::set_process_type(uint32_t value) { + auto pib = + memory_->TranslateVirtual(process_info_block_address_); + pib->process_type = uint8_t(value); +} + void KernelState::RegisterModule(XModule* module) {} void KernelState::UnregisterModule(XModule* module) {} @@ -148,6 +178,15 @@ void KernelState::SetExecutableModule(object_ref module) { return; } executable_module_ = std::move(module); + + auto header = executable_module_->xex_header(); + if (header) { + auto pib = memory_->TranslateVirtual( + process_info_block_address_); + pib->tls_data_size = header->tls_info.data_size; + pib->tls_raw_data_size = header->tls_info.raw_data_size; + pib->tls_slot_size = header->tls_info.slot_count * 4; + } } void KernelState::LoadKernelModule(object_ref kernel_module) { @@ -209,6 +248,10 @@ object_ref KernelState::LoadUserModule(const char* raw_name) { void KernelState::RegisterThread(XThread* thread) { std::lock_guard lock(object_mutex_); threads_by_id_[thread->thread_id()] = thread; + + auto pib = + memory_->TranslateVirtual(process_info_block_address_); + pib->thread_count = pib->thread_count + 1; } void KernelState::UnregisterThread(XThread* thread) { @@ -217,6 +260,10 @@ void KernelState::UnregisterThread(XThread* thread) { if (it != threads_by_id_.end()) { threads_by_id_.erase(it); } + + auto pib = + memory_->TranslateVirtual(process_info_block_address_); + pib->thread_count = pib->thread_count - 1; } void KernelState::OnThreadExecute(XThread* thread) { diff --git a/src/xenia/kernel/kernel_state.h b/src/xenia/kernel/kernel_state.h index dd4bb9181..c9dadb998 100644 --- a/src/xenia/kernel/kernel_state.h +++ b/src/xenia/kernel/kernel_state.h @@ -44,6 +44,31 @@ class XNotifyListener; class XThread; class XUserModule; +struct ProcessInfoBlock { + xe::be unk_00; + xe::be unk_04; // blink + xe::be unk_08; // flink + xe::be unk_0C; + xe::be unk_10; + xe::be thread_count; + xe::be unk_18; + xe::be unk_19; + xe::be unk_1A; + xe::be unk_1B; + xe::be kernel_stack_size; + xe::be unk_20; + xe::be tls_data_size; + xe::be tls_raw_data_size; + xe::be tls_slot_size; + xe::be unk_2E; + xe::be process_type; + xe::be bitmap[0x20 / 4]; + xe::be unk_50; + xe::be unk_54; // blink + xe::be unk_58; // flink + xe::be unk_5C; +}; + class KernelState { public: KernelState(Emulator* emulator); @@ -67,8 +92,11 @@ class KernelState { ObjectTable* object_table() const { return object_table_; } xe::recursive_mutex& object_mutex() { return object_mutex_; } - uint32_t process_type() const { return process_type_; } - void set_process_type(uint32_t value) { process_type_ = value; } + uint32_t process_type() const; + void set_process_type(uint32_t value); + uint32_t process_info_block_address() const { + return process_info_block_address_; + } void RegisterModule(XModule* module); void UnregisterModule(XModule* module); @@ -126,6 +154,8 @@ class KernelState { std::vector> kernel_modules_; std::vector> user_modules_; + uint32_t process_info_block_address_; + friend class XObject; }; diff --git a/src/xenia/kernel/objects/xthread.cc b/src/xenia/kernel/objects/xthread.cc index 9ecca9cb8..426b036c0 100644 --- a/src/xenia/kernel/objects/xthread.cc +++ b/src/xenia/kernel/objects/xthread.cc @@ -253,6 +253,8 @@ X_STATUS XThread::Create() { xe::store_and_swap(p + 0x078, thread_state_address_ + 0x074); xe::store_and_swap(p + 0x07C, thread_state_address_ + 0x07C); xe::store_and_swap(p + 0x080, thread_state_address_ + 0x07C); + xe::store_and_swap(p + 0x084, + kernel_state_->process_info_block_address()); xe::store_and_swap(p + 0x08B, 1); // D4 = APC // FC = semaphore (ptr, 0, 2)