vbeinfo

annotate src/vbe.c @ 3:5b0ef094b8fd

backported changes from more recent VBE projects
author John Tsiombikas <nuclear@member.fsf.org>
date Mon, 07 Jan 2019 12:07:53 +0200
parents 4b33fa83e381
children
rev   line source
nuclear@0 1 #include <stdio.h>
nuclear@0 2 #include <string.h>
nuclear@3 3 #include <conio.h>
nuclear@0 4 #include "vbe.h"
nuclear@0 5 #include "dpmi.h"
nuclear@3 6 #include "inttypes.h"
nuclear@3 7
nuclear@3 8 #ifdef __DJGPP__
nuclear@3 9 #include <pc.h>
nuclear@3 10 #include <sys/nearptr.h>
nuclear@3 11
nuclear@3 12 #define SEG_ADDR(s) (((uint32_t)(s) << 4) - __djgpp_base_address)
nuclear@3 13
nuclear@3 14 #define outp(p, v) outportb(p, v)
nuclear@3 15 #else
nuclear@3 16 #define SEG_ADDR(s) ((uint32_t)(s) << 4)
nuclear@3 17 #endif
nuclear@0 18
nuclear@0 19 /* VGA DAC registers used for palette setting in 8bpp modes */
nuclear@0 20 #define VGA_DAC_STATE 0x3c7
nuclear@0 21 #define VGA_DAC_ADDR_RD 0x3c7
nuclear@0 22 #define VGA_DAC_ADDR_WR 0x3c8
nuclear@0 23 #define VGA_DAC_DATA 0x3c9
nuclear@0 24
nuclear@0 25 #define MODE_LFB (1 << 14)
nuclear@0 26
nuclear@0 27
nuclear@0 28 struct vbe_info *vbe_get_info(void)
nuclear@0 29 {
nuclear@3 30 static uint16_t info_block_seg, info_block_selector;
nuclear@0 31 static struct vbe_info *info;
nuclear@0 32 struct dpmi_real_regs regs;
nuclear@0 33
nuclear@0 34 if(!info) {
nuclear@0 35 /* allocate 32 paragraphs (512 bytes) */
nuclear@3 36 info_block_seg = dpmi_alloc(32, &info_block_selector);
nuclear@3 37 info = (struct vbe_info*)SEG_ADDR(info_block_seg);
nuclear@0 38 }
nuclear@0 39
nuclear@0 40 memcpy(info->sig, "VBE2", 4);
nuclear@0 41
nuclear@0 42 memset(&regs, 0, sizeof regs);
nuclear@0 43 regs.es = info_block_seg;
nuclear@0 44 regs.eax = 0x4f00;
nuclear@0 45
nuclear@0 46 dpmi_real_int(0x10, &regs);
nuclear@0 47
nuclear@0 48 return info;
nuclear@0 49 }
nuclear@0 50
nuclear@0 51 struct vbe_mode_info *vbe_get_mode_info(int mode)
nuclear@0 52 {
nuclear@3 53 static uint16_t mode_info_seg, mode_info_selector;
nuclear@0 54 static struct vbe_mode_info *mi;
nuclear@0 55 struct dpmi_real_regs regs;
nuclear@0 56
nuclear@0 57 if(!mi) {
nuclear@0 58 /* allocate 16 paragraphs (256 bytes) */
nuclear@3 59 mode_info_seg = dpmi_alloc(16, &mode_info_selector);
nuclear@3 60 mi = (struct vbe_mode_info*)SEG_ADDR(mode_info_seg);
nuclear@0 61 }
nuclear@0 62
nuclear@0 63 memset(&regs, 0, sizeof regs);
nuclear@0 64 regs.es = mode_info_seg;
nuclear@0 65 regs.eax = 0x4f01;
nuclear@0 66 regs.ecx = mode;
nuclear@0 67 regs.es = mode_info_seg;
nuclear@0 68
nuclear@0 69 dpmi_real_int(0x10, &regs);
nuclear@0 70 if(regs.eax & 0xff00) {
nuclear@0 71 return 0;
nuclear@0 72 }
nuclear@0 73
nuclear@0 74 return mi;
nuclear@0 75 }
nuclear@0 76
nuclear@0 77 int vbe_set_mode(int mode)
nuclear@0 78 {
nuclear@0 79 struct dpmi_real_regs regs;
nuclear@0 80
nuclear@0 81 memset(&regs, 0, sizeof regs);
nuclear@0 82 regs.eax = 0x4f02;
nuclear@0 83 regs.ebx = mode;
nuclear@0 84 dpmi_real_int(0x10, &regs);
nuclear@0 85
nuclear@0 86 if(regs.eax == 0x100) {
nuclear@0 87 return -1;
nuclear@0 88 }
nuclear@0 89 return 0;
nuclear@0 90 }
nuclear@0 91
nuclear@0 92 int vbe_set_palette_bits(int bits)
nuclear@0 93 {
nuclear@0 94 struct dpmi_real_regs regs;
nuclear@0 95
nuclear@0 96 memset(&regs, 0, sizeof regs);
nuclear@0 97 regs.eax = 0x4f08;
nuclear@0 98 regs.ebx = bits << 8; /* bits in bh */
nuclear@0 99 dpmi_real_int(0x10, &regs);
nuclear@0 100
nuclear@3 101 if(((regs.eax >> 8) & 0xff) == 3) {
nuclear@0 102 return -1;
nuclear@0 103 }
nuclear@0 104 return regs.ebx >> 8 & 0xff; /* new color bits in bh */
nuclear@0 105 }
nuclear@0 106
nuclear@0 107 /* TODO: implement palette setting through the VBE2 interface for
nuclear@0 108 * non-VGA displays (actually don't).
nuclear@0 109 */
nuclear@0 110 void vbe_set_palette(int idx, int *col, int count, int bits)
nuclear@0 111 {
nuclear@0 112 int i, shift = 8 - bits;
nuclear@0 113
nuclear@3 114 outp(VGA_DAC_ADDR_WR, idx);
nuclear@0 115
nuclear@0 116 for(i=0; i<count; i++) {
nuclear@0 117 unsigned char r = *col++;
nuclear@0 118 unsigned char g = *col++;
nuclear@0 119 unsigned char b = *col++;
nuclear@0 120
nuclear@0 121 if(shift) {
nuclear@0 122 r >>= shift;
nuclear@0 123 g >>= shift;
nuclear@0 124 b >>= shift;
nuclear@0 125 }
nuclear@0 126
nuclear@3 127 outp(VGA_DAC_DATA, r);
nuclear@3 128 outp(VGA_DAC_DATA, g);
nuclear@3 129 outp(VGA_DAC_DATA, b);
nuclear@0 130 }
nuclear@0 131 }
nuclear@0 132
nuclear@3 133 int vbe_set_disp_start(int x, int y, int when)
nuclear@3 134 {
nuclear@3 135 struct dpmi_real_regs regs;
nuclear@3 136
nuclear@3 137 memset(&regs, 0, sizeof regs);
nuclear@3 138 regs.eax = 0x4f07;
nuclear@3 139 regs.ebx = when & 0xffff;
nuclear@3 140 regs.ecx = x & 0xffff;
nuclear@3 141 regs.edx = y & 0xffff;
nuclear@3 142 dpmi_real_int(0x10, &regs);
nuclear@3 143
nuclear@3 144 if(regs.eax == 0x100) {
nuclear@3 145 return -1;
nuclear@3 146 }
nuclear@3 147 return 0;
nuclear@3 148 }
nuclear@3 149
nuclear@3 150 int vbe_set_scanlen(int len, int mode)
nuclear@3 151 {
nuclear@3 152 struct dpmi_real_regs regs;
nuclear@3 153
nuclear@3 154 memset(&regs, 0, sizeof regs);
nuclear@3 155 regs.eax = 0x4f06;
nuclear@3 156 regs.ebx = mode;
nuclear@3 157 regs.ecx = len & 0xffff;
nuclear@3 158 dpmi_real_int(0x10, &regs);
nuclear@3 159
nuclear@3 160 if(regs.eax == 0x100) {
nuclear@3 161 return -1;
nuclear@3 162 }
nuclear@3 163 return regs.ecx & 0xffff;
nuclear@3 164 }
nuclear@3 165
nuclear@3 166 int vbe_get_scanlen(int mode)
nuclear@3 167 {
nuclear@3 168 int res;
nuclear@3 169 struct dpmi_real_regs regs;
nuclear@3 170
nuclear@3 171 memset(&regs, 0, sizeof regs);
nuclear@3 172 regs.eax = 0x4f06;
nuclear@3 173 regs.ebx = 1;
nuclear@3 174 dpmi_real_int(0x10, &regs);
nuclear@3 175
nuclear@3 176 if(regs.eax == 0x100) {
nuclear@3 177 return -1;
nuclear@3 178 }
nuclear@3 179
nuclear@3 180 if(mode == VBE_SCANLEN_PIXELS) {
nuclear@3 181 res = regs.ecx & 0xffff;
nuclear@3 182 } else {
nuclear@3 183 res = regs.ebx & 0xffff;
nuclear@3 184 }
nuclear@3 185 return res;
nuclear@3 186 }
nuclear@3 187
nuclear@3 188
nuclear@0 189 static unsigned int get_mask(int sz, int pos)
nuclear@0 190 {
nuclear@0 191 unsigned int i, mask = 0;
nuclear@0 192
nuclear@0 193 for(i=0; i<sz; i++) {
nuclear@0 194 mask |= 1 << i;
nuclear@0 195 }
nuclear@0 196 return mask << pos;
nuclear@0 197 }
nuclear@0 198
nuclear@0 199 void print_mode_info(FILE *fp, struct vbe_mode_info *mi)
nuclear@0 200 {
nuclear@0 201 fprintf(fp, "resolution: %dx%d\n", mi->xres, mi->yres);
nuclear@0 202 fprintf(fp, "color depth: %d\n", mi->bpp);
nuclear@0 203 fprintf(fp, "mode attributes: %x\n", mi->mode_attr);
nuclear@0 204 fprintf(fp, "bytes per scanline: %d\n", mi->scanline_bytes);
nuclear@0 205 fprintf(fp, "number of planes: %d\n", (int)mi->num_planes);
nuclear@0 206 fprintf(fp, "number of banks: %d\n", (int)mi->num_banks);
nuclear@0 207 fprintf(fp, "mem model: %d\n", (int)mi->mem_model);
nuclear@0 208 fprintf(fp, "red bits: %d (mask: %x)\n", (int)mi->rmask_size, get_mask(mi->rmask_size, mi->rpos));
nuclear@0 209 fprintf(fp, "green bits: %d (mask: %x)\n", (int)mi->gmask_size, get_mask(mi->gmask_size, mi->gpos));
nuclear@0 210 fprintf(fp, "blue bits: %d (mask: %x)\n", (int)mi->bmask_size, get_mask(mi->bmask_size, mi->bpos));
nuclear@3 211 fprintf(fp, "framebuffer address: %x\n", (unsigned int)mi->fb_addr);
nuclear@0 212 }