7dd2bada24e6d531fe980a7e5944ba76f664429f
[bootcensus] / src / test / vbetest.c
1 #include <stdio.h>
2 #include <string.h>
3 #include "video.h"
4 #include "asmops.h"
5 #include "keyb.h"
6 #include "psaux.h"
7 #include "contty.h"
8 #include "audio.h"
9
10 static void draw_cursor(int x, int y, uint16_t col);
11 static int click_sound_callback(void *buffer, int size, void *cls);
12
13 static uint16_t *framebuf;
14
15 #define CURSOR_XSZ      12
16 #define CURSOR_YSZ      16
17 static uint16_t cursor[] = {
18         0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
19         0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
20         0xffff, 0x0001, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
21         0xffff, 0x0001, 0x0001, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
22         0xffff, 0x0001, 0x0001, 0x0001, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
23         0xffff, 0x0001, 0x0001, 0x0001, 0x0001, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
24         0xffff, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
25         0xffff, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000,
26         0xffff, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0xffff, 0x0000, 0x0000, 0x0000,
27         0xffff, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, 0x0000,
28         0xffff, 0x0001, 0x0001, 0x0001, 0x0001, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
29         0xffff, 0x0001, 0x0001, 0xffff, 0x0001, 0x0001, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
30         0xffff, 0x0001, 0xffff, 0xffff, 0x0001, 0x0001, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
31         0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0x0001, 0x0001, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000,
32         0xffff, 0x0000, 0x0000, 0x0000, 0xffff, 0x0001, 0x0001, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000,
33         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
34 };
35
36 static int click;
37
38 /* defined in sndsamples.s */
39 extern signed char snd_click[];
40 extern int snd_click_size;
41
42 int vbetest(void)
43 {
44         int i, j, nmodes, mx, my, idx;
45         unsigned int st, prev_st = 0;
46         struct video_mode vi;
47         uint16_t *fbptr;
48
49         nmodes = video_mode_count();
50         printf("%d video modes found:\n", nmodes);
51         for(i=0; i<nmodes; i++) {
52                 if(video_mode_info(i, &vi) == -1) {
53                         continue;
54                 }
55                 printf(" %04x: %dx%d %d bpp", vi.mode, vi.width, vi.height, vi.bpp);
56                 if(vi.bpp > 8) {
57                         printf(" (%d%d%d)\n", vi.rbits, vi.gbits, vi.bbits);
58                 } else {
59                         putchar('\n');
60                 }
61         }
62
63         if((idx = find_video_mode_idx(640, 480, 16)) == -1) {
64                 return -1;
65         }
66         video_mode_info(idx, &vi);
67
68         if(!(framebuf = set_video_mode(vi.mode))) {
69                 return -1;
70         }
71         get_color_bits(&vi.rbits, &vi.gbits, &vi.bbits);
72         get_color_shift(&vi.rshift, &vi.gshift, &vi.bshift);
73         get_color_mask(&vi.rmask, &vi.gmask, &vi.bmask);
74
75         fbptr = framebuf;
76         for(i=0; i<480; i++) {
77                 for(j=0; j<640; j++) {
78                         int xor = i^j;
79                         uint16_t r = xor & 0xff;
80                         uint16_t g = (xor << 1) & 0xff;
81                         uint16_t b = (xor << 2) & 0xff;
82
83                         r >>= 8 - vi.rbits;
84                         g >>= 8 - vi.gbits;
85                         b >>= 8 - vi.bbits;
86
87                         *fbptr++ = ((r << vi.rshift) & vi.rmask) | ((g << vi.gshift) & vi.gmask) |
88                                 ((b << vi.bshift) & vi.bmask);
89                 }
90         }
91
92         set_mouse_bounds(0, 0, 639, 479);
93
94         audio_set_callback(click_sound_callback, 0);
95
96         /* empty the kb queue */
97         while(kb_getkey() != -1);
98
99         for(;;) {
100                 if(kb_getkey() != -1) {
101                         break;
102                 }
103
104                 st = mouse_state(&mx, &my);
105
106                 for(i=0; i<3; i++) {
107                         unsigned int bit = 1 << i;
108                         if(((st & bit) ^ (prev_st & bit)) & (st & bit)) {
109                                 click = 1;
110                         }
111                 }
112                 if(click) {
113                         audio_play(22050, 1);
114                 }
115
116                 prev_st = st;
117
118                 draw_cursor(mx, my, st & 1 ? 0xf800 : (st & 2 ? 0x7e0 : (st & 4 ? 0x00ff : 0)));
119
120                 halt_cpu();
121         }
122
123         set_vga_mode(3);
124         con_clear();
125         return 0;
126 }
127
128 static void draw_cursor(int x, int y, uint16_t col)
129 {
130         static uint16_t saved[CURSOR_XSZ * CURSOR_YSZ];
131         static int saved_x = -1, saved_y, saved_w, saved_h;
132
133         int i, j, w, h;
134         uint16_t *dest, *src, *savp;
135
136         if(saved_x >= 0) {
137                 dest = framebuf + saved_y * 640 + saved_x;
138                 src = saved;
139
140                 for(i=0; i<saved_h; i++) {
141                         for(j=0; j<saved_w; j++) {
142                                 *dest++ = *src++;
143                         }
144                         src += CURSOR_XSZ - saved_w;
145                         dest += 640 - saved_w;
146                 }
147         }
148
149         dest = framebuf + y * 640 + x;
150         src = cursor;
151         savp = saved;
152
153         w = 640 - x;
154         if(w > CURSOR_XSZ) w = CURSOR_XSZ;
155         h = 480 - y;
156         if(h > CURSOR_YSZ) h = CURSOR_YSZ;
157
158         saved_x = x;
159         saved_y = y;
160         saved_w = w;
161         saved_h = h;
162
163         for(i=0; i<h; i++) {
164                 for(j=0; j<w; j++) {
165                         uint16_t c = *src++;
166                         *savp++ = *dest;
167                         if(c) {
168                                 if(c == 1) c = col;
169                                 *dest = c;
170                         }
171                         dest++;
172                 }
173                 src += CURSOR_XSZ - w;
174                 dest += 640 - w;
175                 savp += CURSOR_XSZ - w;
176         }
177 }
178
179 /* snd_click_size is < 65536 so we can just throw it all at once in there */
180 static int click_sound_callback(void *buffer, int size, void *cls)
181 {
182         if(click) {
183                 memcpy(buffer, snd_click, snd_click_size);
184                 click = 0;
185                 return snd_click_size;
186         }
187         return 0;
188 }