diff --git a/src/xenia/kernel/util/object_table.cc b/src/xenia/kernel/util/object_table.cc index 69967ff69..df881e3a1 100644 --- a/src/xenia/kernel/util/object_table.cc +++ b/src/xenia/kernel/util/object_table.cc @@ -112,8 +112,7 @@ X_STATUS ObjectTable::AddHandle(XObject* object, X_HANDLE* out_handle) { ObjectTableEntry& entry = table_[slot]; entry.object = object; entry.handle_ref_count = 1; - - handle = slot << 2; + handle = XObject::kHandleBase + (slot << 2); object->handles().push_back(handle); // Retain so long as the object is in the table. @@ -251,7 +250,7 @@ ObjectTable::ObjectTableEntry* ObjectTable::LookupTable(X_HANDLE handle) { auto global_lock = global_critical_region_.Acquire(); // Lower 2 bits are ignored. - uint32_t slot = handle >> 2; + uint32_t slot = GetHandleSlot(handle); if (slot <= table_capacity_) { return &table_[slot]; } @@ -279,7 +278,7 @@ XObject* ObjectTable::LookupObject(X_HANDLE handle, bool already_locked) { } // Lower 2 bits are ignored. - uint32_t slot = handle >> 2; + uint32_t slot = GetHandleSlot(handle); // Verify slot. if (slot < table_capacity_) { @@ -390,7 +389,7 @@ bool ObjectTable::Restore(ByteStream* stream) { } X_STATUS ObjectTable::RestoreHandle(X_HANDLE handle, XObject* object) { - uint32_t slot = handle >> 2; + uint32_t slot = GetHandleSlot(handle); assert_true(table_capacity_ >= slot); if (table_capacity_ >= slot) { diff --git a/src/xenia/kernel/util/object_table.h b/src/xenia/kernel/util/object_table.h index 5110bc44e..93c98111c 100644 --- a/src/xenia/kernel/util/object_table.h +++ b/src/xenia/kernel/util/object_table.h @@ -92,6 +92,9 @@ class ObjectTable { std::vector>* results); X_HANDLE TranslateHandle(X_HANDLE handle); + static constexpr uint32_t GetHandleSlot(X_HANDLE handle) { + return (handle - XObject::kHandleBase) >> 2; + } X_STATUS FindFreeSlot(uint32_t* out_slot); bool Resize(uint32_t new_capacity); diff --git a/src/xenia/kernel/xobject.h b/src/xenia/kernel/xobject.h index 23ab38d6e..af07a790b 100644 --- a/src/xenia/kernel/xobject.h +++ b/src/xenia/kernel/xobject.h @@ -109,6 +109,13 @@ struct X_OBJECT_TYPE { class XObject { public: + // Burnout Paradise needs proper handle value for certain calculations + // It gets handle value from TLS (without base handle value is 0x88) + // and substract 0xF8000088. Without base we're receiving wrong address + // Instead of receiving address that starts with 0x82... we're receiving + // one with 0x8A... which causes crash + static constexpr uint32_t kHandleBase = 0xF8000000; + enum Type { kTypeUndefined, kTypeEnumerator,