小言_互联网的博客

操作系统的完整代码——显示和键盘管理代码yctty.cpp

584人阅读  评论(0)
#define YCORG -1
#include "ycio.cpp"

ycttyCLASS YCTTY;            //函数接口对象
void main(void **pObj)
{
    *pObj = &YCTTY;          //把函数接口对象地址传给调用者
}

int SCRwide = 80;            //屏幕宽度
int g_curpos = SCRwide * 8;  //光标位置
byte key_buf[32];            //键盘缓冲区
byte *key_head = key_buf;    //键盘缓冲区头指针
byte *key_tail = key_buf;    //键盘缓冲区尾指针
byte bg_color = 0x07;        //屏幕前景颜色和背景颜色属性
int pmt_pos;                 //提示符位置
int disk_no = 2;             //磁盘号

void ycttyCLASS::sys_write(int *pdata)       //向屏幕写字符串
{
    const char *_Source = (const char *)pdata[0];   //字符串地址
    int glen = pdata[1];                            //字符串长度
    int wrpos = pdata[2];           //不小于0时为屏幕缓冲区位置

    auto vidBuf = (byte*)(KERNEL_POS + 0xb8000);  //屏幕缓冲区地址
    if(glen < 0)
      {
        ycio_clear_screen(g_curpos,-glen);   //清屏
        return;
      }

    int maxPos = (25 - 1) * SCRwide;
    int bcurpos = g_curpos;
    if(wrpos >= 0)   g_curpos = wrpos;

    for(int ii=0; ii<glen; ii++)
      {
        byte uu = _Source[ii];
        switch(uu)
          {
            case '\t':   //tab字符
                 g_curpos += 8 - (g_curpos % 8);
                 continue;
            case '\r':   //回车
                 g_curpos -= g_curpos % SCRwide;
                 continue;
            case '\n':   //换行
                 g_curpos -= g_curpos % SCRwide;
                 if(g_curpos >= maxPos)
                    {
                      rn_000:
                      memcpy(vidBuf,&vidBuf[SCRwide*2],maxPos*2);//向上滚动一行
                      ycio_clear_screen(maxPos,SCRwide);    //清除一行
                    }
                 else  g_curpos += SCRwide;
                 continue;
          }

        vidBuf[g_curpos * 2] = uu;             //在位置 g_curpos 写字符
        vidBuf[g_curpos * 2 + 1] = bg_color;   //在位置 g_curpos 写属性
        g_curpos++;
        if(g_curpos>=maxPos + SCRwide)         //位置 g_curpos 超出屏幕底部
          {
            g_curpos = maxPos;
            goto  rn_000;
          }
      }
    if(wrpos >= 0)   g_curpos = bcurpos;
    else             ycio_cursor(g_curpos);    //设置光标位置
}

void ycttyCLASS::clear_screen(int bpos,int len)
{
    auto vidBuf = (byte*)(KERNEL_POS + 0xb8000);
    auto memsetS = asm[](void *_Dst,int _Val,unsigned int _Size)
     {
        push	ebp
        mov	ebp, esp
        push    edi
        mov     edi, _Dst
        mov     eax, _Val
        mov     ecx, _Size
        rep     stosw
        pop     edi
        mov     esp, ebp
        pop     ebp
        ret
     };
    memsetS(&vidBuf[bpos * 2], (bg_color<<8) + ' ', len);
}

void set_cursor_pos(int wrpos,int *pOld=nullptr)
{
    if(pOld)  *pOld = g_curpos;
    if(wrpos == -1)   return;
    g_curpos = wrpos;
    ycio_cursor(g_curpos);
}

void ycttyCLASS::pmt_cursor_pos(int cpos)
{
    set_cursor_pos(pmt_pos + cpos);
}

void ycttyCLASS::wr_prompt()
{
    char hbuf[] = "\nC:\\>";   //写当前路径提示符
    hbuf[1] = 'A' + disk_no;
    printf(hbuf);
    set_cursor_pos(-1,&pmt_pos);
}

void ycttyCLASS::cls()
{
    set_cursor_pos(0);
    ycio_clear_screen(0,25*80);
}

void ycttyCLASS::keyboard_proc()   //该函数被键盘中断服务例程调用(见ycker.cpp)
{
    byte *pHead = key_head + 1;
    if(pHead == key_buf + sizeof(key_buf))  pHead = key_buf; //到达底部,卷回头部
    if(pHead == key_tail)   return;        //头部等于底部缓冲区满, 忽略键盘输入
    *key_head = inb(0x60);     //从60h口读键盘数据
    key_head = pHead;          //设置键盘缓冲区头指针
}

void ycttyCLASS::set_disk(int mval)
{
    disk_no = mval;
}

void ycttyCLASS::display_LED(byte capsV,byte numV,byte scrollV)
{
    outb(0x60, 0xed);
    outb(0x60, (capsV << 2) | (numV << 1) | scrollV);
}

