From deef974c8532bc0f6711e56ead3389b2853f806a Mon Sep 17 00:00:00 2001 From: rogerman Date: Mon, 14 Jul 2025 14:47:12 -0700 Subject: [PATCH] Cocoa Port: Fix a bug where HUD colors would fail to work when running on macOS Leopard or Snow Leopard. - Also fix a bug on big-endian systems where HUD colors were being stored in the user defaults file in big-endian byte order instead of little-endian byte order. --- .../src/frontend/cocoa/ClientDisplayView.cpp | 46 ++++++++--------- desmume/src/frontend/cocoa/cocoa_util.mm | 51 ++++++++++--------- .../userinterface/DisplayWindowController.mm | 14 ++--- 3 files changed, 56 insertions(+), 55 deletions(-) diff --git a/desmume/src/frontend/cocoa/ClientDisplayView.cpp b/desmume/src/frontend/cocoa/ClientDisplayView.cpp index 90fd0969d..c05ac6071 100644 --- a/desmume/src/frontend/cocoa/ClientDisplayView.cpp +++ b/desmume/src/frontend/cocoa/ClientDisplayView.cpp @@ -101,16 +101,16 @@ void ClientDisplayPresenter::__InstanceInit(const ClientDisplayPresenterProperti _showRTC = false; _showInputs = false; - _hudColorExecutionSpeed = LE_TO_LOCAL_32(0xFFFFFFFF); - _hudColorVideoFPS = LE_TO_LOCAL_32(0xFFFFFFFF); - _hudColorRender3DFPS = LE_TO_LOCAL_32(0xFFFFFFFF); - _hudColorFrameIndex = LE_TO_LOCAL_32(0xFFFFFFFF); - _hudColorLagFrameCount = LE_TO_LOCAL_32(0xFFFFFFFF); - _hudColorCPULoadAverage = LE_TO_LOCAL_32(0xFFFFFFFF); - _hudColorRTC = LE_TO_LOCAL_32(0xFFFFFFFF); - _hudColorInputAppliedAndPending = LE_TO_LOCAL_32(0xFFFFFFFF); - _hudColorInputAppliedOnly = LE_TO_LOCAL_32(0xFF3030FF); - _hudColorInputPendingOnly = LE_TO_LOCAL_32(0xFF00C000); + _hudColorExecutionSpeed = 0xFFFFFFFF; + _hudColorVideoFPS = 0xFFFFFFFF; + _hudColorRender3DFPS = 0xFFFFFFFF; + _hudColorFrameIndex = 0xFFFFFFFF; + _hudColorLagFrameCount = 0xFFFFFFFF; + _hudColorCPULoadAverage = 0xFFFFFFFF; + _hudColorRTC = 0xFFFFFFFF; + _hudColorInputAppliedAndPending = 0xFFFFFFFF; + _hudColorInputAppliedOnly = 0xFF3030FF; + _hudColorInputPendingOnly = 0xFF00C000; _clientFrameInfo.videoFPS = 0; _ndsFrameInfo.clear(); @@ -2013,10 +2013,10 @@ void ClientDisplay3DPresenter::SetHUDColorVertices(uint32_t *vtxColorBufferPtr) continue; } - vtxColorBufferPtr[j+0] = currentColor; // Top Left - vtxColorBufferPtr[j+1] = currentColor; // Top Right - vtxColorBufferPtr[j+2] = currentColor; // Bottom Right - vtxColorBufferPtr[j+3] = currentColor; // Bottom Left + vtxColorBufferPtr[j+0] = LE_TO_LOCAL_32(currentColor); // Top Left + vtxColorBufferPtr[j+1] = LE_TO_LOCAL_32(currentColor); // Top Right + vtxColorBufferPtr[j+2] = LE_TO_LOCAL_32(currentColor); // Bottom Right + vtxColorBufferPtr[j+3] = LE_TO_LOCAL_32(currentColor); // Bottom Left } // Fill in the vertices for the inputs. @@ -2039,7 +2039,7 @@ void ClientDisplay3DPresenter::SetHUDColorVertices(uint32_t *vtxColorBufferPtr) inputColors[13] = this->GetInputColorUsingStates( (this->_ndsFrameInfo.inputStatesPending.Lid == 0), (this->_ndsFrameInfo.inputStatesApplied.Lid == 0) ); inputColors[14] = this->GetInputColorUsingStates( (this->_ndsFrameInfo.inputStatesPending.Touch == 0), (this->_ndsFrameInfo.inputStatesApplied.Touch == 0) ); - uint32_t touchColor = inputColors[14]; + uint32_t touchColor = LE_TO_LOCAL_32(inputColors[14]); for (size_t k = 15; k < HUD_INPUT_ELEMENT_LENGTH; k++) { @@ -2048,20 +2048,20 @@ void ClientDisplay3DPresenter::SetHUDColorVertices(uint32_t *vtxColorBufferPtr) for (size_t k = 0; k < HUD_INPUT_ELEMENT_LENGTH; i++, j+=4, k++) { - vtxColorBufferPtr[j+0] = inputColors[k]; // Top Left - vtxColorBufferPtr[j+1] = inputColors[k]; // Top Right - vtxColorBufferPtr[j+2] = inputColors[k]; // Bottom Right - vtxColorBufferPtr[j+3] = inputColors[k]; // Bottom Left + vtxColorBufferPtr[j+0] = LE_TO_LOCAL_32(inputColors[k]); // Top Left + vtxColorBufferPtr[j+1] = LE_TO_LOCAL_32(inputColors[k]); // Top Right + vtxColorBufferPtr[j+2] = LE_TO_LOCAL_32(inputColors[k]); // Bottom Right + vtxColorBufferPtr[j+3] = LE_TO_LOCAL_32(inputColors[k]); // Bottom Left } touchColor = ((this->_ndsFrameInfo.inputStatesPending.Touch != 0) && (this->_ndsFrameInfo.inputStatesApplied.Touch != 0)) ? 0x00000000 : (touchColor & LE_TO_LOCAL_32(0x00FFFFFF)) | LE_TO_LOCAL_32(0x60000000); for (size_t k = 0; k < HUD_INPUT_TOUCH_LINE_ELEMENTS; i++, j+=4, k++) { - vtxColorBufferPtr[j+0] = touchColor; // Top Left - vtxColorBufferPtr[j+1] = touchColor; // Top Right - vtxColorBufferPtr[j+2] = touchColor; // Bottom Right - vtxColorBufferPtr[j+3] = touchColor; // Bottom Left + vtxColorBufferPtr[j+0] = touchColor; // Top Left + vtxColorBufferPtr[j+1] = touchColor; // Top Right + vtxColorBufferPtr[j+2] = touchColor; // Bottom Right + vtxColorBufferPtr[j+3] = touchColor; // Bottom Left } } diff --git a/desmume/src/frontend/cocoa/cocoa_util.mm b/desmume/src/frontend/cocoa/cocoa_util.mm index 0e6841b97..de13ae57d 100644 --- a/desmume/src/frontend/cocoa/cocoa_util.mm +++ b/desmume/src/frontend/cocoa/cocoa_util.mm @@ -1,6 +1,6 @@ /* Copyright (C) 2011 Roger Manuel - Copyright (C) 2012-2022 DeSmuME team + Copyright (C) 2012-2025 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -94,46 +94,49 @@ + (NSColor *) NSColorFromRGBA8888:(uint32_t)theColor { -#ifdef MSB_FIRST - const CGFloat a = (CGFloat)((theColor >> 0) & 0xFF) / 255.0f; - const CGFloat b = (CGFloat)((theColor >> 8) & 0xFF) / 255.0f; - const CGFloat g = (CGFloat)((theColor >> 16) & 0xFF) / 255.0f; - const CGFloat r = (CGFloat)((theColor >> 24) & 0xFF) / 255.0f; -#else const CGFloat r = (CGFloat)((theColor >> 0) & 0xFF) / 255.0f; const CGFloat g = (CGFloat)((theColor >> 8) & 0xFF) / 255.0f; const CGFloat b = (CGFloat)((theColor >> 16) & 0xFF) / 255.0f; const CGFloat a = (CGFloat)((theColor >> 24) & 0xFF) / 255.0f; -#endif return [NSColor colorWithDeviceRed:r green:g blue:b alpha:a]; } + (uint32_t) RGBA8888FromNSColor:(NSColor *)theColor { - if ([theColor colorSpace] != [NSColorSpace deviceRGBColorSpace]) + NSInteger numberOfComponents = [theColor numberOfComponents]; + if ( ([theColor colorSpace] != [NSColorSpace deviceRGBColorSpace]) || (numberOfComponents != 4) ) { theColor = [theColor colorUsingColorSpace:[NSColorSpace deviceRGBColorSpace]]; - if (theColor == nil) + numberOfComponents = [theColor numberOfComponents]; + + if ( (theColor == nil) || (numberOfComponents != 4) ) { return 0x00000000; } } - CGFloat r, g, b, a; - [theColor getRed:&r green:&g blue:&b alpha:&a]; + // Incoming NSColor objects should be under the deviceRGBColorSpace. + // This is typically the case for macOS v10.7 Lion and later. However, + // Leopard and Snow Leopard may use an NSCustomColorSpace that just so + // happens to be compatible with deviceRGBColorSpace. + // + // Unfortunately, calling [NSColor getRed:green:blue:alpha] in Leopard + // or Snow Leopard strictly wants the NSColor to be under + // deviceRGBColorSpace and no other, lest an exception is raised with + // the method call. + // + // Therefore, for compatibility purposes, we'll use the method call + // [NSColor getComponents:], which has looser requirements and works + // with all NSColor objects that are compatible with deviceRGBColorSpace. -#ifdef MSB_FIRST - return (((uint32_t)(a * 255.0f)) << 0) | - (((uint32_t)(b * 255.0f)) << 8) | - (((uint32_t)(g * 255.0f)) << 16) | - (((uint32_t)(r * 255.0f)) << 24); -#else - return (((uint32_t)(r * 255.0f)) << 0) | - (((uint32_t)(g * 255.0f)) << 8) | - (((uint32_t)(b * 255.0f)) << 16) | - (((uint32_t)(a * 255.0f)) << 24); -#endif + CGFloat colorComponent[4]; + [theColor getComponents:colorComponent]; + + return (((uint32_t)(colorComponent[0] * 255.0f)) << 0) | + (((uint32_t)(colorComponent[1] * 255.0f)) << 8) | + (((uint32_t)(colorComponent[2] * 255.0f)) << 16) | + (((uint32_t)(colorComponent[3] * 255.0f)) << 24); } + (NSString *) filePathFromCPath:(const char *)cPath @@ -464,7 +467,6 @@ [NSException raise:NSInternalInconsistencyException format:@"Value (%@) does not respond to -unsignedIntegerValue, -unsignedIntValue, -integerValue or -intValue.", [value class]]; } - color32 = LE_TO_LOCAL_32(color32); return [CocoaDSUtil NSColorFromRGBA8888:color32]; } @@ -483,7 +485,6 @@ } color32 = [CocoaDSUtil RGBA8888FromNSColor:(NSColor *)value]; - color32 = LE_TO_LOCAL_32(color32); return [NSNumber numberWithUnsignedInteger:color32]; } diff --git a/desmume/src/frontend/cocoa/userinterface/DisplayWindowController.mm b/desmume/src/frontend/cocoa/userinterface/DisplayWindowController.mm index 6260d8935..02d616eaf 100644 --- a/desmume/src/frontend/cocoa/userinterface/DisplayWindowController.mm +++ b/desmume/src/frontend/cocoa/userinterface/DisplayWindowController.mm @@ -494,13 +494,13 @@ static std::unordered_map _screenMap; // [[self view] setIsHUDRealTimeClockVisible:[[NSUserDefaults standardUserDefaults] boolForKey:@"HUD_ShowRTC"]]; [[self view] setIsHUDInputVisible:[[NSUserDefaults standardUserDefaults] boolForKey:@"HUD_ShowInput"]]; - [[self view] setHudColorExecutionSpeed:[CocoaDSUtil NSColorFromRGBA8888:LE_TO_LOCAL_32((uint32_t)[[NSUserDefaults standardUserDefaults] integerForKey:@"HUD_Color_ExecutionSpeed"])]]; - [[self view] setHudColorVideoFPS:[CocoaDSUtil NSColorFromRGBA8888:LE_TO_LOCAL_32((uint32_t)[[NSUserDefaults standardUserDefaults] integerForKey:@"HUD_Color_VideoFPS"])]]; - [[self view] setHudColorRender3DFPS:[CocoaDSUtil NSColorFromRGBA8888:LE_TO_LOCAL_32((uint32_t)[[NSUserDefaults standardUserDefaults] integerForKey:@"HUD_Color_Render3DFPS"])]]; - [[self view] setHudColorFrameIndex:[CocoaDSUtil NSColorFromRGBA8888:LE_TO_LOCAL_32((uint32_t)[[NSUserDefaults standardUserDefaults] integerForKey:@"HUD_Color_FrameIndex"])]]; - [[self view] setHudColorLagFrameCount:[CocoaDSUtil NSColorFromRGBA8888:LE_TO_LOCAL_32((uint32_t)[[NSUserDefaults standardUserDefaults] integerForKey:@"HUD_Color_LagFrameCount"])]]; - [[self view] setHudColorCPULoadAverage:[CocoaDSUtil NSColorFromRGBA8888:LE_TO_LOCAL_32((uint32_t)[[NSUserDefaults standardUserDefaults] integerForKey:@"HUD_Color_CPULoadAverage"])]]; - [[self view] setHudColorRTC:[CocoaDSUtil NSColorFromRGBA8888:LE_TO_LOCAL_32((uint32_t)[[NSUserDefaults standardUserDefaults] integerForKey:@"HUD_Color_RTC"])]]; + [[self view] setHudColorExecutionSpeed:[CocoaDSUtil NSColorFromRGBA8888:(uint32_t)[[NSUserDefaults standardUserDefaults] integerForKey:@"HUD_Color_ExecutionSpeed"]]]; + [[self view] setHudColorVideoFPS:[CocoaDSUtil NSColorFromRGBA8888:(uint32_t)[[NSUserDefaults standardUserDefaults] integerForKey:@"HUD_Color_VideoFPS"]]]; + [[self view] setHudColorRender3DFPS:[CocoaDSUtil NSColorFromRGBA8888:(uint32_t)[[NSUserDefaults standardUserDefaults] integerForKey:@"HUD_Color_Render3DFPS"]]]; + [[self view] setHudColorFrameIndex:[CocoaDSUtil NSColorFromRGBA8888:(uint32_t)[[NSUserDefaults standardUserDefaults] integerForKey:@"HUD_Color_FrameIndex"]]]; + [[self view] setHudColorLagFrameCount:[CocoaDSUtil NSColorFromRGBA8888:(uint32_t)[[NSUserDefaults standardUserDefaults] integerForKey:@"HUD_Color_LagFrameCount"]]]; + [[self view] setHudColorCPULoadAverage:[CocoaDSUtil NSColorFromRGBA8888:(uint32_t)[[NSUserDefaults standardUserDefaults] integerForKey:@"HUD_Color_CPULoadAverage"]]]; + [[self view] setHudColorRTC:[CocoaDSUtil NSColorFromRGBA8888:(uint32_t)[[NSUserDefaults standardUserDefaults] integerForKey:@"HUD_Color_RTC"]]]; } - (BOOL) masterStatusBarState