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