more vbe
[vidsys] / vidsys.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <assert.h>
4 #include "vidsys.h"
5 #include "vga.h"
6 #include "drv.h"
7 #include "cdpmi.h"
8
9 struct vid_driver *vid_drvlist[MAX_DRV];
10 int vid_numdrv;
11
12 void *vid_vmem;
13 int vid_vmem_size;
14
15 static struct vid_modeinfo **modes, *cur_mode;
16 static int num_modes, max_modes;
17
18
19 int vid_init(void)
20 {
21         int i, j, len;
22         struct vid_modeinfo *vm;
23
24         vid_numdrv = 0;
25         free(modes);
26         modes = 0;
27         cur_mode = 0;
28         num_modes = max_modes = 0;
29
30         vid_vmem = 0;
31         vid_vmem_size = 0;
32
33         if(dpmi_init() == -1) {
34                 return -1;
35         }
36
37         vid_register_vga();
38         vid_register_vbe();
39         vid_register_s3();
40
41         for(i=0; i<vid_numdrv; i++) {
42                 struct vid_driver *drv = vid_drvlist[i];
43
44                 drv->ops->init();
45
46                 for(j=0; j<drv->num_modes; j++) {
47                         if(num_modes >= max_modes) {
48                                 int newsz = max_modes ? max_modes * 2 : 128;
49                                 void *tmp = realloc(modes, newsz * sizeof *modes);
50                                 if(!tmp) {
51                                         fprintf(stderr, "failed to allocate modes list\n");
52                                         return -1;
53                                 }
54                                 modes = tmp;
55                                 max_modes = newsz;
56                         }
57
58                         modes[num_modes++] = drv->modes + j;
59                 }
60         }
61
62         printf("found %d modes:\n", num_modes);
63         for(i=0; i<num_modes; i+=2) {
64                 vm = modes[i];
65                 len = printf("[%4s] %04x: %dx%d %dbpp", vm->drv->name, vm->modeno,
66                                 vm->width, vm->height, vm->bpp);
67                 if(i + 1 >= num_modes) {
68                         putchar('\n');
69                         break;
70                 }
71                 for(j=len; j<40; j++) putchar(' ');
72                 vm = modes[i + 1];
73                 printf("[%4s] %04x: %dx%d %dbpp\n", vm->drv->name, vm->modeno,
74                                 vm->width, vm->height, vm->bpp);
75         }
76
77         return 0;
78 }
79
80 void vid_cleanup(void)
81 {
82         int i;
83
84         if(cur_mode && cur_mode->modeno != 3) {
85                 vid_setmode(3);
86         }
87
88         if(vid_vmem >= (void*)0x100000) {
89                 dpmi_munmap(vid_vmem);
90         }
91
92         for(i=0; i<vid_numdrv; i++) {
93                 struct vid_driver *drv = vid_drvlist[i];
94                 drv->ops->cleanup();
95         }
96
97         free(modes);
98         dpmi_cleanup();
99 }
100
101
102 int vid_curmode(void)
103 {
104         if(cur_mode) {
105                 return cur_mode->modeno;
106         }
107         return -1;
108 }
109
110 void *vid_setmode(int mode)
111 {
112         int i;
113         struct vid_driver *drv;
114
115         for(i=0; i<num_modes; i++) {
116                 if(modes[i]->modeno == mode) {
117                         drv = modes[i]->drv;
118                         if(drv->ops->setmode(mode) == 0) {
119                                 cur_mode = modes[i];
120
121                                 if(vid_vmem >= (void*)0x100000) {
122                                         assert(vid_vmem_size);
123                                         dpmi_munmap(vid_vmem);
124                                 }
125
126                                 if(modes[i]->vmem_addr < 0x100000) {
127                                         vid_vmem = (void*)modes[i]->vmem_addr;
128                                         vid_vmem_size = 0;
129                                 } else {
130                                         vid_vmem = dpmi_mmap(modes[i]->vmem_addr, modes[i]->vmem_size);
131                                         vid_vmem_size = modes[i]->vmem_size;
132                                 }
133                                 return vid_vmem;
134                         }
135                 }
136         }
137         return 0;
138 }
139
140 #define EQUIV_BPP(a, b) \
141         ((a) == (b) || ((a) == 16 && (b) == 15) || ((a) == 15 && (b) == 16) || \
142          ((a) == 24 && (b) == 32) || ((a) == 32 && (b) == 24))
143
144 int vid_findmode(int xsz, int ysz, int bpp)
145 {
146         int i;
147
148         for(i=0; i<num_modes; i++) {
149                 if(modes[i]->width == xsz && modes[i]->height == ysz && modes[i]->bpp == bpp) {
150                         return modes[i]->modeno;
151                 }
152         }
153
154         /* try fuzzy bpp matching */
155         for(i=0; i<num_modes; i++) {
156                 if(modes[i]->width == xsz && modes[i]->height == ysz &&
157                                 EQUIV_BPP(modes[i]->bpp, bpp)) {
158                         return modes[i]->modeno;
159                 }
160         }
161
162         return -1;
163 }
164
165
166 struct vid_modeinfo *vid_modeinfo(int mode)
167 {
168         int i;
169
170         for(i=0; i<num_modes; i++) {
171                 if(modes[i]->modeno == mode) {
172                         return modes[i];
173                 }
174         }
175         return 0;
176 }
177
178 void vid_vsync(void)
179 {
180         vga_vsync();
181 }
182
183 void vid_setpal(int idx, int count, const struct vid_color *col)
184 {
185         cur_mode->ops.setpal(idx, count, col);
186 }
187
188 void vid_getpal(int idx, int count, struct vid_color *col)
189 {
190         cur_mode->ops.getpal(idx, count, col);
191 }