西門子x65/x75上的
ELF 程序大家已經見識過了,你有沒想過寫出自己的 ELF 程序呢?如果你有C語言基礎,那么加入 ELF 程序開發的隊伍吧。
要在西門子x65/x75上使用 ELF 程序,你應該確定自己的
機器上正確的刷了適合你機型的3個
補丁(如下):
function library
elfloader
swi-hook
查看機型在待機下輸入 *#06# 選更多,sW-Version一行就是了
現在的 ELF 程序一般是被刷過以上3個補丁的正確版本的機器所通用的(也有可能會限制機型,看程序怎么寫的了8-) )
下面進入正題
目錄:
1.IAR SI 安裝
2.在手機上運行 ELF 程序3.如何用 IAR 編寫 ELF
4.例1:內存和文件的操作
5.例2:屏幕輸出和鍵盤控制
6.例3:一個后臺計時的小程序
7.例4:內存駐留程序
8.FAQ1.IAR SI 安裝從
www.iar.com 上
下載 IAR Embedded Workbench
For ARM 的30天試用版,最新版為4.41好象(>100 mb),程序下載是免費的,但是會要你先注冊。填寫正確的油箱以后,就會把使用序列號發給你。安裝沒說的了吧,一路下一步,下一步,等等。
2.在手機上運行 ELF 程序論壇上很多說明了,再扯就遠了點:-')
3.如何用 IAR 編寫 ELF開始一個 ELF 程序的編寫,還是比較簡單 :P
在菜單上選擇 “Project->Create New Project”
然后選添加"Project->Add Files"把你用其他IDE寫好的C程序添加進來就可以了
工程必須還要有 func.asm (入口點) 和 div.r79 (這個好象莫必要?我也不太清楚,我是業余的:( )
C程序知道怎么寫,問題就不大。
你可能會問,怎么使用到手機里面那些需要的功能函數呢?這就需要 swilib.h 這個頭文件了(附件提供),這里面定義了n多函數,大家看名字猜吧。。。因為沒說明,滅辦法,唉。
上面的操作做好以后,就可以編譯我們的程序了,在 IAR 環境里左邊的 Workspace 下面,把 Debug 選成 Release,然后在工程上點右鍵,選屬性 CPU 可以不用改,下面的 Processor mode 改為 Arm,在 Library Configuration 標簽里,把 Library 選成 None,就可以編譯了。這里你也可以在 Linker 里面設置相關連接選項。生成完畢后,你就可以在 你的工程\Release\Exe 目錄里找到生成的 ELF 文件,放到手機里看看呢?:P
4.例1:內存和文件的操作創建 main.c 如下后添加到你的工程里:
//main.c
#include "swilib.h"
void ElfKiller(void) { //用于 elf 退出時的相關操作
extern void *ELF_BEGIN;
//這里一般使用 mfree(), freeWS() 來釋放內存
((void (*)(void *))(mfree_adr()))(ELF_BEGIN); // 懶得解釋 :(
}
int main(char *exename, char *fname) { //主函數
//參數 exename 表示被動使用的ELF? 格式 4:\Zbin\xyz.elf
//參數 fname 傳遞文件名, 格式 0:\Misc\data.txt
//如果 ELF 啟動自身則為 0
char *mem;
int i, err;
int handle;
if (fname) {
//操作標準文件:
handle = fopen(fname, A_ReadWrite+A_BIN+A_Append+A_Create, P_READ+P_WRITE, err);
//表示按記錄文件打開,數據添加到文件末尾,如果文件不存在則創建之
//如果為 handle=fopen (fname,A_ReadOnly+A_BIN, 0,err);
//則表示按只讀方式打開文件,具體常數參看 swilib.h
if (handle != -1) { //-1 = error
mem = malloc(10000); //分配內存: AllocWS() 按行分配 (2b)
if (mem != 0) { //0 = error
i = fread(handle, mem, 10000, err); //返回讀取得字節數,如果錯誤返回 error。
//放置你的代碼在這里 makesomebody (mem,i);
fwrite(handle, mem, i, err);
mfree(mem); //釋放內存: FreeWS() 按行釋放
}
fclose(handle); //關閉文件
}
}
SUBPROC((void *)ElfKiller); //放這個東西在這里就最好了,不存在也沒關系!
return(0);
}
//PS. 由于 x65 中文件的讀取和記錄是按 32767 字節的塊操作的,
//因此將 fread() 和 fwrite() 改造為 fread32 () 和 fwrite32()
int fread32(int fh, char *buf, int len, unsigned int *err) { // (c) Rst7
int clen;
int rlen;
int total=0;
while (len) {
if (len > 16384) clen = 16384; else clen = len;
total += (rlen = fread(fh, buf, clen, err));
if (rlen != clen) break;
buf += rlen;
len -= clen;
}
return(total);
}
最后不要忘了還有 func.asm 這個文件:
;Func.asm
PUBLIC ELF_BEGIN
RSEG ELFBEGIN:DATA
ELF_BEGIN
defadr MACRO a,b
PUBLIC a
a EQU b
ENDM
END
5.例2:屏幕輸出和鍵盤控制通過導航鍵控制屏幕上的符號移動,長按紅鍵退出。本例子基于 TED- A (c) Of rst7
看本例時最好從下往上看:)
創建 main.c 如下后添加到你的工程里:
//main.c
//屏幕和鍵盤處理
#include "swilib.h"
typedef struct {
GUI gui;
//WSHDR *ws1;
//WSHDR *ws2;
//int i1;
} MAIN_GUI;
typedef struct {
CSM_RAM csm;
int gui_id;
} MAIN_CSM;
const int minus11 = -11;
const unsigned int INK = 0;
const unsigned int PAPER = 1;
volatile int xx = 0, yy = 0; //繪圖坐標
const char bmp[12] = {0xFC, 0x86, 0xB3, 0xA9, 0xB1, 0xA9, 0x81, 0xFF, 0, 0, 0, 0};
const IMGHDR img = {8, 12, 0x1, 0, (char *)bmp};
//============
//屏幕輸出
//============
void DrwImg(IMGHDR *img, int x, int y, int *pen, int *brush) {
RECT rc;
DRWOBJ drwobj;
StoreXYWHtoRECT(rc, x, y, img->w, img->h);
SetPropTo_Obj5(drwobj, &rc, 0, img);
SetColor(drwobj, pen, brush);
DrawObject(drwobj);
}
void DrawScreen(void) {
int *ink = GetPaletteAdrByColorIndex(INK);
int *paper = GetPaletteAdrByColorIndex(PAPER);
int x = xx;
DrwImg((IMGHDR *)img, x, yy, ink, paper);
}
//繪制屏幕
void method0(MAIN_GUI *data) {
DrawScreen();
}
void method1(MAIN_GUI *data, void *(*malloc_adr)(int)) {}
void method2(MAIN_GUI *data, void (*mfree_adr)(void *)) {}
void method3(MAIN_GUI *data, void *(*malloc_adr)(int), void (*mfree_adr)(void *)) {}
void method4(MAIN_GUI *data, void (*mfree_adr)(void *)) {}
void method7(MAIN_GUI *data, void (*mfree_adr)(void *)) {}
int method8(void) {return(0);}
int method9(void) {return(0);}
//============
//按鍵控制
//============
int method5 (MAIN_GUI *data, GUI_MSG *msg) {
//if (msg->gbsmsg->msg==KEY_UP) //釋放按鍵時
if ((msg->gbsmsg->msg == KEY_DOWN) || (msg->gbsmsg->msg == LONG_PRESS)) //按下鍵或者長按鍵時
switch(msg->gbsmsg->submess) {
case RED_BUTTON:
return(1); //發生 generalFunc 流調用 GUI - > 關閉 GUI
case UP_BUTTON:
if (yy > 0) --yy; break;
case LEFT_BUTTON:
if (xx > 0) --xx; break;
case DOWN_BUTTON:
if (yy < 130) ++yy; break;
case RIGHT_BUTTON:
if ( xx < 120) ++xx; break;
//case GREEN_BUTTON:
//case RIGHT_SOFT:
//case ENTER_BUTTON:
//case LEFT_SOFT:
//case VOL_UP_BUTTON:
//case VOL_DOWN_BUTTON:
//case '0':
//case '9':
//case '#':
//SUBPROC((void *)DoDiskAccess,1);
//降低其他處理的優先級以繪制窗口
}
DrawScreen();
return(0);
}
const void *const gui_methods[11] = {
(void *)method0, //Redraw
(void *)method1, //Create
(void *)method2, //Close
(void *)method3, //Focus
(void *)method4, //Unfocus
(void *)method5, //OnKey
0,
(void *)method7, //Destroy
(void *)method8,
(void *)method9,
0
};
const RECT Canvas={0,0,131,175};
void maincsm_oncreate(CSM_RAM *data) {
MAIN_GUI *main_gui = malloc(sizeof (MAIN_GUI));
MAIN_CSM *csm = (MAIN_CSM *)data;
zeromem(main_gui, sizeof (MAIN_GUI));
//ustk=malloc(STKSZ); //為程序分配內存
//info_ws=AllocWS(512);
main_gui->gui.canvas = (void *)(Canvas);
main_gui->gui.flag30 = 2;
main_gui->gui.methods = (void *)gui_methods; //基本方法(見上面)
main_gui->gui.item_ll.data_mfree = (void (*)(void *))mfree_adr(); //我也不清楚:(
csm->csm.state = 0;
csm->csm.unk1 = 0;
csm->gui_id = CreateGUI(main_gui); //直接創建 GUI
}
void Killer(void) { //退出程序
extern void *ELF_BEGIN;
//mfree(ustk); //釋放內存
//FreeWS(info_ws);
((void (*)(void *))(mfree_adr()))(ELF_BEGIN);
}
void maincsm_onclose(CSM_RAM *csm) {
//GBS_StopTimer(light_tmr);
SUBPROC((void *)Killer);
}
int maincsm_onmessage(CSM_RAM *data, GBS_MSG *msg) {
return(1);
}
unsigned short maincsm_name_body[140];
const struct {
CSM_DESC maincsm;
WSHDR maincsm_name;
} MAINCSM = {
{
maincsm_onmessage, //信息進程
maincsm_oncreate, //創建時調用的方法
//如果機型為 S75 移除以下4行
//并在 swilib.h 里取消對 #define NEWSGOLD 這行的注釋
//0,
//0,
//0,
//0,
maincsm_onclose, //關閉時調用的方法
sizeof (MAIN_CSM),
1,
minus11
},
{
maincsm_name_body,
NAMECSM_MAGIC1,
NAMECSM_MAGIC2,
0x0,
139
}
};
int main(char *exename, char *fname) {
char dummy[sizeof (MAIN_CSM)];
//strcpy(filename,fname); //保存數據到文件
CreateCSM(MAINCSM.maincsm, dummy, 0);
return 0;
}