7cba547fc337237a6cedbd2b0883bb6d9c7ccb7a
[pcsx_rearmed.git] / libpcsxcore / lightrec / mem_wiiu.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (C) 2022 Ash Logan <ash@heyquark.com>
4  */
5
6 #include <coreinit/memorymap.h>
7 #include <malloc.h>
8 #include <stdbool.h>
9
10 #include "../memmap.h"
11 #include "../psxhw.h"
12 #include "../psxmem.h"
13 #include "../r3000a.h"
14
15 #include "mem.h"
16
17 void wiiu_clear_cache(void *start, void *end);
18
19 static void* wiiu_mmap(uint32_t requested_va, size_t length, void* backing_mem) {
20         if (length < OS_PAGE_SIZE) length = OS_PAGE_SIZE;
21
22         uint32_t va = OSAllocVirtAddr(requested_va, length, 0);
23         if (!va) return MAP_FAILED;
24
25         BOOL mapped = OSMapMemory(va, OSEffectiveToPhysical((uint32_t)backing_mem),
26                                   length, OS_MAP_MEMORY_READ_WRITE);
27         if (!mapped) {
28                 OSFreeVirtAddr(va, length);
29                 return MAP_FAILED;
30         }
31
32         return (void*)va;
33 }
34
35 static void wiiu_unmap(void* va, size_t length) {
36         if (va == MAP_FAILED) return;
37         OSUnmapMemory((uint32_t)va, length);
38         OSFreeVirtAddr((uint32_t)va, length);
39 }
40
41 static void* psx_mem;
42 static void* psx_parallel;
43 static void* psx_scratch;
44 static void* psx_bios;
45
46 int lightrec_init_mmap(void) {
47         psx_mem      = memalign(OS_PAGE_SIZE, 0x200000);
48         psx_parallel = memalign(OS_PAGE_SIZE, 0x10000);
49         psx_scratch  = memalign(OS_PAGE_SIZE, 0x10000);
50         psx_bios     = memalign(OS_PAGE_SIZE, 0x80000);
51         if (!psx_mem || !psx_parallel || !psx_scratch || !psx_bios)
52                 goto cleanup_allocations;
53
54         uint32_t avail_va;
55         uint32_t avail_va_size;
56         OSGetMapVirtAddrRange(&avail_va, &avail_va_size);
57         if (!avail_va || avail_va_size < 0x20000000)
58                 goto cleanup_allocations;
59
60         // Map 4x ram mirrors
61         int i;
62         for (i = 0; i < 4; i++) {
63                 void* ret = wiiu_mmap(avail_va + 0x200000 * i, 0x200000, psx_mem);
64                 if (ret == MAP_FAILED) break;
65         }
66         if (i != 4) {
67                 for (int i = 0; i < 4; i++)
68                         wiiu_unmap(avail_va + 0x200000 * i, 0x200000);
69                 goto cleanup_allocations;
70         }
71         psxM = (void*)avail_va;
72
73         psxP = wiiu_mmap(avail_va + 0x1f000000, 0x10000, psx_parallel);
74         psxH = wiiu_mmap(avail_va + 0x1f800000, 0x10000, psx_scratch);
75         psxR = wiiu_mmap(avail_va + 0x1fc00000, 0x80000, psx_bios);
76
77         if (psxP == MAP_FAILED || psxH == MAP_FAILED || psxR == MAP_FAILED) {
78                 for (int i = 0; i < 4; i++)
79                         wiiu_unmap(psxM + 0x200000 * i, 0x200000);
80                 wiiu_unmap(psxP, 0x10000);
81                 wiiu_unmap(psxH, 0x10000);
82                 wiiu_unmap(psxR, 0x80000);
83                 goto cleanup_allocations;
84         }
85
86         code_buffer = WUP_RWX_MEM_BASE;
87
88         return 0;
89
90 cleanup_allocations:
91         free(psx_mem);
92         free(psx_parallel);
93         free(psx_scratch);
94         free(psx_bios);
95         return -1;
96 }
97
98 void lightrec_free_mmap(void) {
99         for (int i = 0; i < 4; i++)
100                 wiiu_unmap(psxM + 0x200000 * i, 0x200000);
101         wiiu_unmap(psxP, 0x10000);
102         wiiu_unmap(psxH, 0x10000);
103         wiiu_unmap(psxR, 0x80000);
104         free(psx_mem);
105         free(psx_parallel);
106         free(psx_scratch);
107         free(psx_bios);
108 }
109
110 void lightrec_code_inv(void *ptr, uint32_t len)
111 {
112         wiiu_clear_cache(ptr, (void *)((uintptr_t)ptr + len));
113 }