PS2SDK
PS2 Homebrew Libraries
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 
14 extern struct irx_export_table _exp_sysmem;
15 
16 #ifdef _IOP
17 IRX_ID("System_Memory_Manager", 2, 3);
18 #endif
19 // Based on the module from SCE SDK 3.1.0.
20 
21 static sysmem_internals_t sysmem_internals;
22 static KprintfHandler_t *kprintf_cb;
23 static void *kprintf_cb_userdata;
24 
25 extern int sysmem_reinit(void);
26 static int cCpuSuspendIntr(int *state);
27 static int cCpuResumeIntr(int state);
28 static int allocSysMemory_internal(int flags, int size, void *mem);
29 static int freeSysMemory_internal(void *ptr);
30 static void updateSmemCtlBlk(void);
31 static sysmem_alloc_element_t *search_block(void *a1);
32 
33 typedef struct intrman_callbacks_
34 {
35  int (*cbCpuSuspendIntr)(int *state);
36  int (*cbCpuResumeIntr)(int state);
37  // cppcheck-suppress unusedStructMember
38  int (*cbQueryIntrContext)(void);
40 
41 int _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 
56 int 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 
118 u32 QueryMemSize()
119 {
120  if ( sysmem_internals.alloclist )
121  return sysmem_internals.memsize;
122  else
123  return 0;
124 }
125 
126 u32 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 
150 u32 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 
177 void *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 
191 int 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 
214 void *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 
237 int 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 
259 void 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;
266  sysmem_alloc_table_t *next;
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 
323 sysmem_internals_t *GetSysmemInternalData(void)
324 {
325  return &sysmem_internals;
326 }
327 
328 static 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 
546 static 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 
621 static void updateSmemCtlBlk(void)
622 {
623  sysmem_alloc_table_t *alloclist;
624  sysmem_alloc_table_t *next;
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 
686 static 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 
708 static 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 
717 static 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
727 static 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 
737 int 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 
752 void 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 }
sysmem_info_
Definition: xsysmem.h:48
s_info
Definition: xprintf.c:78
sysmem_alloc_element_
Definition: sysmem.h:36
sysmem_alloc_table_
Definition: sysmem.h:42
irx_export_table
Definition: irx.h:90
xsysmem.h
sysmem_internals_
Definition: sysmem.h:50
sysmem.h
intrman_callbacks_
Definition: loadcore.c:209