clean up old IOS handles on startup (dhewg)
[libogc.git] / libogc / system.c
blob06e30218735445f878584a2171ea37107a1d920a
1 /*-------------------------------------------------------------
3 system.c -- OS functions and initialization
5 Copyright (C) 2004
6 Michael Wiedenbauer (shagkur)
7 Dave Murphy (WinterMute)
9 This software is provided 'as-is', without any express or implied
10 warranty. In no event will the authors be held liable for any
11 damages arising from the use of this software.
13 Permission is granted to anyone to use this software for any
14 purpose, including commercial applications, and to alter it and
15 redistribute it freely, subject to the following restrictions:
17 1. The origin of this software must not be misrepresented; you
18 must not claim that you wrote the original software. If you use
19 this software in a product, an acknowledgment in the product
20 documentation would be appreciated but is not required.
22 2. Altered source versions must be plainly marked as such, and
23 must not be misrepresented as being the original software.
25 3. This notice may not be removed or altered from any source
26 distribution.
28 -------------------------------------------------------------*/
30 //#define DEBUG_SYSTEM
32 #include <stdlib.h>
33 #include <string.h>
34 #include <stdio.h>
35 #include <malloc.h>
36 #include <sys/iosupport.h>
38 #include "asm.h"
39 #include "irq.h"
40 #include "exi.h"
41 #if defined(HW_RVL)
42 #include "ipc.h"
43 #include "ios.h"
44 #include "stm.h"
45 #include "es.h"
46 #include "conf.h"
47 #include "wiilaunch.h"
48 #endif
49 #include "cache.h"
50 #include "video.h"
51 #include "system.h"
52 #include "sys_state.h"
53 #include "lwp_threads.h"
54 #include "lwp_priority.h"
55 #include "lwp_watchdog.h"
56 #include "lwp_wkspace.h"
57 #include "lwp_objmgr.h"
58 #include "lwp_config.h"
59 #include "libversion.h"
61 #define SYSMEM1_SIZE 0x01800000
62 #if defined(HW_RVL)
63 #define SYSMEM2_SIZE 0x04000000
64 #endif
65 #define KERNEL_HEAP (1*1024*1024)
67 // DSPCR bits
68 #define DSPCR_DSPRESET 0x0800 // Reset DSP
69 #define DSPCR_DSPDMA 0x0200 // ARAM dma in progress, if set
70 #define DSPCR_DSPINTMSK 0x0100 // * interrupt mask (RW)
71 #define DSPCR_DSPINT 0x0080 // * interrupt active (RWC)
72 #define DSPCR_ARINTMSK 0x0040
73 #define DSPCR_ARINT 0x0020
74 #define DSPCR_AIINTMSK 0x0010
75 #define DSPCR_AIINT 0x0008
76 #define DSPCR_HALT 0x0004 // halt DSP
77 #define DSPCR_PIINT 0x0002 // assert DSP PI interrupt
78 #define DSPCR_RES 0x0001 // reset DSP
80 #define LWP_OBJTYPE_SYSWD 7
82 #define LWP_CHECK_SYSWD(hndl) \
83 { \
84 if(((hndl)==SYS_WD_NULL) || (LWP_OBJTYPE(hndl)!=LWP_OBJTYPE_SYSWD)) \
85 return NULL; \
88 #define _SHIFTL(v, s, w) \
89 ((u32) (((u32)(v) & ((0x01 << (w)) - 1)) << (s)))
90 #define _SHIFTR(v, s, w) \
91 ((u32)(((u32)(v) >> (s)) & ((0x01 << (w)) - 1)))
93 struct _sramcntrl {
94 u8 srambuf[64];
95 u32 offset;
96 s32 enabled;
97 s32 locked;
98 s32 sync;
99 } sramcntrl ATTRIBUTE_ALIGN(32);
101 typedef struct _alarm_st
103 lwp_obj object;
104 wd_cntrl alarm;
105 u64 ticks;
106 u64 periodic;
107 u64 start_per;
108 alarmcallback alarmhandler;
109 void *cb_arg;
110 } alarm_st;
112 typedef struct _yay0header {
113 unsigned int id ATTRIBUTE_PACKED;
114 unsigned int dec_size ATTRIBUTE_PACKED;
115 unsigned int links_offset ATTRIBUTE_PACKED;
116 unsigned int chunks_offset ATTRIBUTE_PACKED;
117 } yay0header;
119 static u16 sys_fontenc = 0xffff;
120 static u32 sys_fontcharsinsheet = 0;
121 static u8 *sys_fontwidthtab = NULL;
122 static u8 *sys_fontimage = NULL;
123 static sys_fontheader *sys_fontdata = NULL;
125 static lwp_queue sys_reset_func_queue;
126 static u32 system_initialized = 0;
127 static lwp_objinfo sys_alarm_objects;
129 static void *__sysarena1lo = NULL;
130 static void *__sysarena1hi = NULL;
132 #if defined(HW_RVL)
133 static void *__sysarena2lo = NULL;
134 static void *__sysarena2hi = NULL;
135 static void *__ipcbufferlo = NULL;
136 static void *__ipcbufferhi = NULL;
137 #endif
139 static void __RSWDefaultHandler();
140 static resetcallback __RSWCallback = NULL;
141 #if defined(HW_RVL)
142 static void __POWDefaultHandler();
143 static powercallback __POWCallback = NULL;
145 static u32 __sys_resetdown = 0;
146 #endif
148 static vu16* const _viReg = (u16*)0xCC002000;
149 static vu32* const _piReg = (u32*)0xCC003000;
150 static vu16* const _memReg = (u16*)0xCC004000;
151 static vu16* const _dspReg = (u16*)0xCC005000;
153 void __SYS_ReadROM(void *buf,u32 len,u32 offset);
154 void* SYS_AllocArena1MemLo(u32 size,u32 align);
156 static s32 __sram_sync(void);
157 static s32 __sram_writecallback(s32 chn,s32 dev);
158 static s32 __mem_onreset(s32 final);
160 extern void __lwp_thread_coreinit(void);
161 extern void __lwp_sysinit(void);
162 extern void __heap_init(void);
163 extern void __exception_init(void);
164 extern void __exception_closeall(void);
165 extern void __systemcall_init(void);
166 extern void __decrementer_init(void);
167 extern void __lwp_mutex_init(void);
168 extern void __lwp_cond_init(void);
169 extern void __lwp_mqbox_init(void);
170 extern void __lwp_sema_init(void);
171 extern void __exi_init(void);
172 extern void __si_init(void);
173 extern void __irq_init(void);
174 extern void __lwp_start_multitasking(void);
175 extern void __timesystem_init(void);
176 extern void __memlock_init(void);
177 extern void __libc_init(int);
179 extern void __libogc_malloc_lock( struct _reent *ptr );
180 extern void __libogc_malloc_unlock( struct _reent *ptr );
182 extern void __exception_console(void);
183 extern void __exception_printf(const char *str, ...);
185 extern void __realmode(void*);
186 extern void __configMEM1_24Mb(void);
187 extern void __configMEM1_48Mb(void);
188 extern void __configMEM2_64Mb(void);
189 extern void __configMEM2_128Mb(void);
190 extern void __reset(u32 reset_code);
192 extern u32 __IPC_ClntInit(void);
193 extern u32 __PADDisableRecalibration(s32 disable);
195 extern void __console_init_ex(void *conbuffer,int tgt_xstart,int tgt_ystart,int tgt_stride,int con_xres,int con_yres,int con_stride);
197 extern int clock_gettime(struct timespec *tp);
198 extern void timespec_subtract(const struct timespec *tp_start,const struct timespec *tp_end,struct timespec *result);
201 extern int __libogc_lock_init(int *lock,int recursive);
202 extern int __libogc_lock_close(int *lock);
203 extern int __libogc_lock_release(int *lock);
204 extern int __libogc_lock_acquire(int *lock);
205 extern void __libogc_exit(int status);
206 extern void * __libogc_sbrk_r(struct _reent *ptr, ptrdiff_t incr);
207 extern int __libogc_gettod_r(struct _reent *ptr, struct timeval *tp, struct timezone *tz);
209 extern u8 __gxregs[];
210 extern u8 __text_start[];
211 extern u8 __isIPL[];
212 extern u8 __Arena1Lo[], __Arena1Hi[];
213 #if defined(HW_RVL)
214 extern u8 __Arena2Lo[], __Arena2Hi[];
215 extern u8 __ipcbufferLo[], __ipcbufferHi[];
216 #endif
218 u8 *__argvArena1Lo = (u8*)0xdeadbeef;
220 static u32 __sys_inIPL = (u32)__isIPL;
222 static u32 _dsp_initcode[] =
224 0x029F0010,0x029F0033,0x029F0034,0x029F0035,
225 0x029F0036,0x029F0037,0x029F0038,0x029F0039,
226 0x12061203,0x12041205,0x00808000,0x0088FFFF,
227 0x00841000,0x0064001D,0x02180000,0x81001C1E,
228 0x00441B1E,0x00840800,0x00640027,0x191E0000,
229 0x00DEFFFC,0x02A08000,0x029C0028,0x16FC0054,
230 0x16FD4348,0x002102FF,0x02FF02FF,0x02FF02FF,
231 0x02FF02FF,0x00000000,0x00000000,0x00000000
234 static sys_resetinfo mem_resetinfo = {
236 __mem_onreset,
240 static const char *__sys_versiondate;
241 static const char *__sys_versionbuild;
243 static __inline__ alarm_st* __lwp_syswd_open(syswd_t wd)
245 LWP_CHECK_SYSWD(wd);
246 return (alarm_st*)__lwp_objmgr_get(&sys_alarm_objects,LWP_OBJMASKID(wd));
249 static __inline__ void __lwp_syswd_free(alarm_st *alarm)
251 __lwp_objmgr_close(&sys_alarm_objects,&alarm->object);
252 __lwp_objmgr_free(&sys_alarm_objects,&alarm->object);
255 #ifdef HW_DOL
256 #define SOFTRESET_ADR *((vu32*)0xCC003024)
257 void __reload() { SOFTRESET_ADR=0; }
259 void __libogc_exit(int status)
261 SYS_ResetSystem(SYS_SHUTDOWN,0,0);
262 __lwp_thread_stopmultitasking(__reload);
264 #else
265 static void (*reload)() = (void(*)())0x80001800;
267 static bool __stub_found()
269 u64 sig = ((u64)(*(u32*)0x80001804) << 32) + *(u32*)0x80001808;
270 if (sig == 0x5354554248415858ULL) // 'STUBHAXX'
271 return true;
272 return false;
275 void __reload()
277 if(__stub_found())
278 reload();
279 SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0);
282 void __libogc_exit(int status)
284 if(__stub_found()) {
285 SYS_ResetSystem(SYS_SHUTDOWN,0,0);
286 __lwp_thread_stopmultitasking(reload);
288 SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0);
290 #endif
292 static void __init_syscall_array() {
293 __syscalls.sbrk_r = __libogc_sbrk_r;
294 __syscalls.lock_init = __libogc_lock_init;
295 __syscalls.lock_close = __libogc_lock_close;
296 __syscalls.lock_release = __libogc_lock_release;
297 __syscalls.lock_acquire = __libogc_lock_acquire;
298 __syscalls.malloc_lock = __libogc_malloc_lock;
299 __syscalls.malloc_unlock = __libogc_malloc_unlock;
300 __syscalls.exit = __libogc_exit;
301 __syscalls.gettod_r = __libogc_gettod_r;
305 static alarm_st* __lwp_syswd_allocate()
307 alarm_st *alarm;
309 __lwp_thread_dispatchdisable();
310 alarm = (alarm_st*)__lwp_objmgr_allocate(&sys_alarm_objects);
311 if(alarm) {
312 __lwp_objmgr_open(&sys_alarm_objects,&alarm->object);
313 return alarm;
315 __lwp_thread_dispatchenable();
316 return NULL;
319 static s32 __mem_onreset(s32 final)
321 if(final==TRUE) {
322 _memReg[8] = 255;
323 __UnmaskIrq(IM_MEM0|IM_MEM1|IM_MEM2|IM_MEM3);
325 return 1;
328 static void __sys_alarmhandler(void *arg)
330 alarm_st *alarm;
331 syswd_t thealarm = (syswd_t)arg;
333 if(thealarm==SYS_WD_NULL || LWP_OBJTYPE(thealarm)!=LWP_OBJTYPE_SYSWD) return;
335 __lwp_thread_dispatchdisable();
336 alarm = (alarm_st*)__lwp_objmgr_getnoprotection(&sys_alarm_objects,LWP_OBJMASKID(thealarm));
337 if(alarm) {
338 if(alarm->alarmhandler) alarm->alarmhandler(thealarm,alarm->cb_arg);
339 if(alarm->periodic) __lwp_wd_insert_ticks(&alarm->alarm,alarm->periodic);
341 __lwp_thread_dispatchunnest();
344 #if defined(HW_DOL)
345 static void __dohotreset(u32 resetcode)
347 u32 level;
349 _CPU_ISR_Disable(level);
350 _viReg[1] = 0;
351 ICFlashInvalidate();
352 __reset(resetcode<<3);
354 #endif
356 static s32 __call_resetfuncs(s32 final)
358 s32 ret;
359 sys_resetinfo *info;
360 lwp_queue *header = &sys_reset_func_queue;
362 ret = 1;
363 info = (sys_resetinfo*)header->first;
364 while(info!=(sys_resetinfo*)__lwp_queue_tail(header)) {
365 if(info->func && info->func(final)==0) ret |= (ret<<1);
366 info = (sys_resetinfo*)info->node.next;
368 if(__sram_sync()==0) ret |= (ret<<1);
370 if(ret&~0x01) return 0;
371 return 1;
374 #if defined(HW_DOL)
375 static void __doreboot(u32 resetcode,s32 force_menu)
377 u32 level;
379 _CPU_ISR_Disable(level);
381 *((u32*)0x817ffffc) = 0;
382 *((u32*)0x817ffff8) = 0;
383 *((u32*)0x800030e2) = 1;
385 #endif
387 static void __MEMInterruptHandler()
389 _memReg[16] = 0;
392 static void __RSWDefaultHandler()
397 #if defined(HW_RVL)
398 static void __POWDefaultHandler()
401 #endif
403 #if defined(HW_DOL)
404 static void __RSWHandler()
406 s64 now;
407 static u32 down = 0;
408 static u32 last_state = 0;
409 static s64 hold_down = 0;
411 hold_down = gettime();
412 do {
413 now = gettime();
414 if(diff_usec(hold_down,now)>=100) break;
415 } while(!(_piReg[0]&0x10000));
417 if(_piReg[0]&0x10000) {
418 down = 0;
419 last_state = 1;
420 __MaskIrq(IRQMASK(IRQ_PI_RSW));
423 if(__RSWCallback) {
424 __RSWCallback();
427 _piReg[0] = 2;
429 #endif
431 #if defined(HW_RVL)
432 static void __STMEventHandler(u32 event)
434 s32 ret;
435 u32 level;
437 if(event==STM_EVENT_RESET) {
438 ret = SYS_ResetButtonDown();
439 if(ret) {
440 _CPU_ISR_Disable(level);
441 __sys_resetdown = 1;
442 __RSWCallback();
443 _CPU_ISR_Restore(level);
447 if(event==STM_EVENT_POWER) {
448 _CPU_ISR_Disable(level);
449 __POWCallback();
450 _CPU_ISR_Restore(level);
453 #endif
455 void * __attribute__ ((weak)) __myArena1Lo = 0;
456 void * __attribute__ ((weak)) __myArena1Hi = 0;
458 static void __lowmem_init()
460 u32 *_gx = (u32*)__gxregs;
462 #if defined(HW_DOL)
463 void *ram_start = (void*)0x80000000;
464 void *ram_end = (void*)(0x80000000|SYSMEM1_SIZE);
465 void *arena_start = (void*)0x80003000;
466 #elif defined(HW_RVL)
467 void *arena_start = (void*)0x80003F00;
468 #endif
470 memset(_gx,0,2048);
471 memset(arena_start,0,0x100);
472 if ( __argvArena1Lo == (u8*)0xdeadbeef ) __argvArena1Lo = __Arena1Lo;
473 if (__myArena1Lo == 0) __myArena1Lo = __argvArena1Lo;
474 if (__myArena1Hi == 0) __myArena1Hi = __Arena1Hi;
476 #if defined(HW_DOL)
477 memset(ram_start,0,0x100);
478 *((u32*)(ram_start+0x20)) = 0x0d15ea5e; // magic word "disease"
479 *((u32*)(ram_start+0x24)) = 1; // version
480 *((u32*)(ram_start+0x28)) = SYSMEM1_SIZE; // physical memory size
481 *((u32*)(ram_start+0x2C)) = 1 + ((*(u32*)0xCC00302c)>>28);
483 *((u32*)(ram_start+0x30)) = (u32)__myArena1Lo;
484 *((u32*)(ram_start+0x34)) = (u32)__myArena1Hi;
486 *((u32*)(ram_start+0xEC)) = (u32)ram_end; // ram_end (??)
487 *((u32*)(ram_start+0xF0)) = SYSMEM1_SIZE; // simulated memory size
488 *((u32*)(ram_start+0xF8)) = TB_BUS_CLOCK; // bus speed: 162 MHz
489 *((u32*)(ram_start+0xFC)) = TB_CORE_CLOCK; // cpu speed: 486 Mhz
491 *((u16*)(arena_start+0xE0)) = 6; // production pads
492 *((u32*)(arena_start+0xE4)) = 0xC0008000;
494 DCFlushRangeNoSync(ram_start, 0x100);
495 #endif
497 DCFlushRangeNoSync(arena_start, 0x100);
498 DCFlushRangeNoSync(_gx, 2048);
499 _sync();
501 SYS_SetArenaLo((void*)__myArena1Lo);
502 SYS_SetArenaHi((void*)__myArena1Hi);
503 #if defined(HW_RVL)
504 SYS_SetArena2Lo((void*)__Arena2Lo);
505 SYS_SetArena2Hi((void*)__Arena2Hi);
506 #endif
509 #if defined(HW_RVL)
510 static void __ipcbuffer_init()
512 __ipcbufferlo = (void*)__ipcbufferLo;
513 __ipcbufferhi = (void*)__ipcbufferHi;
515 #endif
517 static void __bat_config()
519 u32 realmem1 = SYSMEM1_SIZE;
520 u32 simmem1 = SYSMEM1_SIZE;
521 #if defined(HW_RVL)
522 u32 simmem2 = SYSMEM2_SIZE;
523 #endif
525 if(simmem1<realmem1 && !(simmem1-0x1800000)) {
526 DCInvalidateRange((void*)0x81800000,0x01800000);
527 _memReg[20] = 2;
530 if(simmem1<=0x01800000) __realmode(__configMEM1_24Mb);
531 else if(simmem1<=0x03000000) __realmode(__configMEM1_48Mb);
533 #if defined(HW_RVL)
534 if(simmem2<=0x04000000) __realmode(__configMEM2_64Mb);
535 else if(simmem2<=0x08000000) __realmode(__configMEM2_128Mb);
536 #endif
539 static void __memprotect_init()
541 u32 level;
543 _CPU_ISR_Disable(level);
545 __MaskIrq((IM_MEM0|IM_MEM1|IM_MEM2|IM_MEM3));
547 _memReg[16] = 0;
548 _memReg[8] = 255;
550 IRQ_Request(IRQ_MEM0,__MEMInterruptHandler,NULL);
551 IRQ_Request(IRQ_MEM1,__MEMInterruptHandler,NULL);
552 IRQ_Request(IRQ_MEM2,__MEMInterruptHandler,NULL);
553 IRQ_Request(IRQ_MEM3,__MEMInterruptHandler,NULL);
554 IRQ_Request(IRQ_MEMADDRESS,__MEMInterruptHandler,NULL);
556 SYS_RegisterResetFunc(&mem_resetinfo);
557 __bat_config();
558 __UnmaskIrq(IM_MEMADDRESS); //only enable memaddress irq atm
560 _CPU_ISR_Restore(level);
563 static __inline__ u32 __get_fontsize(void *buffer)
565 u8 *ptr = (u8*)buffer;
567 if(ptr[0]=='Y' && ptr[1]=='a' && ptr[2]=='y') return (((u32*)ptr)[1]);
568 else return 0;
571 static u32 __read_rom(void *buf,u32 len,u32 offset)
573 u32 ret;
574 u32 loff;
576 DCInvalidateRange(buf,len);
578 if(EXI_Lock(EXI_CHANNEL_0,EXI_DEVICE_1,NULL)==0) return 0;
579 if(EXI_Select(EXI_CHANNEL_0,EXI_DEVICE_1,EXI_SPEED8MHZ)==0) {
580 EXI_Unlock(EXI_CHANNEL_0);
581 return 0;
584 ret = 0;
585 loff = offset<<6;
586 if(EXI_Imm(EXI_CHANNEL_0,&loff,4,EXI_WRITE,NULL)==0) ret |= 0x0001;
587 if(EXI_Sync(EXI_CHANNEL_0)==0) ret |= 0x0002;
588 if(EXI_Dma(EXI_CHANNEL_0,buf,len,EXI_READ,NULL)==0) ret |= 0x0004;
589 if(EXI_Sync(EXI_CHANNEL_0)==0) ret |= 0x0008;
590 if(EXI_Deselect(EXI_CHANNEL_0)==0) ret |= 0x0010;
591 if(EXI_Unlock(EXI_CHANNEL_0)==0) ret |= 0x00020;
593 if(ret) return 0;
594 return 1;
597 static u32 __getrtc(u32 *gctime)
599 u32 ret;
600 u32 cmd;
601 u32 time;
603 if(EXI_Lock(EXI_CHANNEL_0,EXI_DEVICE_1,NULL)==0) return 0;
604 if(EXI_Select(EXI_CHANNEL_0,EXI_DEVICE_1,EXI_SPEED8MHZ)==0) {
605 EXI_Unlock(EXI_CHANNEL_0);
606 return 0;
609 ret = 0;
610 time = 0;
611 cmd = 0x20000000;
612 if(EXI_Imm(EXI_CHANNEL_0,&cmd,4,EXI_WRITE,NULL)==0) ret |= 0x01;
613 if(EXI_Sync(EXI_CHANNEL_0)==0) ret |= 0x02;
614 if(EXI_Imm(EXI_CHANNEL_0,&time,4,EXI_READ,NULL)==0) ret |= 0x04;
615 if(EXI_Sync(EXI_CHANNEL_0)==0) ret |= 0x08;
616 if(EXI_Deselect(EXI_CHANNEL_0)==0) ret |= 0x10;
618 EXI_Unlock(EXI_CHANNEL_0);
619 *gctime = time;
620 if(ret) return 0;
622 return 1;
625 static u32 __sram_read(void *buffer)
627 u32 command,ret;
629 DCInvalidateRange(buffer,64);
631 if(EXI_Lock(EXI_CHANNEL_0,EXI_DEVICE_1,NULL)==0) return 0;
632 if(EXI_Select(EXI_CHANNEL_0,EXI_DEVICE_1,EXI_SPEED8MHZ)==0) {
633 EXI_Unlock(EXI_CHANNEL_0);
634 return 0;
637 ret = 0;
638 command = 0x20000100;
639 if(EXI_Imm(EXI_CHANNEL_0,&command,4,EXI_WRITE,NULL)==0) ret |= 0x01;
640 if(EXI_Sync(EXI_CHANNEL_0)==0) ret |= 0x02;
641 if(EXI_Dma(EXI_CHANNEL_0,buffer,64,EXI_READ,NULL)==0) ret |= 0x04;
642 if(EXI_Sync(EXI_CHANNEL_0)==0) ret |= 0x08;
643 if(EXI_Deselect(EXI_CHANNEL_0)==0) ret |= 0x10;
644 if(EXI_Unlock(EXI_CHANNEL_0)==0) ret |= 0x20;
646 if(ret) return 0;
647 return 1;
650 static u32 __sram_write(void *buffer,u32 loc,u32 len)
652 u32 cmd,ret;
654 if(EXI_Lock(EXI_CHANNEL_0,EXI_DEVICE_1,__sram_writecallback)==0) return 0;
655 if(EXI_Select(EXI_CHANNEL_0,EXI_DEVICE_1,EXI_SPEED8MHZ)==0) {
656 EXI_Unlock(EXI_CHANNEL_0);
657 return 0;
660 ret = 0;
661 cmd = 0xa0000100+(loc<<6);
662 if(EXI_Imm(EXI_CHANNEL_0,&cmd,4,EXI_WRITE,NULL)==0) ret |= 0x01;
663 if(EXI_Sync(EXI_CHANNEL_0)==0) ret |= 0x02;
664 if(EXI_ImmEx(EXI_CHANNEL_0,buffer,len,EXI_WRITE)==0) ret |= 0x04;
665 if(EXI_Deselect(EXI_CHANNEL_0)==0) ret |= 0x08;
666 if(EXI_Unlock(EXI_CHANNEL_0)==0) ret |= 0x10;
668 if(ret) return 0;
669 return 1;
672 static s32 __sram_writecallback(s32 chn,s32 dev)
674 sramcntrl.sync = __sram_write(sramcntrl.srambuf+sramcntrl.offset,sramcntrl.offset,(64-sramcntrl.offset));
675 if(sramcntrl.sync) sramcntrl.offset = 64;
677 return 1;
680 static s32 __sram_sync()
682 return sramcntrl.sync;
685 void __sram_init()
687 sramcntrl.enabled = 0;
688 sramcntrl.locked = 0;
689 sramcntrl.sync = __sram_read(sramcntrl.srambuf);
691 sramcntrl.offset = 64;
694 static void DisableWriteGatherPipe()
696 mtspr(920,(mfspr(920)&~0x40000000));
699 static void __buildchecksum(u16 *buffer,u16 *c1,u16 *c2)
701 u32 i;
703 *c1 = 0;
704 *c2 = 0;
705 for(i=0;i<4;i++) {
706 *c1 += buffer[6+i];
707 *c2 += buffer[6+i]^-1;
711 static void* __locksram(u32 loc)
713 u32 level;
715 _CPU_ISR_Disable(level);
716 if(!sramcntrl.locked) {
717 sramcntrl.enabled = level;
718 sramcntrl.locked = 1;
719 return (void*)((u32)sramcntrl.srambuf+loc);
721 _CPU_ISR_Restore(level);
722 return NULL;
725 static u32 __unlocksram(u32 write,u32 loc)
727 syssram *sram = (syssram*)sramcntrl.srambuf;
729 if(write) {
730 if(!loc) {
731 if((sram->flags&0x03)>0x02) sram->flags = (sram->flags&~0x03);
732 __buildchecksum((u16*)sramcntrl.srambuf,&sram->checksum,&sram->checksum_inv);
734 if(loc<sramcntrl.offset) sramcntrl.offset = loc;
736 sramcntrl.sync = __sram_write(sramcntrl.srambuf+sramcntrl.offset,sramcntrl.offset,(64-sramcntrl.offset));
737 if(sramcntrl.sync) sramcntrl.offset = 64;
739 sramcntrl.locked = 0;
740 _CPU_ISR_Restore(sramcntrl.enabled);
741 return sramcntrl.sync;
744 //returns the size of font
745 static u32 __read_font(void *buffer)
747 if(SYS_GetFontEncoding()==1) __SYS_ReadROM(buffer,315392,1769216);
748 else __SYS_ReadROM(buffer,12288,2084608);
749 return __get_fontsize(buffer);
752 static void __expand_font(const u8 *src,u8 *dest)
754 s32 cnt;
755 u32 idx;
756 u8 val1,val2;
757 u8 *data = (u8*)sys_fontdata+44;
759 if(sys_fontdata->sheet_format==0x0000) {
760 cnt = (sys_fontdata->sheet_fullsize/2)-1;
762 while(cnt>=0) {
763 idx = _SHIFTR(src[cnt],6,2);
764 val1 = data[idx];
766 idx = _SHIFTR(src[cnt],4,2);
767 val2 = data[idx];
769 dest[(cnt<<1)+0] =((val1&0xf0)|(val2&0x0f));
771 idx = _SHIFTR(src[cnt],2,2);
772 val1 = data[idx];
774 idx = _SHIFTR(src[cnt],0,2);
775 val2 = data[idx];
777 dest[(cnt<<1)+1] =((val1&0xf0)|(val2&0x0f));
779 cnt--;
782 DCStoreRange(dest,sys_fontdata->sheet_fullsize);
785 static void __dsp_bootstrap()
787 u16 status;
788 u32 tick;
790 memcpy(SYS_GetArenaHi()-128,(void*)0x81000000,128);
791 memcpy((void*)0x81000000,_dsp_initcode,128);
792 DCFlushRange((void*)0x81000000,128);
794 _dspReg[9] = 67;
795 _dspReg[5] = (DSPCR_DSPRESET|DSPCR_DSPINT|DSPCR_ARINT|DSPCR_AIINT|DSPCR_HALT);
796 _dspReg[5] |= DSPCR_RES;
797 while(_dspReg[5]&DSPCR_RES);
799 _dspReg[0] = 0;
800 while((_SHIFTL(_dspReg[2],16,16)|(_dspReg[3]&0xffff))&0x80000000);
802 ((u32*)_dspReg)[8] = 0x01000000;
803 ((u32*)_dspReg)[9] = 0;
804 ((u32*)_dspReg)[10] = 32;
806 status = _dspReg[5];
807 while(!(status&DSPCR_ARINT)) status = _dspReg[5];
808 _dspReg[5] = status;
810 tick = gettick();
811 while((gettick()-tick)<2194);
813 ((u32*)_dspReg)[8] = 0x01000000;
814 ((u32*)_dspReg)[9] = 0;
815 ((u32*)_dspReg)[10] = 32;
817 status = _dspReg[5];
818 while(!(status&DSPCR_ARINT)) status = _dspReg[5];
819 _dspReg[5] = status;
821 _dspReg[5] &= ~DSPCR_DSPRESET;
822 while(_dspReg[5]&0x400);
824 _dspReg[5] &= ~DSPCR_HALT;
825 while(!(_dspReg[2]&0x8000));
826 status = _dspReg[3];
828 _dspReg[5] |= DSPCR_HALT;
829 _dspReg[5] = (DSPCR_DSPRESET|DSPCR_DSPINT|DSPCR_ARINT|DSPCR_AIINT|DSPCR_HALT);
830 _dspReg[5] |= DSPCR_RES;
831 while(_dspReg[5]&DSPCR_RES);
833 memcpy((void*)0x81000000,SYS_GetArenaHi()-128,128);
834 #ifdef _SYS_DEBUG
835 printf("__audiosystem_init(finish)\n");
836 #endif
839 static void __dsp_shutdown()
841 u32 tick;
843 _dspReg[5] = (DSPCR_DSPRESET|DSPCR_HALT);
844 _dspReg[27] &= ~0x8000;
845 while(_dspReg[5]&0x400);
846 while(_dspReg[5]&0x200);
848 _dspReg[5] = (DSPCR_DSPRESET|DSPCR_DSPINT|DSPCR_ARINT|DSPCR_AIINT|DSPCR_HALT);
849 _dspReg[0] = 0;
850 while((_SHIFTL(_dspReg[2],16,16)|(_dspReg[3]&0xffff))&0x80000000);
852 tick = gettick();
853 while((gettick()-tick)<44);
855 _dspReg[5] |= DSPCR_RES;
856 while(_dspReg[5]&DSPCR_RES);
859 static void decode_szp(void *src,void *dest)
861 u32 i,k,link;
862 u8 *dest8,*tmp;
863 u32 loff,coff,roff;
864 u32 size,cnt,cmask,bcnt;
865 yay0header *header;
867 dest8 = (u8*)dest;
868 header = (yay0header*)src;
869 size = header->dec_size;
870 loff = header->links_offset;
871 coff = header->chunks_offset;
873 roff = sizeof(yay0header);
874 cmask = 0;
875 cnt = 0;
876 bcnt = 0;
878 do {
879 if(!bcnt) {
880 cmask = *(u32*)(src+roff);
881 roff += 4;
882 bcnt = 32;
885 if(cmask&0x80000000) {
886 dest8[cnt++] = *(u8*)(src+coff);
887 coff++;
888 } else {
889 link = *(u16*)(src+loff);
890 loff += 2;
892 tmp = dest8+(cnt-(link&0x0fff)-1);
893 k = link>>12;
894 if(k==0) {
895 k = (*(u8*)(src+coff))+18;
896 coff++;
897 } else k += 2;
899 for(i=0;i<k;i++) {
900 dest8[cnt++] = tmp[i];
903 cmask <<= 1;
904 bcnt--;
905 } while(cnt<size);
908 syssram* __SYS_LockSram()
910 return (syssram*)__locksram(0);
913 syssramex* __SYS_LockSramEx()
915 return (syssramex*)__locksram(sizeof(syssram));
918 u32 __SYS_UnlockSram(u32 write)
920 return __unlocksram(write,0);
923 u32 __SYS_UnlockSramEx(u32 write)
925 return __unlocksram(write,sizeof(syssram));
928 u32 __SYS_SyncSram()
930 return __sram_sync();
933 void __SYS_ReadROM(void *buf,u32 len,u32 offset)
935 u32 cpy_cnt;
937 while(len>0) {
938 cpy_cnt = (len>256)?256:len;
939 while(__read_rom(buf,cpy_cnt,offset)==0);
940 offset += cpy_cnt;
941 buf += cpy_cnt;
942 len -= cpy_cnt;
946 u32 __SYS_GetRTC(u32 *gctime)
948 u32 cnt,ret;
949 u32 time1,time2;
951 cnt = 0;
952 ret = 0;
953 while(cnt<16) {
954 if(__getrtc(&time1)==0) ret |= 0x01;
955 if(__getrtc(&time2)==0) ret |= 0x02;
956 if(ret) return 0;
957 if(time1==time2) {
958 *gctime = time1;
959 return 1;
961 cnt++;
963 return 0;
966 void __SYS_SetTime(s64 time)
968 u32 level;
969 s64 now;
970 s64 *pBootTime = (s64*)0x800030d8;
972 _CPU_ISR_Disable(level);
973 now = gettime();
974 now -= time;
975 now += *pBootTime;
976 *pBootTime = now;
977 settime(now);
978 EXI_ProbeReset();
979 _CPU_ISR_Restore(level);
982 s64 __SYS_GetSystemTime()
984 u32 level;
985 s64 now;
986 s64 *pBootTime = (s64*)0x800030d8;
988 _CPU_ISR_Disable(level);
989 now = gettime();
990 now += *pBootTime;
991 _CPU_ISR_Restore(level);
992 return now;
995 void __SYS_SetBootTime()
997 syssram *sram;
998 u32 gctime;
1000 sram = __SYS_LockSram();
1001 __SYS_GetRTC(&gctime);
1002 __SYS_SetTime(secs_to_ticks(gctime));
1003 __SYS_UnlockSram(0);
1006 u32 __SYS_LoadFont(void *src,void *dest)
1008 if(__read_font(src)==0) return 0;
1010 decode_szp(src,dest);
1012 sys_fontdata = (sys_fontheader*)dest;
1013 sys_fontwidthtab = (u8*)dest+sys_fontdata->width_table;
1014 sys_fontcharsinsheet = sys_fontdata->sheet_column*sys_fontdata->sheet_row;
1016 /* TODO: implement SJIS handling */
1017 return 1;
1020 #if defined(HW_RVL)
1021 void* __SYS_GetIPCBufferLo()
1023 return __ipcbufferlo;
1026 void* __SYS_GetIPCBufferHi()
1028 return __ipcbufferhi;
1031 #endif
1033 void _V_EXPORTNAME(void)
1034 { __sys_versionbuild = _V_STRING; __sys_versiondate = _V_DATE_; }
1036 #if defined(HW_RVL)
1037 void __SYS_DoPowerCB(void)
1039 u32 level;
1040 powercallback powcb;
1042 _CPU_ISR_Disable(level);
1043 powcb = __POWCallback;
1044 __POWCallback = __POWDefaultHandler;
1045 powcb();
1046 _CPU_ISR_Restore(level);
1048 #endif
1050 void __SYS_InitCallbacks()
1052 #if defined(HW_RVL)
1053 __POWCallback = __POWDefaultHandler;
1054 __sys_resetdown = 0;
1055 #endif
1056 __RSWCallback = __RSWDefaultHandler;
1059 void __attribute__((weak)) __SYS_PreInit()
1064 void SYS_Init()
1066 __SYS_PreInit();
1068 u32 level;
1070 _CPU_ISR_Disable(level);
1072 if(system_initialized) return;
1073 system_initialized = 1;
1075 _V_EXPORTNAME();
1077 __init_syscall_array();
1078 __lowmem_init();
1079 #if defined(HW_RVL)
1080 __ipcbuffer_init();
1081 #endif
1082 __lwp_wkspace_init(KERNEL_HEAP);
1083 __lwp_queue_init_empty(&sys_reset_func_queue);
1084 __lwp_objmgr_initinfo(&sys_alarm_objects,LWP_MAX_WATCHDOGS,sizeof(alarm_st));
1085 __sys_state_init();
1086 __lwp_priority_init();
1087 __lwp_watchdog_init();
1088 __exception_init();
1089 __systemcall_init();
1090 __decrementer_init();
1091 __irq_init();
1092 __exi_init();
1093 __sram_init();
1094 __si_init();
1095 __lwp_thread_coreinit();
1096 __lwp_sysinit();
1097 __memlock_init();
1098 __lwp_mqbox_init();
1099 __lwp_sema_init();
1100 __lwp_mutex_init();
1101 __lwp_cond_init();
1102 __timesystem_init();
1103 __dsp_bootstrap();
1105 if(!__sys_inIPL)
1106 __memprotect_init();
1108 #ifdef SDLOADER_FIX
1109 __SYS_SetBootTime();
1110 #endif
1111 DisableWriteGatherPipe();
1112 __SYS_InitCallbacks();
1113 #if defined(HW_RVL)
1114 __IPC_ClntInit();
1115 #elif defined(HW_DOL)
1116 IRQ_Request(IRQ_PI_RSW,__RSWHandler,NULL);
1117 __MaskIrq(IRQMASK(IRQ_PI_RSW));
1118 #endif
1119 __libc_init(1);
1120 __lwp_thread_startmultitasking();
1121 _CPU_ISR_Restore(level);
1124 // This function gets called inside the main thread, prior to the application's main() function
1125 void SYS_PreMain()
1127 #if defined(HW_RVL)
1128 u32 i;
1130 for (i = 0; i < 32; ++i)
1131 IOS_Close(i);
1133 __IOS_LoadStartupIOS();
1134 __IOS_InitializeSubsystems();
1135 STM_RegisterEventHandler(__STMEventHandler);
1136 CONF_Init();
1137 WII_Initialize();
1138 #endif
1141 u32 SYS_ResetButtonDown()
1143 return (!(_piReg[0]&0x00010000));
1146 #if defined(HW_DOL)
1147 void SYS_ResetSystem(s32 reset,u32 reset_code,s32 force_menu)
1149 u32 level,ret = 0;
1150 syssram *sram;
1152 __dsp_shutdown();
1154 if(reset==SYS_SHUTDOWN) {
1155 ret = __PADDisableRecalibration(TRUE);
1158 while(__call_resetfuncs(FALSE)==0);
1160 if(reset==SYS_HOTRESET && force_menu==TRUE) {
1161 sram = __SYS_LockSram();
1162 sram->flags |= 0x40;
1163 __SYS_UnlockSram(TRUE);
1164 while(!__SYS_SyncSram());
1167 _CPU_ISR_Disable(level);
1168 __call_resetfuncs(TRUE);
1170 LCDisable();
1172 __lwp_thread_dispatchdisable();
1173 if(reset==SYS_HOTRESET) {
1174 __dohotreset(reset_code);
1175 } else if(reset==SYS_RESTART) {
1176 __lwp_thread_closeall();
1177 __lwp_thread_dispatchunnest();
1178 __doreboot(reset_code,force_menu);
1181 __lwp_thread_closeall();
1183 memset((void*)0x80000040,0,140);
1184 memset((void*)0x800000D4,0,20);
1185 memset((void*)0x800000F4,0,4);
1186 memset((void*)0x80003000,0,192);
1187 memset((void*)0x800030C8,0,12);
1188 memset((void*)0x800030E2,0,1);
1190 __PADDisableRecalibration(ret);
1192 #endif
1194 #if defined(HW_RVL)
1196 void SYS_ResetSystem(s32 reset,u32 reset_code,s32 force_menu)
1198 u32 level,ret = 0;
1200 __dsp_shutdown();
1202 if(reset==SYS_SHUTDOWN) {
1203 ret = __PADDisableRecalibration(TRUE);
1206 while(__call_resetfuncs(FALSE)==0);
1208 switch(reset) {
1209 case SYS_RESTART:
1210 STM_RebootSystem();
1211 break;
1212 case SYS_POWEROFF:
1213 if(CONF_GetShutdownMode() == CONF_SHUTDOWN_IDLE) {
1214 ret = CONF_GetIdleLedMode();
1215 if(ret <= 2) STM_SetLedMode(ret);
1216 STM_ShutdownToIdle();
1217 } else {
1218 STM_ShutdownToStandby();
1220 break;
1221 case SYS_POWEROFF_STANDBY:
1222 STM_ShutdownToStandby();
1223 break;
1224 case SYS_POWEROFF_IDLE:
1225 ret = CONF_GetIdleLedMode();
1226 if(ret >= 0 && ret <= 2) STM_SetLedMode(ret);
1227 STM_ShutdownToIdle();
1228 break;
1229 case SYS_RETURNTOMENU:
1230 WII_ReturnToMenu();
1231 break;
1234 //TODO: implement SYS_HOTRESET
1235 // either restart failed or this is SYS_SHUTDOWN
1237 __IOS_ShutdownSubsystems();
1239 _CPU_ISR_Disable(level);
1240 __call_resetfuncs(TRUE);
1242 LCDisable();
1244 __lwp_thread_dispatchdisable();
1245 __lwp_thread_closeall();
1247 memset((void*)0x80000040,0,140);
1248 memset((void*)0x800000D4,0,20);
1249 memset((void*)0x800000F4,0,4);
1250 memset((void*)0x80003000,0,192);
1251 memset((void*)0x800030C8,0,12);
1252 memset((void*)0x800030E2,0,1);
1254 __PADDisableRecalibration(ret);
1256 #endif
1258 void SYS_RegisterResetFunc(sys_resetinfo *info)
1260 u32 level;
1261 sys_resetinfo *after;
1262 lwp_queue *header = &sys_reset_func_queue;
1264 _CPU_ISR_Disable(level);
1265 for(after=(sys_resetinfo*)header->first;after->node.next!=NULL && info->prio>=after->prio;after=(sys_resetinfo*)after->node.next);
1266 __lwp_queue_insertI(after->node.prev,&info->node);
1267 _CPU_ISR_Restore(level);
1270 void SYS_UnregisterResetFunc(sys_resetinfo *info) {
1271 u32 level;
1272 lwp_node *n;
1274 _CPU_ISR_Disable(level);
1275 for (n = sys_reset_func_queue.first; n->next; n = n->next) {
1276 if (n == &info->node) {
1277 __lwp_queue_extractI(n);
1278 break;
1281 _CPU_ISR_Restore(level);
1284 void SYS_SetArena1Lo(void *newLo)
1286 u32 level;
1288 _CPU_ISR_Disable(level);
1289 __sysarena1lo = newLo;
1290 _CPU_ISR_Restore(level);
1293 void* SYS_GetArena1Lo()
1295 u32 level;
1296 void *arenalo;
1298 _CPU_ISR_Disable(level);
1299 arenalo = __sysarena1lo;
1300 _CPU_ISR_Restore(level);
1302 return arenalo;
1305 void SYS_SetArena1Hi(void *newHi)
1307 u32 level;
1309 _CPU_ISR_Disable(level);
1310 __sysarena1hi = newHi;
1311 _CPU_ISR_Restore(level);
1314 void* SYS_GetArena1Hi()
1316 u32 level;
1317 void *arenahi;
1319 _CPU_ISR_Disable(level);
1320 arenahi = __sysarena1hi;
1321 _CPU_ISR_Restore(level);
1323 return arenahi;
1326 u32 SYS_GetArena1Size()
1328 u32 level,size;
1330 _CPU_ISR_Disable(level);
1331 size = ((u32)__sysarena1hi - (u32)__sysarena1lo);
1332 _CPU_ISR_Restore(level);
1334 return size;
1337 void* SYS_AllocArena1MemLo(u32 size,u32 align)
1339 u32 mem1lo;
1340 void *ptr = NULL;
1342 mem1lo = (u32)SYS_GetArena1Lo();
1343 ptr = (void*)((mem1lo+(align-1))&~(align-1));
1344 mem1lo = ((((u32)ptr+size+align)-1)&~(align-1));
1345 SYS_SetArena1Lo((void*)mem1lo);
1347 return ptr;
1350 #if defined(HW_RVL)
1351 void SYS_SetArena2Lo(void *newLo)
1353 u32 level;
1355 _CPU_ISR_Disable(level);
1356 __sysarena2lo = newLo;
1357 _CPU_ISR_Restore(level);
1360 void* SYS_GetArena2Lo()
1362 u32 level;
1363 void *arenalo;
1365 _CPU_ISR_Disable(level);
1366 arenalo = __sysarena2lo;
1367 _CPU_ISR_Restore(level);
1369 return arenalo;
1372 void SYS_SetArena2Hi(void *newHi)
1374 u32 level;
1376 _CPU_ISR_Disable(level);
1377 __sysarena2hi = newHi;
1378 _CPU_ISR_Restore(level);
1381 void* SYS_GetArena2Hi()
1383 u32 level;
1384 void *arenahi;
1386 _CPU_ISR_Disable(level);
1387 arenahi = __sysarena2hi;
1388 _CPU_ISR_Restore(level);
1390 return arenahi;
1393 u32 SYS_GetArena2Size()
1395 u32 level,size;
1397 _CPU_ISR_Disable(level);
1398 size = ((u32)__sysarena2hi - (u32)__sysarena2lo);
1399 _CPU_ISR_Restore(level);
1401 return size;
1404 void* SYS_AllocArena2MemLo(u32 size,u32 align)
1406 u32 mem2lo;
1407 void *ptr = NULL;
1409 mem2lo = (u32)SYS_GetArena2Lo();
1410 ptr = (void*)((mem2lo+(align-1))&~(align-1));
1411 mem2lo = ((((u32)ptr+size+align)-1)&~(align-1));
1412 SYS_SetArena2Lo((void*)mem2lo);
1414 return ptr;
1416 #endif
1418 void SYS_ProtectRange(u32 chan,void *addr,u32 bytes,u32 cntrl)
1420 u16 rcntrl;
1421 u32 pstart,pend,level;
1423 if(chan<SYS_PROTECTCHANMAX) {
1424 pstart = ((u32)addr)&~0x3ff;
1425 pend = ((((u32)addr)+bytes)+1023)&~0x3ff;
1426 DCFlushRange((void*)pstart,(pend-pstart));
1428 _CPU_ISR_Disable(level);
1430 __UnmaskIrq(IRQMASK(chan));
1431 _memReg[chan<<2] = _SHIFTR(pstart,10,16);
1432 _memReg[(chan<<2)+1] = _SHIFTR(pend,10,16);
1434 rcntrl = _memReg[8];
1435 rcntrl = (rcntrl&~(_SHIFTL(3,(chan<<1),2)))|(_SHIFTL(cntrl,(chan<<1),2));
1436 _memReg[8] = rcntrl;
1438 if(cntrl==SYS_PROTECTRDWR)
1439 __MaskIrq(IRQMASK(chan));
1442 _CPU_ISR_Restore(level);
1446 void* SYS_AllocateFramebuffer(GXRModeObj *rmode)
1448 return memalign(32, VIDEO_GetFrameBufferSize(rmode));
1451 u32 SYS_GetFontEncoding()
1453 u32 ret,tv_mode;
1455 if(sys_fontenc<=0x0001) return sys_fontenc;
1457 ret = 0;
1458 tv_mode = VIDEO_GetCurrentTvMode();
1459 if(tv_mode==VI_NTSC && _viReg[55]&0x0002) ret = 1;
1460 sys_fontenc = ret;
1461 return ret;
1464 u32 SYS_InitFont(sys_fontheader *font_data)
1466 void *packed_data = NULL;
1468 if(!font_data) return 0;
1470 if(SYS_GetFontEncoding()==1) {
1471 memset(font_data,0,SYS_FONTSIZE_SJIS);
1472 packed_data = (void*)((u32)font_data+868096);
1473 } else {
1474 memset(font_data,0,SYS_FONTSIZE_ANSI);
1475 packed_data = (void*)((u32)font_data+119072);
1478 if(__SYS_LoadFont(packed_data,font_data)==1) {
1479 sys_fontimage = (u8*)((((u32)font_data+font_data->sheet_image)+31)&~31);
1480 __expand_font((u8*)font_data+font_data->sheet_image,sys_fontimage);
1481 return 1;
1484 return 0;
1487 void SYS_GetFontTexture(s32 c,void **image,s32 *xpos,s32 *ypos,s32 *width)
1489 u32 sheets,rem;
1491 *xpos = 0;
1492 *ypos = 0;
1493 *image = NULL;
1494 if(!sys_fontwidthtab || ! sys_fontimage) return;
1496 if(c<sys_fontdata->first_char || c>sys_fontdata->last_char) c = sys_fontdata->inval_char;
1497 else c -= sys_fontdata->first_char;
1499 sheets = c/sys_fontcharsinsheet;
1500 rem = c%sys_fontcharsinsheet;
1501 *image = sys_fontimage+(sys_fontdata->sheet_size*sheets);
1502 *xpos = (rem%sys_fontdata->sheet_column)*sys_fontdata->cell_width;
1503 *ypos = (rem/sys_fontdata->sheet_column)*sys_fontdata->cell_height;
1504 *width = sys_fontwidthtab[c];
1507 void SYS_GetFontTexel(s32 c,void *image,s32 pos,s32 stride,s32 *width)
1509 u32 sheets,rem;
1510 u32 xoff,yoff;
1511 u32 xpos,ypos;
1512 u8 *img_start;
1513 u8 *ptr1,*ptr2;
1515 if(!sys_fontwidthtab || ! sys_fontimage) return;
1517 if(c<sys_fontdata->first_char || c>sys_fontdata->last_char) c = sys_fontdata->inval_char;
1518 else c -= sys_fontdata->first_char;
1520 sheets = c/sys_fontcharsinsheet;
1521 rem = c%sys_fontcharsinsheet;
1522 xoff = (rem%sys_fontdata->sheet_column)*sys_fontdata->cell_width;
1523 yoff = (rem/sys_fontdata->sheet_column)*sys_fontdata->cell_height;
1524 img_start = sys_fontimage+(sys_fontdata->sheet_size*sheets);
1526 ypos = 0;
1527 while(ypos<sys_fontdata->cell_height) {
1528 xpos = 0;
1529 while(xpos<sys_fontdata->cell_width) {
1530 ptr1 = img_start+(((sys_fontdata->sheet_width/8)<<5)*((ypos+yoff)/8));
1531 ptr1 = ptr1+(((xpos+xoff)/8)<<5);
1532 ptr1 = ptr1+(((ypos+yoff)%8)<<2);
1533 ptr1 = ptr1+(((xpos+xoff)%8)/2);
1535 ptr2 = image+((ypos/8)*(((stride<<1)/8)<<5));
1536 ptr2 = ptr2+(((xpos+pos)/8)<<5);
1537 ptr2 = ptr2+(((xpos+pos)%8)/2);
1538 ptr2 = ptr2+((ypos%8)<<2);
1540 *ptr2 = *ptr1;
1542 xpos += 2;
1544 ypos++;
1546 *width = sys_fontwidthtab[c];
1549 s32 SYS_CreateAlarm(syswd_t *thealarm)
1551 alarm_st *alarm;
1553 alarm = __lwp_syswd_allocate();
1554 if(!alarm) return -1;
1556 alarm->alarmhandler = NULL;
1557 alarm->ticks = 0;
1558 alarm->start_per = 0;
1559 alarm->periodic = 0;
1561 *thealarm = (LWP_OBJMASKTYPE(LWP_OBJTYPE_SYSWD)|LWP_OBJMASKID(alarm->object.id));
1562 __lwp_thread_dispatchenable();
1563 return 0;
1566 s32 SYS_SetAlarm(syswd_t thealarm,const struct timespec *tp,alarmcallback cb,void *cbarg)
1568 alarm_st *alarm;
1570 alarm = __lwp_syswd_open(thealarm);
1571 if(!alarm) return -1;
1573 alarm->cb_arg = cbarg;
1574 alarm->alarmhandler = cb;
1575 alarm->ticks = __lwp_wd_calc_ticks(tp);
1577 alarm->periodic = 0;
1578 alarm->start_per = 0;
1580 __lwp_wd_initialize(&alarm->alarm,__sys_alarmhandler,alarm->object.id,(void*)thealarm);
1581 __lwp_wd_insert_ticks(&alarm->alarm,alarm->ticks);
1582 __lwp_thread_dispatchenable();
1583 return 0;
1586 s32 SYS_SetPeriodicAlarm(syswd_t thealarm,const struct timespec *tp_start,const struct timespec *tp_period,alarmcallback cb,void *cbarg)
1588 alarm_st *alarm;
1590 alarm = __lwp_syswd_open(thealarm);
1591 if(!alarm) return -1;
1593 alarm->start_per = __lwp_wd_calc_ticks(tp_start);
1594 alarm->periodic = __lwp_wd_calc_ticks(tp_period);
1595 alarm->alarmhandler = cb;
1596 alarm->cb_arg = cbarg;
1598 alarm->ticks = 0;
1600 __lwp_wd_initialize(&alarm->alarm,__sys_alarmhandler,alarm->object.id,(void*)thealarm);
1601 __lwp_wd_insert_ticks(&alarm->alarm,alarm->start_per);
1602 __lwp_thread_dispatchenable();
1603 return 0;
1606 s32 SYS_RemoveAlarm(syswd_t thealarm)
1608 alarm_st *alarm;
1610 alarm = __lwp_syswd_open(thealarm);
1611 if(!alarm) return -1;
1613 alarm->alarmhandler = NULL;
1614 alarm->ticks = 0;
1615 alarm->periodic = 0;
1616 alarm->start_per = 0;
1618 __lwp_wd_remove_ticks(&alarm->alarm);
1619 __lwp_syswd_free(alarm);
1620 __lwp_thread_dispatchenable();
1621 return 0;
1624 s32 SYS_CancelAlarm(syswd_t thealarm)
1626 alarm_st *alarm;
1628 alarm = __lwp_syswd_open(thealarm);
1629 if(!alarm) return -1;
1631 alarm->alarmhandler = NULL;
1632 alarm->ticks = 0;
1633 alarm->periodic = 0;
1634 alarm->start_per = 0;
1636 __lwp_wd_remove_ticks(&alarm->alarm);
1637 __lwp_thread_dispatchenable();
1638 return 0;
1641 resetcallback SYS_SetResetCallback(resetcallback cb)
1643 u32 level;
1644 resetcallback old;
1646 _CPU_ISR_Disable(level);
1647 old = __RSWCallback;
1648 __RSWCallback = cb;
1649 #if defined(HW_DOL)
1650 if(__RSWCallback) {
1651 _piReg[0] = 2;
1652 __UnmaskIrq(IRQMASK(IRQ_PI_RSW));
1653 } else
1654 __MaskIrq(IRQMASK(IRQ_PI_RSW));
1655 #endif
1656 _CPU_ISR_Restore(level);
1657 return old;
1660 #if defined(HW_RVL)
1661 powercallback SYS_SetPowerCallback(powercallback cb)
1663 u32 level;
1664 powercallback old;
1666 _CPU_ISR_Disable(level);
1667 old = __POWCallback;
1668 __POWCallback = cb;
1669 _CPU_ISR_Restore(level);
1670 return old;
1672 #endif
1674 void SYS_StartPMC(u32 mcr0val,u32 mcr1val)
1676 mtmmcr0(mcr0val);
1677 mtmmcr1(mcr1val);
1680 void SYS_StopPMC()
1682 mtmmcr0(0);
1683 mtmmcr1(0);
1686 void SYS_ResetPMC()
1688 mtpmc1(0);
1689 mtpmc2(0);
1690 mtpmc3(0);
1691 mtpmc4(0);
1694 void SYS_DumpPMC()
1696 printf("<%d load/stores / %d miss cycles / %d cycles / %d instructions>\n",mfpmc1(),mfpmc2(),mfpmc3(),mfpmc4());
1699 void SYS_SetWirelessID(u32 chan,u32 id)
1701 u32 write;
1702 syssramex *sram;
1704 write = 0;
1705 sram = __SYS_LockSramEx();
1706 if(sram->wirelessPad_id[chan]!=(u16)id) {
1707 sram->wirelessPad_id[chan] = (u16)id;
1708 write = 1;
1710 __SYS_UnlockSramEx(write);
1713 u32 SYS_GetWirelessID(u32 chan)
1715 u16 id;
1716 syssramex *sram;
1718 id = 0;
1719 sram = __SYS_LockSramEx();
1720 id = sram->wirelessPad_id[chan];
1721 __SYS_UnlockSramEx(0);
1722 return id;
1725 #if defined(HW_RVL)
1726 u32 SYS_GetHollywoodRevision()
1728 u32 rev;
1729 DCInvalidateRange((void*)0x80003138,8);
1730 rev = *((u32*)0x80003138);
1731 return rev;
1733 #endif