编程论坛's Archiver

ba_wang_mao 发表于 2006-12-30 16:51

吴进的TC256源程序256basic.h阅读笔记(2)

<P><BR>注释是我加上去的,不知道不明确的正确与否,请指正。<BR><BR>/***********************************************************************************************<BR>//  单扫描线内容拷贝函数,desc与src均使用相对偏移,mode值意义如下:<BR>//  值       意义<BR>//  -----------------------------<BR>//   1     EMS屏幕 ---&gt; VRAM屏幕<BR>//  -1    VRAM屏幕 ---&gt; EMS屏幕<BR>***********************************************************************************************/<BR>void scanline_copy(unsigned long desc,unsigned long src,unsigned int length,char mode)<BR>{<BR>    char pagetype1,pagetype2;<BR>    char far* descPoint;                // 局部变量:目标拷贝起始地址<BR>    char far* srcPoint;                    // 局部变量:源拷贝起始地址    </P>
<P>    unsigned int descpage=desc&gt;&gt;16,        // 目标转换得到BIOS Video(VRAM)页<BR>                   descoffset=desc&amp;0xffff,// 目标相对VRAM页的偏移<BR>                   srcpage=src&gt;&gt;16,        // 源转换得到BIOS Video(VRAM)页<BR>                   srcoffset=src&amp;0xffff;    // 源相对VRAM页的偏移</P>
<P>    if (mode == 1)                        // EMS ---&gt; VRAM 拷贝<BR>     {<BR>        descPoint=VPoint;                // 目标基地址 = 0xa000<BR>        srcPoint=EmsPoint;                // 源基地址 = EMS映射内存基地址<BR>          pagetype1=1;<BR>        pagetype2=0;<BR>    }<BR>    else                                // VRAM ---&gt; EMS 拷贝    <BR>    {<BR>        descPoint=EmsPoint;                // 目标基地址 = EMS映射内存基地址<BR>        srcPoint=VPoint;                // 源基地址 = 0xa000<BR>          pagetype1=0;<BR>        pagetype2=1;<BR>    }<BR>/*----------------------------------------------------------------------------------------------------------------<BR>// 如果 EMS ---&gt; VRAM 拷贝:目标BIOS Video换页, 源EMS逻辑页换页 <BR>// 如果 VRAM ---&gt; EMS 拷贝:目标EMS逻辑页换页, 源BIOS Video换页 <BR>------------------------------------------------------------------------------------------------------------------*/<BR>    MySelectpage1(descpage,pagetype1);<BR>     MySelectpage1(srcpage,pagetype2);<BR>/*----------------------------------------------------------------------------------------------------------------<BR>// 如果源复制区域及目标复制区域都未超过BIOS Video(VRAM)当前页(1页=65535)<BR>------------------------------------------------------------------------------------------------------------------*/<BR>     if ((long)srcoffset+length&lt;=65536L &amp;&amp; (long)descoffset+length&lt;=65536L)<BR>    {<BR>        memcpy(descPoint+descoffset,srcPoint+srcoffset,length);<BR>          return;<BR>     }<BR>/*----------------------------------------------------------------------------------------------<BR>// 跨页处理(源复制区域或目标复制区域超过BIOS Video(VRAM)当前页,需作跨页处理)<BR>-----------------------------------------------------------------------------------------------*/<BR>     else<BR>     {<BR>        unsigned int passed_length;<BR>          if (descoffset == srcoffset)    // 传输块与源的offset相同的情况<BR>          {<BR>            passed_length=65536L-descoffset;//当前页可Copy字节<BR>               memcpy(descPoint+descoffset,srcPoint+srcoffset,passed_length);<BR>               MySelectpage1(descpage+1,pagetype1);// 目标换至下页<BR>            MySelectpage1(srcpage+1,pagetype2);    // 源换至下页<BR>               memcpy(descPoint,srcPoint,length-passed_length);// 复制跨页剩余内容<BR>          }<BR>          else                            // 传输块与源的offset不同的情况<BR>          {<BR>            while (length&gt;0)<BR>               {<BR>                if ((long)srcoffset+length&lt;=65536L &amp;&amp; (long)descoffset+length&lt;=65536L)<BR>                {<BR>                    memcpy(descPoint+descoffset,srcPoint+srcoffset,length);<BR>                    break;<BR>                }<BR>/*----------------------------------------------------------------------------------------------<BR>// 目标offset剩余的比源offset多,即源指针比目标指针先到达VRAM页(1页=65535)的尾部<BR>-----------------------------------------------------------------------------------------------*/<BR>                   if (srcoffset&gt;descoffset)// 说明目标offset剩余的比源offset多<BR>                {<BR>                    passed_length=65536L-srcoffset;// 当前页Copy长度<BR>                     memcpy(descPoint+descoffset,srcPoint+srcoffset,passed_length);<BR>                     srcpage++;            // 源页号+1<BR>                    MySelectpage1(srcpage,pagetype2);// 源换至下页<BR>                     descoffset+=passed_length;// 修正目标偏移<BR>                     srcoffset=0;        // 修正源偏移:由于源已经换页,因此偏移从0重新开始。<BR>// 由于拷贝passed_length长度后,源指针已经到达VRAM页尾部,因此必须将源指针重新修正为0,并换到下页,而目标指针还未到达VRAM尾部,因此,只需修正目标指针即可。<BR>                }<BR>/*----------------------------------------------------------------------------------------------<BR>// 源offset剩余的比目标offset多,即目标指针比源指针到达VRAM页(1页=65535)的尾部<BR>-----------------------------------------------------------------------------------------------*/<BR>                else                    // 说明源offset剩余的比目标offset多<BR>                {<BR>                    passed_length=65536L-descoffset;// 当前页Copy长度<BR>                     memcpy(descPoint+descoffset,srcPoint+srcoffset,passed_length);<BR>                     descpage++;            // 目标页号+1<BR>                     MySelectpage1(descpage,pagetype1);// 目标换至下页<BR>                     srcoffset+=passed_length;// 修正源偏移<BR>                    descoffset=0;        // 修正目标偏移:由于目标已经换页,因此偏移从0重新开始。<BR>// 由于拷贝passed_length长度后,目标指针已经到达VRAM页尾部,因此必须将目标指针重新修正为0,并换到下页,而源指针还未到达VRAM尾部,因此,只需修正源指针即可。<BR>                }<BR>                length-=passed_length;    // 剩余待Copy长度<BR>               }<BR>          }<BR>      }<BR>}</P>
<P><BR>/***********************************************************************************************<BR>//  常规内存与EMS或VRAM间的拷贝函数,不带屏幕剪切。<BR>//    入口参数:<BR>//    (1).mempos为常规内存指针 (2).destoffset为EMS或VRAM起始点偏移.<BR>//    (3).length为待复制长度   (4).mode为数据移动方向<BR>//  -----------------------------------------------------------<BR>//  0 常规内存-&gt;EMS屏幕      例如:MemCopy256(BmpStackPos,buffer,length,0);<BR>//                                 将常规内存数组buffer数据移至EMS<BR>//  1 常规内存-&gt;VRAM屏幕<BR>//  2 EMS屏幕-&gt;常规内存        例如:MemCopy256(HZK_DATA+position,mat,th*2,2); <BR>//                                 将汉字库汉字字模从EMS拷贝到常规内存数组mat中。<BR>//  3 VRAM屏幕-&gt;常规内存<BR>// memcpy函数格式:memcpy(void *dest , void *src , int length)<BR>***********************************************************************************************/<BR>void MemCopy256(unsigned long descoffset,char *mempos,unsigned int length,char mode)<BR>{<BR>    unsigned int page=descoffset&gt;&gt;16,    // 目标转换成BIOS Video页号<BR>                 offset=descoffset&amp;0xffff,    // 目标相对VRAM页的偏移<BR>                 part1;                    // 局部变量<BR>    char far* descPoint;                // 局部变量:目标拷贝起始地址</P>
<P>    if (mode%2)                            // mode = 1,3 常规内存 &lt;---&gt; VRAM屏幕<BR>        descPoint=VPoint;                // 目标基地址 = 0xa000<BR>     else                                // mode = 0,2 常规内存 &lt;---&gt; EMS屏幕        <BR>        descPoint=EmsPoint;                // 目标基地址 = EMS映射基地址<BR>     MySelectpage1(page,mode%2);            // 目标BIOS Video换页或者目标EMS换页<BR>/*----------------------------------------------------------------------------------------------------------------<BR>// 如果复制区域未超出BIOS Video当前页(1页=65535)<BR>------------------------------------------------------------------------------------------------------------------*/<BR>     if ((long)offset+length&lt;=65536L)<BR>     {<BR>        if (mode/2)                        // mode = 2,3 EMS屏幕-&gt;常规内存或VRAM屏幕-&gt;常规内存<BR>            memcpy(mempos,descPoint+offset,length);<BR>          else                            // mode = 0,1 常规内存-&gt;EMS屏幕或常规内存-&gt;VRAM屏幕<BR>            memcpy(descPoint+offset,mempos,length);<BR>          return;<BR>     }<BR>/*----------------------------------------------------------------------------------------------<BR>// 跨页处理 <BR>-----------------------------------------------------------------------------------------------*/<BR>     else<BR>     {<BR>        part1 = 65536L-offset;            // 当前页需Copy内容<BR>          if (mode/2)<BR>            memcpy(mempos,descPoint+offset,part1);<BR>          else<BR>            memcpy(descPoint+offset,mempos,part1);<BR>        MySelectpage1(page+1,mode%2);    // 目标BIOS Video或者目标EMS换至下页<BR>          length-=part1;                    // 跨页剩余待Copy内容<BR>          if (mode/2)<BR>            memcpy(mempos+part1,descPoint,length);<BR>          else<BR>            memcpy(descPoint,mempos+part1,length);<BR>     }<BR>}</P>
<P><BR>/***********************************************************************************************<BR>//  常规内存与绘图屏幕间的水平线拷贝函数,带屏幕剪切。<BR>//  (1).mempos为常规内存指针<BR>//  (2).(x,y)为屏幕上水平数据线的左起始点<BR>//    (3).length为<BR>//    (4).mode为数据移动方向<BR>//  ------------------------<BR>//  0 常规内存-&gt;EMS屏幕<BR>//  1 常规内存-&gt;VRAM屏幕<BR>//  2 EMS屏幕-&gt;常规内存<BR>//  3 VRAM屏幕-&gt;常规内存<BR>***********************************************************************************************/<BR>void screenline_copy(int x,int y,char *mempos,unsigned int length,char mode)<BR>{<BR>    unsigned int scan_seek=0,scan_length;<BR>    unsigned long descoffset;<BR> <BR>    if (x+length&lt;screen_cut.left||x&gt;screen_cut.right||y&lt;screen_cut.top||y&gt;screen_cut.bottom)<BR>        return;<BR>/*---------------------------------------------------------------------------------------------<BR>//        screen_cut.left    ================================== screen_cut.right<BR>//      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [copy line]<BR>//      x                                                                              x+length<BR>-----------------------------------------------------------------------------------------------*/<BR>     if (x&lt;screen_cut.left)                // 如果线的首端超出裁减窗口的左端<BR>        scan_seek=screen_cut.left-x;<BR>     if (x+length&gt;screen_cut.right)        // 如果线的尾端超出裁减窗口右端<BR>        scan_length=screen_cut.right-(scan_seek+x)+1;<BR>     else                                // 线的尾端未超出裁减窗口的右端<BR>        scan_length=length-scan_seek;<BR>     //descoffset=y*640l+x+scan_seek;// 为了提高运算速度,将乘法运算改为移位运算<BR>    descoffset=(((unsigned long)y&lt;&lt;9L)+((unsigned long)y&lt;&lt;7L)+((unsigned long)x))+scan_seek;<BR>     MemCopy256(descoffset,mempos+scan_seek,scan_length,mode);<BR>}</P>

页: [1]

Powered by Discuz! Archiver 6.1.0  © 2001-2007 Comsenz Inc.