📄 dev_uvga.c
字号:
/** SmallBASIC platform driver for Unix + SVGALIB** ndc: 2001-02-13*/#include "device.h"#include "osd.h"#include "str.h"#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <unistd.h>#include <vgamouse.h>static int cur_x = 0;static int cur_y = 0;static int uvgaclr = 0;static int mouse_mode, mouse_x, mouse_y, mouse_b, mouse_upd, mouse_down_x, mouse_down_y, mouse_pc_x, mouse_pc_y;static int tabsize = 32; // from dev_palmstatic int maxline;static int font_h = 16;static int font_w = 8;static int con_use_bold = 0;static int con_use_ul = 0;static int con_use_reverse = 0;// VGA16 colors in RGBstatic unsigned long vga16[] ={0x0, 0x7F, 0x7F00, 0x7F7F, 0x7F0000, 0x7F007F, 0x7F7F00, 0x808080,0x555555, 0xFF, 0xFF00, 0xFFFF, 0xFF0000, 0xFF00FF, 0xFFFF00, 0xFFFFFF };// fonts#include "unix/rom16.c"// mouse cursor (I'll look for something better)unsigned long mag_glass_bits[] = { 0x3f8, 0x60c, 0x9e2, 0x1a13, 0x1401, 0x1401, 0x1001, 0x1001, 0x1001, 0x1003, 0x1802, 0x340c, 0x6ff8, 0xd800, 0xb000, 0xe000, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x3f8, 0x60c, 0x9e2, 0x1a13, 0x1401, 0x1401, 0x1001, 0x1001, 0x1001, 0x1003, 0x1802, 0x340c, 0x6ff8, 0xd800, 0xb000, 0xe000, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,};unsigned long mag_glass_filled[] = { 0x3f8, 0x60c, 0x9e2, 0x1a13, 0x1401, 0x1401, 0x1001, 0x1001, 0x1001, 0x1003, 0x1802, 0x340c, 0x6ff8, 0xd800, 0xb000, 0xe000, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0x3f8, 0x7fc, 0xffe, 0x1fff, 0x1fff, 0x1fff, 0x1fff, 0x1fff, 0x1fff, 0x1fff, 0x1ffe, 0x3ffc, 0x7ff8, 0xf800, 0xe000, 0xe000, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,};static int mouse_hot_x = -16, mouse_hot_y = -16;//#define TAKE_SCREENSHOT#if defined(TAKE_SCREENSHOT)void writeppm(char *name);#endif/** SVGALIB: Initialization*/int osd_devinit(){ int vgamode, i; vga_init(); vgamode = vga_getdefaultmode(); if (vgamode == -1)// vgamode = G640x480x256; vgamode = G640x480x64K;// vgamode = G640x480x16M; if (!vga_hasmode(vgamode)) { fprintf(stderr, "SVGALIB: Mode not available.\n"); return 0; } vga_setmode(vgamode); gl_setcontextvga(vgamode); os_graf_mx = vga_getxdim(); os_graf_my = vga_getydim(); maxline = os_graf_my / font_h; os_graphics = DEVDRV_SVGALIB; os_color = 1; switch ( vga_getcolors() ) { case 16: os_color_depth = 4; break; case 256: os_color_depth = 8; for ( i = 0; i < 16; i ++ ) { gl_setpalettecolor( i, (vga16[i] & 0xff0000) >> 16, (vga16[i] & 0xff00) >> 8, vga16[i] & 0xff ); } break; case 65536: os_color_depth = 16; break; default: os_color_depth = 32; } gl_enableclipping(); gl_setwritemode(FONT_COMPRESSED + WRITEMODE_OVERWRITE); ///// MOUSE CURSOR: UNDOCUMENTED !!!! WWWHHHHHYYYY ??????????// vga_setmousesupport(1); vga_initcursor(0); vga_setcursorposition(mouse_getx() + mouse_hot_x, mouse_gety() + mouse_hot_y); vga_setcursorimage(1,0,0,0x0,(unsigned char *)mag_glass_bits); vga_selectcursor(1); vga_showcursor(1); setsysvar_str(SYSVAR_OSNAME, "Unix/SVGA"); osd_cls(); return 1;}/** close*/int osd_devrestore(){ cur_x = 0; cur_y = (maxline - 1) * font_h; osd_write("SVGALIB: Press any key to exit...");#if defined(TAKE_SCREENSHOT) writeppm("svga.ppm"); #endif vga_getch(); vga_setmode(TEXT); return 1;}void osd_settextcolor(int fg, int bg){ osd_setcolor(fg); if ( bg != -1 ) dev_bgcolor = bg;}//void osd_drawchar(int x, int y, byte ch, int overwrite, int fg_rgb, int bg_rgb){ int offset; int bit, i; int fg, bg; fg = gl_rgbcolor( (vga16[dev_fgcolor] & 0xff0000) >> 16, (vga16[dev_fgcolor] & 0xff00) >> 8, vga16[dev_fgcolor] & 0xff); bg = gl_rgbcolor( (vga16[dev_bgcolor] & 0xff0000) >> 16, (vga16[dev_bgcolor] & 0xff00) >> 8, vga16[dev_bgcolor] & 0xff); offset = ch * 16; for ( i = 0; i < 16; i ++, offset ++ ) { for ( bit = 0; bit < 8; bit ++ ) { if ( *(font8x16+offset) & (1 << (8-bit)) ) gl_setpixel(x+bit, y+i, fg); else if ( overwrite ) gl_setpixel(x+bit, y+i, bg); } }}/** enable or disable PEN code*/void osd_setpenmode(int enable){ mouse_mode = enable;}/**/int osd_getpen(int code){ int r = 0; byte update; osd_events(0); if ( mouse_mode ) { switch ( code ) { case 0: // bool: status changed r = mouse_upd; break; case 1: // last pen-down x r = mouse_down_x; break; case 2: // last pen-down y r = mouse_down_y; break; case 3: // vert. 1 = down, 0 = up .... unsupported r = 0; break; case 4: // last x r = mouse_pc_x; break; case 5: // last y r = mouse_pc_y; break; case 10: r = mouse_x; break; case 11: r = mouse_y; break; case 12: case 13: case 14: r = (mouse_b & (1 << (code - 11))) ? 1 : 0; break; } mouse_upd = 0; } return r;}//void osd_cls(){ cur_x = cur_y = 0; gl_clearscreen(vga_white());}// returns the current x positionint osd_getx(){ return cur_x;}// returns the current y positionint osd_gety(){ return cur_y;}//void osd_setxy(int x, int y){ cur_x = x; cur_y = y;}/*** next line*/void osd_nextln(){ cur_x = 0; if ( cur_y < ((maxline-1) * font_h) ) { cur_y += font_h; } else { // scroll gl_copybox(0, font_h, os_graf_mx, cur_y, 0, 0); gl_fillbox(0, cur_y, os_graf_mx, font_h, vga_white()); }}/** calc next tab position*/int osd_calctab(int x){ int c = 1; while ( x > tabsize ) { x -= tabsize; c ++; } return c * tabsize;}/*** Basic output** Supported control codes:* \t tab (20 px)* \a beep* \n next line (cr/lf)* \xC clear screen* \e[K clear to end of line* \e[0m reset all attributes to their defaults* \e[1m set bold on* \e[4m set underline on* \e[7m reverse video* \e[21m set bold off* \e[24m set underline off* \e[27m set reverse off*/void osd_write(const char *str){ int len, cx, esc_val, esc_cmd; byte *p, buf[3]; int ch, char_len = 1; len = strlen(str); if ( len <= 0 ) return; p = (byte *) str; while ( *p ) { switch ( *p ) { case '\a': // beep osd_beep(); break; case '\t': cur_x = osd_calctab(cur_x+1); break; case '\xC': osd_cls(); break; case '\033': // ESC ctrl chars (man console_codes) if ( *(p+1) == '[' ) { p += 2; esc_val = esc_cmd = 0; if ( is_digit(*p) ) { esc_val = (*p - '0'); p ++; if ( is_digit(*p) ) { esc_val = (esc_val * 10) + (*p - '0'); p ++; } esc_cmd = *p; } else esc_cmd = *p; // control characters switch ( esc_cmd ) { case 'K': // \e[K - clear to eol gl_fillbox(cur_x, cur_y, os_graf_mx - cur_x, font_h, vga_white()); break; case 'm': // \e[...m - ANSI terminal switch ( esc_val ) { case 0: // reset con_use_bold = 0; con_use_ul = 0; con_use_reverse = 0; osd_setcolor(0); osd_settextcolor(0, 15); break; case 1: // set bold on con_use_bold = 1; break; case 4: // set underline on con_use_ul = 1; break; case 7: // reverse video on con_use_reverse = 1; break; case 21: // set bold off con_use_bold = 0; break; case 24: // set underline off con_use_ul = 0; break; case 27: // reverse video off con_use_reverse = 0; break; // colors - 30..37 foreground, 40..47 background case 30: // set black fg osd_setcolor(0); break; case 31: // set red fg osd_setcolor(4); break; case 32: // set green fg osd_setcolor(2); break; case 33: // set brown fg osd_setcolor(6); break; case 34: // set blue fg osd_setcolor(1); break; case 35: // set magenta fg osd_setcolor(5); break; case 36: // set cyan fg osd_setcolor(3); break; case 37: // set white fg osd_setcolor(7); break; case 40: // set black bg osd_settextcolor(dev_fgcolor, 0); break; case 41: // set red bg osd_settextcolor(dev_fgcolor, 4); break; case 42: // set green bg osd_settextcolor(dev_fgcolor, 2); break; case 43: // set brown bg osd_settextcolor(dev_fgcolor, 6); break; case 44: // set blue bg osd_settextcolor(dev_fgcolor, 1); break; case 45: // set magenta bg osd_settextcolor(dev_fgcolor, 5); break; case 46: // set cyan bg osd_settextcolor(dev_fgcolor, 3); break; case 47: // set white bg osd_settextcolor(dev_fgcolor, 7); break; }; break; } } break; case '\n': // new line osd_nextln(); break; case '\r': // return cur_x = 0; gl_fillbox(cur_x, cur_y, os_graf_mx - cur_x, font_h, vga_white()); break; default: // // PRINT THE CHARACTER // buf[0] = *p; cx = 8; buf[1] = '\0'; // new line ? if ( cur_x + cx >= dev_x2clip ) osd_nextln(); // draw // TODO: ??? SJIS on Linux ??? if ( !con_use_reverse ) { osd_drawchar(cur_x, cur_y, *p, 1, vga16[dev_fgcolor], vga16[dev_bgcolor]); if ( con_use_bold ) osd_drawchar(cur_x-1, cur_y, *p, 0, vga16[dev_fgcolor], vga16[dev_bgcolor]); } else { osd_drawchar(cur_x, cur_y, *p, 1, vga16[dev_bgcolor], vga16[dev_fgcolor]); if ( con_use_bold ) osd_drawchar(cur_x-1, cur_y, *p, 0, vga16[dev_bgcolor], vga16[dev_fgcolor]); } if ( con_use_ul ) { osd_setcolor(dev_fgcolor); vga_drawline(cur_x, (cur_y+font_h)-1, cur_x+cx, (cur_y+font_h)-1); } // advance cur_x += cx; }; if ( *p == '\0' ) break; p ++; }}int osd_events(int wait_flag){ int ch, button; int evc = 0; if ( wait_flag == 0 ) { while ( (ch = vga_getkey()) != 0 ) { if ( ch == 127 ) dev_pushkey(8); else dev_pushkey(ch); evc ++; } while ( mouse_update() ) { mouse_x = mouse_getx(); mouse_y = mouse_gety(); // !!! if ( mouse_x < mouse_hot_x ) mouse_x = mouse_hot_x; if ( mouse_y < mouse_hot_y ) mouse_y = mouse_hot_y; if ( mouse_x >= os_graf_mx - 1 ) mouse_x = os_graf_mx - 1; if ( mouse_y >= os_graf_my - 1 ) mouse_y = os_graf_my - 1; vga_setcursorposition(mouse_x + mouse_hot_x, mouse_y + mouse_hot_y); button = mouse_getbutton(); mouse_b = 0; if ( button & MOUSE_LEFTBUTTON ) { if ( (mouse_b & MOUSE_LEFTBUTTON) == 0 ) { // new press mouse_down_x = mouse_x; mouse_down_y = mouse_y; } mouse_upd = 1; mouse_pc_x = mouse_x; mouse_pc_y = mouse_y; mouse_b |= 1; } if (button & MOUSE_RIGHTBUTTON) mouse_b |= 2; if (button & MOUSE_MIDDLEBUTTON) mouse_b |= 4; evc ++; } } else { while ( (evc = osd_events(0)) == 0 ) usleep(50*1000); } return evc;}///////////////////////////////////////////////////////////////void osd_setcolor(int color){ if ( os_color_depth > 8 ) { uvgaclr = gl_rgbcolor( (vga16[color] & 0xff0000) >> 16, (vga16[color] & 0xff00) >> 8, vga16[color] & 0xff); vga_setrgbcolor( (vga16[color] & 0xff0000) >> 16, (vga16[color] & 0xff00) >> 8, vga16[color] & 0xff); } else vga_setcolor((uvgaclr=color)); dev_fgcolor = color;}void osd_line(int x1, int y1, int x2, int y2){ if ( (x1 == x2) && (y1 == y2) ) gl_setpixel(x1, y1, uvgaclr); else gl_line(x1, y1, x2, y2, uvgaclr);}void osd_setpixel(int x, int y){ gl_setpixel(x, y, uvgaclr); }void osd_rect(int x1, int y1, int x2, int y2, int fill){ int y; if ( fill ) { for ( y = y1; y <= y2; y ++ ) gl_line(x1, y, x2, y, uvgaclr); } else { gl_line(x1, y1, x1, y2, uvgaclr); gl_line(x1, y2, x2, y2, uvgaclr); gl_line(x2, y2, x2, y1, uvgaclr); gl_line(x2, y1, x1, y1, uvgaclr); }}///////////////////////////////////////////////////////////////void osd_beep(){ printf("\a");}void osd_sound(int frq, int ms, int vol, int bgplay){}///////////////////////////////////////////////////////////////int osd_textwidth(const char *str){ int l = strlen(str); // SJIS ??? return l * font_w;}int osd_textheight(const char *str){ // TODO: count \n return font_h;}#if defined(TAKE_SCREENSHOT)//void writeppm(char *name){ int y, i, j, k; FILE *file; byte *tmp, *tmp2; int width = os_graf_mx; int height = os_graf_my; int bpp = os_color_depth; file = fopen(name, "wt"); fprintf(file, "P6\n%i %i\n255\n", width, height); tmp = (byte *) malloc(width*4); tmp2 = (byte *) malloc(width*4); for ( y = 0; y < height; y++ ) { vga_getscansegment(tmp, 0, y, width * 4); switch ( bpp ) { case 16: for ( i = 0; i < width; i++ ) { j = tmp[i * 2] + 256 * tmp[i * 2 + 1]; tmp2[i * 3] = (j & 0xf800) >> 8; tmp2[i * 3 + 1] = (j & 0x7e0) >> 3; tmp2[i * 3 + 2] = (j & 0x1f) << 3; } break; case 24: memcpy(tmp2, tmp, width * 3); break; } fwrite(tmp2, width * 3, 1, file); } free(tmp); free(tmp2); fclose(file);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -