#pragma once /** ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** * Copyright 2013 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** * * @modified Tom Clay, 2026 - Adapted for ReXGlue runtime */ #include #include #include namespace rex::system::util { // List is designed for storing pointers to objects in the guest heap. // All values in the list should be assumed to be in big endian. // Pass LIST_ENTRY pointers. // struct MYOBJ { // uint32_t stuff; // LIST_ENTRY list_entry; <-- pass this // ... // } class NativeList { public: NativeList(); explicit NativeList(memory::Memory* memory); void Insert(uint32_t list_entry_ptr); bool IsQueued(uint32_t list_entry_ptr); void Remove(uint32_t list_entry_ptr); uint32_t Shift(); bool HasPending(); uint32_t head() const { return head_; } void set_head(uint32_t head) { head_ = head; } void set_memory(memory::Memory* mem) { memory_ = mem; } private: const uint32_t kInvalidPointer = 0xE0FE0FFF; private: memory::Memory* memory_ = nullptr; uint32_t head_; }; // Guest-memory linked list utilities. // VirtualTranslator is any type with TranslateVirtual(uint32_t) // and HostToGuestVirtual(void*) methods (e.g. memory::Memory*). // Overloads also accept a raw uint32_t guest pointer in place of the // translator when the caller already has the guest address. template X_LIST_ENTRY* XeHostList(uint32_t ptr, VirtualTranslator context) { return context->template TranslateVirtual(ptr); } template uint32_t XeGuestList(X_LIST_ENTRY* ptr, VirtualTranslator context) { return context->HostToGuestVirtual(ptr); } template void XeInitializeListHead(X_LIST_ENTRY* entry, VirtualTranslator context) { if constexpr (std::is_unsigned_v) { entry->blink_ptr = context; entry->flink_ptr = context; } else { uint32_t orig_ptr = XeGuestList(entry, context); entry->blink_ptr = orig_ptr; entry->flink_ptr = orig_ptr; } } template bool XeIsListEmpty(X_LIST_ENTRY* entry, VirtualTranslator context) { return XeHostList(entry->flink_ptr, context) == entry; } template void XeRemoveEntryList(X_LIST_ENTRY* entry, VirtualTranslator context) { uint32_t front = entry->flink_ptr; uint32_t back = entry->blink_ptr; XeHostList(back, context)->flink_ptr = front; XeHostList(front, context)->blink_ptr = back; } template void XeRemoveEntryList(uint32_t entry, VirtualTranslator context) { XeRemoveEntryList(XeHostList(entry, context), context); } template uint32_t XeRemoveHeadList(X_LIST_ENTRY* entry, VirtualTranslator context) { uint32_t result = entry->flink_ptr; XeRemoveEntryList(result, context); return result; } template uint32_t XeRemoveTailList(X_LIST_ENTRY* entry, VirtualTranslator context) { uint32_t result = entry->blink_ptr; XeRemoveEntryList(result, context); return result; } template void XeInsertTailList(X_LIST_ENTRY* list_head, uint32_t list_head_guest, X_LIST_ENTRY* host_entry, uint32_t entry, VirtualTranslator context) { uint32_t old_tail = list_head->blink_ptr; host_entry->flink_ptr = list_head_guest; host_entry->blink_ptr = old_tail; XeHostList(old_tail, context)->flink_ptr = entry; list_head->blink_ptr = entry; } template void XeInsertTailList(uint32_t list_head, uint32_t entry, VirtualTranslator context) { XeInsertTailList(XeHostList(list_head, context), list_head, XeHostList(entry, context), entry, context); } template void XeInsertTailList(X_LIST_ENTRY* list_head, uint32_t entry, VirtualTranslator context) { XeInsertTailList(list_head, XeGuestList(list_head, context), XeHostList(entry, context), entry, context); } template void XeInsertTailList(X_LIST_ENTRY* list_head, X_LIST_ENTRY* entry, VirtualTranslator context) { XeInsertTailList(list_head, XeGuestList(list_head, context), entry, XeGuestList(entry, context), context); } template void XeInsertHeadList(X_LIST_ENTRY* list_head, uint32_t list_head_guest, X_LIST_ENTRY* host_entry, uint32_t entry, VirtualTranslator context) { uint32_t old_list_head_flink = list_head->flink_ptr; host_entry->flink_ptr = old_list_head_flink; host_entry->blink_ptr = list_head_guest; XeHostList(old_list_head_flink, context)->blink_ptr = entry; list_head->flink_ptr = entry; } template void XeInsertHeadList(uint32_t list_head, uint32_t entry, VirtualTranslator context) { XeInsertHeadList(XeHostList(list_head, context), list_head, XeHostList(entry, context), entry, context); } template void XeInsertHeadList(X_LIST_ENTRY* list_head, uint32_t entry, VirtualTranslator context) { XeInsertHeadList(list_head, XeGuestList(list_head, context), XeHostList(entry, context), entry, context); } template void XeInsertHeadList(uint32_t list_head, X_LIST_ENTRY* entry, VirtualTranslator context) { XeInsertHeadList(XeHostList(list_head, context), list_head, entry, XeGuestList(entry, context), context); } template void XeInsertHeadList(X_LIST_ENTRY* list_head, X_LIST_ENTRY* entry, VirtualTranslator context) { XeInsertHeadList(list_head, XeGuestList(list_head, context), entry, XeGuestList(entry, context), context); } // Typed intrusive list built on X_LIST_ENTRY. // TObject is the containing struct, EntryListOffset is offsetof the // X_LIST_ENTRY member within TObject. template struct X_TYPED_LIST : public X_LIST_ENTRY { using this_type = X_TYPED_LIST; static X_LIST_ENTRY* ObjectListEntry(TObject* obj) { return reinterpret_cast( &reinterpret_cast(obj)[static_cast(EntryListOffset)]); } static TObject* ListEntryObject(X_LIST_ENTRY* entry) { return reinterpret_cast( &reinterpret_cast(entry)[-static_cast(EntryListOffset)]); } template struct ForwardIterator { VirtualTranslator vt; uint32_t current_entry; ForwardIterator& operator++() { current_entry = vt->template TranslateVirtual(current_entry)->flink_ptr; return *this; } bool operator!=(uint32_t other_ptr) const { return current_entry != other_ptr; } TObject& operator*() { return *ListEntryObject(vt->template TranslateVirtual(current_entry)); } }; template struct ForwardIteratorBegin { VirtualTranslator vt; this_type* const thiz; ForwardIterator begin() { return ForwardIterator{vt, thiz->flink_ptr}; } uint32_t end() { return vt->HostToGuestVirtual(thiz); } }; template ForwardIteratorBegin IterateForward(VirtualTranslator vt) { return ForwardIteratorBegin{vt, this}; } template void Initialize(VirtualTranslator translator) { XeInitializeListHead(this, translator); } template void InsertHead(TObject* entry, VirtualTranslator translator) { XeInsertHeadList(static_cast(this), ObjectListEntry(entry), translator); } template void InsertTail(TObject* entry, VirtualTranslator translator) { XeInsertTailList(this, ObjectListEntry(entry), translator); } template bool empty(VirtualTranslator vt) const { return vt->template TranslateVirtual(flink_ptr) == this; } template TObject* HeadObject(VirtualTranslator vt) { return ListEntryObject(vt->template TranslateVirtual(flink_ptr)); } template TObject* TailObject(VirtualTranslator vt) { return ListEntryObject(vt->template TranslateVirtual(blink_ptr)); } }; } // namespace rex::system::util