vbeinfo
changeset 0:4b33fa83e381
vbeinfo initial commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 05 Dec 2015 07:28:47 +0200 |
parents | |
children | d2d777a5da95 |
files | Makefile src/dpmi.c src/dpmi.h src/inttypes.h src/main.c src/vbe.c src/vbe.h |
diffstat | 7 files changed, 440 insertions(+), 0 deletions(-) [+] |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/Makefile Sat Dec 05 07:28:47 2015 +0200 1.3 @@ -0,0 +1,22 @@ 1.4 +obj = main.obj vbe.obj dpmi.obj 1.5 +bin = vbeinfo.exe 1.6 + 1.7 +#opt = -5 -fp5 -otexan 1.8 +dbg = -d1 1.9 + 1.10 +CC = wcc386 1.11 +CFLAGS = $(dbg) $(opt) -zq -bt=dos -Isrc\stl 1.12 +LD = wlink 1.13 + 1.14 +$(bin): $(obj) 1.15 + %write objects.lnk file { $(obj) } 1.16 + $(LD) debug all name $@ @objects $(LDFLAGS) 1.17 + 1.18 +.c: src 1.19 + 1.20 +.c.obj: .autodepend 1.21 + $(CC) $(CFLAGS) $[* 1.22 + 1.23 +clean: .symbolic 1.24 + del *.obj 1.25 + del $(bin)
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/src/dpmi.c Sat Dec 05 07:28:47 2015 +0200 2.3 @@ -0,0 +1,55 @@ 2.4 +#include "dpmi.h" 2.5 + 2.6 +void dpmi_real_int(int inum, struct dpmi_real_regs *regs) 2.7 +{ 2.8 + unsigned char int_num = (unsigned char)inum; 2.9 + __asm { 2.10 + mov eax, 0x300 2.11 + mov edi, regs 2.12 + mov bl, int_num 2.13 + mov bh, 0 2.14 + xor ecx, ecx 2.15 + int 0x31 2.16 + } 2.17 +} 2.18 + 2.19 +void *dpmi_mmap(uint32_t phys_addr, unsigned int size) 2.20 +{ 2.21 + uint16_t mem_high, mem_low; 2.22 + uint16_t phys_high = phys_addr >> 16; 2.23 + uint16_t phys_low = phys_addr & 0xffff; 2.24 + uint16_t size_high = size >> 16; 2.25 + uint16_t size_low = size & 0xffff; 2.26 + unsigned int err, res = 0; 2.27 + 2.28 + __asm { 2.29 + mov eax, 0x800 2.30 + mov bx, phys_high 2.31 + mov cx, phys_low 2.32 + mov si, size_high 2.33 + mov di, size_low 2.34 + int 0x31 2.35 + add res, 1 2.36 + mov err, eax 2.37 + mov mem_high, bx 2.38 + mov mem_low, cx 2.39 + } 2.40 + 2.41 + if(res == 2) { 2.42 + return 0; 2.43 + } 2.44 + return (void*)(((uint32_t)mem_high << 16) | ((uint32_t)mem_low)); 2.45 +} 2.46 + 2.47 +void dpmi_munmap(void *addr) 2.48 +{ 2.49 + uint16_t mem_high = (uint32_t)addr >> 16; 2.50 + uint16_t mem_low = (uint16_t)addr; 2.51 + 2.52 + __asm { 2.53 + mov eax, 0x801 2.54 + mov bx, mem_high 2.55 + mov cx, mem_low 2.56 + int 0x31 2.57 + } 2.58 +}
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/src/dpmi.h Sat Dec 05 07:28:47 2015 +0200 3.3 @@ -0,0 +1,26 @@ 3.4 +#ifndef DPMI_H_ 3.5 +#define DPMI_H_ 3.6 + 3.7 +#include "inttypes.h" 3.8 + 3.9 +struct dpmi_real_regs { 3.10 + uint32_t edi, esi, ebp; 3.11 + uint32_t reserved; 3.12 + uint32_t ebx, edx, ecx, eax; 3.13 + uint16_t flags; 3.14 + uint16_t es, ds, fs, gs; 3.15 + uint16_t ip, cs, sp, ss; 3.16 +}; 3.17 + 3.18 +unsigned short dpmi_alloc(unsigned int par); 3.19 +#pragma aux dpmi_alloc = \ 3.20 + "mov eax, 0x100" \ 3.21 + "int 0x31" \ 3.22 + value[ax] parm[ebx]; 3.23 + 3.24 +void dpmi_real_int(int inum, struct dpmi_real_regs *regs); 3.25 + 3.26 +void *dpmi_mmap(uint32_t phys_addr, unsigned int size); 3.27 +void dpmi_munmap(void *addr); 3.28 + 3.29 +#endif /* DPMI_H_ */
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/src/inttypes.h Sat Dec 05 07:28:47 2015 +0200 4.3 @@ -0,0 +1,18 @@ 4.4 +#ifndef INT_TYPES_H_ 4.5 +#define INT_TYPES_H_ 4.6 + 4.7 +#if defined(__DOS__) || defined(WIN32) 4.8 +typedef char int8_t; 4.9 +typedef short int16_t; 4.10 +typedef long int32_t; 4.11 + 4.12 +typedef unsigned char uint8_t; 4.13 +typedef unsigned short uint16_t; 4.14 +typedef unsigned long uint32_t; 4.15 + 4.16 +typedef unsigned long intptr_t; 4.17 +#else 4.18 +#include <stdint.h> 4.19 +#endif 4.20 + 4.21 +#endif /* INT_TYPES_H_ */
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/src/main.c Sat Dec 05 07:28:47 2015 +0200 5.3 @@ -0,0 +1,96 @@ 5.4 +#include <stdio.h> 5.5 +#include <stdlib.h> 5.6 +#include "vbe.h" 5.7 + 5.8 +#define REALPTR(s, o) (void*)(((uint32_t)(s) << 4) + (uint32_t)(o)) 5.9 +#define VBEPTR(x) REALPTR(((x) & 0xffff0000) >> 16, (x) & 0xffff) 5.10 +#define VBEPTR_SEG(x) (((x) & 0xffff0000) >> 16) 5.11 +#define VBEPTR_OFF(x) ((x) & 0xffff) 5.12 + 5.13 +struct video_mode { 5.14 + int xres, yres, bpp; 5.15 +}; 5.16 + 5.17 +void sort_modes(struct video_mode *arr, int sz, int field); 5.18 +/*int modecmp(const void *pa, const void *pb);*/ 5.19 + 5.20 +int main(int argc, char **argv) 5.21 +{ 5.22 + int i, nmodes; 5.23 + struct vbe_info *vbe; 5.24 + struct vbe_mode_info *mode; 5.25 + uint16_t *modes; 5.26 + struct video_mode *vmodes; 5.27 + 5.28 + if(!(vbe = vbe_get_info())) { 5.29 + fprintf(stderr, "VBE not found\n"); 5.30 + return 1; 5.31 + } 5.32 + printf("VBE version: %x.%x\n", vbe->version >> 8, vbe->version & 0xff); 5.33 + printf("Graphics adapter: %s, %s (%s)\n", VBEPTR(vbe->oem_vendor_name_ptr), 5.34 + VBEPTR(vbe->oem_product_name_ptr), VBEPTR(vbe->oem_product_rev_ptr)); 5.35 + printf("Video memory: %dmb\n", vbe->total_mem << 6); 5.36 + 5.37 + modes = VBEPTR(vbe->vid_mode_ptr); 5.38 + nmodes = 0; 5.39 + for(i=0; i<1024; i++) { 5.40 + if(modes[i] == 0xffff) break; 5.41 + nmodes++; 5.42 + } 5.43 + printf("%d video modes found:\n", nmodes); 5.44 + 5.45 + if(!(vmodes = malloc(nmodes * sizeof *vmodes))) { 5.46 + fprintf(stderr, "failed to allocate video modes array\n"); 5.47 + return 1; 5.48 + } 5.49 + 5.50 + for(i=0; i<nmodes; i++) { 5.51 + if(!(mode = vbe_get_mode_info(modes[i]))) { 5.52 + fprintf(stderr, "failed to get mode %d info\n", i); 5.53 + } 5.54 + vmodes[i].xres = mode->xres; 5.55 + vmodes[i].yres = mode->yres; 5.56 + vmodes[i].bpp = mode->bpp; 5.57 + } 5.58 + 5.59 + /*qsort(vmodes, nmodes, sizeof *vmodes, modecmp);*/ 5.60 + sort_modes(vmodes, nmodes, 2); 5.61 + sort_modes(vmodes, nmodes, 1); 5.62 + 5.63 + for(i=0; i<nmodes; i++) { 5.64 + if(i == 0 || vmodes[i].xres != vmodes[i - 1].xres || 5.65 + vmodes[i].yres != vmodes[i - 1].yres) { 5.66 + printf("\n%4dx%d - depth:", vmodes[i].xres, vmodes[i].yres); 5.67 + } 5.68 + printf(" %d", vmodes[i].bpp); 5.69 + } 5.70 + putchar('\n'); 5.71 + 5.72 + free(vmodes); 5.73 + return 0; 5.74 +} 5.75 +/* 5.76 +int modecmp(const void *pa, const void *pb) 5.77 +{ 5.78 + const struct video_mode *va = pa; 5.79 + const struct video_mode *vb = pb; 5.80 + 5.81 + return va->xres * va->yres < vb->xres * vb->yres; 5.82 +} 5.83 +*/ 5.84 + 5.85 +void sort_modes(struct video_mode *arr, int sz, int field) 5.86 +{ 5.87 + int i, j; 5.88 + struct video_mode tmp; 5.89 + 5.90 + for(i=0; i<sz; i++) { 5.91 + for(j=i+1; j<sz; j++) { 5.92 + if(((int*)(arr + i))[field] >= ((int*)(arr + j))[field]) { 5.93 + tmp = arr[i]; 5.94 + arr[i] = arr[j]; 5.95 + arr[j] = tmp; 5.96 + } 5.97 + } 5.98 + } 5.99 +}
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/src/vbe.c Sat Dec 05 07:28:47 2015 +0200 6.3 @@ -0,0 +1,153 @@ 6.4 +#include <stdio.h> 6.5 +#include <string.h> 6.6 +#include "vbe.h" 6.7 +#include "dpmi.h" 6.8 + 6.9 +/* VGA DAC registers used for palette setting in 8bpp modes */ 6.10 +#define VGA_DAC_STATE 0x3c7 6.11 +#define VGA_DAC_ADDR_RD 0x3c7 6.12 +#define VGA_DAC_ADDR_WR 0x3c8 6.13 +#define VGA_DAC_DATA 0x3c9 6.14 + 6.15 +#define MODE_LFB (1 << 14) 6.16 + 6.17 + 6.18 +struct vbe_info *vbe_get_info(void) 6.19 +{ 6.20 + static unsigned short info_block_seg; 6.21 + static struct vbe_info *info; 6.22 + struct dpmi_real_regs regs; 6.23 + 6.24 + if(!info) { 6.25 + /* allocate 32 paragraphs (512 bytes) */ 6.26 + info_block_seg = dpmi_alloc(32); 6.27 + info = (struct vbe_info*)(info_block_seg << 4); 6.28 + } 6.29 + 6.30 + memcpy(info->sig, "VBE2", 4); 6.31 + 6.32 + memset(®s, 0, sizeof regs); 6.33 + regs.es = info_block_seg; 6.34 + regs.eax = 0x4f00; 6.35 + 6.36 + dpmi_real_int(0x10, ®s); 6.37 + 6.38 + return info; 6.39 +} 6.40 + 6.41 +struct vbe_mode_info *vbe_get_mode_info(int mode) 6.42 +{ 6.43 + static unsigned short mode_info_seg; 6.44 + static struct vbe_mode_info *mi; 6.45 + struct dpmi_real_regs regs; 6.46 + 6.47 + if(!mi) { 6.48 + /* allocate 16 paragraphs (256 bytes) */ 6.49 + mode_info_seg = dpmi_alloc(16); 6.50 + mi = (struct vbe_mode_info*)(mode_info_seg << 4); 6.51 + } 6.52 + 6.53 + memset(®s, 0, sizeof regs); 6.54 + regs.es = mode_info_seg; 6.55 + regs.eax = 0x4f01; 6.56 + regs.ecx = mode; 6.57 + regs.es = mode_info_seg; 6.58 + 6.59 + dpmi_real_int(0x10, ®s); 6.60 + if(regs.eax & 0xff00) { 6.61 + return 0; 6.62 + } 6.63 + 6.64 + return mi; 6.65 +} 6.66 + 6.67 +int vbe_set_mode(int mode) 6.68 +{ 6.69 + struct dpmi_real_regs regs; 6.70 + 6.71 + memset(®s, 0, sizeof regs); 6.72 + regs.eax = 0x4f02; 6.73 + regs.ebx = mode; 6.74 + dpmi_real_int(0x10, ®s); 6.75 + 6.76 + if(regs.eax == 0x100) { 6.77 + return -1; 6.78 + } 6.79 + return 0; 6.80 +} 6.81 + 6.82 +int vbe_set_palette_bits(int bits) 6.83 +{ 6.84 + struct dpmi_real_regs regs; 6.85 + 6.86 + memset(®s, 0, sizeof regs); 6.87 + regs.eax = 0x4f08; 6.88 + regs.ebx = bits << 8; /* bits in bh */ 6.89 + dpmi_real_int(0x10, ®s); 6.90 + 6.91 + if((regs.eax >> 8) & 0xff == 3) { 6.92 + return -1; 6.93 + } 6.94 + return regs.ebx >> 8 & 0xff; /* new color bits in bh */ 6.95 +} 6.96 + 6.97 +/* TODO: implement palette setting through the VBE2 interface for 6.98 + * non-VGA displays (actually don't). 6.99 + */ 6.100 +void vbe_set_palette(int idx, int *col, int count, int bits) 6.101 +{ 6.102 + int i, shift = 8 - bits; 6.103 + 6.104 + __asm { 6.105 + mov dx, VGA_DAC_ADDR_WR 6.106 + mov eax, idx 6.107 + out dx, al 6.108 + } 6.109 + 6.110 + for(i=0; i<count; i++) { 6.111 + unsigned char r = *col++; 6.112 + unsigned char g = *col++; 6.113 + unsigned char b = *col++; 6.114 + 6.115 + if(shift) { 6.116 + r >>= shift; 6.117 + g >>= shift; 6.118 + b >>= shift; 6.119 + } 6.120 + 6.121 + __asm { 6.122 + mov dx, VGA_DAC_DATA 6.123 + mov al, r 6.124 + out dx, al 6.125 + mov al, g 6.126 + out dx, al 6.127 + mov al, b 6.128 + out dx, al 6.129 + } 6.130 + } 6.131 +} 6.132 + 6.133 +static unsigned int get_mask(int sz, int pos) 6.134 +{ 6.135 + unsigned int i, mask = 0; 6.136 + 6.137 + for(i=0; i<sz; i++) { 6.138 + mask |= 1 << i; 6.139 + } 6.140 + return mask << pos; 6.141 +} 6.142 + 6.143 +void print_mode_info(FILE *fp, struct vbe_mode_info *mi) 6.144 +{ 6.145 + fprintf(fp, "resolution: %dx%d\n", mi->xres, mi->yres); 6.146 + fprintf(fp, "color depth: %d\n", mi->bpp); 6.147 + fprintf(fp, "mode attributes: %x\n", mi->mode_attr); 6.148 + fprintf(fp, "bytes per scanline: %d\n", mi->scanline_bytes); 6.149 + fprintf(fp, "number of planes: %d\n", (int)mi->num_planes); 6.150 + fprintf(fp, "number of banks: %d\n", (int)mi->num_banks); 6.151 + fprintf(fp, "mem model: %d\n", (int)mi->mem_model); 6.152 + fprintf(fp, "red bits: %d (mask: %x)\n", (int)mi->rmask_size, get_mask(mi->rmask_size, mi->rpos)); 6.153 + fprintf(fp, "green bits: %d (mask: %x)\n", (int)mi->gmask_size, get_mask(mi->gmask_size, mi->gpos)); 6.154 + fprintf(fp, "blue bits: %d (mask: %x)\n", (int)mi->bmask_size, get_mask(mi->bmask_size, mi->bpos)); 6.155 + fprintf(fp, "framebuffer address: %x\n", mi->fb_addr); 6.156 +}
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/src/vbe.h Sat Dec 05 07:28:47 2015 +0200 7.3 @@ -0,0 +1,70 @@ 7.4 +#ifndef VBE_H_ 7.5 +#define VBE_H_ 7.6 + 7.7 +#include "inttypes.h" 7.8 + 7.9 +#define VBE_ATTR_LFB (1 << 7) 7.10 +#define VBE_MODE_LFB (1 << 14) 7.11 + 7.12 +#pragma pack (push, 0) 7.13 +struct vbe_info { 7.14 + uint8_t sig[4]; 7.15 + uint16_t version; 7.16 + uint32_t oem_str_ptr; 7.17 + uint8_t caps[4]; /* capabilities */ 7.18 + uint32_t vid_mode_ptr; /* vbefarptr to video mode list */ 7.19 + uint16_t total_mem; /* num of 64k mem blocks */ 7.20 + uint16_t oem_sw_rev; /* VBE implementation software revision */ 7.21 + uint32_t oem_vendor_name_ptr; 7.22 + uint32_t oem_product_name_ptr; 7.23 + uint32_t oem_product_rev_ptr; 7.24 + uint8_t reserved[222]; 7.25 + uint8_t oem_data[256]; 7.26 +}; 7.27 + 7.28 +struct vbe_mode_info { 7.29 + uint16_t mode_attr; 7.30 + uint8_t wina_attr, winb_attr; 7.31 + uint16_t win_gran, win_size; 7.32 + uint16_t wina_seg, winb_seg; 7.33 + uint32_t win_func; 7.34 + uint16_t scanline_bytes; 7.35 + 7.36 + /* VBE 1.2 and above */ 7.37 + uint16_t xres, yres; 7.38 + uint8_t xcharsz, ycharsz; 7.39 + uint8_t num_planes; 7.40 + uint8_t bpp; 7.41 + uint8_t num_banks; 7.42 + uint8_t mem_model; 7.43 + uint8_t bank_size; /* bank size in KB */ 7.44 + uint8_t num_img_pages; 7.45 + uint8_t reserved1; 7.46 + 7.47 + /* direct color fields */ 7.48 + uint8_t rmask_size, rpos; 7.49 + uint8_t gmask_size, gpos; 7.50 + uint8_t bmask_size, bpos; 7.51 + uint8_t xmask_size, xpos; 7.52 + uint8_t cmode_info; /* direct color mode attributes */ 7.53 + 7.54 + /* VBE 2.0 and above */ 7.55 + uint32_t fb_addr; /* physical address of the linear framebuffer */ 7.56 + uint32_t reserved2; 7.57 + uint16_t reserved3; 7.58 + 7.59 + uint8_t reserved4[206]; 7.60 +}; 7.61 +#pragma pack (pop) 7.62 + 7.63 +struct vbe_info *vbe_get_info(void); 7.64 +struct vbe_mode_info *vbe_get_mode_info(unsigned int mode); 7.65 + 7.66 +int vbe_set_mode(unsigned int mode); 7.67 + 7.68 +int vbe_set_palette_bits(int bits); 7.69 +void vbe_set_palette(int idx, int *col, int count, int bits); 7.70 + 7.71 +void print_mode_info(FILE *fp, struct vbe_mode_info *modei); 7.72 + 7.73 +#endif /* VBE_H_ */