]> git.lizzy.rs Git - plan9front.git/blob - sys/src/games/doom/i_video.c
games/doom: #A/audio -> /dev/audio
[plan9front.git] / sys / src / games / doom / i_video.c
1 /* i_video.c */
2
3 #include "doomdef.h"    // printf
4 #include "i_system.h"
5 #include "v_video.h"    // screens[]
6 #include "d_main.h"     // D_PostEvent
7
8 #include <draw.h>
9 #include <mouse.h>
10 #include <keyboard.h>
11
12 static int resized;
13 static int mouseactive;
14
15 static Rectangle grabout;
16 static Point center;
17
18 static void kbdproc(void*);
19 static void mouseproc(void*);
20
21 static uchar cmap[3*256];
22
23 void I_InitGraphics(void)
24 {
25         if(initdraw(nil, nil, "doom") < 0)
26                 I_Error("I_InitGraphics failed");
27
28         draw(screen, screen->r, display->black, nil, ZP);
29
30         center = addpt(screen->r.min, Pt(Dx(screen->r)/2, Dy(screen->r)/2));
31         grabout = insetrect(screen->r, Dx(screen->r)/8);
32
33         proccreate(kbdproc, nil, 8*1024);
34         proccreate(mouseproc, nil, 8*1024);
35
36         screens[0] = (unsigned char*) malloc(SCREENWIDTH * SCREENHEIGHT);
37 }
38
39 void I_ShutdownGraphics(void)
40 {
41 }
42
43 void I_SetPalette(byte *palette)
44 {
45         memcpy(cmap, palette, 3*256);
46 }
47
48 void I_UpdateNoBlit(void)
49 {
50         // DELETEME?
51 }
52
53 void I_FinishUpdate(void)
54 {
55         Image *rowimg;
56         Rectangle r;
57         int y, scale;
58         uchar *s, *e, *d, *m;
59         uchar buf[SCREENWIDTH*3*4];
60
61         if(resized){
62                 resized = 0;
63                 if(getwindow(display, Refnone) < 0)
64                         sysfatal("getwindow failed: %r");
65
66                 /* make black background */
67                 draw(screen, screen->r, display->black, nil, ZP);
68
69                 center = addpt(screen->r.min, Pt(Dx(screen->r)/2, Dy(screen->r)/2));
70                 grabout = insetrect(screen->r, Dx(screen->r)/8);
71         }
72
73         scale = Dx(screen->r)/SCREENWIDTH;
74         if(scale <= 0)
75                 scale = 1;
76         else if(scale > 4)
77                 scale = 4;
78
79         /* where to draw the scaled row */
80         r = rectsubpt(rectaddpt(Rect(0, 0, scale*SCREENWIDTH, scale), center),
81                 Pt(scale*SCREENWIDTH/2, scale*SCREENHEIGHT/2));
82
83         /* the row image, y-axis gets scaled with repl flag */
84         rowimg = allocimage(display, Rect(0, 0, scale*SCREENWIDTH, 1), RGB24, 1, DNofill);
85
86         s = screens[0];
87         for(y = 0; y < SCREENHEIGHT; y++){
88                 d = buf;
89                 e = s + SCREENWIDTH;
90                 for(; s < e; s++){
91                         m = &cmap[*s * 3];
92                         switch(scale){
93                         case 4:
94                                 *d++ = m[2];
95                                 *d++ = m[1];
96                                 *d++ = m[0];
97                         case 3:
98                                 *d++ = m[2];
99                                 *d++ = m[1];
100                                 *d++ = m[0];
101                         case 2:
102                                 *d++ = m[2];
103                                 *d++ = m[1];
104                                 *d++ = m[0];
105                         case 1:
106                                 *d++ = m[2];
107                                 *d++ = m[1];
108                                 *d++ = m[0];
109                         }
110                 }
111                 loadimage(rowimg, rowimg->r, buf, d - buf);
112                 draw(screen, r, rowimg, nil, ZP);
113                 r.min.y += scale;
114                 r.max.y += scale;
115         }
116         freeimage(rowimg);
117
118         flushimage(display, 1);
119 }
120
121 void I_MouseEnable(int on)
122 {
123         static char nocurs[2*4+2*2*16];
124         static int fd = -1;
125
126         if(mouseactive == on)
127                 return;
128         if(mouseactive = on){
129                 if((fd = open("/dev/cursor", ORDWR|OCEXEC)) < 0)
130                         return;
131                 write(fd, nocurs, sizeof(nocurs));
132         }else if(fd >= 0) {
133                 close(fd);
134                 fd = -1;
135         }
136 }
137
138 void I_ReadScreen(byte *scr)
139 {
140         memcpy (scr, screens[0], SCREENWIDTH*SCREENHEIGHT);
141 }
142
143 void I_BeginRead(void)
144 {
145         I_Error("PORTME i_video.c I_BeginRead");
146 }
147
148 void I_EndRead(void)
149 {
150         I_Error("PORTME i_video.c I_EndRead");
151 }
152
153 void I_StartTic(void)
154 {
155 }
156
157 void I_WaitVBL(int)
158 {
159 }
160
161
162 static int
163 runetokey(Rune r)
164 {
165         switch(r){
166         case Kleft:
167                 return KEY_LEFTARROW;
168         case Kright:
169                 return KEY_RIGHTARROW;
170         case Kup:
171                 return KEY_UPARROW;
172         case Kdown:
173                 return KEY_DOWNARROW;
174
175         case Kshift:
176                 return KEY_RSHIFT;
177         case Kctl:
178                 return KEY_RCTRL;
179         case Kalt:
180                 return KEY_RALT;
181
182         case KEY_MINUS:
183         case KEY_EQUALS:
184         case KEY_BACKSPACE:
185         case KEY_ESCAPE:
186         case KEY_TAB:
187                 return r;
188
189         case '\n':
190                 return KEY_ENTER;
191
192         case KF|1:
193         case KF|2:
194         case KF|3:
195         case KF|4:
196         case KF|5:
197         case KF|6:
198         case KF|7:
199         case KF|8:
200         case KF|9:
201         case KF|10:
202         case KF|11:
203         case KF|12:
204                 return KEY_F1+(r-(KF|1));
205         }
206
207         if(r > 0x7f)
208                 return 0;
209         return r;
210 }
211
212 static void
213 kbdproc(void *)
214 {
215         char buf[128], buf2[128], *s;
216         int kfd, n;
217         Rune r;
218         event_t e;
219
220         threadsetname("kbdproc");
221
222         if((kfd = open("/dev/kbd", OREAD)) < 0)
223                 sysfatal("can't open kbd: %r");
224
225         buf2[0] = 0;
226         while((n = read(kfd, buf, sizeof(buf))) > 0){
227                 buf[n-1] = 0;
228
229                 s = buf;
230                 while(*s){
231                         s += chartorune(&r, s);
232                         if(utfrune(buf2, r) == nil){
233                                 e.type = ev_keydown;
234                                 if(e.data1 = runetokey(r))
235                                         D_PostEvent(&e);
236                         }
237                 }
238                 s = buf2;
239                 while(*s){
240                         s += chartorune(&r, s);
241                         if(utfrune(buf, r) == nil){
242                                 e.type = ev_keyup;
243                                 if(e.data1 = runetokey(r))
244                                         D_PostEvent(&e);
245                         }
246                 }
247                 strcpy(buf2, buf);
248         }
249         close(kfd);
250 }
251
252 static void
253 mouseproc(void *)
254 {
255         int fd, n, nerr;
256         Mouse m, om;
257         char buf[1+5*12];
258         event_t e;
259
260         threadsetname("mouseproc");
261
262         if((fd = open("/dev/mouse", ORDWR)) < 0)
263                 sysfatal("can't open mouse: %r");
264
265         memset(&m, 0, sizeof m);
266         memset(&om, 0, sizeof om);
267         nerr = 0;
268         for(;;){
269                 n = read(fd, buf, sizeof buf);
270                 if(n != 1+4*12){
271                         yield();        /* if error is due to exiting, we'll exit here */
272                         fprint(2, "mouse: bad count %d not 49: %r\n", n);
273                         if(n<0 || ++nerr>10)
274                                 break;
275                         continue;
276                 }
277                 nerr = 0;
278                 switch(buf[0]){
279                 case 'r':
280                         resized = 1;
281                         /* fall through */
282                 case 'm':
283                         if(!mouseactive)
284                                 break;
285
286                         m.xy.x = atoi(buf+1+0*12);
287                         m.xy.y = atoi(buf+1+1*12);
288                         m.buttons = atoi(buf+1+2*12);
289                         m.msec = atoi(buf+1+3*12);
290
291                         if(!ptinrect(m.xy, grabout)){
292                                 fprint(fd, "m%d %d", center.x, center.y);
293
294                                 m.xy = center;
295                                 om.xy = center;
296                         }
297                         
298                         e.type = ev_mouse;
299                         e.data1 = m.buttons;
300                         e.data2 = 10*(m.xy.x - om.xy.x);
301                         e.data3 = 10*(om.xy.y - m.xy.y);
302                         D_PostEvent(&e);
303                         om = m;
304
305                         break;
306                 }
307         }
308         close(fd);
309 }
310