rayzor

annotate src/vbe.c @ 17:79609d482762

the renderer renders, also fixed an unnoticed matrix conversion problem between scenegraph and min3d
author John Tsiombikas <nuclear@member.fsf.org>
date Mon, 14 Apr 2014 07:34:45 +0300
parents
children
rev   line source
nuclear@0 1 #include <stdio.h>
nuclear@0 2 #include <string.h>
nuclear@0 3 #include "vbe.h"
nuclear@0 4 #include "dpmi.h"
nuclear@0 5
nuclear@0 6 /* VGA DAC registers used for palette setting in 8bpp modes */
nuclear@0 7 #define VGA_DAC_STATE 0x3c7
nuclear@0 8 #define VGA_DAC_ADDR_RD 0x3c7
nuclear@0 9 #define VGA_DAC_ADDR_WR 0x3c8
nuclear@0 10 #define VGA_DAC_DATA 0x3c9
nuclear@0 11
nuclear@0 12 #define MODE_LFB (1 << 14)
nuclear@0 13
nuclear@0 14
nuclear@0 15 struct vbe_info *vbe_get_info(void)
nuclear@0 16 {
nuclear@0 17 static unsigned short info_block_seg;
nuclear@0 18 static struct vbe_info *info;
nuclear@0 19 struct dpmi_real_regs regs;
nuclear@0 20
nuclear@0 21 if(!info) {
nuclear@0 22 /* allocate 32 paragraphs (512 bytes) */
nuclear@0 23 info_block_seg = dpmi_alloc(32);
nuclear@0 24 info = (struct vbe_info*)(info_block_seg << 4);
nuclear@0 25 }
nuclear@0 26
nuclear@0 27 memcpy(info->sig, "VBE2", 4);
nuclear@0 28
nuclear@0 29 memset(&regs, 0, sizeof regs);
nuclear@0 30 regs.es = info_block_seg;
nuclear@0 31 regs.eax = 0x4f00;
nuclear@0 32
nuclear@0 33 dpmi_real_int(0x10, &regs);
nuclear@0 34
nuclear@0 35 return info;
nuclear@0 36 }
nuclear@0 37
nuclear@0 38 struct vbe_mode_info *vbe_get_mode_info(int mode)
nuclear@0 39 {
nuclear@0 40 static unsigned short mode_info_seg;
nuclear@0 41 static struct vbe_mode_info *mi;
nuclear@0 42 struct dpmi_real_regs regs;
nuclear@0 43
nuclear@0 44 if(!mi) {
nuclear@0 45 /* allocate 16 paragraphs (256 bytes) */
nuclear@0 46 mode_info_seg = dpmi_alloc(16);
nuclear@0 47 mi = (struct vbe_mode_info*)(mode_info_seg << 4);
nuclear@0 48 }
nuclear@0 49
nuclear@0 50 memset(&regs, 0, sizeof regs);
nuclear@0 51 regs.es = mode_info_seg;
nuclear@0 52 regs.eax = 0x4f01;
nuclear@0 53 regs.ecx = mode;
nuclear@0 54 regs.es = mode_info_seg;
nuclear@0 55
nuclear@0 56 dpmi_real_int(0x10, &regs);
nuclear@0 57 if(regs.eax & 0xff00) {
nuclear@0 58 return 0;
nuclear@0 59 }
nuclear@0 60
nuclear@0 61 return mi;
nuclear@0 62 }
nuclear@0 63
nuclear@0 64 int vbe_set_mode(int mode)
nuclear@0 65 {
nuclear@0 66 struct dpmi_real_regs regs;
nuclear@0 67
nuclear@0 68 memset(&regs, 0, sizeof regs);
nuclear@0 69 regs.eax = 0x4f02;
nuclear@0 70 regs.ebx = mode;
nuclear@0 71 dpmi_real_int(0x10, &regs);
nuclear@0 72
nuclear@0 73 if(regs.eax == 0x100) {
nuclear@0 74 return -1;
nuclear@0 75 }
nuclear@0 76 return 0;
nuclear@0 77 }
nuclear@0 78
nuclear@0 79 int vbe_set_palette_bits(int bits)
nuclear@0 80 {
nuclear@0 81 struct dpmi_real_regs regs;
nuclear@0 82
nuclear@0 83 memset(&regs, 0, sizeof regs);
nuclear@0 84 regs.eax = 0x4f08;
nuclear@0 85 regs.ebx = bits << 8; /* bits in bh */
nuclear@0 86 dpmi_real_int(0x10, &regs);
nuclear@0 87
nuclear@0 88 if((regs.eax >> 8) & 0xff == 3) {
nuclear@0 89 return -1;
nuclear@0 90 }
nuclear@0 91 return regs.ebx >> 8 & 0xff; /* new color bits in bh */
nuclear@0 92 }
nuclear@0 93
nuclear@0 94 /* TODO: implement palette setting through the VBE2 interface for
nuclear@0 95 * non-VGA displays (actually don't).
nuclear@0 96 */
nuclear@0 97 void vbe_set_palette(int idx, int *col, int count, int bits)
nuclear@0 98 {
nuclear@0 99 int i, shift = 8 - bits;
nuclear@0 100
nuclear@0 101 __asm {
nuclear@0 102 mov dx, VGA_DAC_ADDR_WR
nuclear@0 103 mov eax, idx
nuclear@0 104 out dx, al
nuclear@0 105 }
nuclear@0 106
nuclear@0 107 for(i=0; i<count; i++) {
nuclear@0 108 unsigned char r = *col++;
nuclear@0 109 unsigned char g = *col++;
nuclear@0 110 unsigned char b = *col++;
nuclear@0 111
nuclear@0 112 if(shift) {
nuclear@0 113 r >>= shift;
nuclear@0 114 g >>= shift;
nuclear@0 115 b >>= shift;
nuclear@0 116 }
nuclear@0 117
nuclear@0 118 __asm {
nuclear@0 119 mov dx, VGA_DAC_DATA
nuclear@0 120 mov al, r
nuclear@0 121 out dx, al
nuclear@0 122 mov al, g
nuclear@0 123 out dx, al
nuclear@0 124 mov al, b
nuclear@0 125 out dx, al
nuclear@0 126 }
nuclear@0 127 }
nuclear@0 128 }
nuclear@0 129
nuclear@0 130 static unsigned int get_mask(int sz, int pos)
nuclear@0 131 {
nuclear@0 132 unsigned int i, mask = 0;
nuclear@0 133
nuclear@0 134 for(i=0; i<sz; i++) {
nuclear@0 135 mask |= 1 << i;
nuclear@0 136 }
nuclear@0 137 return mask << pos;
nuclear@0 138 }
nuclear@0 139
nuclear@0 140 void print_mode_info(FILE *fp, struct vbe_mode_info *mi)
nuclear@0 141 {
nuclear@0 142 fprintf(fp, "resolution: %dx%d\n", mi->xres, mi->yres);
nuclear@0 143 fprintf(fp, "color depth: %d\n", mi->bpp);
nuclear@0 144 fprintf(fp, "mode attributes: %x\n", mi->mode_attr);
nuclear@0 145 fprintf(fp, "bytes per scanline: %d\n", mi->scanline_bytes);
nuclear@0 146 fprintf(fp, "number of planes: %d\n", (int)mi->num_planes);
nuclear@0 147 fprintf(fp, "number of banks: %d\n", (int)mi->num_banks);
nuclear@0 148 fprintf(fp, "mem model: %d\n", (int)mi->mem_model);
nuclear@0 149 fprintf(fp, "red bits: %d (mask: %x)\n", (int)mi->rmask_size, get_mask(mi->rmask_size, mi->rpos));
nuclear@0 150 fprintf(fp, "green bits: %d (mask: %x)\n", (int)mi->gmask_size, get_mask(mi->gmask_size, mi->gpos));
nuclear@0 151 fprintf(fp, "blue bits: %d (mask: %x)\n", (int)mi->bmask_size, get_mask(mi->bmask_size, mi->bpos));
nuclear@0 152 fprintf(fp, "framebuffer address: %x\n", mi->fb_addr);
nuclear@0 153 }