Skip to content

Commit df07109

Browse files
committed
Add RPL fixes and notice
See devkitPro#388 for more info. Credits go to both Exzap and Crementif for the original PR.
1 parent 6f9a380 commit df07109

3 files changed

Lines changed: 171 additions & 4 deletions

File tree

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
[![Build status](https://github.com/devkitPro/wut/workflows/C%2FC%2B%2B%20CI/badge.svg)](https://github.com/devkitPro/wut/actions?workflow=C%2FC%2B%2B+CI)
22

3+
# Notice
4+
This fork of wut temporarily applies the changes from [PR #388](https://github.com/devkitPro/wut/pull/388) in the upstream repository.
5+
The PR is applied here in order to apply the improved RPL support before it gets merged upstream. Please note that there are still bugs
6+
and limitations that haven't been addressed yet. Credits go to both Exzap and Crementif for the original PR.
7+
8+
Original readme and build instructions below:
9+
310
# wut
411
Let's try to make a Wii U Toolchain / SDK for creating rpx/rpl.
512

libraries/wutcrt/crt0_rpl.s

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,15 @@ __rpl_start:
1717
load:
1818
# Load
1919
bl __init_wut
20-
# rpl files use wutmalloc instead of the custom heap
21-
bl __init_wut_malloc
20+
# rpl files uses a special RPL version of wutmalloc
21+
bl __init_wut_malloc_rpl
22+
bl __init_wut_thread
2223
bl __eabi
2324
lwz 3, 0x8(1)
2425
lwz 4, 0xC(1)
2526
bl rpl_entry
27+
lwz 0, 0x14(1)
28+
mtlr 0
2629
addi 1, 1, 0x10
2730
blr
2831

@@ -32,5 +35,4 @@ unload:
3235
lwz 4, 0xC(1)
3336
bl rpl_entry
3437
addi 1, 1, 0x10
35-
b exit
36-
38+
b exit
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
#include <coreinit/memexpheap.h>
2+
#include <coreinit/memdefaultheap.h>
3+
#include <coreinit/memorymap.h>
4+
#include <coreinit/debug.h>
5+
#include <malloc.h>
6+
#include <string.h>
7+
#include <errno.h>
8+
#include <assert.h>
9+
10+
/**
11+
* A special version of wutmalloc for RPLs.
12+
*
13+
* RPLs can't reliable assume that the main application is using ExpHeap,
14+
* which means that MEMGetSizeForMBlockExpHeap can't be used for realloc.
15+
* This version co-allocates a header alongside the memory to be able to
16+
* reallocate the memory.
17+
*/
18+
void
19+
__init_wut_malloc_rpl(void)
20+
{
21+
}
22+
23+
void
24+
__fini_wut_malloc_rpl(void)
25+
{
26+
}
27+
28+
#define WUT_MALLOC_RPL_CANARY (0x376296a9)
29+
30+
struct wut_alloc_header_rpl
31+
{
32+
uint32_t canary;
33+
size_t size;
34+
size_t offset;
35+
};
36+
37+
static struct wut_alloc_header_rpl *get_alloc_header(const void* ptr)
38+
{
39+
struct wut_alloc_header_rpl *header = (struct wut_alloc_header_rpl*)ptr - 1;
40+
assert(header->canary == WUT_MALLOC_RPL_CANARY);
41+
if(header->canary != WUT_MALLOC_RPL_CANARY)
42+
OSFatal("WUT detected a memory corruption in get_alloc_header");
43+
return header;
44+
}
45+
46+
static void *get_alloc_base(struct wut_alloc_header_rpl* header)
47+
{
48+
return (char*)header - header->offset;
49+
}
50+
51+
void *
52+
_malloc_r(struct _reent *r, size_t size)
53+
{
54+
return _memalign_r(r, 0x40, size);
55+
}
56+
57+
void
58+
_free_r(struct _reent *r, void *ptr)
59+
{
60+
if (ptr) {
61+
void *basePtr = get_alloc_base(get_alloc_header(ptr));
62+
MEMFreeToDefaultHeap(basePtr);
63+
}
64+
}
65+
66+
void *
67+
_realloc_r(struct _reent *r, void *ptr, size_t size)
68+
{
69+
void *new_ptr = _malloc_r(r, size);
70+
if (!new_ptr) {
71+
r->_errno = ENOMEM;
72+
return new_ptr;
73+
}
74+
75+
if (ptr) {
76+
struct wut_alloc_header_rpl *header = get_alloc_header(ptr);
77+
size_t old_size = header->size;
78+
memcpy(new_ptr, ptr, old_size <= size ? old_size : size);
79+
MEMFreeToDefaultHeap(get_alloc_base(header));
80+
}
81+
return new_ptr;
82+
}
83+
84+
void *
85+
_calloc_r(struct _reent *r, size_t num, size_t size)
86+
{
87+
void *ptr = _malloc_r(r, num * size);
88+
if (ptr) {
89+
memset(ptr, 0, num * size);
90+
} else {
91+
r->_errno = ENOMEM;
92+
}
93+
return ptr;
94+
}
95+
96+
void *
97+
_memalign_r(struct _reent *r, size_t align, size_t size)
98+
{
99+
if(align < 0x40)
100+
align = 0x40;
101+
size_t offset;
102+
void* basePtr;
103+
if(sizeof(struct wut_alloc_header_rpl) > align)
104+
offset = align - (sizeof(struct wut_alloc_header_rpl) % align);
105+
else
106+
offset = align - sizeof(struct wut_alloc_header_rpl);
107+
basePtr = MEMAllocFromDefaultHeapEx(offset + sizeof(struct wut_alloc_header_rpl) + size, align);
108+
if (!basePtr) {
109+
r->_errno = ENOMEM;
110+
return basePtr;
111+
}
112+
struct wut_alloc_header_rpl *header = (struct wut_alloc_header_rpl*)((char*)basePtr + offset);
113+
header->canary = WUT_MALLOC_RPL_CANARY;
114+
header->size = size;
115+
header->offset = offset;
116+
return (header+1);
117+
}
118+
119+
struct mallinfo _mallinfo_r(struct _reent *r)
120+
{
121+
struct mallinfo info = { 0 };
122+
return info;
123+
}
124+
125+
void
126+
_malloc_stats_r(struct _reent *r)
127+
{
128+
}
129+
130+
int
131+
_mallopt_r(struct _reent *r, int param, int value)
132+
{
133+
return 0;
134+
}
135+
136+
size_t
137+
_malloc_usable_size_r(struct _reent *r, void *ptr)
138+
{
139+
return 0; // we do not know the total available size
140+
}
141+
142+
void *
143+
_valloc_r(struct _reent *r, size_t size)
144+
{
145+
return _memalign_r(r, OS_PAGE_SIZE, size);
146+
}
147+
148+
void *
149+
_pvalloc_r(struct _reent *r, size_t size)
150+
{
151+
return _memalign_r(r, OS_PAGE_SIZE, (size + (OS_PAGE_SIZE - 1)) & ~(OS_PAGE_SIZE - 1));
152+
}
153+
154+
int
155+
_malloc_trim_r(struct _reent *r, size_t pad)
156+
{
157+
return 0;
158+
}

0 commit comments

Comments
 (0)