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, 10 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

# User Rev Content
1 nigel 1.1 /*
2     * EmulatorView.mm - Custom NSView for Basilisk II graphics output
3     *
4 nigel 1.7 * $Id: EmulatorView.mm,v 1.6 2002/10/06 23:26:07 nigel Exp $
5 nigel 1.1 *
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 nigel 1.4 fullScreen = NO;
51 nigel 1.1
52     return self;
53     }
54    
55 nigel 1.5 // Mouse click in this window. If window is not active,
56     // should the click be passed to this view?
57 nigel 1.1 - (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 nigel 1.4 NSRect box;
107 nigel 1.5 NSPoint loc;
108    
109 nigel 1.4 if ( fullScreen )
110 nigel 1.5 {
111     box = displayBox;
112     loc = [NSEvent mouseLocation];
113     }
114 nigel 1.4 else
115 nigel 1.5 {
116 nigel 1.4 box = [self frame];
117 nigel 1.5 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 nigel 1.1 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 nigel 1.7 cgDrawInto([self bounds], cgImgRep);
155 nigel 1.1 #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 nigel 1.7 numBytes = [theBitmap bytesPerRow] * height;
188 nigel 1.1 #endif
189     #ifdef CGIMAGEREF
190     - (void) readyToDraw: (CGImageRef) image
191     imageWidth: (short) width
192     imageHeight: (short) height
193     {
194 nigel 1.7 cgImgRep = image;
195     numBytes = CGImageGetBytesPerRow(image);
196 nigel 1.1 #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 nigel 1.7 numBytes = bpr * height;
216 nigel 1.1 #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 nigel 1.5 - (void) startedFullScreen: (CGDirectDisplayID) display
231 nigel 1.4 {
232 nigel 1.5 CGRect displayBounds = CGDisplayBounds(display);
233    
234 nigel 1.4 fullScreen = YES;
235 nigel 1.5 memcpy(&displayBox, &displayBounds, sizeof(displayBox));
236     screen_height = (int)displayBounds.size.height;
237 nigel 1.4 }
238    
239 nigel 1.1 - (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 nigel 1.4 - (BOOL) isFullScreen
250     {
251     return fullScreen;
252     }
253    
254 nigel 1.1 - (BOOL) isOpaque
255     {
256     return drawView;
257     }
258    
259     - (BOOL) processKeyEvent: (NSEvent *) event
260     {
261 nigel 1.4 if ( fullScreen || [self acceptsFirstMouse: event] )
262 nigel 1.1 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 nigel 1.2 {
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 nigel 1.1 }
285    
286     - (void) keyUp: (NSEvent *) event
287     {
288     if ( [self processKeyEvent: event] )
289 nigel 1.2 {
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 nigel 1.1 }
300    
301     static NSPoint mouse; // Previous/current mouse location
302    
303     - (BOOL) processMouseMove: (NSEvent *) event
304     {
305 nigel 1.5 NSPoint location;
306 nigel 1.1
307 nigel 1.4 if ( fullScreen )
308 nigel 1.5 location = [NSEvent mouseLocation];
309 nigel 1.1 else
310 nigel 1.5 location = [self convertPoint: [event locationInWindow] fromView:nil];
311 nigel 1.1
312 nigel 1.5 if ( NSEqualPoints(location, mouse) )
313 nigel 1.1 return NO;
314    
315 nigel 1.5 mouse = location;
316 nigel 1.1
317 nigel 1.4 if ( fullScreen )
318 nigel 1.1 {
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 nigel 1.7 #if DEBUG && ! defined(CGIMAGEREF)
365 nigel 1.1 - (void) randomise // Draw some coloured snow in the bitmap
366     {
367 nigel 1.7 unsigned char *data,
368     *pixel;
369    
370     #ifdef CGDRAWBITMAP
371     data = bitmap;
372     #endif
373     #ifdef NSBITMAP
374     data = [bitmap bitmapData];
375     #endif
376 nigel 1.1
377     for ( int i = 0; i < 1000; ++i )
378     {
379 nigel 1.7 pixel = data + (int) (numBytes * rand() / RAND_MAX);
380 nigel 1.1 *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 nigel 1.7 # ifndef CGIMAGEREF
393     [self randomise];
394     # endif
395 nigel 1.1 #endif
396    
397     #ifdef NSBITMAP
398     NSRectClip(rect);
399     [bitmap draw];
400     #endif
401     #ifdef CGIMAGEREF
402 nigel 1.7 cgDrawInto(rect, cgImgRep);
403 nigel 1.1 #endif
404     #ifdef CGDRAWBITMAP
405     [self CGDrawBitmap];
406     #endif
407     }
408    
409     //
410     // Extra drawing stuff
411     //
412    
413     #ifdef CGDRAWBITMAP
414 nigel 1.6 extern "C" void CGDrawBitmap(...);
415 nigel 1.1
416     - (void) CGDrawBitmap
417     {
418 nigel 1.7 CGContextRef cgContext = (CGContextRef) [[NSGraphicsContext currentContext]
419     graphicsPort];
420 nigel 1.1 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 nigel 1.7 // CGContextSetShouldAntialias(cgContext, NO); // Seems to have no effect?
430 nigel 1.1
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 nigel 1.7 cgDrawInto(NSRect rect, CGImageRef cgImgRep)
439 nigel 1.1 {
440 nigel 1.7 CGContextRef cgContext = (CGContextRef) [[NSGraphicsContext currentContext]
441     graphicsPort];
442 nigel 1.1 CGRect cgRect = {
443     {rect.origin.x, rect.origin.y},
444     {rect.size.width, rect.size.height}
445     };
446    
447 nigel 1.7 // CGContextSetShouldAntialias(cgContext, NO); // Seems to have no effect?
448 nigel 1.1
449 nigel 1.7 CGContextDrawImage(cgContext, cgRect, cgImgRep);
450 nigel 1.1 }
451     #endif
452    
453 nigel 1.3 @end