correct window size in banked vbe, and added doublebuffered test
[vidsys] / main.c
1 #include <stdio.h>
2 #include <math.h>
3 #include <limits.h>
4 #include <conio.h>
5 #include "vidsys.h"
6
7 void test8bpp(void);
8 void testrgb(void);
9
10 struct vid_modeinfo *vm;
11 void *vmem, *framebuf;
12 int doublebuf;
13
14 static const char *usage_fmt = "Usage %s: [options]\n"
15         "Options:      \n"
16         " -s <XxY>: video resolution\n"
17         " -b <bpp>: color depth\n"
18         " -d: double buffer\n";
19
20 int main(int argc, char **argv)
21 {
22         int i;
23         int mode;
24         int xres = 640;
25         int yres = 480;
26         int bpp = 8;
27
28         for(i=1; i<argc; i++) {
29                 if(argv[i][0] == '-') {
30                         if(argv[i][2]) {
31 invalopt:               fprintf(stderr, "invalid option: %s\n", argv[i]);
32                                 return 1;
33                         }
34                         switch(argv[i][1]) {
35                         case 's':
36                                 if(!argv[++i] || sscanf(argv[i], "%dx%d", &xres, &yres) != 2) {
37                                         fprintf(stderr, "invalid resolution: %s\n", argv[i]);
38                                         return 1;
39                                 }
40                                 break;
41
42                         case 'b':
43                                 if(!argv[++i] || (bpp = atoi(argv[i])) <= 0) {
44                                         fprintf(stderr, "invalid color depth: %s\n", argv[i]);
45                                         return 1;
46                                 }
47                                 break;
48
49                         case 'd':
50                                 doublebuf = 1;
51                                 break;
52
53                         case 'h':
54                                 printf(usage_fmt, argv[0]);
55                                 return 0;
56
57                         default:
58                                 goto invalopt;
59                         }
60                 } else {
61                         fprintf(stderr, "unexpected argument: %s\n", argv[i]);
62                         return 1;
63                 }
64         }
65
66
67         if(vid_init() == -1) {
68                 fprintf(stderr, "failed to initialize video\n");
69                 return 1;
70         }
71         printf("press any key...\n");
72         getch();
73
74         if((mode = vid_findmode(xres, yres, bpp)) == -1) {
75                 fprintf(stderr, "failed to find video mode: %dx%d %dbpp\n", xres, yres, bpp);
76                 return 1;
77         }
78         vm = vid_modeinfo(mode);
79
80         if(!(framebuf = malloc(vm->pitch * vm->width))) {
81                 fprintf(stderr, "failed to allocate main memory framebuffer\n");
82                 return 1;
83         }
84
85         if(!(vmem = vid_setmode(mode))) {
86                 fprintf(stderr, "failed to set video mode %04x\n", mode);
87                 return 1;
88         }
89
90         if(vm->bpp == 8) {
91                 test8bpp();
92         } else {
93                 testrgb();
94         }
95
96         for(;;) {
97                 while(kbhit()) {
98                         if(getch() == 27) {
99                                 goto end;
100                         }
101                 }
102         }
103
104 end:
105         vid_setmode(3);
106         vid_cleanup();
107         return 0;
108 }
109
110 static float fmin(float a, float b)
111 {
112         return a < b ? a : b;
113 }
114
115 #define PI              3.14159265
116 #define TWO_PI  (PI * 2.0f)
117
118 void test8bpp(void)
119 {
120         int i, j;
121         unsigned char *fb;
122         struct vid_color cmap[256];
123         int winsz, winleft, winpos;
124
125         for(i=0; i<256; i++) {
126                 float x = (float)i / (256.0f / TWO_PI);
127                 cmap[i].r = (int)fmin(0.0f, sin(x) * 255.0f);
128                 cmap[i].g = (int)fmin(0.0f, sin(x - PI) * 255.0f);
129                 cmap[i].b = (int)fmin(0.0f, cos(x - TWO_PI) * 255.0f);
130         }
131         vid_setpal(0, 256, cmap);
132
133         if(doublebuf) {
134                 fb = framebuf;
135                 for(i=0; i<vm->height; i++) {
136                         for(j=0; j<vm->width; j++) {
137                                 *fb++ = i ^ j;
138                         }
139                 }
140                 vid_blitfb(framebuf, 0);
141         } else {
142                 if(vid_islinear()) {
143                         winsz = INT_MAX;
144                 } else {
145                         winsz = vm->win_size << 10;
146                         winpos = 0;
147                         vid_setwin(0, 0);
148                 }
149                 winleft = winsz;
150                 fb = vmem;
151
152                 vid_vsync();
153
154                 for(i=0; i<vm->height; i++) {
155                         for(j=0; j<vm->width; j++) {
156                                 if(winleft-- <= 0) {
157                                         winpos += vm->win_step;
158                                         vid_setwin(0, winpos);
159                                         winleft = winsz;
160                                         fb = vmem;
161                                 }
162                                 *fb++ = i ^ j;
163                         }
164                 }
165         }
166 }
167
168 void testrgb(void)
169 {
170         int i, j, r, g, b;
171         unsigned char *fb24;
172         uint16_t *fb16;
173         uint32_t *fb32;
174         uint32_t pcol;
175         int winsz, winleft, winpos;
176
177         if(!doublebuf) {
178                 if(vid_islinear()) {
179                         winsz = INT_MAX;
180                 } else {
181                         winsz = vm->win_size << 10;
182                         winpos = 0;
183                         vid_setwin(0, 0);
184                 }
185                 winleft = winsz;
186                 fb24 = vmem;
187                 fb32 = vmem;
188                 fb16 = vmem;
189
190                 vid_vsync();
191         } else {
192                 fb24 = framebuf;
193                 fb32 = framebuf;
194                 fb16 = framebuf;
195         }
196
197         for(i=0; i<vm->height; i++) {
198                 for(j=0; j<vm->width; j++) {
199                         if(!doublebuf) {
200                                 if(winleft <= 0) {
201                                         winpos += vm->win_step;
202                                         vid_setwin(0, winpos);
203                                         winleft = winsz;
204                                         fb24 = vmem;
205                                         fb16 = vmem;
206                                         fb32 = vmem;
207                                 }
208                                 winleft -= (vm->bpp + 7) >> 3;
209                         }
210                         r = (i ^ j) >> 1;
211                         g = i ^ j;
212                         b = (i ^ j) << 1;
213                         vm->ops.pack(&pcol, r, g, b);
214
215                         switch(vm->bpp) {
216                         case 15:
217                         case 16:
218                                 *fb16++ = pcol;
219                                 break;
220
221                         case 24:
222                                 fb24[0] = r;
223                                 fb24[1] = g;
224                                 fb24[2] = b;
225                                 fb24 += 3;
226                                 break;
227
228                         case 32:
229                                 *fb32++ = pcol;
230                                 break;
231                         }
232                 }
233         }
234
235         if(doublebuf) {
236                 vid_vsync();
237                 vid_blitfb(framebuf, 0);
238         }
239 }