new vbe sortof works
[retroray] / src / dos / vidsys.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <limits.h>
4 #include <assert.h>
5 #include "vidsys.h"
6 #include "vga.h"
7 #include "drv.h"
8 #include "cdpmi.h"
9 #include "logger.h"
10
11 struct vid_driver *vid_drvlist[MAX_DRV];
12 int vid_numdrv;
13
14 void *vid_vmem;
15 int vid_vmem_size;
16
17 static struct vid_modeinfo **modes, *cur_mode;
18 static int num_modes, max_modes;
19
20
21 int vid_init(void)
22 {
23         int i, j, len;
24         struct vid_modeinfo *vm;
25
26         vid_numdrv = 0;
27         free(modes);
28         modes = 0;
29         cur_mode = 0;
30         num_modes = max_modes = 0;
31
32         vid_vmem = 0;
33         vid_vmem_size = 0;
34
35         if(dpmi_init() == -1) {
36                 return -1;
37         }
38
39         vid_register_vga();
40         vid_register_vbe();
41         vid_register_s3();
42
43         for(i=0; i<vid_numdrv; i++) {
44                 struct vid_driver *drv = vid_drvlist[i];
45
46                 drv->ops->init();
47
48                 for(j=0; j<drv->num_modes; j++) {
49                         if(num_modes >= max_modes) {
50                                 int newsz = max_modes ? max_modes * 2 : 128;
51                                 void *tmp = realloc(modes, newsz * sizeof *modes);
52                                 if(!tmp) {
53                                         errormsg("failed to allocate modes list\n");
54                                         return -1;
55                                 }
56                                 modes = tmp;
57                                 max_modes = newsz;
58                         }
59
60                         modes[num_modes++] = drv->modes + j;
61                 }
62         }
63
64         infomsg("found %d modes:\n", num_modes);
65         for(i=0; i<num_modes; i+=2) {
66                 vm = modes[i];
67                 len = infomsg("[%4s] %04x: %dx%d %dbpp", vm->drv->name, vm->modeno,
68                                 vm->width, vm->height, vm->bpp);
69                 if(i + 1 >= num_modes) {
70                         infomsg("\n");
71                         break;
72                 }
73                 for(j=len; j<40; j++) infomsg(" ");
74                 vm = modes[i + 1];
75                 infomsg("[%4s] %04x: %dx%d %dbpp\n", vm->drv->name, vm->modeno,
76                                 vm->width, vm->height, vm->bpp);
77         }
78
79         return 0;
80 }
81
82 void vid_cleanup(void)
83 {
84         int i;
85
86         if(cur_mode && cur_mode->modeno != 3) {
87                 vid_setmode(3);
88         }
89
90         if(vid_vmem >= (void*)0x100000) {
91                 dpmi_munmap(vid_vmem);
92         }
93
94         for(i=0; i<vid_numdrv; i++) {
95                 struct vid_driver *drv = vid_drvlist[i];
96                 drv->ops->cleanup();
97         }
98
99         free(modes);
100         dpmi_cleanup();
101 }
102
103
104 int vid_curmode(void)
105 {
106         if(cur_mode) {
107                 return cur_mode->modeno;
108         }
109         return -1;
110 }
111
112 void *vid_setmode(int mode)
113 {
114         int i;
115         struct vid_driver *drv;
116
117         for(i=0; i<num_modes; i++) {
118                 if(modes[i]->modeno == mode) {
119                         drv = modes[i]->drv;
120                         if(drv->ops->setmode(mode) == 0) {
121                                 cur_mode = modes[i];
122
123                                 if(vid_vmem >= (void*)0x100000) {
124                                         assert(vid_vmem_size);
125                                         dpmi_munmap(vid_vmem);
126                                 }
127
128                                 if(modes[i]->vmem_addr < 0x100000) {
129                                         vid_vmem = (void*)modes[i]->vmem_addr;
130                                         vid_vmem_size = 0;
131                                 } else {
132                                         vid_vmem = dpmi_mmap(modes[i]->vmem_addr, modes[i]->vmem_size);
133                                         vid_vmem_size = modes[i]->vmem_size;
134                                 }
135                                 return vid_vmem;
136                         }
137                 }
138         }
139         return 0;
140 }
141
142 #define EQUIV_BPP(a, b) \
143         ((a) == (b) || ((a) == 16 && (b) == 15) || ((a) == 15 && (b) == 16) || \
144          ((a) == 24 && (b) == 32) || ((a) == 32 && (b) == 24))
145
146 int vid_findmode(int xsz, int ysz, int bpp)
147 {
148         int i;
149
150         for(i=0; i<num_modes; i++) {
151                 if(modes[i]->width == xsz && modes[i]->height == ysz && modes[i]->bpp == bpp) {
152                         return modes[i]->modeno;
153                 }
154         }
155
156         /* try fuzzy bpp matching */
157         for(i=0; i<num_modes; i++) {
158                 if(modes[i]->width == xsz && modes[i]->height == ysz &&
159                                 EQUIV_BPP(modes[i]->bpp, bpp)) {
160                         return modes[i]->modeno;
161                 }
162         }
163
164         return -1;
165 }
166
167
168 struct vid_modeinfo *vid_modeinfo(int mode)
169 {
170         int i;
171
172         for(i=0; i<num_modes; i++) {
173                 if(modes[i]->modeno == mode) {
174                         return modes[i];
175                 }
176         }
177         return 0;
178 }
179
180 int vid_islinear(void)
181 {
182         return !vid_isbanked();
183 }
184
185 int vid_isbanked(void)
186 {
187         return cur_mode->win_size && vid_vmem < (void*)0x100000;
188 }
189
190 void vid_setpal(int idx, int count, const struct vid_color *col)
191 {
192         cur_mode->ops.setpal(idx, count, col);
193 }
194
195 void vid_getpal(int idx, int count, struct vid_color *col)
196 {
197         cur_mode->ops.getpal(idx, count, col);
198 }
199
200 void vid_blitfb(void *fb, int pitch)
201 {
202         if(pitch <= 0) {
203                 pitch = cur_mode->pitch;
204         }
205         cur_mode->ops.blitfb(fb, pitch);
206 }
207
208 void vid_blitfb32(uint32_t *src, int pitch)
209 {
210         int i, j, winpos, winleft;
211         unsigned char *dest;
212         uint16_t *dest16;
213
214         if(cur_mode->bpp == 32) {
215                 vid_blitfb(src, pitch);
216                 return;
217         }
218
219         if(pitch <= 0) {
220                 pitch = cur_mode->width << 2;
221         }
222
223         if(vid_islinear()) {
224                 winleft = INT_MAX;
225         } else {
226                 winleft = 65536;/*cur_mode->win_size << 10;*/
227                 winpos = 0;
228                 vid_setwin(0, 0);
229         }
230
231         switch(cur_mode->bpp) {
232         case 8:
233                 /* TODO */
234                 break;
235
236         case 15:
237                 /* TODO */
238                 break;
239         case 16:
240                 /* TODO */
241                 break;
242
243         case 24:
244                 dest = vid_vmem;
245                 for(i=0; i<cur_mode->height; i++) {
246                         for(j=0; j<cur_mode->width; j++) {
247                                 uint32_t pixel = src[j];
248                                 if(winleft <= 0) {
249                                         winpos += cur_mode->win_step;
250                                         vid_setwin(0, winpos);
251                                         winleft = 65536;/*cur_mode->win_size << 10;*/
252                                         dest = vid_vmem;
253                                 }
254                                 dest[0] = (pixel >> 16) & 0xff;
255                                 dest[1] = (pixel >> 8) & 0xff;
256                                 dest[2] = pixel & 0xff;
257                                 dest += 3;
258                                 winleft -= 3;
259                         }
260                         src = (uint32_t*)((char*)src + pitch);
261                 }
262                 break;
263
264         default:
265                 break;
266         }
267 }