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