update DI disc code
[libogc.git] / libogc / system.c
blob091afdee1ffc969f46b1140e516963d4a2552028
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 __IOS_LoadStartupIOS();
1129 __IOS_InitializeSubsystems();
1130 STM_RegisterEventHandler(__STMEventHandler);
1131 CONF_Init();
1132 WII_Initialize();
1133 #endif
1136 u32 SYS_ResetButtonDown()
1138 return (!(_piReg[0]&0x00010000));
1141 #if defined(HW_DOL)
1142 void SYS_ResetSystem(s32 reset,u32 reset_code,s32 force_menu)
1144 u32 level,ret = 0;
1145 syssram *sram;
1147 __dsp_shutdown();
1149 if(reset==SYS_SHUTDOWN) {
1150 ret = __PADDisableRecalibration(TRUE);
1153 while(__call_resetfuncs(FALSE)==0);
1155 if(reset==SYS_HOTRESET && force_menu==TRUE) {
1156 sram = __SYS_LockSram();
1157 sram->flags |= 0x40;
1158 __SYS_UnlockSram(TRUE);
1159 while(!__SYS_SyncSram());
1162 _CPU_ISR_Disable(level);
1163 __call_resetfuncs(TRUE);
1165 LCDisable();
1167 __lwp_thread_dispatchdisable();
1168 if(reset==SYS_HOTRESET) {
1169 __dohotreset(reset_code);
1170 } else if(reset==SYS_RESTART) {
1171 __lwp_thread_closeall();
1172 __lwp_thread_dispatchunnest();
1173 __doreboot(reset_code,force_menu);
1176 __lwp_thread_closeall();
1178 memset((void*)0x80000040,0,140);
1179 memset((void*)0x800000D4,0,20);
1180 memset((void*)0x800000F4,0,4);
1181 memset((void*)0x80003000,0,192);
1182 memset((void*)0x800030C8,0,12);
1183 memset((void*)0x800030E2,0,1);
1185 __PADDisableRecalibration(ret);
1187 #endif
1189 #if defined(HW_RVL)
1191 void SYS_ResetSystem(s32 reset,u32 reset_code,s32 force_menu)
1193 u32 level,ret = 0;
1195 __dsp_shutdown();
1197 if(reset==SYS_SHUTDOWN) {
1198 ret = __PADDisableRecalibration(TRUE);
1201 while(__call_resetfuncs(FALSE)==0);
1203 switch(reset) {
1204 case SYS_RESTART:
1205 STM_RebootSystem();
1206 break;
1207 case SYS_POWEROFF:
1208 if(CONF_GetShutdownMode() == CONF_SHUTDOWN_IDLE) {
1209 ret = CONF_GetIdleLedMode();
1210 if(ret <= 2) STM_SetLedMode(ret);
1211 STM_ShutdownToIdle();
1212 } else {
1213 STM_ShutdownToStandby();
1215 break;
1216 case SYS_POWEROFF_STANDBY:
1217 STM_ShutdownToStandby();
1218 break;
1219 case SYS_POWEROFF_IDLE:
1220 ret = CONF_GetIdleLedMode();
1221 if(ret >= 0 && ret <= 2) STM_SetLedMode(ret);
1222 STM_ShutdownToIdle();
1223 break;
1224 case SYS_RETURNTOMENU:
1225 WII_ReturnToMenu();
1226 break;
1229 //TODO: implement SYS_HOTRESET
1230 // either restart failed or this is SYS_SHUTDOWN
1232 __IOS_ShutdownSubsystems();
1234 _CPU_ISR_Disable(level);
1235 __call_resetfuncs(TRUE);
1237 LCDisable();
1239 __lwp_thread_dispatchdisable();
1240 __lwp_thread_closeall();
1242 memset((void*)0x80000040,0,140);
1243 memset((void*)0x800000D4,0,20);
1244 memset((void*)0x800000F4,0,4);
1245 memset((void*)0x80003000,0,192);
1246 memset((void*)0x800030C8,0,12);
1247 memset((void*)0x800030E2,0,1);
1249 __PADDisableRecalibration(ret);
1251 #endif
1253 void SYS_RegisterResetFunc(sys_resetinfo *info)
1255 u32 level;
1256 sys_resetinfo *after;
1257 lwp_queue *header = &sys_reset_func_queue;
1259 _CPU_ISR_Disable(level);
1260 for(after=(sys_resetinfo*)header->first;after->node.next!=NULL && info->prio>=after->prio;after=(sys_resetinfo*)after->node.next);
1261 __lwp_queue_insertI(after->node.prev,&info->node);
1262 _CPU_ISR_Restore(level);
1265 void SYS_UnregisterResetFunc(sys_resetinfo *info) {
1266 u32 level;
1267 lwp_node *n;
1269 _CPU_ISR_Disable(level);
1270 for (n = sys_reset_func_queue.first; n->next; n = n->next) {
1271 if (n == &info->node) {
1272 __lwp_queue_extractI(n);
1273 break;
1276 _CPU_ISR_Restore(level);
1279 void SYS_SetArena1Lo(void *newLo)
1281 u32 level;
1283 _CPU_ISR_Disable(level);
1284 __sysarena1lo = newLo;
1285 _CPU_ISR_Restore(level);
1288 void* SYS_GetArena1Lo()
1290 u32 level;
1291 void *arenalo;
1293 _CPU_ISR_Disable(level);
1294 arenalo = __sysarena1lo;
1295 _CPU_ISR_Restore(level);
1297 return arenalo;
1300 void SYS_SetArena1Hi(void *newHi)
1302 u32 level;
1304 _CPU_ISR_Disable(level);
1305 __sysarena1hi = newHi;
1306 _CPU_ISR_Restore(level);
1309 void* SYS_GetArena1Hi()
1311 u32 level;
1312 void *arenahi;
1314 _CPU_ISR_Disable(level);
1315 arenahi = __sysarena1hi;
1316 _CPU_ISR_Restore(level);
1318 return arenahi;
1321 u32 SYS_GetArena1Size()
1323 u32 level,size;
1325 _CPU_ISR_Disable(level);
1326 size = ((u32)__sysarena1hi - (u32)__sysarena1lo);
1327 _CPU_ISR_Restore(level);
1329 return size;
1332 void* SYS_AllocArena1MemLo(u32 size,u32 align)
1334 u32 mem1lo;
1335 void *ptr = NULL;
1337 mem1lo = (u32)SYS_GetArena1Lo();
1338 ptr = (void*)((mem1lo+(align-1))&~(align-1));
1339 mem1lo = ((((u32)ptr+size+align)-1)&~(align-1));
1340 SYS_SetArena1Lo((void*)mem1lo);
1342 return ptr;
1345 #if defined(HW_RVL)
1346 void SYS_SetArena2Lo(void *newLo)
1348 u32 level;
1350 _CPU_ISR_Disable(level);
1351 __sysarena2lo = newLo;
1352 _CPU_ISR_Restore(level);
1355 void* SYS_GetArena2Lo()
1357 u32 level;
1358 void *arenalo;
1360 _CPU_ISR_Disable(level);
1361 arenalo = __sysarena2lo;
1362 _CPU_ISR_Restore(level);
1364 return arenalo;
1367 void SYS_SetArena2Hi(void *newHi)
1369 u32 level;
1371 _CPU_ISR_Disable(level);
1372 __sysarena2hi = newHi;
1373 _CPU_ISR_Restore(level);
1376 void* SYS_GetArena2Hi()
1378 u32 level;
1379 void *arenahi;
1381 _CPU_ISR_Disable(level);
1382 arenahi = __sysarena2hi;
1383 _CPU_ISR_Restore(level);
1385 return arenahi;
1388 u32 SYS_GetArena2Size()
1390 u32 level,size;
1392 _CPU_ISR_Disable(level);
1393 size = ((u32)__sysarena2hi - (u32)__sysarena2lo);
1394 _CPU_ISR_Restore(level);
1396 return size;
1399 void* SYS_AllocArena2MemLo(u32 size,u32 align)
1401 u32 mem2lo;
1402 void *ptr = NULL;
1404 mem2lo = (u32)SYS_GetArena2Lo();
1405 ptr = (void*)((mem2lo+(align-1))&~(align-1));
1406 mem2lo = ((((u32)ptr+size+align)-1)&~(align-1));
1407 SYS_SetArena2Lo((void*)mem2lo);
1409 return ptr;
1411 #endif
1413 void SYS_ProtectRange(u32 chan,void *addr,u32 bytes,u32 cntrl)
1415 u16 rcntrl;
1416 u32 pstart,pend,level;
1418 if(chan<SYS_PROTECTCHANMAX) {
1419 pstart = ((u32)addr)&~0x3ff;
1420 pend = ((((u32)addr)+bytes)+1023)&~0x3ff;
1421 DCFlushRange((void*)pstart,(pend-pstart));
1423 _CPU_ISR_Disable(level);
1425 __UnmaskIrq(IRQMASK(chan));
1426 _memReg[chan<<2] = _SHIFTR(pstart,10,16);
1427 _memReg[(chan<<2)+1] = _SHIFTR(pend,10,16);
1429 rcntrl = _memReg[8];
1430 rcntrl = (rcntrl&~(_SHIFTL(3,(chan<<1),2)))|(_SHIFTL(cntrl,(chan<<1),2));
1431 _memReg[8] = rcntrl;
1433 if(cntrl==SYS_PROTECTRDWR)
1434 __MaskIrq(IRQMASK(chan));
1437 _CPU_ISR_Restore(level);
1441 void* SYS_AllocateFramebuffer(GXRModeObj *rmode)
1443 return memalign(32, VIDEO_GetFrameBufferSize(rmode));
1446 u32 SYS_GetFontEncoding()
1448 u32 ret,tv_mode;
1450 if(sys_fontenc<=0x0001) return sys_fontenc;
1452 ret = 0;
1453 tv_mode = VIDEO_GetCurrentTvMode();
1454 if(tv_mode==VI_NTSC && _viReg[55]&0x0002) ret = 1;
1455 sys_fontenc = ret;
1456 return ret;
1459 u32 SYS_InitFont(sys_fontheader *font_data)
1461 void *packed_data = NULL;
1463 if(!font_data) return 0;
1465 if(SYS_GetFontEncoding()==1) {
1466 memset(font_data,0,SYS_FONTSIZE_SJIS);
1467 packed_data = (void*)((u32)font_data+868096);
1468 } else {
1469 memset(font_data,0,SYS_FONTSIZE_ANSI);
1470 packed_data = (void*)((u32)font_data+119072);
1473 if(__SYS_LoadFont(packed_data,font_data)==1) {
1474 sys_fontimage = (u8*)((((u32)font_data+font_data->sheet_image)+31)&~31);
1475 __expand_font((u8*)font_data+font_data->sheet_image,sys_fontimage);
1476 return 1;
1479 return 0;
1482 void SYS_GetFontTexture(s32 c,void **image,s32 *xpos,s32 *ypos,s32 *width)
1484 u32 sheets,rem;
1486 *xpos = 0;
1487 *ypos = 0;
1488 *image = NULL;
1489 if(!sys_fontwidthtab || ! sys_fontimage) return;
1491 if(c<sys_fontdata->first_char || c>sys_fontdata->last_char) c = sys_fontdata->inval_char;
1492 else c -= sys_fontdata->first_char;
1494 sheets = c/sys_fontcharsinsheet;
1495 rem = c%sys_fontcharsinsheet;
1496 *image = sys_fontimage+(sys_fontdata->sheet_size*sheets);
1497 *xpos = (rem%sys_fontdata->sheet_column)*sys_fontdata->cell_width;
1498 *ypos = (rem/sys_fontdata->sheet_column)*sys_fontdata->cell_height;
1499 *width = sys_fontwidthtab[c];
1502 void SYS_GetFontTexel(s32 c,void *image,s32 pos,s32 stride,s32 *width)
1504 u32 sheets,rem;
1505 u32 xoff,yoff;
1506 u32 xpos,ypos;
1507 u8 *img_start;
1508 u8 *ptr1,*ptr2;
1510 if(!sys_fontwidthtab || ! sys_fontimage) return;
1512 if(c<sys_fontdata->first_char || c>sys_fontdata->last_char) c = sys_fontdata->inval_char;
1513 else c -= sys_fontdata->first_char;
1515 sheets = c/sys_fontcharsinsheet;
1516 rem = c%sys_fontcharsinsheet;
1517 xoff = (rem%sys_fontdata->sheet_column)*sys_fontdata->cell_width;
1518 yoff = (rem/sys_fontdata->sheet_column)*sys_fontdata->cell_height;
1519 img_start = sys_fontimage+(sys_fontdata->sheet_size*sheets);
1521 ypos = 0;
1522 while(ypos<sys_fontdata->cell_height) {
1523 xpos = 0;
1524 while(xpos<sys_fontdata->cell_width) {
1525 ptr1 = img_start+(((sys_fontdata->sheet_width/8)<<5)*((ypos+yoff)/8));
1526 ptr1 = ptr1+(((xpos+xoff)/8)<<5);
1527 ptr1 = ptr1+(((ypos+yoff)%8)<<2);
1528 ptr1 = ptr1+(((xpos+xoff)%8)/2);
1530 ptr2 = image+((ypos/8)*(((stride<<1)/8)<<5));
1531 ptr2 = ptr2+(((xpos+pos)/8)<<5);
1532 ptr2 = ptr2+(((xpos+pos)%8)/2);
1533 ptr2 = ptr2+((ypos%8)<<2);
1535 *ptr2 = *ptr1;
1537 xpos += 2;
1539 ypos++;
1541 *width = sys_fontwidthtab[c];
1544 s32 SYS_CreateAlarm(syswd_t *thealarm)
1546 alarm_st *alarm;
1548 alarm = __lwp_syswd_allocate();
1549 if(!alarm) return -1;
1551 alarm->alarmhandler = NULL;
1552 alarm->ticks = 0;
1553 alarm->start_per = 0;
1554 alarm->periodic = 0;
1556 *thealarm = (LWP_OBJMASKTYPE(LWP_OBJTYPE_SYSWD)|LWP_OBJMASKID(alarm->object.id));
1557 __lwp_thread_dispatchenable();
1558 return 0;
1561 s32 SYS_SetAlarm(syswd_t thealarm,const struct timespec *tp,alarmcallback cb,void *cbarg)
1563 alarm_st *alarm;
1565 alarm = __lwp_syswd_open(thealarm);
1566 if(!alarm) return -1;
1568 alarm->cb_arg = cbarg;
1569 alarm->alarmhandler = cb;
1570 alarm->ticks = __lwp_wd_calc_ticks(tp);
1572 alarm->periodic = 0;
1573 alarm->start_per = 0;
1575 __lwp_wd_initialize(&alarm->alarm,__sys_alarmhandler,alarm->object.id,(void*)thealarm);
1576 __lwp_wd_insert_ticks(&alarm->alarm,alarm->ticks);
1577 __lwp_thread_dispatchenable();
1578 return 0;
1581 s32 SYS_SetPeriodicAlarm(syswd_t thealarm,const struct timespec *tp_start,const struct timespec *tp_period,alarmcallback cb,void *cbarg)
1583 alarm_st *alarm;
1585 alarm = __lwp_syswd_open(thealarm);
1586 if(!alarm) return -1;
1588 alarm->start_per = __lwp_wd_calc_ticks(tp_start);
1589 alarm->periodic = __lwp_wd_calc_ticks(tp_period);
1590 alarm->alarmhandler = cb;
1591 alarm->cb_arg = cbarg;
1593 alarm->ticks = 0;
1595 __lwp_wd_initialize(&alarm->alarm,__sys_alarmhandler,alarm->object.id,(void*)thealarm);
1596 __lwp_wd_insert_ticks(&alarm->alarm,alarm->start_per);
1597 __lwp_thread_dispatchenable();
1598 return 0;
1601 s32 SYS_RemoveAlarm(syswd_t thealarm)
1603 alarm_st *alarm;
1605 alarm = __lwp_syswd_open(thealarm);
1606 if(!alarm) return -1;
1608 alarm->alarmhandler = NULL;
1609 alarm->ticks = 0;
1610 alarm->periodic = 0;
1611 alarm->start_per = 0;
1613 __lwp_wd_remove_ticks(&alarm->alarm);
1614 __lwp_syswd_free(alarm);
1615 __lwp_thread_dispatchenable();
1616 return 0;
1619 s32 SYS_CancelAlarm(syswd_t thealarm)
1621 alarm_st *alarm;
1623 alarm = __lwp_syswd_open(thealarm);
1624 if(!alarm) return -1;
1626 alarm->alarmhandler = NULL;
1627 alarm->ticks = 0;
1628 alarm->periodic = 0;
1629 alarm->start_per = 0;
1631 __lwp_wd_remove_ticks(&alarm->alarm);
1632 __lwp_thread_dispatchenable();
1633 return 0;
1636 resetcallback SYS_SetResetCallback(resetcallback cb)
1638 u32 level;
1639 resetcallback old;
1641 _CPU_ISR_Disable(level);
1642 old = __RSWCallback;
1643 __RSWCallback = cb;
1644 #if defined(HW_DOL)
1645 if(__RSWCallback) {
1646 _piReg[0] = 2;
1647 __UnmaskIrq(IRQMASK(IRQ_PI_RSW));
1648 } else
1649 __MaskIrq(IRQMASK(IRQ_PI_RSW));
1650 #endif
1651 _CPU_ISR_Restore(level);
1652 return old;
1655 #if defined(HW_RVL)
1656 powercallback SYS_SetPowerCallback(powercallback cb)
1658 u32 level;
1659 powercallback old;
1661 _CPU_ISR_Disable(level);
1662 old = __POWCallback;
1663 __POWCallback = cb;
1664 _CPU_ISR_Restore(level);
1665 return old;
1667 #endif
1669 void SYS_StartPMC(u32 mcr0val,u32 mcr1val)
1671 mtmmcr0(mcr0val);
1672 mtmmcr1(mcr1val);
1675 void SYS_StopPMC()
1677 mtmmcr0(0);
1678 mtmmcr1(0);
1681 void SYS_ResetPMC()
1683 mtpmc1(0);
1684 mtpmc2(0);
1685 mtpmc3(0);
1686 mtpmc4(0);
1689 void SYS_DumpPMC()
1691 printf("<%d load/stores / %d miss cycles / %d cycles / %d instructions>\n",mfpmc1(),mfpmc2(),mfpmc3(),mfpmc4());
1694 void SYS_SetWirelessID(u32 chan,u32 id)
1696 u32 write;
1697 syssramex *sram;
1699 write = 0;
1700 sram = __SYS_LockSramEx();
1701 if(sram->wirelessPad_id[chan]!=(u16)id) {
1702 sram->wirelessPad_id[chan] = (u16)id;
1703 write = 1;
1705 __SYS_UnlockSramEx(write);
1708 u32 SYS_GetWirelessID(u32 chan)
1710 u16 id;
1711 syssramex *sram;
1713 id = 0;
1714 sram = __SYS_LockSramEx();
1715 id = sram->wirelessPad_id[chan];
1716 __SYS_UnlockSramEx(0);
1717 return id;
1720 #if defined(HW_RVL)
1721 u32 SYS_GetHollywoodRevision()
1723 u32 rev;
1724 DCInvalidateRange((void*)0x80003138,8);
1725 rev = *((u32*)0x80003138);
1726 return rev;
1728 #endif