32 |
|
#include <cpu_emulation.h> |
33 |
|
#include <main.h> |
34 |
|
#include "macos_util_macosx.h" |
35 |
+ |
#include "main_macosx.h" |
36 |
|
#include <prefs.h> |
37 |
|
#include <user_strings.h> |
38 |
|
#include "video_macosx.h" |
50 |
|
frame_skip; |
51 |
|
uint16 init_width = MIN_WIDTH, // as well as this code |
52 |
|
init_height = MIN_HEIGHT, |
53 |
< |
init_depth = 32, |
53 |
< |
screen_height = 0; // Used by processMouseMove: |
53 |
> |
init_depth = 32; |
54 |
|
|
55 |
|
EmulatorView *output = nil; // Set by [EmulatorView init] |
56 |
|
NSWindow *the_win = nil; // Set by [Emulator awakeFromNib] |
71 |
|
static CGDirectDisplayID theDisplay = NULL; |
72 |
|
static CFDictionaryRef originalMode = NULL, |
73 |
|
newMode = NULL; |
74 |
< |
|
74 |
> |
static BOOL singleDisplay = YES; |
75 |
|
|
76 |
|
|
77 |
|
// Prototypes |
78 |
|
|
79 |
– |
static void add_mode (const uint16 width, const uint16 height, |
80 |
– |
const uint32 resolution_id, |
81 |
– |
const uint32 bytes_per_row, |
82 |
– |
const video_depth depth); |
83 |
– |
static void add_standard_modes (const video_depth depth); |
84 |
– |
|
79 |
|
static bool video_open (const video_mode &mode); |
80 |
|
static void video_close (void); |
81 |
|
|
85 |
|
* Utility functions |
86 |
|
*/ |
87 |
|
|
88 |
< |
uint8 bits_from_depth(const video_depth depth) |
88 |
> |
static uint8 |
89 |
> |
bits_from_depth(const video_depth depth) |
90 |
|
{ |
91 |
|
int bits = 1 << depth; |
92 |
|
// if (bits == 16) |
96 |
|
return bits; |
97 |
|
} |
98 |
|
|
99 |
< |
char * |
99 |
> |
static char * |
100 |
|
colours_from_depth(const video_depth depth) |
101 |
|
{ |
102 |
|
switch ( depth ) |
112 |
|
return "illegal colour depth"; |
113 |
|
} |
114 |
|
|
115 |
< |
char * |
115 |
> |
static char * |
116 |
|
colours_from_depth(const uint16 depth) |
117 |
|
{ |
118 |
|
return colours_from_depth(DepthModeForPixelDepth(depth) ); |
227 |
|
if ( err != CGDisplayNoErr ) |
228 |
|
n = 1, displays[n] = kCGDirectMainDisplay; |
229 |
|
|
230 |
+ |
if ( n > 1 ) |
231 |
+ |
singleDisplay = NO; |
232 |
+ |
|
233 |
|
for ( CGDisplayCount dc = 0; dc < n; ++dc ) |
234 |
|
{ |
235 |
|
CGDirectDisplayID d = displays[dc]; |
236 |
|
CFArrayRef m = CGDisplayAvailableModes(d); |
237 |
|
|
238 |
< |
if ( m == NULL ) // Store the current display mode |
238 |
> |
if ( ! m ) // Store the current display mode |
239 |
|
add_mode(CGDisplayPixelsWide(d), |
240 |
|
CGDisplayPixelsHigh(d), |
241 |
|
res_id++, CGDisplayBytesPerRow(d), |
305 |
|
D(bug("VideoMonitor.mac_frame_base = %08x\n", VideoMonitor.mac_frame_base)); |
306 |
|
} |
307 |
|
|
308 |
< |
void resizeWinBy(const short deltaX, const short deltaY) |
308 |
> |
static void |
309 |
> |
resizeWinBy(const short deltaX, const short deltaY) |
310 |
|
{ |
311 |
|
NSRect rect = [the_win frame]; |
312 |
|
|
352 |
|
|
353 |
|
|
354 |
|
// Open window |
355 |
< |
if (the_win == NULL) |
355 |
> |
if ( ! the_win ) |
356 |
|
{ |
357 |
|
ErrorAlert(STR_OPEN_WINDOW_ERR); |
358 |
|
return false; |
363 |
|
// Create frame buffer ("height + 2" for safety) |
364 |
|
the_buffer_size = mode.bytes_per_row * (mode.y + 2); |
365 |
|
the_buffer = calloc(the_buffer_size, 1); |
366 |
< |
if (the_buffer == NULL) |
366 |
> |
if ( ! the_buffer ) |
367 |
|
{ |
368 |
|
NSLog(@"calloc(%d) failed", the_buffer_size); |
369 |
|
ErrorAlert(STR_NO_MEM_ERR); |
444 |
|
bytesPerRow: mode.bytes_per_row |
445 |
|
bitsPerPixel: bits_from_depth(mode.depth)]; |
446 |
|
|
447 |
< |
if ( bitmap == nil ) |
447 |
> |
if ( ! bitmap ) |
448 |
|
{ |
449 |
|
ErrorAlert("Could not allocate an NSBitmapImageRep"); |
450 |
|
return false; |
485 |
|
theDisplay = kCGDirectMainDisplay; // For now |
486 |
|
|
487 |
|
originalMode = CGDisplayCurrentMode(theDisplay); |
488 |
< |
if ( nil == originalMode ) |
488 |
> |
if ( ! originalMode ) |
489 |
|
{ |
490 |
|
ErrorSheet(@"Could not get current mode of display", the_win); |
491 |
|
return false; |
495 |
|
newMode = CGDisplayBestModeForParameters(theDisplay, |
496 |
|
bits_from_depth(mode.depth), |
497 |
|
mode.x, mode.y, NULL); |
498 |
< |
if ( NULL == newMode ) |
498 |
> |
if ( ! newMode ) |
499 |
|
{ |
500 |
|
ErrorSheet(@"Could not find a matching screen mode", the_win); |
501 |
|
return false; |
513 |
|
return false; |
514 |
|
} |
515 |
|
|
516 |
< |
// Set screen height for mouse co-ordinate flipping |
518 |
< |
if ( ! screen_height ) |
519 |
< |
screen_height = CGDisplayPixelsHigh(theDisplay); |
516 |
> |
[output startedFullScreen: theDisplay]; // For mouse event processing |
517 |
|
|
518 |
|
D(NSLog(@"About to call CGDisplaySwitchToMode()")); |
519 |
|
if ( CGDisplaySwitchToMode(theDisplay, newMode) != CGDisplayNoErr ) |
520 |
|
{ |
521 |
+ |
CGDisplayRelease(theDisplay); |
522 |
|
// [the_win deminiaturize: nil]; |
523 |
|
ErrorSheet(@"Could not switch to matching screen mode", the_win); |
524 |
|
return false; |
532 |
|
} |
533 |
|
|
534 |
|
HideMenuBar(); |
535 |
< |
CGDisplayHideCursor(theDisplay); |
535 |
> |
|
536 |
> |
if ( singleDisplay ) |
537 |
> |
{ |
538 |
> |
CGDisplayHideCursor(theDisplay); |
539 |
> |
|
540 |
> |
// Send real mouse to emulated location |
541 |
> |
if ( CGDisplayMoveCursorToPoint(theDisplay, CGPointMake(15,15)) |
542 |
> |
!= CGDisplayNoErr ) |
543 |
> |
{ |
544 |
> |
video_close(); |
545 |
> |
ErrorSheet(@"Could move (jump) cursor on screen", the_win); |
546 |
> |
return false; |
547 |
> |
} |
548 |
> |
} |
549 |
> |
else |
550 |
> |
{ |
551 |
> |
// Should set up something to hide the cursor when it enters theDisplay? |
552 |
> |
} |
553 |
|
|
554 |
|
the_buffer = CGDisplayBaseAddress(theDisplay); |
555 |
< |
if ( the_buffer == NULL ) |
555 |
> |
if ( ! the_buffer ) |
556 |
|
{ |
557 |
|
video_close(); |
558 |
|
ErrorSheet(@"Could not get base address of screen", the_win); |
559 |
|
return false; |
560 |
|
} |
561 |
|
|
547 |
– |
// Send emulated mouse to current location |
548 |
– |
NSPoint mouse = [NSEvent mouseLocation]; |
549 |
– |
ADBMouseMoved((int)mouse.x, screen_height - (int)mouse.y); |
550 |
– |
//[output performSelector: @selector(processMouseMove:) |
551 |
– |
// withObject: nil |
552 |
– |
// afterDelay: 10.0]; |
553 |
– |
|
562 |
|
// Set VideoMonitor |
563 |
|
VideoMonitor.mode = mode; |
564 |
|
set_mac_frame_buffer(mode.depth); |
565 |
|
|
558 |
– |
[output startedFullScreen]; // For [Controller sendEvent:] |
566 |
|
|
567 |
|
return true; |
568 |
|
} |
696 |
|
case DISPLAY_SCREEN: |
697 |
|
if ( theDisplay && originalMode ) |
698 |
|
{ |
699 |
< |
CGDisplayShowCursor(theDisplay); |
699 |
> |
if ( singleDisplay ) |
700 |
> |
CGDisplayShowCursor(theDisplay); |
701 |
|
ShowMenuBar(); |
702 |
|
CGDisplaySwitchToMode(theDisplay, originalMode); |
703 |
|
CGDisplayRelease(theDisplay); |
749 |
|
|
750 |
|
void video_switch_to_mode(const video_mode &mode) |
751 |
|
{ |
752 |
< |
// Close and reopen display |
753 |
< |
video_close(); |
754 |
< |
if (!video_open(mode)) |
752 |
> |
char *failure = NULL; |
753 |
> |
|
754 |
> |
|
755 |
> |
D(bug("switch_to_current_mode(): width=%d height=%d depth=%d bytes_per_row=%d\n", mode.x, mode.y, bits_from_depth(mode.depth), mode.bytes_per_row)); |
756 |
> |
|
757 |
> |
if ( display_type == DISPLAY_SCREEN && originalMode ) |
758 |
|
{ |
759 |
+ |
D(NSLog(@"About to call CGDisplayBestModeForParameters()")); |
760 |
+ |
newMode = CGDisplayBestModeForParameters(theDisplay, |
761 |
+ |
bits_from_depth(mode.depth), |
762 |
+ |
mode.x, mode.y, NULL); |
763 |
+ |
if ( ! newMode ) |
764 |
+ |
failure = "Could not find a matching screen mode"; |
765 |
+ |
else |
766 |
+ |
{ |
767 |
+ |
D(NSLog(@"About to call CGDisplaySwitchToMode()")); |
768 |
+ |
if ( CGDisplaySwitchToMode(theDisplay, newMode) != CGDisplayNoErr ) |
769 |
+ |
failure = "Could not switch to matching screen mode"; |
770 |
+ |
} |
771 |
+ |
|
772 |
+ |
if ( ! failure && |
773 |
+ |
mode.bytes_per_row != CGDisplayBytesPerRow(theDisplay) ) |
774 |
+ |
{ |
775 |
+ |
D(bug("Bytes per row (%d) doesn't match current (%ld)\n", |
776 |
+ |
mode.bytes_per_row, CGDisplayBytesPerRow(theDisplay))); |
777 |
+ |
((video_mode &)mode).bytes_per_row |
778 |
+ |
= CGDisplayBytesPerRow(theDisplay); |
779 |
+ |
} |
780 |
+ |
|
781 |
+ |
if ( ! failure && |
782 |
+ |
! ( the_buffer = CGDisplayBaseAddress(theDisplay) ) ) |
783 |
+ |
failure = "Could not get base address of screen"; |
784 |
+ |
else |
785 |
+ |
// Send emulated mouse to current location |
786 |
+ |
[output processMouseMove: nil]; |
787 |
+ |
} |
788 |
+ |
else if ( ! video_open(mode) ) |
789 |
+ |
failure = "Could not video_open() requested mode"; |
790 |
+ |
|
791 |
+ |
if ( failure ) |
792 |
+ |
{ |
793 |
+ |
NSLog(@"In switch_to_current_mode():"); |
794 |
+ |
NSLog(@"%s.", failure); |
795 |
+ |
video_close(); |
796 |
|
if ( display_type == DISPLAY_SCREEN ) |
797 |
|
ErrorAlert("Cannot switch screen to selected video mode"); |
798 |
|
else |
799 |
|
ErrorAlert(STR_OPEN_WINDOW_ERR); |
800 |
|
QuitEmulator(); |
801 |
|
} |
802 |
+ |
else |
803 |
+ |
set_mac_frame_buffer(mode.depth); |
804 |
|
} |
805 |
|
|
806 |
|
/* |