Telkin
Loading...
Searching...
No Matches
Runtime.h
Go to the documentation of this file.
1#pragma once
2
3namespace tk {
4
5 [[nodiscard]]
6 bool isCemu();
7
8}
9
10#include <cafe.h>
11#include <cmath>
12#include <cctype>
13#include <cstdarg>
14#include <climits>
15
16#ifdef TK_IMPL_OPERATOR_NEW
17void* operator new(std::size_t size) {
18 return MEMAllocFromDefaultHeap(size);
19}
20#endif
21
22#ifdef TK_IMPL_OPERATOR_DELETE
23void operator delete(void* ptr) noexcept {
24 return MEMFreeToDefaultHeap(ptr);
25}
26#endif
27
28#ifdef TK_IMPL_FREE
29extern "C" void free(void* ptr) {
30 MEMFreeToDefaultHeap(ptr);
31}
32#endif
33
34#ifdef TK_IMPL_CALLOC
35extern "C" void* calloc(size_t num, size_t size) {
36 void* p = MEMAllocFromDefaultHeap(num * size);
37 memset(p, 0, num * size);
38 return p;
39}
40#endif
41
42#ifdef TK_IMPL_MEMALIGN
43extern "C" void* memalign(size_t align, size_t size) {
44 return MEMAllocFromDefaultHeapEx(size, align);
45}
46#endif
47
48#ifdef TK_IMPL_MEMCHR
49extern "C" void* memchr(const void* p, int ch, size_t count) {
50 for (size_t i = 0; i < count; i++) {
51 const u8 b = reinterpret_cast<const u8*>(p)[i];
52 if (b == (u8)ch) {
53 return (void*) (&reinterpret_cast<const u8*>(p)[i]);
54 }
55 }
56
57 return nullptr;
58}
59#endif
60
61#ifdef TK_IMPL_STRNCPY
62extern "C" char* strncpy(char* __restrict dst0, const char* __restrict src0, size_t count) {
63 char* dscan;
64 const char* sscan;
65
66 dscan = dst0;
67 sscan = src0;
68 while (count > 0) {
69 --count;
70 if ((*dscan++ = *sscan++) == '\0') break;
71 }
72 while (count-- > 0) *dscan++ = '\0';
73 return dst0;
74}
75#endif
76
77#ifdef TK_IMPL_STRSTR
78extern "C" char* strstr(const char* hs, const char* ne) {
79 size_t i;
80 int c = ne[0];
81
82 if (c == 0) return (char*)hs;
83
84 for (; hs[0] != '\0'; hs++) {
85 if (hs[0] != c) continue;
86 for (i = 1; ne[i] != 0; i++)
87 if (hs[i] != ne[i]) break;
88 if (ne[i] == '\0') return (char*)hs;
89 }
90 return NULL;
91}
92#endif
93
94#ifdef TK_IMPL_MEMCPY
95extern "C" void* memcpy(void* dest, const void* src, size_t n) {
96 return OSBlockMove(dest, src, n, true);
97}
98#endif
99
100#ifdef TK_IMPL_STRLEN
101extern "C" size_t strlen(const char* s) {
102 const char* p = s;
103 while (*p) p++;
104 return (size_t)(p - s);
105}
106#endif
107
108#ifdef TK_IMPL_MEMSET
109extern "C" void* memset(void* dst, int value, size_t size) {
110 return OSBlockSet(dst, value, size);
111}
112#endif
113
114#ifdef TK_IMPL_SPRINTF
115extern "C" int sprintf(char* buffer, const char* format, ...) {
116 __va_list va;
117 va_start(va, format);
118 const int ret = vsnprintf(buffer, INT_MAX, format, va);
119 va_end(va);
120 return ret;
121}
122#endif
123
124#ifdef TK_IMPL_STRCHR
125extern "C" char* strchr(const char* s1, int i) {
126 const unsigned char* s = (const unsigned char*)s1;
127 unsigned char c = i;
128
129 while (*s && *s != c) s++;
130 if (*s == c) return (char*)s;
131 return nullptr;
132}
133#endif
134
135#ifdef TK_IMPL_STRCPY
136extern "C" char* strcpy(char* dst0, const char* src0) {
137 char* s = dst0;
138 while ((*dst0++ = *src0++));
139 return s;
140}
141#endif
142
143#ifdef TK_IMPL_FLOOR
144extern "C" double floor(double x) {
145 return floorf(x);
146}
147#endif
148
149#ifdef TK_IMPL_CEIL
150extern "C" double ceil(double x) {
151 return ceilf(x);
152}
153#endif
154
155#ifdef TK_IMPL_SIN
156extern "C" double sin(double x) {
157 return sinf(x);
158}
159#endif
160
161#ifdef TK_IMPL_COS
162extern "C" double cos(double x) {
163 return cosf(x);
164}
165#endif
166
167#ifdef TK_IMPL_ATAN2
168extern "C" double atan2(double y, double x) {
169 return atan2f(y, x);
170}
171#endif
172
173#ifdef TK_IMPL_POW
174extern "C" double pow(double x, double y) {
175 return powf(x, y);
176}
177#endif
178
179#ifdef TK_IMPL_LOG
180extern "C" double log(double x) {
181 return logf(x);
182}
183#endif
184
185#ifdef TK_IMPL_ISSPACE
186extern "C" int isspace(int c) {
187 return (c == ' ');
188}
189#endif
190
191#ifdef TK_IMPL_ISDIGIT
192extern "C" int isdigit(int c) {
193 return (c >= '0' && c <= '9');
194}
195#endif
196
197#ifdef TK_IMPL_ISUPPER
198extern "C" int isupper(int c) {
199 return (c >= 'A' && c <= 'Z');
200}
201#endif
202
203#ifdef TK_IMPL_ISALPHA
204extern "C" int isalpha(int c) {
205 return ((isupper(c) || (c >= 'a' && c <= 'z')));
206}
207#endif
208
209#ifdef TK_IMPL_STRTOL
210extern "C" long strtol(const char *nptr, char **endptr, int base) {
211 const char* s = nptr;
212 unsigned long acc;
213 int c;
214 unsigned long cutoff;
215 int cutlim;
216 int any;
217 int neg = 0;
218
219 while (isspace((unsigned char)*s)) {
220 s++;
221 }
222
223 if (*s == '-') {
224 neg = 1;
225 s++;
226 } else if (*s == '+') {
227 s++;
228 }
229
230 if ((base == 0 || base == 16) &&
231 *s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X')) {
232 s += 2;
233 base = 16;
234 }
235 if (base == 0) {
236 base = *s == '0' ? 8 : 10;
237 }
238
239 acc = neg ? -(unsigned long)std::numeric_limits<long>::min() : std::numeric_limits<long>::max();
240 cutoff = acc / (unsigned long)base;
241 cutlim = acc % (unsigned long)base;
242
243 acc = 0;
244 any = 0;
245
246 for (;; s++) {
247 c = *s;
248
249 if (isdigit(c))
250 c -= '0';
251 else if (isalpha(c))
252 c -= (isupper(c) ? 'A' : 'a') - 10;
253 else
254 break;
255
256 if (c >= base)
257 break;
258
259 if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) {
260 any = -1;
261 } else {
262 any = 1;
263 acc *= base;
264 acc += c;
265 }
266 }
267
268 if (any < 0) {
269 acc = neg ? std::numeric_limits<long>::min() : std::numeric_limits<long>::max();
270 } else if (neg) {
271 acc = -acc;
272 }
273
274 if (endptr != 0) {
275 *endptr = (char *)(any ? s : nptr);
276 }
277
278 return acc;
279}
280#endif
281
282#ifdef TK_IMPL_STRNCMP
283extern "C" int strncmp(const char* s1, const char* s2, size_t n) {
284 if (n == 0) return 0;
285
286 while (n-- != 0 && *s1 == *s2) {
287 if (n == 0 || *s1 == '\0') break;
288 s1++;
289 s2++;
290 }
291 return (*(unsigned char*)s1) - (*(unsigned char*)s2);
292}
293#endif
294
295#ifdef TK_IMPL_STRCAT
296extern "C" char* strcat(char* dest, const char* src) {
297 char* ptr = dest;
298
299 while (*ptr != '\0') {
300 ptr++;
301 }
302
303 while (*src != '\0') {
304 *ptr = *src;
305 ptr++;
306 src++;
307 }
308
309 *ptr = '\0';
310
311 return dest;
312}
313#endif
314
315#ifdef TK_IMPL_STRPBRK
316extern "C" char* strpbrk(const char* str, const char* charset) {
317 if (!str || !charset) {
318 return NULL;
319 }
320
321 // For each character in the string
322 while (*str) {
323 // Check if it matches any character in the charset
324 const char* c = charset;
325 while (*c) {
326 if (*str == *c) {
327 return (char*)str; // Return pointer to first matching character
328 }
329 c++;
330 }
331 str++;
332 }
333
334 return NULL; // No match found
335}
336#endif
337
338#ifdef TK_IMPL_STRCMP
339extern "C" int strcmp(const char* a, const char* b) {
340 while (*a && (*a == *b)) {
341 a++;
342 b++;
343 }
344 return (unsigned char)*a - (unsigned char)*b;
345}
346#endif
347
348#ifdef TK_IMPL_MEMMOVE
349extern "C" void* memmove(void* dst, const void* src, size_t size) {
350 return OSBlockMove(dst, src, size, true);
351}
352#endif
353
354#ifdef TK_IMPL_MEMCMP
355extern "C" int memcmp(const void* a, const void* b, size_t size) {
356 const unsigned char *pa = (const unsigned char *)a;
357 const unsigned char *pb = (const unsigned char *)b;
358
359 while (size--) {
360 if (*pa != *pb)
361 return *pa - *pb;
362 pa++;
363 pb++;
364 }
365 return 0;
366}
367#endif
368
369#ifdef TK_IMPL_ABORT
370extern "C" void abort() {
371 OSFatal("abort() called");
372}
373#endif
374
375#ifdef TK_IMPL_PRINTF
376#define TELKIN_REGISTERS
377#include <telkin/Assembly.h>
378extern "C" int printf(const char* format, ...) tAssembly(
379 // r2 is persistent/unused
380 lis r2, OSReport@ha;
381 lwz r2, OSReport@l(r2);
382 mtctr r2;
383 mflr r2;
384 bctrl;
385 mtlr r2;
386 li r3, 0;
387 blr;
388)
389#endif
390
391#ifdef TK_IMPL_ISLOWER
392#define _U 01
393#define _L 02
394#define _N 04
395#define _S 010
396#define _P 020
397#define _C 040
398#define _X 0100
399#define _B 0200
400
401#define _CTYPE_DATA_0_127
402 _C, _C, _C, _C, _C, _C, _C, _C, _C, _C | _S, _C | _S, _C | _S, _C | _S,
403 _C | _S, _C, _C, _C, _C, _C, _C, _C, _C, _C, _C, _C, _C, _C, _C, _C,
404 _C, _C, _C, _S | _B, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P, _P,
405 _P, _P, _P, _N, _N, _N, _N, _N, _N, _N, _N, _N, _N, _P, _P, _P, _P,
406 _P, _P, _P, _U | _X, _U | _X, _U | _X, _U | _X, _U | _X, _U | _X, _U,
407 _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U, _U,
408 _U, _U, _P, _P, _P, _P, _P, _P, _L | _X, _L | _X, _L | _X, _L | _X,
409 _L | _X, _L | _X, _L, _L, _L, _L, _L, _L, _L, _L, _L, _L, _L, _L, _L,
410 _L, _L, _L, _L, _L, _L, _L, _P, _P, _P, _P, _C
411
412#define _CTYPE_DATA_128_255
413 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
414 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
415 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
416 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
417 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
418 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
419
420const char _ctype_[1 + 256] = {0, _CTYPE_DATA_0_127,
421 _CTYPE_DATA_128_255};
422
423#ifndef __locale_ctype_ptr
424#define __locale_ctype_ptr() _ctype_
425#endif
426
427#ifndef __CTYPE_PTR
428#define __CTYPE_PTR (__locale_ctype_ptr())
429#endif
430
431extern "C" int islower(int c) {
432 return ((__CTYPE_PTR[c + 1] & (_U | _L)) == _L);
433}
434#endif
435
436#ifdef TK_IMPL_TOUPPER
437extern "C" int toupper(int c) {
438 return islower(c) ? c - 'a' + 'A' : c;
439}
440#endif
441
442#ifdef TK_IMPL_FABSF
443extern "C" float fabsf(float a) {
444 return (a > 0) ? a : -a;
445}
446#endif
447
448#ifdef TK_IMPL_FABS
449extern "C" double fabs(double a) {
450 return (a > 0) ? a : -a;
451}
452#endif
453
454#ifdef TK_IMPL_ATOF
455extern "C" double atof(const char *s) {
456 double a = 0.0;
457 int e = 0;
458 int c;
459 int sign = 1;
460
461 // Skip whitespace
462 while (*s == ' ' || *s == '\t' || *s == '\n') {
463 s++;
464 }
465
466 // Handle sign
467 if (*s == '+') {
468 s++;
469 } else if (*s == '-') {
470 sign = -1;
471 s++;
472 }
473
474 while ((c = *s++) != '\0' && isdigit(c)) {
475 a = a * 10.0 + (c - '0');
476 }
477
478 if (c == '.') {
479 while ((c = *s++) != '\0' && isdigit(c)) {
480 a = a * 10.0 + (c - '0');
481 e = e - 1;
482 }
483 }
484
485 if (c == 'e' || c == 'E') {
486 int exp_sign = 1;
487 int i = 0;
488 c = *s++;
489
490 if (c == '+') {
491 c = *s++;
492 } else if (c == '-') {
493 c = *s++;
494 exp_sign = -1;
495 }
496
497 while (isdigit(c)) {
498 i = i * 10 + (c - '0');
499 c = *s++;
500 }
501
502 e += i * exp_sign;
503 }
504
505 while (e > 0) {
506 a *= 10.0;
507 e--;
508 }
509
510 while (e < 0) {
511 a *= 0.1;
512 e++;
513 }
514
515 return a * sign;
516}
517#endif
bool isCemu()
u64(*)() getTitleID_t
Definition Mod.h:16