void ycttyCLASS::sys_cursor(int curpos)
{
    outb(0x3D4, 0x0E);
    outb(0x3D5, (curpos >> 8) & 0xFF);
    outb(0x3D4, 0x0F);
    outb(0x3D5, curpos & 0xFF);
}

void ycttyCLASS::keyboard_read(int &vk_char,int &vk_value,int &vk_press,
        byte &capsL,byte &numL,byte &scrollL,byte &shiftV,byte &altV,byte &ctrlV)
{
    auto get_scanCode = []()   //可在函数内部定义的lambda局部函数
      {
        if(key_tail == key_head)   return (byte)0;           //键盘缓冲区无数据
        byte scan_code = *key_tail++;            //从键盘缓冲区尾部读出键盘数据
        if(key_tail == key_buf + sizeof(key_buf))   key_tail = key_buf;
        return scan_code;
      };

    byte scan_code = get_scanCode();
    int bb,ii = scan_code & ~0x80;
    vk_press = !(scan_code & 0x80);

    static byte vk_buf[] = { 0,VK_ESCAPE,'1','2','3','4','5','6','7','8','9','0',
                '-','=',VK_BACK,VK_TAB,'Q','W','E','R','T','Y','U','I','O','P',
                '[',']',VK_RETURN,VK_LCONTROL,'A','S','D','F','G','H','J','K',
                'L',';','\'','`',VK_LSHIFT,'\\','Z','X','C','V','B','N','M',',',
                '.','/',VK_RSHIFT,VK_MULTIPLY,VK_LMENU,' ',VK_CAPITAL,
                VK_F1,VK_F2,VK_F3,VK_F4,VK_F5,VK_F6,VK_F7,VK_F8,VK_F9,VK_F10,
                VK_NUMLOCK,VK_SCROLL,VK_HOME,VK_UP,VK_PRIOR,VK_SUBTRACT,VK_LEFT,
                VK_CLEAR,VK_RIGHT,VK_ADD,VK_END,VK_DOWN,VK_NEXT,VK_INSERT,
                VK_DELETE,0,0,0,VK_F11,VK_F12,0,0,0,0,0,0,0,VK_PRINT,VK_PAUSE};

    if(ii < sizeof vk_buf/sizeof vk_buf[0])   vk_value = vk_buf[ii];

    switch(vk_value)
      {
        case VK_LSHIFT:   case VK_RSHIFT:    shiftV = vk_press;  return;
        case VK_LCONTROL: case VK_RCONTROL:  ctrlV = vk_press;  return;
        case VK_LMENU:    case VK_RMENU:     altV = vk_press;  return;
        case VK_PAUSE:    for(bb=0; bb<5; bb++)  get_scanCode();   break;
        case VK_CAPITAL:
        case VK_NUMLOCK:
        case VK_SCROLL:
             if(!vk_press)   return;
             if(vk_value == VK_CAPITAL)          capsL = !capsL;
             else  if(vk_value == VK_NUMLOCK)    numL = !numL;
             else                                scrollL = !scrollL;
             YCTTY.display_LED(capsL,numL,scrollL);
             return;
      }

    if(!vk_press)  return;
    if(vk_value>='A' && vk_value<='Z')
      {
        vk_char = vk_value;
        if(!capsL && !shiftV || capsL && shiftV)  vk_char += ' ';
      }

    auto get_real_key = [ vk_value ](byte *kmap,int pnum)
      {
        for(int ii=0; ii<pnum/2; ii++)  if(kmap[ii*2] == vk_value)  return ii*2;
        return -1;
      };

    if(numL)
      {
        static byte pad_map[] = { VK_HOME,'7',VK_UP,'8',VK_PRIOR,'9',VK_LEFT,'4',
                                  VK_CLEAR,'5',VK_RIGHT,'6',VK_END,'1',VK_DOWN,
                                  '2',VK_NEXT,'3',VK_INSERT,'0',VK_DELETE,'.'};

        bb = get_real_key(pad_map,sizeof pad_map/sizeof pad_map[0]);
        if(bb >= 0)   vk_char = pad_map[bb + 1];
      }

    if(ii < 0x37)
      {
        static byte shift_map[] = {'1','!','2','@','3','#','4','$','5','%','6',
                                   '^','7','&','8','*','9','(','0',')','-','_',
                                   '=','+',';',':','\'','"','`','~','\\','|',
                                   ',','<','.','>','/','?','[','{',']','}'};

        bb = get_real_key(shift_map,sizeof shift_map/sizeof shift_map[0]);
        if(bb >= 0)  vk_char = shift_map[bb + shiftV];
      }
    else
      {
        static byte Amap[]={VK_ADD,'+',VK_SUBTRACT,'-',VK_MULTIPLY,'*',' ',' '};
        bb = get_real_key(Amap,sizeof Amap/sizeof Amap[0]);
        if(bb >= 0)  vk_char = Amap[bb + 1];
      }
}

                        C/C++代码文件: yctty.cpp


转载:https://blog.csdn.net/xiaobingyang/article/details/105009848
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场