📄 pm.c
字号:
old_flags = fcntl(_PM_console_fd,F_GETFL); if (ioctl(_PM_console_fd, KDSKBMODE, K_MEDIUMRAW)) perror("KDSKBMODE"); atexit(_PM_restore_kb_mode); signal(SIGINT, _PM_abort); signal(SIGTERM, _PM_abort); signal(SIGHUP, _PM_abort); signal(SIGFPE, _PM_abort); signal(SIGSEGV, _PM_abort); signal(SIGABRT, _PM_abort); in_raw_mode = true; }}int PMAPI PM_kbhit(void){ fd_set s; struct timeval tv = { 0, 0 }; if (console_count == 0) PM_fatalError("You *must* open a console before using PM_kbhit!"); if (!in_raw_mode) _PM_keyboard_rawmode(); FD_ZERO(&s); FD_SET(_PM_console_fd, &s); return select(_PM_console_fd+1, &s, NULL, NULL, &tv) > 0;}int PMAPI PM_getch(void){ static uchar c; int release; static struct kbentry ke; if (console_count == 0) PM_fatalError("You *must* open a console before using PM_getch!"); if (!in_raw_mode) _PM_keyboard_rawmode(); while (read(_PM_console_fd, &c, 1) > 0) { release = c & 0x80; c &= 0x7F; if (release) { switch(c){ case 42: case 54: // Shift _PM_modifiers &= ~KB_SHIFT; break; case 29: case 97: // Control _PM_modifiers &= ~KB_CONTROL; break; case 56: case 100: // Alt / AltGr _PM_modifiers &= ~KB_ALT; break; } continue; } switch (c) { case 42: case 54: // Shift _PM_modifiers |= KB_SHIFT; break; case 29: case 97: // Control _PM_modifiers |= KB_CONTROL; break; case 56: case 100: // Alt / AltGr _PM_modifiers |= KB_ALT; break; case 58: // Caps Lock _PM_modifiers ^= KB_CAPS; ioctl(_PM_console_fd, KDSETLED, _PM_modifiers & 7); break; case 69: // Num Lock _PM_modifiers ^= KB_NUMLOCK; ioctl(_PM_console_fd, KDSETLED, _PM_modifiers & 7); break; case 70: // Scroll Lock _PM_modifiers ^= KB_SCROLL; ioctl(_PM_console_fd, KDSETLED, _PM_modifiers & 7); break; case 28: return 0x1C; default: ke.kb_index = c; ke.kb_table = 0; if ((_PM_modifiers & KB_SHIFT) || (_PM_modifiers & KB_CAPS)) ke.kb_table |= K_SHIFTTAB; if (_PM_modifiers & KB_ALT) ke.kb_table |= K_ALTTAB; ioctl(_PM_console_fd, KDGKBENT, (ulong)&ke); c = ke.kb_value & 0xFF; return c; } } return 0;}/* VGA index register ports */#define CRT_I 0x3D4 /* CRT Controller Index */#define ATT_IW 0x3C0 /* Attribute Controller Index & Data */#define GRA_I 0x3CE /* Graphics Controller Index */#define SEQ_I 0x3C4 /* Sequencer Index *//* VGA data register ports */#define CRT_D 0x3D5 /* CRT Controller Data Register */#define ATT_R 0x3C1 /* Attribute Controller Data Read Register */#define GRA_D 0x3CF /* Graphics Controller Data Register */#define SEQ_D 0x3C5 /* Sequencer Data Register */#define MIS_R 0x3CC /* Misc Output Read Register */#define MIS_W 0x3C2 /* Misc Output Write Register */#define IS1_R 0x3DA /* Input Status Register 1 */#define PEL_IW 0x3C8 /* PEL Write Index */#define PEL_IR 0x3C7 /* PEL Read Index */#define PEL_D 0x3C9 /* PEL Data Register *//* standard VGA indexes max counts */#define CRT_C 24 /* 24 CRT Controller Registers */#define ATT_C 21 /* 21 Attribute Controller Registers */#define GRA_C 9 /* 9 Graphics Controller Registers */#define SEQ_C 5 /* 5 Sequencer Registers */#define MIS_C 1 /* 1 Misc Output Register */#define PAL_C 768 /* 768 Paletet Registers */#define FONT_C 0x10000 /* 64KB for font data *//* VGA registers saving indexes */#define CRT 0 /* CRT Controller Registers start */#define ATT (CRT+CRT_C) /* Attribute Controller Registers start */#define GRA (ATT+ATT_C) /* Graphics Controller Registers start */#define SEQ (GRA+GRA_C) /* Sequencer Registers */#define MIS (SEQ+SEQ_C) /* General Registers */#define PAL (MIS+MIS_C) /* VGA Palette Registers */#define FONT (PAL+PAL_C) /* Font data *//****************************************************************************REMARKS:Delay for a short period of time.****************************************************************************/static void vga_delay(void){ int i; for (i = 0; i < 10; i++) ;}/****************************************************************************REMARKS:Sleep until the virtual terminal is active****************************************************************************/static void wait_vt_active( int _PM_console_fd){ while (ioctl(_PM_console_fd, VT_WAITACTIVE, tty_vc) < 0) { if ((errno != EAGAIN) && (errno != EINTR)) { perror("ioctl(VT_WAITACTIVE)"); exit(1); } usleep(150000); }}/****************************************************************************REMARKS:Checks the owner of the specified virtual console.****************************************************************************/static int check_owner( int vc){ struct stat sbuf; char fname[30]; sprintf(fname, "/dev/tty%d", vc); if ((stat(fname, &sbuf) >= 0) && (getuid() == sbuf.st_uid)) return 1; printf("You must be the owner of the current console to use this program.\n"); return 0;}/****************************************************************************REMARKS:Opens up the console device for output by finding an appropriate virutalconsole that we can run on.****************************************************************************/PM_HWND PMAPI PM_openConsole( PM_HWND hwndUser, int device, int xRes, int yRes, int bpp, ibool fullScreen){ struct vt_mode vtm; struct vt_stat vts; struct stat sbuf; char fname[30]; /* Check if we have already opened the console */ if (console_count++) return _PM_console_fd; /* Now, it would be great if we could use /dev/tty and see what it is * connected to. Alas, we cannot find out reliably what VC /dev/tty is * bound to. Thus we parse stdin through stderr for a reliable VC. */ startup_vc = 0; for (_PM_console_fd = 0; _PM_console_fd < 3; _PM_console_fd++) { if (fstat(_PM_console_fd, &sbuf) < 0) continue; if (ioctl(_PM_console_fd, VT_GETMODE, &vtm) < 0) continue; if ((sbuf.st_rdev & 0xFF00) != 0x400) continue; if (!(sbuf.st_rdev & 0xFF)) continue; tty_vc = sbuf.st_rdev & 0xFF; return _PM_console_fd; } if ((_PM_console_fd = open("/dev/console", O_RDWR)) < 0) { printf("open_dev_console: can't open /dev/console \n"); exit(1); } if (ioctl(_PM_console_fd, VT_OPENQRY, &tty_vc) < 0) goto Error; if (tty_vc <= 0) goto Error; sprintf(fname, "/dev/tty%d", tty_vc); close(_PM_console_fd); /* Change our control terminal */ setsid(); /* We must use RDWR to allow for output... */ if (((_PM_console_fd = open(fname, O_RDWR)) >= 0) && (ioctl(_PM_console_fd, VT_GETSTATE, &vts) >= 0)) { if (!check_owner(vts.v_active)) goto Error; /* Success, redirect all stdios */ fflush(stdin); fflush(stdout); fflush(stderr); close(0); close(1); close(2); dup(_PM_console_fd); dup(_PM_console_fd); dup(_PM_console_fd); /* clear screen and switch to it */ fwrite("\e[H\e[J", 6, 1, stderr); fflush(stderr); if (tty_vc != vts.v_active) { startup_vc = vts.v_active; ioctl(_PM_console_fd, VT_ACTIVATE, tty_vc); wait_vt_active(_PM_console_fd); } } return _PM_console_fd;Error: if (_PM_console_fd > 2) close(_PM_console_fd); console_count = 0; PM_fatalError( "Not running in a graphics capable console,\n" "and unable to find one.\n"); return -1;}/****************************************************************************REMARKS:Returns the size of the console state buffer.****************************************************************************/int PMAPI PM_getConsoleStateSize(void){ if (!inited) PM_init(); return CRT_C + ATT_C + GRA_C + SEQ_C + MIS_C + PAL_C + FONT_C*2;}/****************************************************************************REMARKS:Disables the VGA display for screen output making it blank.****************************************************************************/void PMAPI PM_vgaBlankDisplay(void){ /* turn screen off */ port_out(0x01, SEQ_I); port_out(port_in(SEQ_D) | 0x20, SEQ_D); /* disable video output */ port_in(IS1_R); vga_delay(); port_out(0x00, ATT_IW);}/****************************************************************************REMARKS:Enables the VGA display for screen output.****************************************************************************/void PMAPI PM_vgaUnblankDisplay(void){ /* turn screen back on */ port_out(0x01, SEQ_I); port_out(port_in(SEQ_D) & 0xDF, SEQ_D); /* enable video output */ port_in(IS1_R); vga_delay(); port_out(0x20, ATT_IW);}/****************************************************************************REMARKS:Save the color palette values****************************************************************************/static void vga_savepalette(uchar *pal){ int i; port_out(0, PEL_IR); for (i = 0; i < 768; i++) { vga_delay(); *pal++ = port_in(PEL_D); }}/****************************************************************************REMARKS:Restore the color palette values****************************************************************************/static void vga_restorepalette(const uchar *pal){ int i; /* restore saved palette */ port_out(0, PEL_IW); for (i = 0; i < 768; i++) { vga_delay(); port_out(*pal++, PEL_D); }}/****************************************************************************REMARKS:Save the state of all VGA compatible registers****************************************************************************/void PMAPI PM_saveVGAState(void *stateBuf){ uchar *regs = stateBuf; int i; /* Save state of VGA registers */ for (i = 0; i < CRT_C; i++) { port_out(i, CRT_I); regs[CRT + i] = port_in(CRT_D); } for (i = 0; i < ATT_C; i++) { port_in(IS1_R); vga_delay(); port_out(i, ATT_IW); vga_delay(); regs[ATT + i] = port_in(ATT_R); vga_delay(); } for (i = 0; i < GRA_C; i++) { port_out(i, GRA_I); regs[GRA + i] = port_in(GRA_D); } for (i = 0; i < SEQ_C; i++) { port_out(i, SEQ_I); regs[SEQ + i] = port_in(SEQ_D); } regs[MIS] = port_in(MIS_R); /* Save the VGA palette values */ vga_savepalette(®s[PAL]); /* Turn the VGA display back on */ PM_vgaUnblankDisplay();}/****************************************************************************REMARKS:Retore the state of all VGA compatible registers****************************************************************************/void PMAPI PM_restoreVGAState(const void *stateBuf){ const uchar *regs = stateBuf; int i; /* Restore the state of the VGA compatible registers */ port_out(regs[MIS], MIS_W); port_outw(0x0100,SEQ_I); port_out(1, SEQ_I); port_out(regs[SEQ + 1] | 0x20, SEQ_D); for (i = 2; i < SEQ_C; i++) { port_out(i, SEQ_I); port_out(regs[SEQ + i], SEQ_D); } port_outw(0x0300,SEQ_I); /* Deprotect CRT registers 0-7 and write CRTC */ port_out(0x11, CRT_I); port_out(port_in(CRT_D) & 0x7F, CRT_D); for (i = 0; i < CRT_C; i++) { port_out(i, CRT_I); port_out(regs[CRT + i], CRT_D); } for (i = 0; i < GRA_C; i++) { port_out(i, GRA_I); port_out(regs[GRA + i], GRA_D); } for (i = 0; i < ATT_C; i++) { port_in(IS1_R); /* reset flip-flop */ vga_delay(); port_out(i, ATT_IW); vga_delay(); port_out(regs[ATT + i], ATT_IW); vga_delay(); } /* Restore the VGA palette values */ vga_restorepalette(®s[PAL]); /* Ensure the VGA screen is turned on */ PM_vgaUnblankDisplay();}/****************************************************************************REMARKS:Save the state of the Linux console.****************************************************************************/void PMAPI PM_saveConsoleState(void *stateBuf,int console_id){ uchar *regs = stateBuf; /* Save the current console font */ if (ioctl(console_id,GIO_FONT,®s[FONT]) < 0) perror("ioctl(GIO_FONT)"); /* Inform the Linux console that we are going into graphics mode */ if (ioctl(console_id, KDSETMODE, KD_GRAPHICS) < 0) perror("ioctl(KDSETMODE)"); /* Save state of VGA registers */ PM_saveVGAState(stateBuf);}void PMAPI PM_changeResolution(PM_HWND hwndConsole,int xRes,int yRes,int bpp){ /* Not used for Linux fullscreen consoles */}void PMAPI PM_setSuspendAppCallback(int (_ASMAPIP saveState)(int flags)){ /* TODO: Implement support for allowing console switching! */}/****************************************************************************REMARKS:Restore the state of the Linux console.****************************************************************************/void PMAPI PM_restoreConsoleState(const void *stateBuf,PM_HWND console_id){ const uchar *regs = stateBuf; /* Restore the state of the VGA compatible registers */ PM_restoreVGAState(stateBuf); /* Inform the Linux console that we are back from graphics modes */ if (ioctl(console_id, KDSETMODE, KD_TEXT) < 0) perror("ioctl(KDSETMODE)");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -