📄 fbdev.c
字号:
#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/mman.h>#include <linux/fb.h>#include <sys/ioctl.h>#include <sys/fcntl.h>#include "defs.h"#include "fb.h"#include "rc.h"#include "matrox.h"struct fb fb;#define FBSET_CMD "fbset"static char *fb_mode;static int fb_depth;static int vmode[3];#define FB_DEVICE "/dev/fb0"static char *fb_device;static int fbfd = -1;static byte *fbmap;static int maplen;static byte *mmio;static int bes;static int base;static int use_yuv = -1;static int use_interp;static struct fb_fix_screeninfo fi;static struct fb_var_screeninfo vi, initial_vi;rcvar_t vid_exports[] ={ RCV_VECTOR("vmode", &vmode, 3), RCV_STRING("fb_device", &fb_device), RCV_STRING("fb_mode", &fb_mode), RCV_INT("fb_depth", &fb_depth), RCV_BOOL("yuv", &use_yuv), RCV_BOOL("yuvinterp", &use_interp), RCV_END};static void wrio4(int a, int v){#ifndef IS_LITTLE_ENDIAN v = (v<<24) | ((v&0xff00)<<8) | ((v&0xff0000)>>8) | (v>>24);#endif *(int*)(mmio+a) = v;}static void overlay_switch(){ int a, b; if (!fb.yuv) return; if (!fb.enabled) { if (bes) wrio4(BESCTL, 0); bes = 0; return; } if (bes) return; bes = 1; memset(fbmap, 0, maplen); /* color keying (turn it off) */ mmio[PALWTADD] = XKEYOPMODE; mmio[X_DATAREG] = 0; /* src */ wrio4(BESA1ORG, base); wrio4(BESA2ORG, base); wrio4(BESB1ORG, base); wrio4(BESB2ORG, base); wrio4(BESPITCH, 512); /* dest */ a = (vi.xres - vmode[0])>>1; b = vi.xres - a; wrio4(BESHCOORD, (a << 16) | b - 1); /* scale horiz */ wrio4(BESHISCAL, 320*65536/(b-a) & 0x001ffffc); wrio4(BESHSRCST, 0 << 16); wrio4(BESHSRCEND, 320 << 16); wrio4(BESHSRCLST, 319 << 16); /* dest */ a = (vi.yres - vmode[1])>>1; b = vi.yres - a; wrio4(BESVCOORD, (a << 16) | b - 1); /* scale vert */ wrio4(BESVISCAL, 144*65536/(b-a) & 0x001ffffc); wrio4(BESV1WGHT, 0); wrio4(BESV2WGHT, 0); wrio4(BESV1SRCLST, 143); wrio4(BESV2SRCLST, 143); /* turn on (enable, horizontal+vertical interpolation filters */ if (use_interp) wrio4(BESCTL, (1 << 0) | (1 << 10) | (1 << 11)); else wrio4(BESCTL, 1); wrio4(BESGLOBCTL, 0);}static void overlay_init(){ if (!mmio | !use_yuv) return; if (use_yuv < 0) if ((vmode[0] < 320) || (vmode[1] < 288)) return; switch (fi.accel) {#ifdef FB_ACCEL_MATROX_MGAG200 case FB_ACCEL_MATROX_MGAG200:#endif#ifdef FB_ACCEL_MATROX_MGAG400 case FB_ACCEL_MATROX_MGAG400:#endif break; default: return; } fb.w = 160; fb.h = 144; fb.pitch = 1024; fb.pelsize = 4; fb.yuv = 1; fb.cc[0].r = fb.cc[1].r = fb.cc[2].r = fb.cc[3].r = 0; fb.cc[0].l = 0; fb.cc[1].l = 24; fb.cc[2].l = 8; fb.cc[3].l = 16; base = vi.yres * vi.xres_virtual * ((vi.bits_per_pixel+7)>>3); maplen = base + fb.pitch * fb.h;}static void plain_init(){ fb.w = vi.xres; fb.h = vi.yres; fb.pelsize = (vi.bits_per_pixel+7)>>3; fb.pitch = vi.xres_virtual * fb.pelsize; fb.indexed = fi.visual == FB_VISUAL_PSEUDOCOLOR; fb.cc[0].r = 8 - vi.red.length; fb.cc[1].r = 8 - vi.green.length; fb.cc[2].r = 8 - vi.blue.length; fb.cc[0].l = vi.red.offset; fb.cc[1].l = vi.green.offset; fb.cc[2].l = vi.blue.offset; maplen = fb.pitch * fb.h;}void vid_init(){ char cmd[256]; kb_init(); joy_init(); if (!fb_device) if (!(fb_device = getenv("FRAMEBUFFER"))) fb_device = strdup(FB_DEVICE); fbfd = open(fb_device, O_RDWR); if (fbfd < 0) die("cannot open %s\n", fb_device); ioctl(fbfd, FBIOGET_VSCREENINFO, &initial_vi); initial_vi.xoffset = initial_vi.yoffset = 0; if (fb_mode) { sprintf(cmd, FBSET_CMD " %.80s", fb_mode); system(cmd); } ioctl(fbfd, FBIOGET_VSCREENINFO, &vi); if (fb_depth) vi.bits_per_pixel = fb_depth; vi.xoffset = vi.yoffset = 0; vi.accel_flags = 0; vi.activate = FB_ACTIVATE_NOW; ioctl(fbfd, FBIOPUT_VSCREENINFO, &vi); ioctl(fbfd, FBIOGET_VSCREENINFO, &vi); ioctl(fbfd, FBIOGET_FSCREENINFO, &fi); if (!vmode[0] || !vmode[1]) { int scale = rc_getint("scale"); if (scale < 1) scale = 1; vmode[0] = 160 * scale; vmode[1] = 144 * scale; } if (vmode[0] > vi.xres) vmode[0] = vi.xres; if (vmode[1] > vi.yres) vmode[1] = vi.yres; mmio = mmap(0, fi.mmio_len, PROT_READ|PROT_WRITE, MAP_SHARED, fbfd, fi.smem_len); if ((int)mmio == -1) mmio = 0; overlay_init(); if (!fb.yuv) plain_init(); fbmap = mmap(0, maplen, PROT_READ|PROT_WRITE, MAP_SHARED, fbfd, 0); if (!fbmap) die("cannot mmap %s (%d bytes)\n", fb_device, maplen); fb.ptr = fbmap + base; memset(fbmap, 0, maplen); fb.dirty = 0; fb.enabled = 1; overlay_switch();}void vid_close(){ fb.enabled = 0; overlay_switch(); joy_close(); kb_close(); ioctl(fbfd, FBIOPUT_VSCREENINFO, &initial_vi); memset(fbmap, 0, maplen);}void vid_preinit(){}void vid_settitle(char *title){}void vid_setpal(int i, int r, int g, int b){ unsigned short rr = r<<8, gg = g<<8, bb = b<<8; struct fb_cmap cmap = { i, 1, &rr, &gg, &bb }; ioctl(fbfd, FBIOPUTCMAP, &cmap);}void vid_begin(){ overlay_switch();}void vid_end(){ overlay_switch();}void ev_poll(){ kb_poll(); joy_poll();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -