jak-project/game/overlord/jak2/pages.cpp
Tyler Wilding 5e987cc0e2
jak2: overlord rework (#2544)
Fixes #2545
Fixes #2546
Fixes #2547
Fixes #2548
Fixes #2549
Fixes #2550
Fixes #2551
Fixes #2552
Fixes #2553
Fixes #2554
Fixes #2555
Fixes #2556
Fixes #2557
Fixes #2558
Fixes #2559
Fixes #2560
Fixes #2561
Fixes #2562
Fixes #2563
Fixes #2564
Fixes #2565
Fixes #2567
Fixes #2566
Fixes #2568
Fixes #2569
Fixes #2570
Fixes #2522
Fixes #2571

---------

Co-authored-by: water <awaterford111445@gmail.com>
Co-authored-by: Hat Kid <6624576+Hat-Kid@users.noreply.github.com>
Co-authored-by: ManDude <7569514+ManDude@users.noreply.github.com>
2023-04-29 16:13:57 -04:00

205 lines
6.2 KiB
C++

#include "pages.h"
#include <cstdio>
#include <cstring>
#include "common/util/Assert.h"
#include "game/overlord/jak2/iso_queue.h"
#include "game/sce/iop.h"
using namespace iop;
namespace jak2 {
void InitPagedMemory(PageList* pool, int page_count, int page_size) {
// this is such a hack...
// we assume that we're allocated on the scratchpad, and can jump bump the pointer again.
pool->pages = (Page*)(pool + 1);
pool->page_count = page_count;
pool->page_size = page_size;
ScratchPadMemory = ScratchPadMemory + page_count * sizeof(Page);
int fixed_page_size = page_size;
if (page_size < 0) {
fixed_page_size = page_size + 0x7ff;
}
pool->sector_per_page = fixed_page_size >> 0xb;
pool->free_pages = page_count;
pool->page_memory = nullptr;
uintptr_t addr = (uintptr_t)AllocSysMemory(0, page_count * page_size + 0x100, nullptr);
addr += 0x3f;
addr &= ~uintptr_t(63);
u8* mem = (u8*)addr;
if (mem == 0) {
printf("======================================================================\n");
printf("IOP: pages InitPagedMemory: no memory for pages\n");
printf("======================================================================\n");
ASSERT_NOT_REACHED();
}
Page* page = pool->pages;
pool->page_memory = mem;
if (0 < page_count) {
for (int i = 0; i < page_count; i++) {
page->state = PageState::FREE;
page->buffer = mem;
page->maybe_page_id = i;
page->free_pages = 0;
page->ptr = mem + page_size - 1;
page->next = nullptr;
page->prev = nullptr;
page->end_page_first_only = nullptr;
page++;
mem += page_size;
}
}
}
/*!
* Allocate a list of pages that contain at least size_bytes in total.
*/
Page* AllocPagesBytes(PageList* page_list, u32 size_bytes) {
u32 num_pages = (size_bytes + page_list->page_size - 1) / page_list->page_size;
return AllocPages(page_list, num_pages);
}
/*!
* Allocate a list of pages.
*/
Page* AllocPages(PageList* page_list, u32 num_pages) {
if (page_list->page_count < num_pages) {
printf("======================================================================\n");
printf("IOP: pages AllocPages: %d pages requested %d maximum pages\n", num_pages,
page_list->page_count);
printf("======================================================================\n");
ASSERT_NOT_REACHED();
}
if (page_list->free_pages < num_pages) {
printf("======================================================================\n");
printf("IOP: pages AllocPages: need %d only %d free pages\n", num_pages, page_list->free_pages);
printf("======================================================================\n");
num_pages = page_list->free_pages;
ASSERT_NOT_REACHED(); // added.
}
Page* first_page = nullptr;
if (num_pages == 0) {
first_page = nullptr;
} else {
Page* prev_page = nullptr;
int page_idx_in_page_list = 0;
u32 added_pages = 0;
Page* iter = page_list->pages;
do {
if (iter->state == PageState::FREE) {
added_pages++;
page_list->free_pages = page_list->free_pages + -1;
iter->state = PageState::ALLOCATED_EMPTY;
iter->pages_after_this = num_pages - added_pages;
if (!first_page) {
iter->prev = nullptr;
first_page = iter;
} else {
prev_page->next = iter;
iter->prev = prev_page;
}
iter->end_page_first_only = nullptr;
prev_page = iter;
}
page_idx_in_page_list++;
iter++;
} while ((page_idx_in_page_list < MAX_PAGES_IN_POOL) && (added_pages < num_pages));
prev_page->next = nullptr;
first_page->end_page_first_only = prev_page;
first_page->free_pages = added_pages;
}
return first_page;
}
/*!
* Return the linked list of pages to the page list.
*/
Page* FreePagesList(PageList* page_list, Page* pages) {
if (pages) {
if (pages->prev) {
printf("======================================================================\n");
printf("IOP: pages FreePages: First page %d is not top of list\n", pages->maybe_page_id);
printf("======================================================================\n");
ASSERT_NOT_REACHED();
}
Page* next;
do {
next = pages->next;
pages->prev = nullptr;
pages->next = nullptr;
pages->end_page_first_only = nullptr;
pages->state = PageState::FREE;
page_list->free_pages = page_list->free_pages + 1;
pages = next;
} while (next);
}
return nullptr;
}
/*!
* Free the "top" page (the first one)
*/
Page* StepTopPage(PageList* param_1, Page* top_page) {
Page* result = nullptr;
if (top_page) {
// if we're first, shouldn't have a prev.
if (top_page->prev) {
printf("======================================================================\n");
printf("IOP: pages StepTopPage: Page %d is not top of list\n", top_page->maybe_page_id);
printf("======================================================================\n");
ASSERT_NOT_REACHED();
}
// new top page
result = top_page->next;
if (result) {
// set up new top page.
result->free_pages = top_page->free_pages + -1;
result->prev = nullptr;
result->end_page_first_only = top_page->end_page_first_only;
}
// return to pool
top_page->next = nullptr;
top_page->state = PageState::FREE;
param_1->free_pages = param_1->free_pages + 1;
}
return result;
}
/*!
* Copy bytes from pages
*/
void FromPagesCopy(const Page* page, const u8* page_ptr, u8* dest, int bytes_to_copy) {
Page* next_page;
const auto* page_data_end = page->ptr;
do {
auto n_this_time = (page_data_end - page_ptr) + 1;
do {
while (true) {
if (!bytes_to_copy) {
return;
}
if (n_this_time <= bytes_to_copy)
break;
memcpy(dest, page_ptr, bytes_to_copy);
bytes_to_copy = 0;
}
memcpy(dest, page_ptr, n_this_time);
dest = dest + n_this_time;
next_page = page->next;
bytes_to_copy = bytes_to_copy - n_this_time;
} while (!next_page);
page_ptr = (uint8_t*)next_page->buffer;
page_data_end = next_page->ptr;
page = next_page;
} while (true);
}
} // namespace jak2