ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/MacOSX/EmulatorView.mm
Revision: 1.7
Committed: 2002-12-18T11:53:11Z (21 years, 6 months ago) by nigel
Branch: MAIN
Changes since 1.6: +29 -30 lines
Log Message:
Allow randomise to work with different drawing strategies

File Contents

# Content
1 /*
2 * EmulatorView.mm - Custom NSView for Basilisk II graphics output
3 *
4 * $Id: EmulatorView.mm,v 1.6 2002/10/06 23:26:07 nigel Exp $
5 *
6 * Basilisk II (C) 1997-2002 Christian Bauer
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23 #import "sysdeps.h" // Types used in Basilisk C++ code,
24
25 #define DEBUG 0
26 #import <debug.h>
27
28 #import <Cocoa/Cocoa.h>
29
30 #import "main_macosx.h" // For WarningAlert() et al prototypes
31 #import "misc_macosx.h" // For InfoSheet() prototype
32 #import "video_macosx.h" // For init_* globals, and bitmap drawing strategy
33
34 #import "EmulatorView.h"
35
36 @implementation EmulatorView
37
38
39 //
40 // Standard NSView methods that we override
41 //
42
43 - (id) initWithFrame: (NSRect) frameRect
44 {
45 self = [super initWithFrame: frameRect];
46
47 output = self; // Set global for access by Basilisk C++ code
48 // bitmap = nil; // Set by readyToDraw:
49 drawView = NO; // Disable drawing until later
50 fullScreen = NO;
51
52 return self;
53 }
54
55 // Mouse click in this window. If window is not active,
56 // should the click be passed to this view?
57 - (BOOL) acceptsFirstMouse: (NSEvent *) event
58 {
59 return [self mouseInView];
60 }
61
62
63 #include <adb.h>
64
65 static int prevFlags;
66
67 - (void) flagsChanged: (NSEvent *) event
68 {
69 int flags = [event modifierFlags];
70
71 if ( (flags & NSAlphaShiftKeyMask) != (prevFlags & NSAlphaShiftKeyMask) )
72 if ( flags & NSAlphaShiftKeyMask )
73 ADBKeyDown(0x39); // CAPS_LOCK
74 else
75 ADBKeyUp(0x39);
76
77 if ( (flags & NSShiftKeyMask) != (prevFlags & NSShiftKeyMask) )
78 if ( flags & NSShiftKeyMask )
79 ADBKeyDown(0x38); // SHIFT_LEFT
80 else
81 ADBKeyUp(0x38);
82
83 if ( (flags & NSControlKeyMask) != (prevFlags & NSControlKeyMask) )
84 if ( flags & NSControlKeyMask )
85 ADBKeyDown(0x36); // CTL_LEFT
86 else
87 ADBKeyUp(0x36);
88
89 if ( (flags & NSAlternateKeyMask) != (prevFlags & NSAlternateKeyMask) )
90 if ( flags & NSAlternateKeyMask )
91 ADBKeyDown(0x3a); // OPTION_LEFT
92 else
93 ADBKeyUp(0x3a);
94
95 if ( (flags & NSCommandKeyMask) != (prevFlags & NSCommandKeyMask) )
96 if ( flags & NSCommandKeyMask )
97 ADBKeyDown(0x37); // APPLE_LEFT
98 else
99 ADBKeyUp(0x37);
100
101 prevFlags = flags;
102 }
103
104 - (BOOL) mouseInView: (NSEvent *) event
105 {
106 NSRect box;
107 NSPoint loc;
108
109 if ( fullScreen )
110 {
111 box = displayBox;
112 loc = [NSEvent mouseLocation];
113 }
114 else
115 {
116 box = [self frame];
117 loc = [event locationInWindow];
118 }
119
120 D(NSLog (@"%s - loc.x=%f, loc.y=%f, box.origin.x=%f, box.origin.y=%f, box.size.width=%f, box.size.height=%f", __PRETTY_FUNCTION__, loc.x, loc.y, box.origin.x, box.origin.y, box.size.width, box.size.height));
121 return [self mouse: loc inRect: box];
122 }
123
124 - (BOOL) mouseInView
125 {
126 NSPoint loc = [[self window] mouseLocationOutsideOfEventStream];
127 NSRect box = [self frame];
128 D(NSLog (@"%s - loc.x=%f, loc.y=%f, box.origin.x=%f, box.origin.y=%f",
129 __PRETTY_FUNCTION__, loc.x, loc.y, box.origin.x, box.origin.y));
130 return [self mouse: loc inRect: box];
131 }
132
133 //
134 // Custom methods
135 //
136
137 - (void) benchmark
138 {
139 int i;
140 float seconds;
141 NSDate *startDate;
142
143 if ( ! drawView )
144 return;
145
146 drawView = NO;
147 [self lockFocus];
148 startDate = [NSDate date];
149 for (i = 1; i < 300; ++i )
150 #ifdef NSBITMAP
151 [bitmap draw];
152 #endif
153 #ifdef CGIMAGEREF
154 cgDrawInto([self bounds], cgImgRep);
155 #endif
156 #ifdef CGDRAWBITMAP
157 [self CGDrawBitmap];
158 #endif
159 seconds = -[startDate timeIntervalSinceNow];
160 [self unlockFocus];
161 drawView = YES;
162
163 InfoSheet(@"Benchmark run. 300 frames.",
164 [NSString stringWithFormat:
165 @"%.2f seconds, %.3f frames per second", seconds, i/seconds],
166 @"Thanks", [self window]);
167 }
168
169 // Return a TIFF for a snapshot of the screen image
170 - (NSData *) TIFFrep
171 {
172 #ifdef NSBITMAP
173 return [bitmap TIFFRepresentation];
174 #else
175 WarningAlert("How do I get a TIFF from a CGImageRef?");
176 #endif
177 return nil;
178 }
179
180 // Enable display of, and drawing into, the view
181 #ifdef NSBITMAP
182 - (void) readyToDraw: (NSBitmapImageRep *) theBitmap
183 imageWidth: (short) width
184 imageHeight: (short) height
185 {
186 bitmap = theBitmap;
187 numBytes = [theBitmap bytesPerRow] * height;
188 #endif
189 #ifdef CGIMAGEREF
190 - (void) readyToDraw: (CGImageRef) image
191 imageWidth: (short) width
192 imageHeight: (short) height
193 {
194 cgImgRep = image;
195 numBytes = CGImageGetBytesPerRow(image);
196 #endif
197 #ifdef CGDRAWBITMAP
198 - (void) readyToDraw: (void *) theBitmap
199 width: (short) width
200 height: (short) height
201 bps: (short) bitsPerSample
202 spp: (short) samplesPerPixel
203 bpp: (short) bitsPerPixel
204 bpr: (int) bpr
205 isPlanar: (BOOL) planar
206 hasAlpha: (BOOL) alpha
207 {
208 bitmap = theBitmap;
209 bps = bitsPerSample;
210 spp = samplesPerPixel;
211 bpp = bitsPerPixel;
212 bytesPerRow = bpr;
213 isPlanar = planar;
214 hasAlpha = alpha;
215 numBytes = bpr * height;
216 #endif
217 x = width, y = height;
218 drawView = YES;
219
220 [[self window] setAcceptsMouseMovedEvents: YES];
221 // [[self window] setInitialFirstResponder: self];
222 [[self window] makeFirstResponder: self];
223 }
224
225 - (void) disableDrawing
226 {
227 drawView = NO;
228 }
229
230 - (void) startedFullScreen: (CGDirectDisplayID) display
231 {
232 CGRect displayBounds = CGDisplayBounds(display);
233
234 fullScreen = YES;
235 memcpy(&displayBox, &displayBounds, sizeof(displayBox));
236 screen_height = (int)displayBounds.size.height;
237 }
238
239 - (short) width
240 {
241 return (short)[self bounds].size.width;
242 }
243
244 - (short) height
245 {
246 return (short)[self bounds].size.height;
247 }
248
249 - (BOOL) isFullScreen
250 {
251 return fullScreen;
252 }
253
254 - (BOOL) isOpaque
255 {
256 return drawView;
257 }
258
259 - (BOOL) processKeyEvent: (NSEvent *) event
260 {
261 if ( fullScreen || [self acceptsFirstMouse: event] )
262 if ( [event isARepeat] )
263 return NO;
264 else
265 return YES;
266
267 [self interpretKeyEvents:[NSArray arrayWithObject:event]];
268 return NO;
269 }
270
271 - (void) keyDown: (NSEvent *) event
272 {
273 if ( [self processKeyEvent: event] )
274 {
275 int code = [event keyCode];
276
277 if ( code == 126 ) code = 0x3e; // CURS_UP
278 if ( code == 125 ) code = 0x3d; // CURS_DOWN
279 if ( code == 124 ) code = 0x3c; // CURS_RIGHT
280 if ( code == 123 ) code = 0x3b; // CURS_LEFT
281
282 ADBKeyDown(code);
283 }
284 }
285
286 - (void) keyUp: (NSEvent *) event
287 {
288 if ( [self processKeyEvent: event] )
289 {
290 int code = [event keyCode];
291
292 if ( code == 126 ) code = 0x3e; // CURS_UP
293 if ( code == 125 ) code = 0x3d; // CURS_DOWN
294 if ( code == 124 ) code = 0x3c; // CURS_RIGHT
295 if ( code == 123 ) code = 0x3b; // CURS_LEFT
296
297 ADBKeyUp(code);
298 }
299 }
300
301 static NSPoint mouse; // Previous/current mouse location
302
303 - (BOOL) processMouseMove: (NSEvent *) event
304 {
305 NSPoint location;
306
307 if ( fullScreen )
308 location = [NSEvent mouseLocation];
309 else
310 location = [self convertPoint: [event locationInWindow] fromView:nil];
311
312 if ( NSEqualPoints(location, mouse) )
313 return NO;
314
315 mouse = location;
316
317 if ( fullScreen )
318 {
319 ADBMouseMoved((int)mouse.x, screen_height - (int)mouse.y);
320 return YES;
321 }
322
323 #ifdef CAN_RESIZE_VIEW
324 int mouseY = y - y * mouse.y / [self height];
325 int mouseX = x * mouse.x / [self width];
326 #else
327 int mouseY = y - (int) mouse.y;
328 int mouseX = (int) mouse.x;
329 #endif
330
331 ADBMouseMoved(mouseX, mouseY);
332 return YES;
333 }
334
335 - (void) mouseDown: (NSEvent *) event
336 {
337 [self processMouseMove: event];
338 ADBMouseDown(0);
339 }
340
341 - (void) mouseDragged: (NSEvent *) event
342 {
343 [self processMouseMove: event];
344 }
345
346 - (void) mouseMoved: (NSEvent *) event
347 {
348 #if DEBUG
349 if ( ! [self mouseInView] )
350 {
351 NSLog (@"%s - Received event while outside of view", __PRETTY_FUNCTION__);
352 return;
353 }
354 #endif
355 [self processMouseMove: event];
356 }
357
358 - (void) mouseUp: (NSEvent *) event
359 {
360 [self processMouseMove: event];
361 ADBMouseUp(0);
362 }
363
364 #if DEBUG && ! defined(CGIMAGEREF)
365 - (void) randomise // Draw some coloured snow in the bitmap
366 {
367 unsigned char *data,
368 *pixel;
369
370 #ifdef CGDRAWBITMAP
371 data = bitmap;
372 #endif
373 #ifdef NSBITMAP
374 data = [bitmap bitmapData];
375 #endif
376
377 for ( int i = 0; i < 1000; ++i )
378 {
379 pixel = data + (int) (numBytes * rand() / RAND_MAX);
380 *pixel = (unsigned char) (256.0 * rand() / RAND_MAX);
381 }
382 }
383 #endif
384
385 - (void) drawRect: (NSRect) rect
386 {
387 if ( ! drawView ) // If the emulator is still being setup,
388 return; // we do not want to draw
389
390 #if DEBUG
391 NSLog(@"In drawRect");
392 # ifndef CGIMAGEREF
393 [self randomise];
394 # endif
395 #endif
396
397 #ifdef NSBITMAP
398 NSRectClip(rect);
399 [bitmap draw];
400 #endif
401 #ifdef CGIMAGEREF
402 cgDrawInto(rect, cgImgRep);
403 #endif
404 #ifdef CGDRAWBITMAP
405 [self CGDrawBitmap];
406 #endif
407 }
408
409 //
410 // Extra drawing stuff
411 //
412
413 #ifdef CGDRAWBITMAP
414 extern "C" void CGDrawBitmap(...);
415
416 - (void) CGDrawBitmap
417 {
418 CGContextRef cgContext = (CGContextRef) [[NSGraphicsContext currentContext]
419 graphicsPort];
420 NSRect rect = [self bounds];
421 CGRect cgRect = {
422 {rect.origin.x, rect.origin.y},
423 {rect.size.width, rect.size.height}
424 };
425
426 CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB();
427
428
429 // CGContextSetShouldAntialias(cgContext, NO); // Seems to have no effect?
430
431 CGDrawBitmap(cgContext, cgRect, x, y, bps, spp, bpp,
432 bytesPerRow, isPlanar, hasAlpha, colourSpace, &bitmap);
433 }
434 #endif
435
436 #ifdef CGIMAGEREF
437 void
438 cgDrawInto(NSRect rect, CGImageRef cgImgRep)
439 {
440 CGContextRef cgContext = (CGContextRef) [[NSGraphicsContext currentContext]
441 graphicsPort];
442 CGRect cgRect = {
443 {rect.origin.x, rect.origin.y},
444 {rect.size.width, rect.size.height}
445 };
446
447 // CGContextSetShouldAntialias(cgContext, NO); // Seems to have no effect?
448
449 CGContextDrawImage(cgContext, cgRect, cgImgRep);
450 }
451 #endif
452
453 @end