|
|
1.1 root 1: #import <AppKit/AppKit.h>
2: #import <Interceptor/NSDirectScreen.h>
3: #import <AppKit/NSColor.h>
4: #include "../ref_soft/r_local.h"
5:
6: @interface QuakeView : NSView
7: @end
8:
9: NSWindow *vid_window_i;
10: QuakeView *vid_view_i;
11: NSDirectScreen *vid_screen;
12: byte *vid_buffer; // real framebuffer
13: int vid_rowbytes; // framebuffer rowbytes
14:
15: unsigned *buffernative; // 24 bit off-screen back buffer for window
16: unsigned swimp_palette[256];
17:
18: typedef enum {
19: rhap_shutdown,
20: rhap_windowed,
21: rhap_fullscreen
22: } rhapMode_t;
23:
24: rhapMode_t rhap_mode;
25:
26: /*
27: =======================================================================
28:
29: FULLSCREEN
30:
31: =======================================================================
32: */
33:
34: /*
35: ** InitFullscreen
36: */
37: rserr_t InitFullscreen (int width, int height)
38: {
39: NSDictionary *mode, *bestMode;
40: int modeWidth, bestWidth;
41: int modeHeight, bestHeight;
42: NSArray *modes;
43: int i;
44: NSString *string;
45:
46:
47: vid_screen = [[NSDirectScreen alloc] initWithScreen:[NSScreen mainScreen]];
48:
49: // search for an apropriate mode
50: modes = [vid_screen availableDisplayModes];
51: bestMode = NULL;
52: bestWidth = 99999;
53: bestHeight = 99999;
54: for (i=0 ; i<[modes count] ; i++) {
55: mode = [modes objectAtIndex: i];
56: string = [mode objectForKey: @"NSDirectScreenPixelEncoding"];
57: if ( ![string isEqualToString: @"PPPPPPPP"] )
58: continue; // only look at paletted modes
59: modeWidth = [[mode objectForKey: @"NSDirectScreenWidth"] intValue];
60: modeHeight = [[mode objectForKey: @"NSDirectScreenHeight"] intValue];
61: if (modeWidth < width || modeHeight < height)
62: continue;
63: if (modeWidth < bestWidth) {
64: bestWidth = modeWidth;
65: bestHeight = modeHeight;
66: bestMode = mode;
67: }
68: }
69:
70: // if there wasn't any paletted mode of that res or greater, fail
71: if (!bestMode)
72: return rserr_invalid_fullscreen;
73:
74: ri.Con_Printf (PRINT_ALL, "SheildDisplay\n");
75: [vid_screen shieldDisplay];
76:
77: // hide the cursor in all fullscreen modes
78: [NSCursor hide];
79:
80: vid_window_i = [vid_screen shieldingWindow];
81:
82: ri.Con_Printf (PRINT_ALL, "switchToDisplayMode\n");
83: [vid_screen switchToDisplayMode:bestMode];
84: // [vid_screen fadeDisplayOutToColor:[NSColor blackColor]];
85: // [vid_screen fadeDisplayInFromColor:[NSColor blackColor]];
86:
87: vid_buffer = [vid_screen data];
88: vid_rowbytes = [vid_screen bytesPerRow];
89:
90: return rserr_ok;
91: }
92:
93: void ShutdownFullscreen (void)
94: {
95: [vid_screen dealloc];
96: [NSCursor unhide];
97: }
98:
99: void SetPaletteFullscreen (const unsigned char *palette) {
100: #if 0
101: byte *p;
102: int i;
103: NSDirectPalette *pal;
104:
105: pal = [NSDirectPalette init];
106: for (i=0 ; i<256 ; i++)
107: [pal setRed: palette[0]*(1.0/255)
108: green: palette[1]*(1.0/255)
109: blue: palette[2]*(1.0/255)
110: atIndex: i];
111: [vid_screen setPalette: pal];
112: [pal release];
113: #endif
114: }
115:
116:
117:
118: void BlitFullscreen (void)
119: {
120: int i, j;
121: int w;
122: int *dest, *source;
123:
124: w = vid.width>>2;
125:
126: source = (int *)vid.buffer; // off-screen buffer
127: dest = (int *)vid_buffer; // directly on screen
128: for (j=0 ; j<vid.height ; j++
129: , source += (vid.rowbytes>>2), dest += (vid_rowbytes>>2) ) {
130: for (i=0 ; i<w ; i++ ) {
131: dest[i] = source[i];
132: }
133: }
134: }
135:
136: /*
137: =======================================================================
138:
139: WINDOWED
140:
141: =======================================================================
142: */
143:
144: /*
145: ** InitWindowed
146: */
147: rserr_t InitWindowed (int width, int height)
148: {
149: rserr_t retval = rserr_ok;
150: NSRect content;
151: cvar_t *vid_xpos;
152: cvar_t *vid_ypos;
153:
154: //
155: // open a window
156: //
157: vid_xpos = ri.Cvar_Get ("vid_xpos", "0", 0);
158: vid_ypos = ri.Cvar_Get ("vid_ypos", "0", 0);
159:
160: content = NSMakeRect (vid_xpos->value,vid_ypos->value, width, height);
161: vid_window_i = [[NSWindow alloc]
162: initWithContentRect: content
163: styleMask: NSTitledWindowMask
164: backing: NSBackingStoreRetained
165: defer: NO
166: ];
167:
168: // [vid_window_i addToEventMask: NS_FLAGSCHANGEDMASK];
169: [vid_window_i setTitle: @"Quake2"];
170:
171: buffernative = malloc(width * height * 4);
172:
173: return retval;
174: }
175:
176: void ShutdownWindowed (void)
177: {
178: if (vid_window_i)
179: {
180: [vid_window_i release];
181: vid_window_i = NULL;
182: }
183: if (buffernative)
184: {
185: free (buffernative);
186: buffernative = NULL;
187: }
188: }
189:
190: void SetPaletteWindowed (const unsigned char *palette) {
191: byte *p;
192: int i;
193:
194: p = (byte *)swimp_palette;
195: for (i=0 ; i<256 ; i++, p+=4, palette+=4)
196: {
197: p[0] = palette[0];
198: p[1] = palette[1];
199: p[2] = palette[2];
200: p[3] = 0xff;
201: }
202: }
203:
204:
205: void BlitWindowed (void)
206: {
207: int i, c;
208: int bps, spp, bpp, bpr;
209: unsigned char *planes[5];
210: NSRect bounds;
211:
212: if (!vid_view_i)
213: return;
214:
215: // translate to 24 bit color
216: c = vid.width*vid.height;
217: for (i=0 ; i<c ; i++)
218: buffernative[i] = swimp_palette[vid.buffer[i]];
219:
220: bps = 8;
221: spp = 3;
222: bpp = 32;
223: bpr = vid.width * 4;
224: planes[0] = (unsigned char *)buffernative;
225:
226: bounds = [vid_view_i bounds];
227:
228: [vid_view_i lockFocus];
229:
230: NSDrawBitmap(
231: bounds,
232: vid.width,
233: vid.height,
234: bps,
235: spp,
236: bpp,
237: bpr,
238: NO,
239: NO,
240: @"NSDeviceRGBColorSpace",
241: planes
242: );
243:
244: [vid_view_i unlockFocus];
245: PSWait ();
246: }
247:
248:
249: //======================================================================
250:
251: /*
252: ** RW_IMP.C
253: **
254: ** This file contains ALL Win32 specific stuff having to do with the
255: ** software refresh. When a port is being made the following functions
256: ** must be implemented by the port:
257: **
258: ** SWimp_EndFrame
259: ** SWimp_Init
260: ** SWimp_SetPalette
261: ** SWimp_Shutdown
262: */
263:
264:
265: /*
266: ** SWimp_Init
267: **
268: ** This routine is responsible for initializing the implementation
269: ** specific stuff in a software rendering subsystem.
270: */
271: int SWimp_Init( void *hInstance, void *wndProc )
272: {
273: if (!NSApp)
274: {
275: [NSApplication sharedApplication];
276: [NSApp finishLaunching];
277: }
278:
279: return true;
280: }
281:
282:
283: /*
284: ** SWimp_SetMode
285: */
286: rserr_t SWimp_SetMode( int *pwidth, int *pheight, int mode, qboolean fullscreen)
287: {
288: const char *win_fs[] = { "W", "FS" };
289: NSRect content;
290: rserr_t ret;
291:
292: // free resources in use
293: SWimp_Shutdown ();
294:
295: ri.Con_Printf (PRINT_ALL, "setting mode %d:", mode );
296:
297: if ( !ri.Vid_GetModeInfo( pwidth, pheight, mode ) )
298: {
299: ri.Con_Printf( PRINT_ALL, " invalid mode\n" );
300: return rserr_invalid_mode;
301: }
302:
303: ri.Con_Printf( PRINT_ALL, " %d %d %s\n", *pwidth, *pheight, win_fs[fullscreen] );
304:
305: vid.buffer = malloc(*pwidth * *pheight);
306: vid.rowbytes = *pwidth;
307:
308: if (fullscreen) {
309: rhap_mode = rhap_fullscreen;
310: ret = InitFullscreen (*pwidth, *pheight);
311: } else {
312: rhap_mode = rhap_windowed;
313: ret = InitWindowed (*pwidth, *pheight);
314: }
315:
316: if (ret != rserr_ok) {
317: SWimp_Shutdown ();
318: return ret;
319: }
320:
321: /*
322: ** the view is identical in windowed and fullscreen modes
323: */
324: content.origin.x = content.origin.y = 0;
325: content.size.width = *pwidth;
326: content.size.height = *pheight;
327: vid_view_i = [[QuakeView alloc] initWithFrame: content];
328: [vid_window_i setContentView: vid_view_i];
329: [vid_window_i makeFirstResponder: vid_view_i];
330: [vid_window_i setDelegate: vid_view_i];
331:
332: [NSApp activateIgnoringOtherApps: YES];
333: [vid_window_i makeKeyAndOrderFront: nil];
334: [vid_window_i display];
335:
336: return ret;
337: }
338:
339: /*
340: ** SWimp_Shutdown
341: **
342: ** System specific graphics subsystem shutdown routine
343: */
344: void SWimp_Shutdown( void )
345: {
346: if (rhap_mode == rhap_windowed)
347: ShutdownWindowed ();
348: else if (rhap_mode == rhap_fullscreen)
349: ShutdownFullscreen ();
350:
351: rhap_mode = rhap_shutdown;
352:
353: if (vid.buffer)
354: {
355: free (vid.buffer);
356: vid.buffer = NULL;
357: }
358: }
359:
360:
361: /*
362: ** SWimp_SetPalette
363: **
364: ** System specific palette setting routine. A NULL palette means
365: ** to use the existing palette. The palette is expected to be in
366: ** a padded 4-byte xRGB format.
367: */
368: void SWimp_SetPalette( const unsigned char *palette )
369: {
370: if (rhap_mode == rhap_windowed)
371: SetPaletteWindowed (palette);
372: else if (rhap_mode == rhap_fullscreen)
373: SetPaletteFullscreen (palette);
374: }
375:
376:
377: /*
378: ** SWimp_EndFrame
379: **
380: ** This does an implementation specific copy from the backbuffer to the
381: ** front buffer. In the Win32 case it uses BitBlt or BltFast depending
382: ** on whether we're using DIB sections/GDI or DDRAW.
383: */
384: void SWimp_EndFrame (void)
385: {
386: if (rhap_mode == rhap_windowed)
387: BlitWindowed ();
388: else if (rhap_mode == rhap_fullscreen)
389: BlitFullscreen ();
390: }
391:
392:
393: /*
394: ** SWimp_AppActivate
395: */
396: void SWimp_AppActivate( qboolean active )
397: {
398: }
399:
400:
401: /*
402: ==========================================================================
403:
404: NEXTSTEP VIEW CLASS
405:
406: ==========================================================================
407: */
408: #include "../client/keys.h"
409:
410: void IN_ActivateMouse (void);
411: void IN_DeactivateMouse (void);
412:
413: @implementation QuakeView
414:
415: -(BOOL) acceptsFirstResponder
416: {
417: return YES;
418: }
419:
420: - (void)windowDidMove: (NSNotification *)note
421: {
422: NSRect r;
423:
424: r = [vid_window_i frame];
425: ri.Cmd_ExecuteText (EXEC_NOW, va("vid_xpos %i", (int)r.origin.x+1));
426: ri.Cmd_ExecuteText (EXEC_NOW, va("vid_ypos %i", (int)r.origin.y+1));
427: }
428:
429: - (void)becomeKeyWindow
430: {
431: IN_ActivateMouse ();
432: }
433:
434: - (void)resignKeyWindow
435: {
436: IN_DeactivateMouse ();
437: }
438:
439:
440: typedef struct
441: {
442: int source, dest;
443: } keymap_t;
444:
445: keymap_t keymaps[] =
446: {
447: {0xf703, K_RIGHTARROW},
448: {0xf702, K_LEFTARROW},
449: {0xf700, K_UPARROW},
450: {0xf701, K_DOWNARROW},
451:
452: {0xf704, K_F1},
453: {0xf705, K_F2},
454: {0xf706, K_F3},
455: {0xf707, K_F4},
456: {0xf708, K_F5},
457: {0xf709, K_F6},
458: {0xf70a, K_F7},
459: {0xf70b, K_F8},
460: {0xf70c, K_F9},
461: {0xf70d, K_F10},
462: {0xf70e, K_F11},
463: {0xf70f, K_F12},
464:
465: {-1,-1}
466: };
467:
468: keymap_t flagmaps[] =
469: {
470: {NSShiftKeyMask, K_SHIFT},
471: {NSControlKeyMask, K_CTRL},
472: {NSAlternateKeyMask, K_ALT},
473: {NSCommandKeyMask, K_ALT},
474:
475: {-1,-1}
476: };
477:
478: - (void)mouseDown:(NSEvent *)theEvent
479: {
480: Key_Event (K_MOUSE1, true, 0);
481: }
482: - (void)mouseUp:(NSEvent *)theEvent
483: {
484: Key_Event (K_MOUSE1, false, 0);
485: }
486: - (void)rightMouseDown:(NSEvent *)theEvent
487: {
488: Key_Event (K_MOUSE2, true, 0);
489: }
490: - (void)rightMouseUp:(NSEvent *)theEvent
491: {
492: Key_Event (K_MOUSE2, false, 0);
493: }
494:
495:
496: /*
497: ===================
498: keyboard methods
499: ===================
500: */
501: - (void)keyDown:(NSEvent *)theEvent
502: {
503: int ch;
504: keymap_t *km;
505:
506: // PSobscurecursor ();
507:
508: ch = [[theEvent charactersIgnoringModifiers] characterAtIndex:0];
509: // check for non-ascii first
510: for (km=keymaps;km->source!=-1;km++)
511: if (ch == km->source)
512: {
513: Key_Event (km->dest, true, 0);
514: return;
515: }
516:
517: if (ch >= 'A' && ch <= 'Z')
518: ch += 'a' - 'A';
519: if (ch>=256)
520: return;
521:
522: Key_Event (ch, true, 0);
523: }
524:
525: - (void)flagsChanged:(NSEvent *)theEvent
526: {
527: static int oldflags;
528: int newflags;
529: int delta;
530: keymap_t *km;
531: int i;
532:
533: // PSobscurecursor ();
534: newflags = [theEvent modifierFlags];
535: delta = newflags ^ oldflags;
536: for (i=0 ; i<32 ; i++)
537: {
538: if ( !(delta & (1<<i)))
539: continue;
540: // changed
541: for (km=flagmaps;km->source!=-1;km++)
542: if ( (1<<i) == km->source)
543: {
544: if (newflags & (1<<i))
545: Key_Event (km->dest, true, 0);
546: else
547: Key_Event (km->dest, false, 0);
548: }
549:
550: }
551:
552: oldflags = newflags;
553: }
554:
555:
556: - (void)keyUp:(NSEvent *)theEvent
557: {
558: int ch;
559: keymap_t *km;
560:
561: ch = [[theEvent charactersIgnoringModifiers] characterAtIndex:0];
562:
563: // check for non-ascii first
564: for (km=keymaps;km->source!=-1;km++)
565: if (ch == km->source)
566: {
567: Key_Event (km->dest, false, 0);
568: return;
569: }
570:
571: if (ch >= 'A' && ch <= 'Z')
572: ch += 'a' - 'A';
573: if (ch>=256)
574: return;
575: Key_Event (ch, false, 0);
576: }
577:
578: @end
579:
580:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.