?? tl_vesa.c
字號(hào):
/*** thinlib (c) 2000 Matthew Conte (matt@conte.com)****** This program is free software; you can redistribute it and/or** modify it under the terms of version 2 of the GNU Library General ** Public License as published by the Free Software Foundation.**** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ** Library General Public License for more details. To obtain a ** copy of the GNU Library General Public License, write to the Free ** Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.**** Any permitted reproduction of these routines, in whole or in part,** must bear this legend.****** tl_vesa.c**** VESA code.** $Id: tl_vesa.c,v 1.8 2001/03/12 06:06:55 matt Exp $*/#include <stdio.h>#include <string.h>#include <assert.h>#include <go32.h>#include <dos.h>#include <dpmi.h>#include "tl_types.h"#include "tl_log.h"#include "tl_bmp.h"#include "tl_djgpp.h"#include "tl_vga.h"#include "tl_vesa.h"#define __PACKED__ __attribute__ ((packed))/* VESA information block structure */typedef struct vesainfo_s{ char VESASignature[4] __PACKED__; uint16 VESAVersion __PACKED__; uint32 OEMStringPtr __PACKED__; char Capabilities[4] __PACKED__; uint32 VideoModePtr __PACKED__; uint16 TotalMemory __PACKED__; uint16 OemSoftwareRev __PACKED__; uint32 OemVendorNamePtr __PACKED__; uint32 OemProductNamePtr __PACKED__; uint32 OemProductRevPtr __PACKED__; uint8 Reserved[222] __PACKED__; char OemData[256] __PACKED__; } vesainfo_t;/* SuperVGA mode information block */typedef struct modeinfo_s{ uint16 ModeAttributes __PACKED__; uint8 WinAAttributes __PACKED__; uint8 WinBAttributes __PACKED__; uint16 WinGranularity __PACKED__; uint16 WinSize __PACKED__; uint16 WinASegment __PACKED__; uint16 WinBSegment __PACKED__; uint32 WinFuncPtr __PACKED__; uint16 BytesPerScanLine __PACKED__; uint16 XResolution __PACKED__; uint16 YResolution __PACKED__; uint8 XCharSize __PACKED__; uint8 YCharSize __PACKED__; uint8 NumberOfPlanes __PACKED__; uint8 BitsPerPixel __PACKED__; uint8 NumberOfBanks __PACKED__; uint8 MemoryModel __PACKED__; uint8 BankSize __PACKED__; uint8 NumberOfImagePages __PACKED__; uint8 Reserved_page __PACKED__; uint8 RedMaskSize __PACKED__; uint8 RedMaskPos __PACKED__; uint8 GreenMaskSize __PACKED__; uint8 GreenMaskPos __PACKED__; uint8 BlueMaskSize __PACKED__; uint8 BlueMaskPos __PACKED__; uint8 ReservedMaskSize __PACKED__; uint8 ReservedMaskPos __PACKED__; uint8 DirectColorModeInfo __PACKED__; /* VBE 2.0 extensions */ uint32 PhysBasePtr __PACKED__; uint32 OffScreenMemOffset __PACKED__; uint16 OffScreenMemSize __PACKED__; /* VBE 3.0 extensions */ uint16 LinBytesPerScanLine __PACKED__; uint8 BnkNumberOfPages __PACKED__; uint8 LinNumberOfPages __PACKED__; uint8 LinRedMaskSize __PACKED__; uint8 LinRedFieldPos __PACKED__; uint8 LinGreenMaskSize __PACKED__; uint8 LinGreenFieldPos __PACKED__; uint8 LinBlueMaskSize __PACKED__; uint8 LinBlueFieldPos __PACKED__; uint8 LinRsvdMaskSize __PACKED__; uint8 LinRsvdFieldPos __PACKED__; uint32 MaxPixelClock __PACKED__; uint8 Reserved[190] __PACKED__; } modeinfo_t;#define MASK_LINEAR(addr) (addr & 0x000FFFFF)#define RM_TO_LINEAR(addr) (((addr & 0xFFFF0000) >> 12) + (addr & 0xFFFF))#define RM_OFFSET(addr) (addr & 0xF)#define RM_SEGMENT(addr) ((addr >> 4) & 0xFFFF)#define VBE_LINEAR_ADDR 0x4000#define VBE_LINEAR_AVAIL 0x0080#define VBE_INT 0x10#define VBE_SUCCESS 0x004F#define VBE_FUNC_DETECT 0x4F00#define VBE_FUNC_GETMODEINFO 0x4F01#define VBE_FUNC_SETMODE 0x4F02#define VBE_FUNC_GETMODE 0x4F03#define VBE_FUNC_FLIPPAGE 0x4F07#define VBE_MAX_NUM_MODES 1024 /* liberal */static struct{ uint32 address; int width, height; int bpp;} cur_mode;static vesainfo_t vesa_info;static bitmap_t *screen = NULL;static bitmap_t *hardware = NULL;/* look for vesa */static int vesa_detect(vesainfo_t *vesainfo){ __dpmi_regs regs; /* Use DOS transfer buffer to hold VBE info */ THIN_ASSERT(sizeof(*vesainfo) < _go32_info_block.size_of_transfer_buffer); memset(®s, 0, sizeof(regs)); strncpy(vesainfo->VESASignature, "VBE2", 4); dosmemput(vesainfo, sizeof(*vesainfo), MASK_LINEAR(__tb)); regs.x.ax = VBE_FUNC_DETECT; regs.x.di = RM_OFFSET(__tb); regs.x.es = RM_SEGMENT(__tb); __dpmi_int(VBE_INT, ®s); if (VBE_SUCCESS != regs.x.ax) return -1; dosmemget(MASK_LINEAR(__tb), sizeof(*vesainfo), vesainfo); if (strncmp(vesainfo->VESASignature, "VESA", 4) != 0) return -1; return 0;}static int vesa_getmodeinfo(uint16 mode, modeinfo_t *modeinfo){ __dpmi_regs regs; THIN_ASSERT(sizeof(*modeinfo) < _go32_info_block.size_of_transfer_buffer); memset(®s, 0, sizeof(regs)); regs.x.ax = VBE_FUNC_GETMODEINFO; regs.x.cx = mode; regs.x.di = RM_OFFSET(__tb); regs.x.es = RM_SEGMENT(__tb); __dpmi_int(VBE_INT, ®s); if (VBE_SUCCESS != regs.x.ax) return -1; dosmemget(MASK_LINEAR(__tb), sizeof(*modeinfo), modeinfo); return 0;}static uint16 vesa_findmode(vesainfo_t *vesainfo, int width, int height, int bpp){ modeinfo_t mode_info; uint16 modes[VBE_MAX_NUM_MODES], mode; int i, mode_total = 0; long list_ptr; list_ptr = RM_TO_LINEAR(vesainfo->VideoModePtr); while (mode_total < VBE_MAX_NUM_MODES) { dosmemget(list_ptr, 2, &mode); if (0xFFFF == mode) break; modes[mode_total++] = mode; list_ptr += 2; } /* VESA card on steroids? */ THIN_ASSERT(mode_total < VBE_MAX_NUM_MODES); for (i = 0; i < mode_total; i++) { mode = modes[i]; if (vesa_getmodeinfo(mode, &mode_info)) return -1; /* we are definitely screwed */ if (mode_info.XResolution == width && mode_info.YResolution == height && mode_info.BitsPerPixel == bpp) return mode; } return 0;}short int vid_selector = -1;static int vesa_setmodenum(uint16 mode){ __dpmi_regs regs; __dpmi_meminfo mi; modeinfo_t mode_info; if (vesa_getmodeinfo(mode, &mode_info)) return -1; mi.size = mode_info.BytesPerScanLine * mode_info.YResolution; mi.address = mode_info.PhysBasePtr; if (-1 == __dpmi_physical_address_mapping(&mi)) return -1; if (0 == thinlib_nearptr) { vid_selector = __dpmi_allocate_ldt_descriptors(1); if (-1 == vid_selector) return -1; /* paranoid */ if (-1 == __dpmi_set_descriptor_access_rights(vid_selector, 0x40f3)) return -1; if (-1 == __dpmi_set_segment_base_address(vid_selector, mi.address)) return -1; if (-1 == __dpmi_set_segment_limit(vid_selector, vesa_info.TotalMemory << 16 | 0xfff)) return -1; } memset(®s, 0, sizeof(regs)); regs.x.ax = VBE_FUNC_SETMODE; regs.x.bx = mode | VBE_LINEAR_ADDR; __dpmi_int(VBE_INT, ®s); if (VBE_SUCCESS != regs.x.ax) return -1; if (0 == thinlib_nearptr) cur_mode.address = 0; else cur_mode.address = mi.address; cur_mode.width = mode_info.XResolution; cur_mode.height = mode_info.YResolution; cur_mode.bpp = mode_info.BitsPerPixel; if (NULL != screen) thin_bmp_destroy(&screen); if (thinlib_nearptr) { screen = thin_bmp_createhw((uint8 *) THIN_PHYS_ADDR(cur_mode.address), cur_mode.width, cur_mode.height, cur_mode.bpp, cur_mode.width); if (NULL == screen) return -1; } else { if (NULL != hardware) thin_bmp_destroy(&hardware); hardware = thin_bmp_createhw((uint8 *) cur_mode.address, cur_mode.width, cur_mode.height, cur_mode.bpp, cur_mode.width); if (NULL == hardware) return -1; screen = thin_bmp_create(cur_mode.width, cur_mode.height, cur_mode.bpp, 0); if (NULL == screen) return -1; } return 0;}void thin_vesa_shutdown(void){ __dpmi_regs regs; memset(®s, 0, sizeof(regs)); regs.x.ax = 0x0003; __dpmi_int(VBE_INT, ®s); thin_bmp_destroy(&screen); if (0 == thinlib_nearptr) thin_bmp_destroy(&hardware);}int thin_vesa_setmode(int width, int height, int bpp){ uint16 mode; mode = vesa_findmode(&vesa_info, width, height, bpp); if (0 == mode) return -1; return vesa_setmodenum(mode);}int thin_vesa_init(int width, int height, int bpp){ memset(&vesa_info, 0, sizeof(vesa_info)); screen = NULL; hardware = NULL; if (vesa_detect(&vesa_info)) return -1; /* check to see if linear framebuffer is available */ if ((vesa_info.VESAVersion >> 8) < 2) { thin_printf("thin@vesa: no linear framebuffer available\n"); return -1; } return thin_vesa_setmode(width, height, bpp);}bitmap_t *thin_vesa_lockwrite(void){ return screen;}void thin_vesa_freewrite(int num_dirties, rect_t *dirty_rects){ UNUSED(num_dirties); UNUSED(dirty_rects); if (0 == thinlib_nearptr) { movedata(_my_ds(), (unsigned) screen->line[0], vid_selector, (unsigned) hardware->line[0], hardware->pitch * hardware->height); }}/*** $Log: tl_vesa.c,v $** Revision 1.8 2001/03/12 06:06:55 matt** better keyboard driver, support for bit depths other than 8bpp**** Revision 1.7 2001/02/01 06:28:26 matt** thinlib now works under NT/2000**** Revision 1.6 2001/01/15 05:25:52 matt** i hate near pointers**** Revision 1.5 2000/12/14 14:10:32 matt** cleaner initialization**** Revision 1.4 2000/11/25 20:28:34 matt** moved verboseness into correct places**** Revision 1.3 2000/11/06 02:22:33 matt** generalized video driver (tl_video.c)**** Revision 1.2 2000/11/05 16:32:36 matt** thinlib round 2**** Revision 1.1 2000/11/05 06:29:03 matt** initial revision***/
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -