diff --git a/projectfiles/xcode/Emulator/AppDelegate.m b/projectfiles/xcode/Emulator/AppDelegate.m index ace0f17d1..f2607114a 100644 --- a/projectfiles/xcode/Emulator/AppDelegate.m +++ b/projectfiles/xcode/Emulator/AppDelegate.m @@ -11,7 +11,7 @@ // FIXME: errors during load // FIXME: starting without ROM selected // FIXME: dropping file into window -// FIXME: rotation (mimonkey) +// FIXME: sound when load fails @interface AppDelegate () @property (weak) IBOutlet NSWindow *window; diff --git a/src/burner/macos/main.cpp b/src/burner/macos/main.cpp index 2698e0332..0ad7f5ca4 100644 --- a/src/burner/macos/main.cpp +++ b/src/burner/macos/main.cpp @@ -14,7 +14,7 @@ int MainInit(const char *path, const char *setname) return 0; } - fprintf(stderr, "Initializing '%s' with path '%s'\n", setname, path); + fprintf(stderr, "Initializing '%s' in '%s'\n", setname, path); SDL_Init(SDL_INIT_AUDIO); BurnLibInit(); diff --git a/src/intf/video/macos/FBScreenView.mm b/src/intf/video/macos/FBScreenView.mm index bab4121b5..9242cad7d 100644 --- a/src/intf/video/macos/FBScreenView.mm +++ b/src/intf/video/macos/FBScreenView.mm @@ -24,19 +24,20 @@ @implementation FBScreenView { - GLuint screenTextureId; - unsigned char *texture; - int imageWidth; - int imageHeight; - BOOL isRotated; - int textureWidth; - int textureHeight; - int textureBytesPerPixel; - NSLock *renderLock; - NSSize screenSize; - CFAbsoluteTime _lastMouseAction; - NSPoint _lastCursorPosition; - NSTrackingArea *_trackingArea; + GLuint screenTextureId; + unsigned char *texture; + int imageWidth; + int imageHeight; + BOOL isRotated; + BOOL isFlipped; + int textureWidth; + int textureHeight; + int textureBytesPerPixel; + NSLock *renderLock; + NSSize screenSize; + CFAbsoluteTime _lastMouseAction; + NSPoint _lastCursorPosition; + NSTrackingArea *_trackingArea; NSRect viewBounds; // Access from non-UI thread } @@ -45,16 +46,16 @@ - (void) dealloc { glDeleteTextures(1, &screenTextureId); - free(self->texture); + free(texture); } - (void) awakeFromNib { - self->renderLock = [[NSLock alloc] init]; - _lastMouseAction = CFAbsoluteTimeGetCurrent(); - _lastCursorPosition = NSMakePoint(-1, -1); + renderLock = [[NSLock alloc] init]; + _lastMouseAction = CFAbsoluteTimeGetCurrent(); + _lastCursorPosition = NSMakePoint(-1, -1); - [self resetTrackingArea]; + [self resetTrackingArea]; } #pragma mark - Cocoa Callbacks @@ -62,43 +63,43 @@ - (void) prepareOpenGL { [super prepareOpenGL]; - + NSLog(@"FBScreenView/prepareOpenGL"); - - [self->renderLock lock]; - + + [renderLock lock]; + // Synchronize buffer swaps with vertical refresh rate GLint swapInt = 1; [[self openGLContext] setValues:&swapInt - forParameter:NSOpenGLCPSwapInterval]; - + forParameter:NSOpenGLCPSwapInterval]; + glClearColor(0, 0, 0, 1.0); glClear(GL_COLOR_BUFFER_BIT); - + glGenTextures(1, &screenTextureId); - - [self->renderLock unlock]; + + [renderLock unlock]; } - (void) drawRect:(NSRect)dirtyRect { - [self->renderLock lock]; - + [renderLock lock]; + NSOpenGLContext *nsContext = [self openGLContext]; [nsContext makeCurrentContext]; - + glClear(GL_COLOR_BUFFER_BIT); - - GLfloat coordX = (GLfloat)self->imageWidth / self->textureWidth; - GLfloat coordY = (GLfloat)self->imageHeight / self->textureHeight; - + + GLfloat coordX = (GLfloat)imageWidth / textureWidth; + GLfloat coordY = (GLfloat)imageHeight / textureHeight; + glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, screenTextureId); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - + NSSize size = [self bounds].size; CGFloat offset = 0; - + glBegin(GL_QUADS); glTexCoord2f(0.0, 0.0); glVertex3f(-offset, 0.0, 0.0); @@ -110,109 +111,111 @@ glVertex3f(-offset, size.height, 0.0); glEnd(); glDisable(GL_TEXTURE_2D); - + [nsContext flushBuffer]; - - [self->renderLock unlock]; + + [renderLock unlock]; } - (void) reshape { viewBounds = [self bounds]; - [self->renderLock lock]; - + [renderLock lock]; + [[self openGLContext] makeCurrentContext]; [[self openGLContext] update]; - + [self resetProjection]; - + glClear(GL_COLOR_BUFFER_BIT); - - [self->renderLock unlock]; + + [renderLock unlock]; } #pragma mark - FBVideoRenderDelegate -- (void)initTextureOfWidth:(int)width - height:(int)height - isRotated:(BOOL)rotated - bytesPerPixel:(int)bytesPerPixel +- (void)initTextureOfWidth:(int) width + height:(int) height + isRotated:(BOOL) rotated + isFlipped:(BOOL) flipped + bytesPerPixel:(int) bytesPerPixel { NSLog(@"FBScreenView/initTexture"); - - [self->renderLock lock]; - + + [renderLock lock]; + NSOpenGLContext *nsContext = [self openGLContext]; [nsContext makeCurrentContext]; - - free(self->texture); - - self->imageWidth = width; - self->imageHeight = height; - self->isRotated = rotated; - self->textureWidth = [FBScreenView powerOfTwoClosestTo:self->imageWidth]; - self->textureHeight = [FBScreenView powerOfTwoClosestTo:self->imageHeight]; - self->textureBytesPerPixel = bytesPerPixel; - self->screenSize = NSMakeSize((CGFloat)width, (CGFloat)height); - - int texSize = self->textureWidth * self->textureHeight * bytesPerPixel; - self->texture = (unsigned char *)malloc(texSize); - + + free(texture); + + imageWidth = width; + imageHeight = height; + isRotated = rotated; + isFlipped = flipped; + textureWidth = [FBScreenView powerOfTwoClosestTo:imageWidth]; + textureHeight = [FBScreenView powerOfTwoClosestTo:imageHeight]; + textureBytesPerPixel = bytesPerPixel; + screenSize = NSMakeSize((CGFloat)width, (CGFloat)height); + + int texSize = textureWidth * textureHeight * bytesPerPixel; + texture = (unsigned char *)malloc(texSize); + glEnable(GL_TEXTURE_2D); - + glBindTexture(GL_TEXTURE_2D, screenTextureId); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - + glTexImage2D(GL_TEXTURE_2D, 0, bytesPerPixel, - self->textureWidth, self->textureHeight, - 0, GL_BGR, GL_UNSIGNED_BYTE, self->texture); - + textureWidth, textureHeight, + 0, GL_BGR, GL_UNSIGNED_BYTE, texture); + glDisable(GL_TEXTURE_2D); - + [self resetProjection]; - - [self->renderLock unlock]; + + [renderLock unlock]; } - (void)renderFrame:(unsigned char *)bitmap { - if (NSPointInRect(_lastCursorPosition, viewBounds)) { - CFAbsoluteTime interval = CFAbsoluteTimeGetCurrent() - _lastMouseAction; - if (interval > HIDE_CURSOR_TIMEOUT_SECONDS) { - if ([_delegate respondsToSelector:@selector(mouseDidIdle)]) { - [_delegate mouseDidIdle]; - } - _lastCursorPosition.x = -1; - } - } - - [self->renderLock lock]; - + if (NSPointInRect(_lastCursorPosition, viewBounds)) { + CFAbsoluteTime interval = CFAbsoluteTimeGetCurrent() - _lastMouseAction; + if (interval > HIDE_CURSOR_TIMEOUT_SECONDS) { + if ([_delegate respondsToSelector:@selector(mouseDidIdle)]) { + [_delegate mouseDidIdle]; + } + _lastCursorPosition.x = -1; + } + } + + [renderLock lock]; + NSOpenGLContext *nsContext = [self openGLContext]; [nsContext makeCurrentContext]; - + glClear(GL_COLOR_BUFFER_BIT); - - GLfloat coordX = (GLfloat)self->imageWidth / self->textureWidth; - GLfloat coordY = (GLfloat)self->imageHeight / self->textureHeight; - + + GLfloat coordX = (GLfloat)imageWidth / textureWidth; + GLfloat coordY = (GLfloat)imageHeight / textureHeight; + glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, screenTextureId); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - - for (int y = 0; y < self->imageHeight; y += 1) { - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, y, self->imageWidth, 1, + + for (int y = 0; y < imageHeight; y += 1) { + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, y, imageWidth, 1, GL_BGR, GL_UNSIGNED_BYTE, - bitmap + y * self->imageWidth * self->textureBytesPerPixel); + bitmap + y * imageWidth * textureBytesPerPixel); } - + NSSize size = viewBounds.size; CGFloat offset = 0; - + glBegin(GL_QUADS); glTexCoord2f(0.0, 0.0); glVertex3f(-offset, 0.0, 0.0); @@ -224,10 +227,10 @@ glVertex3f(-offset, size.height, 0.0); glEnd(); glDisable(GL_TEXTURE_2D); - + [nsContext flushBuffer]; - [self->renderLock unlock]; + [renderLock unlock]; } #pragma mark - Keyboard @@ -259,80 +262,78 @@ - (void) mouseEntered:(NSEvent *) event { - [self handleMouseChange:[event locationInWindow]]; + [self handleMouseChange:[event locationInWindow]]; } - (void) mouseMoved:(NSEvent *) event { - [self handleMouseChange:[event locationInWindow]]; + [self handleMouseChange:[event locationInWindow]]; } - (void) mouseExited:(NSEvent *) event { - [self handleMouseChange:NSMakePoint(-1, -1)]; + [self handleMouseChange:NSMakePoint(-1, -1)]; } - (void) mouseDown:(NSEvent *) event { - [self handleMouseChange:[event locationInWindow]]; + [self handleMouseChange:[event locationInWindow]]; } - (void) rightMouseDown:(NSEvent *) event { - [self handleMouseChange:[event locationInWindow]]; + [self handleMouseChange:[event locationInWindow]]; } #pragma mark - Public methods - (NSSize) screenSize { - return self->screenSize; + return screenSize; } #pragma mark - Private methods - (void) resetTrackingArea { - if (_trackingArea) { - [self removeTrackingArea:_trackingArea]; - } + if (_trackingArea) { + [self removeTrackingArea:_trackingArea]; + } - NSTrackingAreaOptions opts = NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingActiveInKeyWindow | NSTrackingInVisibleRect; - _trackingArea = [[NSTrackingArea alloc] initWithRect:NSZeroRect - options:opts - owner:self - userInfo:nil]; - [self addTrackingArea:_trackingArea]; + NSTrackingAreaOptions opts = NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingActiveInKeyWindow | NSTrackingInVisibleRect; + _trackingArea = [[NSTrackingArea alloc] initWithRect:NSZeroRect + options:opts + owner:self + userInfo:nil]; + [self addTrackingArea:_trackingArea]; } - (void) handleMouseChange:(NSPoint) position { - _lastMouseAction = CFAbsoluteTimeGetCurrent(); - _lastCursorPosition = [self convertPoint:position - fromView:nil]; - - if ([_delegate respondsToSelector:@selector(mouseStateDidChange)]) { - [_delegate mouseStateDidChange]; - } + _lastMouseAction = CFAbsoluteTimeGetCurrent(); + _lastCursorPosition = [self convertPoint:position + fromView:nil]; + + if ([_delegate respondsToSelector:@selector(mouseStateDidChange)]) { + [_delegate mouseStateDidChange]; + } } - (void)resetProjection { NSSize size = [self bounds].size; - + glViewport(0, 0, size.width, size.height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); - - if (!self->isRotated) { - glOrtho(0, size.width, size.height, 0, -1, 1); - } - else - { - glRotatef(90.0, 0.0, 0.0, 1.0); - glOrtho(0, size.width, size.height, 0, -1, 5); - } - + + if (!isRotated) { + glOrtho(0, size.width, size.height, 0, -1, 1); + } else { + glRotatef(isFlipped ? 270 : 90.0, 0.0, 0.0, 1.0); + glOrtho(0, size.width, size.height, 0, -1, 5); + } + glMatrixMode(GL_MODELVIEW); } diff --git a/src/intf/video/macos/FBVideo.h b/src/intf/video/macos/FBVideo.h index c33857574..52b35ae2e 100644 --- a/src/intf/video/macos/FBVideo.h +++ b/src/intf/video/macos/FBVideo.h @@ -10,12 +10,13 @@ @protocol FBVideoDelegate @optional -- (void)screenSizeDidChange:(NSSize)newSize; -- (void)initTextureOfWidth:(int)width - height:(int)height - isRotated:(BOOL)rotated - bytesPerPixel:(int)bytesPerPixel; -- (void)renderFrame:(unsigned char *)bitmap; +- (void) screenSizeDidChange:(NSSize) newSize; +- (void) initTextureOfWidth:(int) width + height:(int) height + isRotated:(BOOL) rotated + isFlipped:(BOOL) flipped + bytesPerPixel:(int) bytesPerPixel; +- (void) renderFrame:(unsigned char *) bitmap; @end diff --git a/src/intf/video/macos/FBVideo.mm b/src/intf/video/macos/FBVideo.mm index 07977585a..2028f20be 100644 --- a/src/intf/video/macos/FBVideo.mm +++ b/src/intf/video/macos/FBVideo.mm @@ -42,16 +42,18 @@ - (void) notifyTextureReadyOfWidth:(int) texWidth height:(int) texHeight isRotated:(BOOL) isRotated + isFlipped:(BOOL) isFlipped bytesPerPixel:(int) bpp screenSize:(NSSize) size { dispatch_async(dispatch_get_main_queue(), ^{ id vd = [self delegate]; - if ([vd respondsToSelector:@selector(initTextureOfWidth:height:isRotated:bytesPerPixel:)]) + if ([vd respondsToSelector:@selector(initTextureOfWidth:height:isRotated:isFlipped:bytesPerPixel:)]) [vd initTextureOfWidth:texWidth - height:texHeight - isRotated:isRotated - bytesPerPixel:bpp]; + height:texHeight + isRotated:isRotated + isFlipped:isFlipped + bytesPerPixel:bpp]; if ([vd respondsToSelector:@selector(screenSizeDidChange:)]) [vd screenSizeDidChange:size]; @@ -82,14 +84,15 @@ static int MacOSVideoInit() int gameWidth; int gameHeight; int rotationMode = 0; + int flags = BurnDrvGetFlags(); BurnDrvGetVisibleSize(&gameWidth, &gameHeight); - if (BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL) { + if (flags & BDF_ORIENTATION_VERTICAL) { rotationMode |= 1; } - if (BurnDrvGetFlags() & BDF_ORIENTATION_FLIPPED) { + if (flags & BDF_ORIENTATION_FLIPPED) { rotationMode ^= 2; } @@ -140,6 +143,7 @@ static int MacOSVideoInit() [AppDelegate.sharedInstance.video notifyTextureReadyOfWidth:textureWidth height:textureHeight isRotated:isRotated + isFlipped:flags & BDF_ORIENTATION_FLIPPED bytesPerPixel:bufferBytesPerPixel screenSize:screenSize];