diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_memory.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_memory.cc index 37ca7c620..e756fa341 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_memory.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_memory.cc @@ -444,13 +444,30 @@ SHIM_CALL MmQueryStatistics_shim(PPCContext* ppc_context, // this won't work :/ stats->size = size; - stats->total_physical_pages = 0x00020000; + stats->total_physical_pages = 0x00020000; // 512mb / 4kb pages stats->kernel_pages = 0x00000300; - stats->title.available_pages = 0x00013300; - stats->title.total_virtual_memory_bytes = 0x2FFF0000; - stats->title.reserved_virtual_memory_bytes = 0x00160000; - stats->title.physical_pages = 0x00001000; + // TODO(gibbed): maybe use LookupHeapByType instead? + auto physA = kernel_memory()->LookupHeap(0xA0000000); + auto physC = kernel_memory()->LookupHeap(0xC0000000); + auto physE = kernel_memory()->LookupHeap(0xE0000000); + assert_not_null(physA); + assert_not_null(physC); + assert_not_null(physE); + + uint32_t available_pages = 0; + available_pages += + (physA->GetUnreservedPageCount() * physA->page_size()) / 4096; + available_pages += + (physC->GetUnreservedPageCount() * physC->page_size()) / 4096; + available_pages += + (physE->GetUnreservedPageCount() * physE->page_size()) / 4096; + + stats->title.available_pages = available_pages; + stats->title.total_virtual_memory_bytes = 0x2FFF0000; // TODO(gibbed): FIXME + stats->title.reserved_virtual_memory_bytes = + 0x00160000; // TODO(gibbed): FIXME + stats->title.physical_pages = 0x00001000; // TODO(gibbed): FIXME stats->title.pool_pages = 0x00000010; stats->title.stack_pages = 0x00000100; stats->title.image_pages = 0x00000100; diff --git a/src/xenia/memory.cc b/src/xenia/memory.cc index 8c909e887..b7174102c 100644 --- a/src/xenia/memory.cc +++ b/src/xenia/memory.cc @@ -551,6 +551,32 @@ void BaseHeap::DumpMap() { } } +uint32_t BaseHeap::GetUnreservedPageCount() { + auto global_lock = global_critical_region_.Acquire(); + uint32_t count = 0; + bool is_empty_span = false; + uint32_t empty_span_start = 0; + uint32_t size = uint32_t(page_table_.size()); + for (uint32_t i = 0; i < size; ++i) { + auto& page = page_table_[i]; + if (!page.state) { + if (!is_empty_span) { + is_empty_span = true; + empty_span_start = i; + } + continue; + } + if (is_empty_span) { + count += i - empty_span_start; + } + i += page.region_page_count - 1; + } + if (is_empty_span) { + count += size - empty_span_start; + } + return count; +} + bool BaseHeap::Save(ByteStream* stream) { XELOGD("Heap %.8X-%.8X", heap_base_, heap_base_ + heap_size_); diff --git a/src/xenia/memory.h b/src/xenia/memory.h index e27976de2..67b519e3c 100644 --- a/src/xenia/memory.h +++ b/src/xenia/memory.h @@ -101,6 +101,8 @@ class BaseHeap { // Dumps information about all allocations within the heap to the log. void DumpMap(); + uint32_t GetUnreservedPageCount(); + // Allocates pages with the given properties and allocation strategy. // This can reserve and commit the pages as well as set protection modes. // This will fail if not enough contiguous pages can be found.