爱西窝·西门子手机发烧友自留地
Would you like to react to this message? Create an account in a few clicks or log in to continue.

构建标准的中文转换程序gb2ws和ws2gb(讨论)

向下

构建标准的中文转换程序gb2ws和ws2gb(讨论) Empty 构建标准的中文转换程序gb2ws和ws2gb(讨论)

帖子 由 无泪の城 2012-01-03, 06:28

构建标准的中文转换程序GB&WS

以along当时写的code.c即cnfont.dat为基础。严重感谢along1976大侠。

我的设想如下:
cnfont.dat直接刷入flash。
gb2ws,ws2gb(原along用ascii2ws,ws2ascii,由于这两个函数俄国人用过了,在65上被用作了API函数,0xAD,0xAE)这两个也让它用作为swilib的函数,序号大约为0x242,0x243,我去和俄国人商量一下,应该没什么大问题。

补丁和cnfont.dat占用的空白地址我差不多找到了。
NEWSGOLD/ELKA,0x01568000-0x015681FF用作补丁数据,0x01568200-0x0157A24F用作cnfont.dat
SGOLD,0x00FE0000-0x00FE01FF用作补丁数据,0x00FE0200-0x00FF224F用作cnfont.dat


补丁的工程文件已经传到了http://sieelf.googlecode.com/svn/SieELF/gb2ws
VKP补丁下载:http://sieelf.googlecode.com/svn/SieELF/gb2ws/vkp

还请各路高手来观摩观摩。
我们要让代码尽量简洁,而效率又要是是尽量的高。

补丁代码用的是16位的THUMB模式,比起32位的ARM模式代码简短,效率相对较高。
但是由于调用到了序号为0x126的CutWSTR,超出了THUMB模式的SWI调用范围(0-0xFF)
于是我直接用汇编代码写了一个ARM模式的函数CutWSTRT来做调用。THUMB模式和ARM模式是可以无缝切换的,还好还好^_^。
我不大熟悉这个CutWSTR函数,如果能用简短的代码把它替换掉,就替换之。

弟兄们说说想法啊。

更多讨论请移步:http://bbs.0110.cn/forum.php?mod=viewthread&tid=357985


由无泪の城于2012-01-03, 06:31进行了最后一次编辑,总共编辑了1次
无泪の城
无泪の城
管理组
管理组

帖子数 : 329
注册日期 : 11-10-13

返回页首 向下

构建标准的中文转换程序gb2ws和ws2gb(讨论) Empty 回复: 构建标准的中文转换程序gb2ws和ws2gb(讨论)

帖子 由 无泪の城 2012-01-03, 06:29

现在的代码,code.c:
代码:
#include "..\inc\swilib.h"


#ifdef NEWSGOLD
#define CODEMAP_ADDR 0xA1568200  //-0xA157A24F
#else
#define CODEMAP_ADDR 0xA0FE0200
#endif

extern CutWSTRT(WSHDR *,int );

#pragma swi_number=0x0A0
__swi        __arm        int wsprintf_2 (WSHDR *,const char *format,...);

__thumb void ws2ascii(WSHDR *ws, char *s, int maxlen)
{
  unsigned short *codemap=(unsigned short *)CODEMAP_ADDR;
  int len=ws->wsbody[0];
  if(maxlen != 0 && len > maxlen)
    len = maxlen;
  if(codemap == 0)
  {
    ws_2str(ws, s, len);
    return;
  }
  int i,j=0;
  unsigned short temp;
  for(i=1; i<=len; i++)
  {
    temp=ws->wsbody[i];
    if(temp < 256)
      s[j++] = (unsigned char)temp;
    else if(temp >= 0x4E00 && temp <= 0x9FA5)
    {
      s[j++] = (unsigned char)(codemap[temp-0x4E00+32004]>>8);
      s[j++] = (unsigned char)((codemap[temp-0x4E00+32004]<<8)>>8);
    }
    else
      s[j++] = '?';
  }
  s[j] = 0;
}

__thumb void ascii2ws(WSHDR *ws, const char *s, int maxlen)
{
  unsigned short *codemap=(unsigned short *)CODEMAP_ADDR;
  if(codemap == 0)
  {
    wsprintf_2(ws, "%t", s);
    return;
  }
  char *p=(char *)s;
  unsigned char uc,uc2;
  //CutWSTR(ws,0);
  CutWSTRT(ws,0);
  while((uc=*s++) && (maxlen == 0 || s-p<=maxlen))
  {
    if(uc <= 128)
      wsAppendChar(ws,uc);
    else
    {
      uc2=*s++;
      if(uc2 < 128)
        wsAppendChar(ws, uc2);
      else
        wsAppendChar(ws, codemap[(uc-129)*127+(uc2-128)]);
    }
  }
}

#pragma diag_suppress=Pe177
__root static const int SWILIB_242_GB2WS @ "SWILIB_242_GB2WS" = (int)ascii2ws;
#pragma diag_default=Pe177

#pragma diag_suppress=Pe177
__root static const int SWILIB_243_WS2GB @ "SWILIB_243_WS2GB" = (int)ws2ascii;
#pragma diag_default=Pe177
这里我做了一句修改:
while((uc=*s++) && (maxlen == 0 || s-p<=maxlen))
原为。。: while((uc=*s++) && (maxlen == 0 || s-p<maxlen))
之前的代码会使第一个英文字母消失掉,不知道这样改有没有道理。
arm_swi.asm:
代码:
    RSEG    CODE
    PUBLIC  CutWSTRT
    CODE32
CutWSTRT:
    STMFD  SP!, {LR}
    SWI    0x126 //CutWSTR
    LDMFD  SP!, {PC}
    END
俄国论坛已发帖:http://forum.siemens-club.org/viewtopic.php?TopicID=57264&page=20,见笑。
无泪の城
无泪の城
管理组
管理组

帖子数 : 329
注册日期 : 11-10-13

返回页首 向下

返回页首


 
您在这个论坛的权限:
不能在这个论坛回复主题