Wudy 发表于 2012-8-10 18:14:34

【SDK教程】syscall的使用

本帖最后由 Wudy 于 2012-8-11 14:29 编辑

这几天论坛的9860SDK开发好像又热闹起来了,我奉上我的处女教程贴~

官方提供的SDK虽然可以满足一般需要,但是还有很多更强大的功能没有被记录,比如...
打开其他add-in,模拟按键,获取设置文件,获取变量,获取电池电量,传输数据,执行对Storage Mem的opt等等。
这些功能都用一句简单的syscall来实现,本文就将教大家如何在add-in编写中用c语言使用syscall。方法来自
http://martin.poupe.org/casio/tsr/index.html提供的示例代码。

先看一段代码:const int SysCallWrapper[] = { 0xD201422B, 0x60F20000, 0x80010070 };
const int (*iSysCallFuncPtr)( int R4, int R5, int R6, int R7, int FNo ) = (void*)&SysCallWrapper;

#define App_RUN_MAT() (int)(*iSysCallFuncPtr)( 0, 0, 0, 0, 0xAAE )

int AddIn_main(int isAppli, unsigned short OptionNum)
{
      unsigned int key;

         // 显示提示字符
         locate( 1, 1 );
         Print( "Press Any key to go" );
         locate( 1, 2 );
         Print( "to RUN.MAT..." );
         GetKey( &key );

         // 使用syscall进入RUN.MAT
         App_RUN_MAT();

         return 1;
}
打开add-in后,按下任意键,你就会神奇地进入到了RUN.MAT里!下面来简单分析一下这段代码。
SysCallWrapper就是调用syscall的机器码的封装,然后用一个函数指针iSysCallFuncPtr指向SysCallWrapper,就相当于在C中嵌入了一个机器码编的函数。
iSysCallFuncPtr的前4个参数R4,R5,R6,R7就是寄存器4,5,6,7用来放syscall的参数。
iSysCallFuncPtr的最后一个参数FNo是syscall的编号(应该是类似中断向量的东西)。

在本例中,打开RUN.MAT这个syscall的编号就是0xAAE,它不需要任何参数,所以可以定义如下一个宏来使用它。
#define App_RUN_MAT() (int)(*iSysCallFuncPtr)( 0, 0, 0, 0, 0xAAE )
或者写成一个函数也可以
void App_RUN_MAT( void )
{
      (int)(*iSysCallFuncPtr)( 0, 0, 0, 0, 0xAAE );
}
写成函数的优点是如果syscall有参数,可以让编译器为你进行类型检查。宏定义的优点是方便和速度(SDK好像不支持内联函数)

接下来就可以到文档里查找需要的syscall然后让你的add-in功能更强大(文档是老外写的,见附件里的chm文件)!
在这里列举一些有用或好玩的syscall..

0x03B: int RTC_GetTicks( void )
返回从0点开始的秒数的128倍,可用于做随机数种子。

0x0AE8: int CatalogDialog( void )
打开目录,和shift+7的那个一样,返回选择的项目的opcode

0x0645: int CalculateExpression( char**expression, char*c, TBCDvalue*value, int mode )
好像可以计算表达式,我还没仔细研究

0x4DF: char *Alpha_GetData(char variablecode, char *datadest)
获取main memory中字母变量的值

0x4DC: char Setup_GetEntry(uint index);
0x4DD: char *Setup_SetEntry(uint index, char setting);
设置、获取shift-menu里的设置

0x3F4: void PowerOff( int mode )
关机,可以选择显示或不显示logo

0x236: void RebootOS( void )
重启

0x0A6A: int App_Optimization( void )
执行对Storage Mem的opt

0x136: unsigned char *GetCharacterGlyph(short character);
0x137: unsigned char *GetCharacterMiniGlyph(short character, short*width);
获取内置字体的位图,mini模式还可以获取宽度

0x0804: int CLIP_Store( unsigned char*buffer, in length )
复制字符到剪切板

0x135: Bdisp_GetVRAMPtr()
获取显存地址,可以更底层地绘图

还有很多MSC_开头的是操作main memory里的文件的函数
还有很多Serial_开头的,可能是操作串口的
还有很多Comm_开头的,与通信有关,具体可以看那个pdf。
还有很多XXX...


Wudy 发表于 2012-8-10 18:21:02

还有一个比较有用的syscall
0x0910 : int Keyboard_PutKeycode( int keycode )
它的功能是把一个按键加入到按键队列里,就相当于模拟按键,可以做个按键精灵之类的!下面的示例程序是到RUN.MAT模式里输入一段字符串,因为执行过程中到了RUN.MAT,程序会被暂停,所以要用定时器来实现按键。const int SysCallWrapper[] = { 0xD201422B, 0x60F20000, 0x80010070 };
const int (*iSysCallFuncPtr)( int R4, int R5, int R6, int R7, int FNo ) = (void*)&SysCallWrapper;
#define App_RUN_MAT() (int)(*iSysCallFuncPtr)( 0, 0, 0, 0, 0xAAE )

int Keyboard_PutKeycode( int keycode )
{
      return (int)(*iSysCalleycode, keycode<256, 0, 0, 0x0910 );
}

// 字符按键的代码就是ASCII码
const char *text = "Hello World!";

int index = 0;
void TimerHandler( void )
{
      int key = text;

      // 模拟按键
      Keyboard_PutKeycode( key );
      // 所有按键都被模拟了,关闭定时器
      if( key == '\0' )
                KillTimer( 1 );
}

int AddIn_main(int isAppli, unsigned short OptionNum)
{
      // 设置定时器
      SetTimer( 1, 250, TimerHandler );

      // 进入RUN.MAT
      App_RUN_MAT();
      return 0;
}

diameter 发表于 2012-8-10 18:34:06

用syscall确实很方便,可是在新版的9860怎么办?
有点蛋疼..

Wudy 发表于 2012-8-10 19:52:07

3# diameter
是一个问题。不过syscall都是SDK实现不了的功能,有总比没有好。

wtof1996 发表于 2012-8-11 00:36:43

我一直很好奇这些玩意怎么被发现的……

chuxianbing 发表于 2012-8-11 11:35:41

怎样获取list 1数据
是否可以给casio的basic添加函数或其他功能

Wudy 发表于 2012-8-11 14:34:30

不过要是有能够直接用计算器内置函数的syscall就好了
ExAcler 发表于 2012-8-11 11:27
可以看一下
0x0645: int CalculateExpression( char**expression, char*c, TBCDvalue*value, int mode )
不过具体我也不知道,文档已经附件上传!


怎样获取list 1数据
是否可以给casio的basic添加函数或其他功能
chuxianbing 发表于 2012-8-11 11:35

可以给basic添加功能!
最简单的(就是那个网址里的例子),比如那A这个变量当函数标号,用你的add-in进到prgm模式,然后让用户执行一个程序,设置定时器不断检查a的值然后提供相应的功能。
list 1的值肯定是可以获取的,我还没研究完,你自己看一下吧。

GWHBOB 发表于 2012-8-11 14:48:40

Tbcd value 肯定是一种类型,如果能和谐的话对我们的自然书写会有很大帮助

geotri 发表于 2013-5-4 11:29:08

真是大神啊,弱弱地问一下,调用App_RUN_MAT()后该如何返回?

geotri 发表于 2013-5-4 16:09:35

9860 GII SD 一运行就死机,Version 02.02.0201,有没有办法解决?

slymitec 发表于 2014-12-21 18:35:44

要是能读取LIST、MAT就好了
页: [1]
查看完整版本: 【SDK教程】syscall的使用