PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
sysmem.c
1/*
2# _____ ___ ____ ___ ____
3# ____| | ____| | | |____|
4# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5#-----------------------------------------------------------------------
6# Copyright ps2dev - http://www.ps2dev.org
7# Licenced under Academic Free License version 2.0
8# Review ps2sdk README & LICENSE files for further details.
9*/
10
11#include "sysmem.h"
12#include "xsysmem.h"
13
14extern struct irx_export_table _exp_sysmem;
15
16#ifdef _IOP
17IRX_ID("System_Memory_Manager", 2, 3);
18#endif
19// Based on the module from SCE SDK 3.1.0.
20
21static sysmem_internals_t sysmem_internals;
22static KprintfHandler_t *kprintf_cb;
23static void *kprintf_cb_userdata;
24
25extern int sysmem_reinit(void);
26static int cCpuSuspendIntr(int *state);
27static int cCpuResumeIntr(int state);
28static int allocSysMemory_internal(int flags, int size, void *mem);
29static int freeSysMemory_internal(void *ptr);
30static void updateSmemCtlBlk(void);
31static sysmem_alloc_element_t *search_block(void *a1);
32
33typedef struct intrman_callbacks_
34{
35 int (*cbCpuSuspendIntr)(int *state);
36 int (*cbCpuResumeIntr)(int state);
37 // cppcheck-suppress unusedStructMember
38 int (*cbQueryIntrContext)(void);
40
41int _start(unsigned int memsize)
42{
43 if ( memsize > 0x7FFF00 )
44 memsize = 0x7FFF00;
45 sysmem_internals.alloclist = (sysmem_alloc_table_t *)0x401100;
46 sysmem_internals.memsize = memsize & 0xFFFFFF00;
47 sysmem_internals.intr_suspend_tbl = 0;
48 sysmem_internals.allocation_count = 0;
49 sysmem_internals.smemupdate_cur = 0;
50 if ( (memsize & 0xFFFFFF00) >= 0x401200 )
51 return sysmem_reinit();
52 sysmem_internals.alloclist = 0;
53 return 0;
54}
55
56int sysmem_reinit(void)
57{
58 sysmem_alloc_table_t *alloclist;
60 int v2;
61 int v3;
64 int memsize;
65 unsigned int info;
66 const sysmem_alloc_table_t *v8;
67 const sysmem_alloc_element_t *list;
68 int result;
69
70 alloclist = sysmem_internals.alloclist;
71 if ( !sysmem_internals.alloclist )
72 return 0;
73 v1 = sysmem_internals.alloclist;
74 sysmem_internals.alloclist->next = 0;
75 v2 = 0;
76 v3 = 12;
77 v4 = alloclist;
78 do
79 {
80 v5 = (sysmem_alloc_element_t *)((char *)v1 + v3);
81 v3 += 8;
82 v4->list[0].next = v5;
83 v4->list[0].info = 0;
84 ++v2;
85 v4 = (sysmem_alloc_table_t *)((char *)v4 + 8);
86 } while ( v2 < 31 );
87 memsize = sysmem_internals.memsize;
88 info = v1->list[0].info;
89 v1->list[30].next = 0;
90 v1->list[0].info = (info & 0x1FFFF) | ((memsize / 256) << 17);
91 sysmem_internals.allocation_count = 1;
92 if (
93 AllocSysMemory(0, (int)sysmem_internals.alloclist, 0)
94 || (v8 = (sysmem_alloc_table_t *)AllocSysMemory(0, 0xFC, 0), list = v8->list, v8 != sysmem_internals.alloclist) )
95 {
96 sysmem_internals.alloclist = 0;
97 return 0;
98 }
99 result = 0;
100 if ( list )
101 {
102 unsigned int v11;
103
104 while ( 1 )
105 {
106 v11 = list->info;
107 if ( (v11 & 1) == 0 )
108 break;
109 list = list->next;
110 if ( !list )
111 return 0;
112 }
113 return (u16)v11 >> 1 << 8;
114 }
115 return result;
116}
117
118u32 QueryMemSize()
119{
120 if ( sysmem_internals.alloclist )
121 return sysmem_internals.memsize;
122 else
123 return 0;
124}
125
126u32 QueryMaxFreeMemSize()
127{
128 unsigned int v0;
129 const sysmem_alloc_element_t *list;
130 int state;
131
132 v0 = 0;
133 if ( !sysmem_internals.alloclist )
134 return 0;
135 cCpuSuspendIntr(&state);
136 list = sysmem_internals.alloclist->list;
137 if ( sysmem_internals.alloclist != (sysmem_alloc_table_t *)-4 )
138 {
139 do
140 {
141 if ( (list->info & 1) == 0 && v0 < list->info >> 17 )
142 v0 = list->info >> 17;
143 list = list->next;
144 } while ( list );
145 }
146 cCpuResumeIntr(state);
147 return v0 << 8;
148}
149
150u32 QueryTotalFreeMemSize()
151{
152 int v0;
153 const sysmem_alloc_element_t *list;
154 int state;
155
156 v0 = 0;
157 if ( !sysmem_internals.alloclist )
158 return 0;
159 cCpuSuspendIntr(&state);
160 list = sysmem_internals.alloclist->list;
161 if ( sysmem_internals.alloclist != (sysmem_alloc_table_t *)-4 )
162 {
163 do
164 {
165 unsigned int info;
166
167 info = list->info;
168 if ( (info & 1) == 0 )
169 v0 += info >> 17;
170 list = list->next;
171 } while ( list );
172 }
173 cCpuResumeIntr(state);
174 return v0 << 8;
175}
176
177void *AllocSysMemory(int mode, int size, void *ptr)
178{
179 void *v6;
180 int state;
181
182 if ( !sysmem_internals.alloclist || (unsigned int)mode >= 3 )
183 return 0;
184 cCpuSuspendIntr(&state);
185 v6 = (void *)allocSysMemory_internal(mode, size, ptr);
186 updateSmemCtlBlk();
187 cCpuResumeIntr(state);
188 return v6;
189}
190
191int FreeSysMemory(void *ptr)
192{
193 const sysmem_alloc_table_t *alloclist;
194 int v4;
195 int state;
196
197 alloclist = sysmem_internals.alloclist;
198 while ( alloclist && ptr != alloclist )
199 {
200 alloclist = alloclist->next;
201 }
202 if ( alloclist )
203 {
204 return -1;
205 }
206 cCpuSuspendIntr(&state);
207 v4 = freeSysMemory_internal(ptr);
208 if ( !v4 )
209 updateSmemCtlBlk();
210 cCpuResumeIntr(state);
211 return v4;
212}
213
214void *QueryBlockTopAddress(void *address)
215{
216 int v2;
217 const sysmem_alloc_element_t *v3;
218 int state;
219
220 v2 = -1;
221 cCpuSuspendIntr(&state);
222 v3 = search_block(address);
223 if ( v3 )
224 {
225 unsigned int info;
226
227 info = v3->info;
228 if ( (info & 1) != 0 )
229 v2 = (u16)info >> 1 << 8;
230 else
231 v2 = ((u16)info >> 1 << 8) + 0x80000000;
232 }
233 cCpuResumeIntr(state);
234 return (void *)v2;
235}
236
237int QueryBlockSize(void *address)
238{
239 int v2;
240 const sysmem_alloc_element_t *v3;
241 int state;
242
243 v2 = -1;
244 cCpuSuspendIntr(&state);
245 v3 = search_block(address);
246 if ( v3 )
247 {
248 unsigned int info;
249
250 info = v3->info;
251 v2 = info >> 17 << 8;
252 if ( (info & 1) == 0 )
253 v2 |= 0x80000000;
254 }
255 cCpuResumeIntr(state);
256 return v2;
257}
258
259void GetSysMemoryInfo(int flag, sysmem_info_t *info)
260{
261 sysmem_alloc_table_t *table_info;
262 void *memsize;
264 u32 v7;
265 const sysmem_alloc_table_t *alloclist;
267 int state;
268
269 cCpuSuspendIntr(&state);
270 if ( flag )
271 {
272 info->meminfo.allocation_count = sysmem_internals.allocation_count;
273 info->meminfo.memsize = sysmem_internals.memsize;
274 info->meminfo.memlist_last = sysmem_internals.smemupdate_cur;
275 info->meminfo.memlist_first = (sysmem_alloc_table_t *)sysmem_internals.alloclist->list;
276 cCpuResumeIntr(state);
277 return;
278 }
279 if ( info->meminfo.memlist_last != sysmem_internals.smemupdate_cur )
280 {
281 info->blockinfo.block_address = (void *)-1;
282 info->blockinfo.flags_memsize = -1;
283 info->blockinfo.table_info = 0;
284 cCpuResumeIntr(state);
285 return;
286 }
287 table_info = info->blockinfo.table_info;
288 if ( !table_info )
289 {
290 memsize = (void *)sysmem_internals.memsize;
291 info->blockinfo.flags_memsize = 1;
292 info->blockinfo.block_address = memsize;
293 cCpuResumeIntr(state);
294 return;
295 }
296 v6 = info->blockinfo.table_info;
297 info->blockinfo.block_address = (void *)((((unsigned int)table_info->list[0].next >> 1) & 0x7FFF) << 8);
298 v7 = (unsigned int)v6->list[0].next >> 17 << 8;
299 info->blockinfo.flags_memsize = v7;
300 if ( ((int)v6->list[0].next & 1) != 0 )
301 {
302 alloclist = sysmem_internals.alloclist;
303 while ( alloclist && alloclist != info->blockinfo.block_address )
304 {
305 alloclist = alloclist->next;
306 }
307 if ( alloclist )
308 {
309 info->blockinfo.flags_memsize |= 2u;
310 }
311 }
312 else
313 {
314 info->blockinfo.flags_memsize |= 1;
315 }
316 next = info->blockinfo.table_info->next;
317 info->blockinfo.table_info = next;
318 if ( !((unsigned int)next->list[0].next >> 17) )
319 info->blockinfo.table_info = 0;
320 cCpuResumeIntr(state);
321}
322
323sysmem_internals_t *GetSysmemInternalData(void)
324{
325 return &sysmem_internals;
326}
327
328static int allocSysMemory_internal(int flags, int size, void *mem)
329{
330 unsigned int v3;
331 int result;
333 unsigned int v6;
334 unsigned int v7;
337 s16 v12;
339 int v16;
340 unsigned int v17;
341 unsigned int v18;
342 unsigned int v19;
343 unsigned int v20;
344 int v21;
345 int v22;
346 unsigned int v23;
347 unsigned int v24;
350 unsigned int v27;
351 int v28;
352 unsigned int v31;
353 unsigned int v32;
354 unsigned int v35;
355 unsigned int v36;
356
357 v31 = 0;
358 v3 = (unsigned int)(size + 255) >> 8;
359 result = 0;
360 if ( !v3 )
361 return result;
362 if ( flags == 1 )
363 {
364 list = sysmem_internals.alloclist->list;
365 v9 = 0;
366 if ( sysmem_internals.alloclist != (sysmem_alloc_table_t *)-4 )
367 {
368 do
369 {
370 unsigned int info;
371
372 info = list->info;
373 if ( (info & 1) == 0 && info >> 17 >= v3 )
374 v9 = list;
375 list = list->next;
376 } while ( list );
377 }
378 i = v9;
379 result = 0;
380 if ( v9 )
381 {
382 v7 = v9->info;
383 if ( v7 >> 17 != v3 )
384 {
385 unsigned int v11;
386 int v13;
387 int v14;
388
389 ++sysmem_internals.allocation_count;
390 v11 = (v9->info & 0x1FFFF) | (((v9->info >> 17) - v3) << 17);
391 v12 = (v11 >> 1) & 0x7FFF;
392 i->info = v11;
393 v11 >>= 17;
394 v13 = (v31 & 0x10001) | (u16)(2 * ((v12 + v11) & 0x7FFF)) | (v3 << 17) | 1;
395 v14 = (u16)((((u8 *)&v31)[0] & 1) | (2 * ((v12 + v11) & 0x7FFF)) | 1) >> 1;
396 v31 = v13;
397 next = i->next;
398 v16 = v14 << 8;
399 result = v16;
400 if ( v31 >> 17 )
401 {
402 do
403 {
404 v36 = next->info;
405 next->info = v31;
406 v31 = v36;
407 next = next->next;
408 result = v16;
409 } while ( v36 >> 17 );
410 }
411 return result;
412 }
413 i->info = v7 | 1;
414 return (((v7 | 1) >> 1) & 0x7FFF) << 8;
415 }
416 }
417 else if ( flags >= 2 )
418 {
419 result = 0;
420 if ( flags == 2 )
421 {
422 result = 0;
423 if ( (((uiptr)mem) & 0xFF) == 0 )
424 {
425 v17 = (unsigned int)mem >> 8;
426 for ( i = sysmem_internals.alloclist->list;; i = i->next )
427 {
428 result = 0;
429 if ( !i )
430 break;
431 v18 = i->info;
432 v19 = (u16)v18 >> 1;
433 result = 0;
434 if ( v17 < v19 )
435 break;
436 if ( (v18 & 1) == 0 && v19 + (v18 >> 17) >= ((unsigned int)mem >> 8) + v3 )
437 {
438 if ( ((i->info >> 1) & 0x7FFF) < v17 )
439 {
440 ++sysmem_internals.allocation_count;
441 v20 = i->info;
442 v21 = v20 & 0x1FFFF;
443 v22 = (u16)v20 >> 1;
444 v20 >>= 17;
445 v23 = v22 + v20 - v17;
446 v24 = v21 | ((v20 - v23) << 17);
447 i->info = v24;
448 v32 = (u16)(2 * ((((v24 >> 1) & 0x7FFF) + (v24 >> 17)) & 0x7FFF)) | (v23 << 17);
449 v25 = i->next;
450 v26 = v25;
451 if ( v32 >> 17 )
452 {
453 do
454 {
455 v35 = v25->info;
456 v25->info = v32;
457 v32 = v35;
458 v25 = v25->next;
459 } while ( v35 >> 17 );
460 }
461 i = v26;
462 }
463 v7 = i->info;
464 if ( v7 >> 17 != v3 )
465 {
466 ++sysmem_internals.allocation_count;
467 v27 = i->info;
468 i->info = (v27 & 0x1FFFE) | 1 | (v3 << 17);
469 v28 = 2 * ((((v27 >> 1) & 0x7FFF) + (u16)v3) & 0x7FFF);
470 v31 = (v27 & 0x10001) | (v28 & 0x1FFFF) | (((((v27 & 0xFFFF0001) | v28) >> 17) - v3) << 17);
471 next = i->next;
472 v16 = (u16)v27 >> 1 << 8;
473 result = v16;
474 if ( v31 >> 17 )
475 {
476 do
477 {
478 v36 = next->info;
479 next->info = v31;
480 v31 = v36;
481 next = next->next;
482 result = v16;
483 } while ( v36 >> 17 );
484 }
485 return result;
486 }
487 i->info = v7 | 1;
488 return (((v7 | 1) >> 1) & 0x7FFF) << 8;
489 }
490 }
491 }
492 }
493 }
494 else
495 {
496 result = 0;
497 if ( !flags )
498 {
499 i = sysmem_internals.alloclist->list;
500 result = 0;
501 if ( sysmem_internals.alloclist != (sysmem_alloc_table_t *)-4 )
502 {
503 do
504 {
505 v6 = i->info;
506 if ( (v6 & 1) == 0 && v6 >> 17 >= v3 )
507 break;
508 i = i->next;
509 } while ( i );
510 result = 0;
511 if ( i )
512 {
513 v7 = i->info;
514 if ( v7 >> 17 != v3 )
515 {
516 ++sysmem_internals.allocation_count;
517 v27 = i->info;
518 i->info = (v27 & 0x1FFFE) | 1 | (v3 << 17);
519 v28 = 2 * ((((v27 >> 1) & 0x7FFF) + (u16)v3) & 0x7FFF);
520 v31 = (v27 & 0x10001) | (v28 & 0x1FFFF) | (((((v27 & 0xFFFF0001) | v28) >> 17) - v3) << 17);
521 next = i->next;
522 v16 = (u16)v27 >> 1 << 8;
523 result = v16;
524 if ( v31 >> 17 )
525 {
526 do
527 {
528 v36 = next->info;
529 next->info = v31;
530 v31 = v36;
531 next = next->next;
532 result = v16;
533 } while ( v36 >> 17 );
534 }
535 return result;
536 }
537 i->info = v7 | 1;
538 return (((v7 | 1) >> 1) & 0x7FFF) << 8;
539 }
540 }
541 }
542 }
543 return result;
544}
545
546static int freeSysMemory_internal(void *ptr)
547{
548 unsigned int v2;
551 unsigned int v7;
552 int v8;
554 const sysmem_alloc_element_t *next;
555 int v12;
556 const sysmem_alloc_element_t *i;
557
558 v2 = (unsigned int)ptr >> 8;
559 if ( (((uiptr)ptr) & 0xFF) != 0 )
560 return -1;
561 v4 = &sysmem_internals.alloclist->list[2];
562 v5 = 0;
563 if ( sysmem_internals.alloclist == (sysmem_alloc_table_t *)-20 )
564 return -1;
565 do
566 {
567 unsigned int info;
568
569 info = v4->info;
570 if ( info >> 17 && (u16)info >> 1 == v2 )
571 break;
572 v5 = v4;
573 v4 = v4->next;
574 } while ( v4 );
575 if ( !v4 )
576 return -1;
577 v7 = v4->info;
578 v8 = 0;
579 if ( (v7 & 1) == 0 )
580 return -1;
581 v9 = 0;
582 next = v4->next;
583 v4->info = v7 & 0xFFFFFFFE;
584 if ( v4->next != 0 )
585 {
586 unsigned int v11;
587
588 v11 = next->info;
589 if ( v11 >> 17 )
590 {
591 if ( (v11 & 1) == 0 )
592 {
593 v8 = 1;
594 --sysmem_internals.allocation_count;
595 v9 = v4->next;
596 v4->info = (v4->info & 0x1FFFF) | (((v4->info >> 17) + (v4->next->info >> 17)) << 17);
597 }
598 }
599 }
600 if ( v5 && (v5->info & 1) == 0 )
601 {
602 v9 = v4;
603 ++v8;
604 --sysmem_internals.allocation_count;
605 v5->info = (v5->info & 0x1FFFF) | (((v5->info >> 17) + (v4->info >> 17)) << 17);
606 }
607 v12 = v8 - 1;
608 if ( v8 == 0 )
609 return 0;
610 for ( i = v9; v12 != -1; --v12 )
611 i = i->next;
612 while ( i )
613 {
614 v9->info = i->info;
615 i = i->next;
616 v9 = v9->next;
617 }
618 return 0;
619}
620
621static void updateSmemCtlBlk(void)
622{
623 sysmem_alloc_table_t *alloclist;
627
628 alloclist = sysmem_internals.alloclist;
629 ++sysmem_internals.smemupdate_cur;
630 if ( sysmem_internals.alloclist->next )
631 {
632 do
633 alloclist = alloclist->next;
634 while ( alloclist->next );
635 }
636 if ( alloclist->list[27].info >> 17 )
637 {
638 int v1;
639
640 v1 = allocSysMemory_internal(0, 256, 0);
641 alloclist->next = (sysmem_alloc_table_t *)v1;
642 if ( v1 )
643 {
644 unsigned int v2;
645 int v4;
647
648 v2 = 0;
649 alloclist->list[30].next = (sysmem_alloc_element_t *)(v1 + 4);
650 next = alloclist->next;
651 v4 = 12;
652 v5 = next;
653 next->next = 0;
654 do
655 {
656 v6 = (sysmem_alloc_element_t *)((char *)next + v4);
657 v4 += 8;
658 v5->list[0].next = v6;
659 v5->list[0].info = 0;
660 ++v2;
661 v5 = (sysmem_alloc_table_t *)((char *)v5 + 8);
662 } while ( v2 < 0x1F );
663 next->list[30].next = 0;
664 }
665 }
666 v7 = sysmem_internals.alloclist;
667 if ( sysmem_internals.alloclist->next )
668 {
670
671 while ( v7->next->next )
672 v7 = v7->next;
673 v8 = v7->next;
674 if ( v7->next )
675 {
676 if ( !(v7->list[27].info >> 17) )
677 {
678 v7->list[30].next = 0;
679 v7->next = 0;
680 freeSysMemory_internal(v8);
681 }
682 }
683 }
684}
685
686static sysmem_alloc_element_t *search_block(void *a1)
687{
689
690 list = sysmem_internals.alloclist->list;
691 if ( sysmem_internals.alloclist != (sysmem_alloc_table_t *)-4 )
692 {
693 do
694 {
695 unsigned int info;
696 int v3;
697
698 info = list->info;
699 v3 = (u16)info >> 1;
700 if ( (unsigned int)a1 >= (unsigned int)(v3 << 8) && (unsigned int)a1 < (v3 + (info >> 17)) << 8 )
701 break;
702 list = list->next;
703 } while ( list );
704 }
705 return list;
706}
707
708static int cCpuSuspendIntr(int *state)
709{
710 intrman_callbacks_t *intrman_callbacks = (intrman_callbacks_t *)(sysmem_internals.intr_suspend_tbl);
711 if ( intrman_callbacks && intrman_callbacks->cbCpuSuspendIntr )
712 return intrman_callbacks->cbCpuSuspendIntr(state);
713 else
714 return 0;
715}
716
717static int cCpuResumeIntr(int state)
718{
719 intrman_callbacks_t *intrman_callbacks = (intrman_callbacks_t *)(sysmem_internals.intr_suspend_tbl);
720 if ( intrman_callbacks && intrman_callbacks->cbCpuResumeIntr )
721 return intrman_callbacks->cbCpuResumeIntr(state);
722 else
723 return 0;
724}
725
726#if 0
727static int cQueryIntrContext(void)
728{
729 intrman_callbacks_t *intrman_callbacks = (intrman_callbacks_t *)(sysmem_internals.intr_suspend_tbl);
730 if ( intrman_callbacks && intrman_callbacks->cbQueryIntrContext )
731 return intrman_callbacks->cbQueryIntrContext();
732 else
733 return 0;
734}
735#endif
736
737int Kprintf(const char *format, ...)
738{
739 if ( kprintf_cb )
740 {
741 int ret;
742 va_list va;
743
744 va_start(va, format);
745 ret = kprintf_cb(kprintf_cb_userdata, format, va);
746 va_end(va);
747 return ret;
748 }
749 return 0;
750}
751
752void KprintfSet(KprintfHandler_t *new_cb, void *context)
753{
754 if ( kprintf_cb && new_cb )
755 {
756 new_cb(context, (const char *)Kprintf(NULL), NULL);
757 }
758 kprintf_cb = new_cb;
759 kprintf_cb_userdata = context;
760}