📄 console.c
字号:
/* * All video and keyboard functions were gathered into one file. * * In version 3.2, this file was split into 3 sections: 1) unix curses * made to look and feel like a PC, 2) our PC hardware specific stuff, * and 3) hardware independent stuff. * * This file contains the keyboard and video i/o stuff. Most of this stuff * is specific to the PC hardware, but it should be easily modified when * porting to other platforms. With a few key functions written in * assembly, we have fairly fast video performance and good keyboard control. * Incidentally, the commented C code in the functions perform the same * function as the assembly code. In earlier versions of TDE, I didn't * update the commented C code when I changed the assembly code. The * C and assembly should be equivalent in version 2.2. * * Although using a curses type package would be more portable, curses * can be slow on PCs. Let's keep our video and keyboard routines in * assembly. I feel the need for speed. * * Being that TDE 2.2 keeps an accurate count of characters in each line, we * can allow the user to enter any ASCII or Extended ASCII key. * * Determining the video adapter type on the PC requires a function. In * TDE, that function is: * * void video_config( struct vcfg *cfg ) * * video_config( ) is based on Appendix C in _Programmer's Guide to * PC & PS/2 Video Systems_ by Richard Wilton. * * See: * * Richard Wilton, _Programmer's Guide to PC & PS/2 Video Systems_, * Microsoft Press, Redmond, Washington, 1987, Appendix C, pp 511-521. * ISBN 1-55615-103-9. * * * New editor name: TDE, the Thomson-Davis Editor. * Author: Frank Davis * Date: June 5, 1991, version 1.0 * Date: July 29, 1991, version 1.1 * Date: October 5, 1991, version 1.2 * Date: January 20, 1992, version 1.3 * Date: February 17, 1992, version 1.4 * Date: April 1, 1992, version 1.5 * Date: June 5, 1992, version 2.0 * Date: October 31, 1992, version 2.1 * Date: April 1, 1993, version 2.2 * Date: June 5, 1993, version 3.0 * Date: August 29, 1993 version 3.1 * Date: November 13, version 3.2 * Date: June 5, 1994, version 4.0 * Date: December 5, 1998, version 5.0 (jmh) * * This code is released into the public domain, Frank Davis. * You may distribute it freely. */#include "tdestr.h"#include "common.h"#include "define.h"#include "tdefunc.h"#define __dj_include_pc_h_ /* don't include pc.h and its getkey */#include <bios.h> /* for direct BIOS keyboard input */#include <sys/movedata.h> /* for reading the BIOS memory */#include <inlines/pc.h> /* for inportb to access the keyboard */#include <sys/exceptn.h>static unsigned long display_address; /* address of display memory */static int s_cbrk; /* original control-break checking flag */static int stdoutput; /* stdout for redirected shelling */static int kbd_active = TRUE; /* should my INT09 be used? */volatilestatic unsigned int kbd_shift = 0; /* the actual shift states */static unsigned char kbd_bios_shift, /* the fake BIOS shift states */ kbd_scancode, /* the hardware scan code */ kbd_prefix = 0, /* detect prefixed codes */ kbd_menu; /* the Menu key */static _go32_dpmi_seginfo kbd_old_int; /* the original INT09 */static _go32_dpmi_seginfo kbd_new_int; /* my new INT09 */#define KBD_INT (_go32_info_block.master_interrupt_controller_base + 1)/* * Convert a row and column co-ordinate into a screen memory address. */#define SCREEN_PTR( row, col ) \ (display_address + ((row) * g_display.ncols + (col)) * 2)static void bright_background( void );static int shadow_width( int, int, int );static void kbd_int( void );/* * Name: console_init * Purpose: initialise the console (video and keyboard) * Author: Jason Hood * Date: October 23, 2002 * Passed: cfg: pointer to hold video config data * Notes: initialises both video and keyboard hardware. * moved some stuff from main.c into here. */void console_init( struct vcfg *cfg ){ /* * May as well make use of additional video memory. There may be a * problem with hi-res text modes (greater than 100x80, 132x61), but * since I've been using page 1 since 5.0 without complaints, I guess * it's not a problem, after all. (Whilst I can set 132x66, I never do, * at least not for any period of time. :) ) */ page( 1 ); video_config( cfg ); __djgpp_set_ctrl_c( 0 ); /* turn off Ctrl-C breaking */ s_cbrk = getcbrk( ); /* disable DOS Ctrl-Break checking */ setcbrk( 0 ); /* * Setup and install the keyboard hardware interrupt. * * The method of finding the length of a function by defining another * function after it doesn't work in newer GCCs (functions get reordered), * so just use GDB to disassemble it and find its length that way. */ _go32_dpmi_lock_code( kbd_int, 428 ); _go32_dpmi_lock_data( (void *)&kbd_shift, sizeof(kbd_shift) ); _go32_dpmi_lock_data( (void *)&kbd_bios_shift, sizeof(kbd_bios_shift) ); _go32_dpmi_lock_data( (void *)&kbd_scancode, sizeof(kbd_scancode) ); _go32_dpmi_lock_data( (void *)&kbd_prefix, sizeof(kbd_prefix) ); _go32_dpmi_get_protected_mode_interrupt_vector( KBD_INT, &kbd_old_int ); kbd_new_int.pm_selector = _go32_my_cs(); kbd_new_int.pm_offset = (unsigned long)kbd_int; _go32_dpmi_chain_protected_mode_interrupt_vector( KBD_INT, &kbd_new_int );}/* * Name: console_suspend * Purpose: temporarily shutdown the console * Author: Jason Hood * Date: October 23, 2002 * Notes: readies the console for a shell */void console_suspend( void ){ page( 0 ); set_cursor_size( g_display.curses_cursor ); if (g_display.adapter != MDA) set_overscan_color( g_display.old_overscan ); kbd_active = FALSE; setcbrk( s_cbrk ); /* * If output has been redirected then put it back to the screen for the * shell and restore it afterwards. */ if (g_status.output_redir) { stdoutput = dup( fileno( stdout ) ); freopen( STDFILE, "w", stdout ); } __djgpp_exception_toggle( );}/* * Name: console_resume * Purpose: restore the console * Author: Jason Hood * Date: October 23, 2002 * Notes: restores the console for TDE */void console_resume( int pause ){ __djgpp_exception_toggle( ); if (g_status.output_redir) dup2( stdoutput, fileno( stdout ) ); kbd_active = TRUE; kbd_shift = 0; setcbrk( 0 ); if (pause) getkey( ); page( 1 ); bright_background( ); if (g_display.adapter != MDA) set_overscan_color( Color( Overscan ) );}/* * Name: console_exit * Purpose: resets the console * Author: Jason Hood * Date: October 23, 2002 * Notes: resets the console after TDE has finished */void console_exit( void ){ setcbrk( s_cbrk ); /* * reset the cursor size and unload the keyboard utility */ set_cursor_size( g_display.curses_cursor ); _go32_dpmi_set_protected_mode_interrupt_vector( KBD_INT, &kbd_old_int ); page( 0 ); /* back to page 0 for DOS */}/* * BIOS Data Areas * * See: * * IBM Corp., _Technical Reference: Personal Computer AT_, * Boca Raton, Florida, 1984, IBM part no. 1502494, * pp 5-29 thru 5-32. * * These addresses, variable names, types, and descriptions are directly * from the IBM AT Technical Reference manual, BIOS listing, copyright IBM. * * Address Name Type Description * 0x0449 CRT_MODE Byte Current CRT mode * 0x044a CRT_COLS Word Number columns on screen * 0x044c CRT_LEN Word length of regen buffer, video buffer, bytes * 0x044e CRT_START Word Starting address of regen buffer * 0x0450 CURSOR_POSN Word cursor for each of up to 8 pages. * 0x0460 CURSOR_MODE Word current cursor mode setting. * 0x0462 ACTIVE_PAGE Byte Current page * 0x0463 ADDR_6845 Word base address for active display card * 0x0465 CRT_MODE_SET Byte current mode of display card * 0x0466 CRT_PALETTE Byte overscan color for CGA, EGA, and VGA. * 0x0467 io_rom_init Word Pointer to optional i/o rom init routine * 0x0469 io_rom_seg Word Pointer to io rom segment * 0x046b intr_flag Byte Flag to indicate an interrupt happened * 0x046c timer_low Word Low word of timer count * 0x046e timer_high Word High word of timer count * 0x0470 timer_ofl Byte Timer has rolled over since last count * 0x0471 bios_break Byte Bit 7 = 1 if Break Key has been hit * 0x0472 reset_flag Word Word = 1234h if keyboard reset underway * 0x0484 ROWS Byte Number of displayed character rows - 1 * 0x0485 POINTS Word Height of character matrix * 0x0487 INFO Byte EGA and VGA display data * 0x0488 INFO_3 Byte Configuration switches for EGA and VGA * 0x0489 flags Byte Miscellaneous flags * 0x0496 kb_flag_3 Byte Additional keyboard flag * 0x048A DCC Byte Display Combination Code * 0x04A8 SAVE_PTR Dword Pointer to BIOS save area */void video_config( struct vcfg *cfg ){struct LOWMEMVID{ unsigned char vidmode; /* 0x449 */ unsigned short scrwid; /* 0x44A */ unsigned short scrlen; /* 0x44C */ unsigned short scroff; /* 0x44E */ struct LOCATE { unsigned char col; unsigned char row; } __attribute__ ((packed)) csrpos[8];/* 0x450 */ unsigned short csrsize; /* 0x460 */ unsigned char page; /* 0x462 */ unsigned short addr_6845; /* 0x463 */ unsigned char crt_mode_set; /* 0x465 */ unsigned char crt_palette; /* 0x466 */ unsigned char system_stuff[29]; /* 0x467 */ unsigned char rows; /* 0x484 */ unsigned short points; /* 0x485 */ unsigned char ega_info; /* 0x487 */ unsigned char info_3; /* 0x488 */ unsigned char skip[13]; /* 0x489 */ unsigned char kb_flag_3; /* 0x496 */} __attribute__ ((packed)) vid;union REGS in, out;unsigned char temp, active_display; /* * Move system information into our video structure. */ dosmemget( 0x449, sizeof( vid ), &vid ); /* * this next code was contributed by Jim Derr <jim.derr@spacebbs.com> * jmh 991024: slightly modified, since I moved it from hw_initialize(). */ cfg->cols = vid.scrwid; cfg->rows = vid.rows + 1; if (cfg->rows == 1) cfg->rows = 25; in.w.ax = 0x1a00; int86( VIDEO_INT, &in, &out ); temp = out.h.al; active_display = out.h.bl; if (temp == 0x1a && (active_display == 7 || active_display == 8)) g_display.adapter = VGA; else { in.h.ah = 0x12; in.h.bl = 0x10; int86( VIDEO_INT, &in, &out ); if (out.h.bl != 0x10) { /* EGA */ if (vid.ega_info & 0x08) g_display.adapter = vid.addr_6845 == 0x3d4 ? CGA : MDA; else g_display.adapter = EGA; } else if (vid.addr_6845 == 0x3d4) g_display.adapter = CGA; else g_display.adapter = MDA; } /* * jmh 990213: Due to the config file being read after the cursor style * variable, just set cursor sizes. */ if (g_display.adapter == CGA || g_display.adapter == EGA) { g_display.cursor[SMALL_CURSOR] = 0x0607; g_display.cursor[MEDIUM_CURSOR] = 0x0407; g_display.cursor[LARGE_CURSOR] = 0x0007; } else { g_display.cursor[SMALL_CURSOR] = 0x0b0c; g_display.cursor[MEDIUM_CURSOR] = 0x070b; g_display.cursor[LARGE_CURSOR] = 0x000b; } /* * jmh 990213: remember original cursor size. */ g_display.curses_cursor = vid.csrsize; /* jmh - added the vid.scroff for proper page offset */ display_address = 0xb8000ul + vid.scroff; cfg->color = (vid.addr_6845 == 0x3D4); if (!cfg->color) display_address -= 0x8000; /* monochrome is at 0xb0000 */ /* * let's save the overscan color */ g_display.old_overscan = vid.crt_palette; /* * Get keyboard type. Since there is no interrupt that determines * keyboard type, use this method. Look at bit 4 in keyboard flag3. * This method is not always foolproof on clones. */ if ((vid.kb_flag_3 & 0x10) != 0) mode.enh_kbd = TRUE; else mode.enh_kbd = FALSE; /* * jmh 991023: determine the width of the right edge of the shadow.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -