/* All the various stuff needed for configuration is done here, including reading the Config file and displaying a dialog box AboutDlgProc() is a plug-in function called from the PCSXR app, as is DlgProc() */ #import "NetSfPeopsOpenGLPluginConfigController.h" #include "gpu.h" #include "cfg.h" #include "menu.h" #include // bah, "externals.h" thinks include files are for wimps; OpenGL header, in fact, is needed #include "externals.h" #import "PluginGLView.h" #ifdef ENABLE_NLS #include #include #define _(x) gettext(x) #define N_(x) (x) //If running under Mac OS X, use the Localizable.strings file instead. #elif defined(_MACOSX) #ifdef PCSXRCORE __private_extern char* Pcsxr_locale_text(char* toloc); #define _(String) Pcsxr_locale_text(String) #define N_(String) String #else #ifndef PCSXRPLUG #warning please define the plug being built to use Mac OS X localization! #define _(msgid) msgid #define N_(msgid) msgid #else //Kludge to get the preprocessor to accept PCSXRPLUG as a variable. #define PLUGLOC_x(x,y) x ## y #define PLUGLOC_y(x,y) PLUGLOC_x(x,y) #define PLUGLOC PLUGLOC_y(PCSXRPLUG,_locale_text) __private_extern char* PLUGLOC(char* toloc); #define _(String) PLUGLOC(String) #define N_(String) String #endif #endif #else #define _(x) (x) #define N_(x) (x) #endif #define APP_ID @"net.sf.peops.GpuOpenGLPlugin" #define PrefsKey APP_ID @" Settings" static NetSfPeopsOpenGLPluginConfigController *windowController = nil; void AboutDlgProc() { // Get parent application instance NSBundle *bundle = [NSBundle bundleWithIdentifier:APP_ID]; // Get Credits.rtf NSString *path = [bundle pathForResource:@"Credits" ofType:@"rtf"]; NSAttributedString *credits; if (!path) { path = [bundle pathForResource:@"Credits" ofType:@"rtfd"]; } if (path) { credits = [[NSAttributedString alloc] initWithPath:path documentAttributes:NULL]; } else { credits = [[NSAttributedString alloc] initWithString:@""]; } // Get Application Icon NSImage *icon = [[NSWorkspace sharedWorkspace] iconForFile:[bundle bundlePath]]; NSSize size = NSMakeSize(64, 64); [icon setSize:size]; NSDictionary *infoPaneDict = @{@"ApplicationName": [bundle objectForInfoDictionaryKey:@"CFBundleName"], @"ApplicationIcon": icon, @"ApplicationVersion": [bundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"], @"Version": [bundle objectForInfoDictionaryKey:@"CFBundleVersion"], @"Copyright": [bundle objectForInfoDictionaryKey:@"NSHumanReadableCopyright"], @"Credits": credits}; dispatch_async(dispatch_get_main_queue(), ^{ [NSApp orderFrontStandardAboutPanelWithOptions:infoPaneDict]; }); } void DlgProc() { RunOnMainThreadSync(^{ NSWindow *window; PrepFactoryDefaultPreferences(); if (windowController == nil) { windowController = [[PluginConfigController alloc] initWithWindowNibName:@"NetSfPeopsOpenGLConfig"]; } window = [windowController window]; /* load values */ [windowController loadValues]; [window center]; [window makeKeyAndOrderFront:nil]; }); } #define kFPSCounter @"FPS Counter" #define kHacks @"Hacks" #define kAutoFullScreen @"Auto Full Screen" #define kFrameSkipping @"Frame Skipping" #define kFrameLimit @"Frame Limit" #define kVSync @"VSync" #define kHacksEnable @"Enable Hacks" #define kWindowSize @"Window Size" void PrepFactoryDefaultPreferences(void) { // THE place to find the names of settings. // If it's not here, you can't set it. // create or read a sub-dictionary beneath the main PCSXR app prefs. // dictionary is named "net.sf.GpuOpenGLPlugin Settings" // and contains all our key/values // the prefs .plist will store this dictionary ("net.sf...") as an object NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; NSDictionary* keyValues = [defaults dictionaryForKey:PrefsKey]; BOOL windowSizeNeedsReset = NO; if (keyValues) { NSSize size = NSSizeFromString(keyValues[kWindowSize]); if (!keyValues[kWindowSize]) { windowSizeNeedsReset = YES; } else if ([keyValues[kWindowSize] isKindOfClass:[NSNumber class]]) { windowSizeNeedsReset = YES; } else if (size.height == 0 || size.width == 0) { windowSizeNeedsReset = YES; } } if (windowSizeNeedsReset) { NSMutableDictionary *tmpDict = [[NSMutableDictionary alloc] initWithDictionary:keyValues]; tmpDict[kWindowSize] = NSStringFromSize(NSMakeSize(800, 600)); [defaults setObject:tmpDict forKey:PrefsKey]; [defaults synchronize]; } keyValues = nil; [defaults registerDefaults: @{PrefsKey: @{kFPSCounter: @NO, kAutoFullScreen: @NO, kFrameSkipping: @NO, kFrameLimit: @YES, kVSync: @NO, kHacksEnable: @NO, @"Dither Mode": @0, kHacks: @0, @"Proportional Resize": @YES, //[NSSize stringWithCString: @"default"], @"Fullscreen Resolution", @"Offscreen Drawing Level": @2, @"Texture Color Depth Level": @0, @"Texture Enhancement Level": @0, @"Texture Filter Level": @0, @"Frame Buffer Level": @0, @"Frame Buffer Access": @0, kWindowSize: NSStringFromSize(NSMakeSize(800, 600)), @"Draw Scanlines": @NO, // nasty: @"Scanline Color": [NSArchiver archivedDataWithRootObject: [NSColor colorWithCalibratedRed:0 green:0 blue:0 alpha:0.25]], @"Advanced Blending": @NO, @"Opaque Pass": @NO, @"Blur": @NO, @"Z Mask Clipping": @YES, @"Wireframe Mode": @NO, @"Emulate mjpeg decoder": @YES, // helps remove unsightly vertical line in movies @"Fast mjpeg decoder": @NO, @"GteAccuracy": @YES}}]; } void ReadConfig(void) { // set up PCSXR GPU plug's global variables according to user preferences. // this is called from the PCSXR GPU plugin thread via GPUOpen. // has nothing to do with the Configuration dialog box, btw., other than the // fact that the config dialog writes to user prefs. This only reads, which // is important because PCSXR will change its globals on the fly // and saving those new ad hoc changes is Bad for the user. PrepFactoryDefaultPreferences(); // in case user deletes, or on new startup NSDictionary* keyValues = [[NSUserDefaults standardUserDefaults] dictionaryForKey:PrefsKey]; // bind all prefs settings to their PCSXR counterparts // with a little finagling to make it work as expected iShowFPS = [keyValues[kFPSCounter] boolValue]; if ([keyValues[kFrameLimit] boolValue]) { bUseFrameLimit = 1; iFrameLimit = 2; // required fFrameRate = 60; // required (some number, 60 seems ok) } iForceVSync = [keyValues[kVSync] boolValue] ? 1 : 0; // Dithering is either on or off in OpenGL plug, but hey bDrawDither = [keyValues[@"Dither Mode"] intValue]; bChangeWinMode = [keyValues[kAutoFullScreen] boolValue] ? 2 : 1; bUseFrameSkip = [keyValues[kFrameSkipping] boolValue]; bUseFixes = [keyValues[kHacksEnable] boolValue]; dwCfgFixes = [keyValues[kHacks] unsignedIntValue]; // we always start out at 800x600 (at least until resizing the window is implemented) NSSize winSize = NSSizeFromString(keyValues[kWindowSize]); if (bChangeWinMode == 1) { iResX = winSize.width; iResY = winSize.height; } else { iResX = 800; iResY = 600; } iBlurBuffer = [keyValues[@"Blur"] boolValue]; // not noticeable, but doesn't harm iUseScanLines = [keyValues[@"Draw Scanlines"] boolValue]; // works NSColor* scanColor = [NSUnarchiver unarchiveObjectWithData:keyValues[@"Scanline Color"]]; scanColor = [scanColor colorUsingColorSpace:[NSColorSpace deviceRGBColorSpace]]; iScanlineColor[0] = [scanColor redComponent]; iScanlineColor[1] = [scanColor greenComponent]; iScanlineColor[2] = [scanColor blueComponent]; iScanlineColor[3] = [scanColor alphaComponent]; iScanBlend = 0; // we always draw nice since it costs nothing. iUseMask = [keyValues[@"Z Mask Clipping"] boolValue]; // works, clips polygons with primitive "Z" buffer bUseLines = [keyValues[@"Wireframe Mode"] boolValue]; // works, aka "Wireframe" mode iOffscreenDrawing = [keyValues[@"Offscreen Drawing Level"] intValue]; // draw offscreen for texture building? if (iOffscreenDrawing > 4) iOffscreenDrawing = 4; if (iOffscreenDrawing < 0) iOffscreenDrawing = 0; // texture quality, whatever that means (doesn't hurt), more like "texture handling" or "texture performance" iFrameTexType = [keyValues[@"Frame Buffer Level"] intValue]; if (iFrameTexType > 3) iFrameTexType = 3; if (iFrameTexType < 0) iFrameTexType = 0; iFrameReadType = [keyValues[@"Frame Buffer Access"] intValue]; if (iFrameReadType > 4) iFrameReadType = 4; if (iFrameReadType < 0) iFrameReadType = 0; iTexQuality = [keyValues[@"Texture Color Depth Level"] intValue]; if (iTexQuality > 4) iTexQuality = 4; if (iTexQuality < 0) iTexQuality = 0; // MAG_FILTER = LINEAR, etc. iFilterType = [keyValues[@"Texture Filter Level"] intValue]; if (iFilterType > 6) iFilterType = 6; if (iFilterType < 0) iFilterType = 0; // stretches textures (more detail). You'd think it would look great, but it's not massively better. NEEDS iFilterType to be of any use. iHiResTextures = [keyValues[@"Texture Enhancement Level"] intValue]; if (iHiResTextures > 2) iHiResTextures = 2; if (iHiResTextures < 0) iHiResTextures = 0; // well actually, the "SaI" mode is best, but is #1, so swap qualities: if (iHiResTextures != 0) iHiResTextures = 3 - iHiResTextures; if (iHiResTextures && !iFilterType) iFilterType = 1; // needed to see any real effect bUseFastMdec = [keyValues[@"Emulate mjpeg decoder"] boolValue]; bUse15bitMdec = [keyValues[@"Fast mjpeg decoder"] boolValue]; bGteAccuracy = [keyValues[@"GteAccuracy"] boolValue]; if (iShowFPS) ulKeybits |= KEY_SHOWFPS; else ulKeybits &=~ KEY_SHOWFPS; // additional checks if(!iColDepth) iColDepth=32; if(bUseFixes) { dwActFixes = dwCfgFixes; } else { dwActFixes = 0; } SetFixes(); // need this or you'll be playing at light speed: if(iFrameLimit == 2) SetAutoFrameCap(); bSkipNextFrame = FALSE; szDispBuf[0] = 0; BuildDispMenu(0); } @implementation NetSfPeopsOpenGLPluginConfigController @synthesize autoFullScreen; @synthesize limitFrameRate; @synthesize fpsCounter; @synthesize frameSkipping; @synthesize vSync; @synthesize proportionalResize; @synthesize fullscreenSize; @synthesize windowWidth; @synthesize windowHeighth; @synthesize offscreenDrawing; @synthesize texColorDepth; @synthesize texFiltering; @synthesize texEnhancment; @synthesize frameBufferEffects; @synthesize frameBufferAccess; @synthesize drawScanlines; @synthesize advancedBlending; @synthesize opaquePass; @synthesize zMaskClipping; @synthesize wireframeOnly; @synthesize blurEffect; @synthesize mjpegDecoder; @synthesize mjpegDecoder15bit; @synthesize gteAccuracy; @synthesize colorDithering; @synthesize scanlineColorWell; @synthesize hacksMatrix; @synthesize hackEnable; @synthesize hacksWindow; @synthesize keyValues; - (IBAction)cancel:(id)sender { [self close]; } - (IBAction)ok:(id)sender { NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; NSMutableDictionary *writeDic = [keyValues mutableCopy]; writeDic[kFPSCounter] = ([fpsCounter integerValue] ? @YES : @NO); writeDic[@"Scanline Color"] = [NSArchiver archivedDataWithRootObject:[scanlineColorWell color]]; writeDic[kFrameSkipping] = ([frameSkipping integerValue] ? @YES : @NO); writeDic[kAutoFullScreen] = ([autoFullScreen integerValue] ? @YES : @NO); writeDic[kFrameLimit] = ([limitFrameRate integerValue] ? @YES : @NO); writeDic[@"Proportional Resize"] = ([proportionalResize integerValue] ? @YES : @NO); writeDic[@"Offscreen Drawing Level"] = @([offscreenDrawing indexOfSelectedItem]); writeDic[@"Texture Color Depth Level"] = @([texColorDepth indexOfSelectedItem]); writeDic[@"Texture Enhancement Level"] = @([texEnhancment integerValue]); writeDic[@"Texture Filter Level"] = @([texFiltering integerValue]); writeDic[@"Frame Buffer Level"] = @([frameBufferEffects indexOfSelectedItem]); writeDic[@"Frame Buffer Access"] = @([frameBufferAccess indexOfSelectedItem]); writeDic[@"Draw Scanlines"] = ([drawScanlines integerValue] ? @YES : @NO); writeDic[@"Advanced Blending"] = ([advancedBlending integerValue] ? @YES : @NO); writeDic[@"Opaque Pass"] = ([opaquePass integerValue] ? @YES : @NO); writeDic[@"Blur"] = ([blurEffect integerValue] ? @YES : @NO); writeDic[@"Z Mask Clipping"] = ([zMaskClipping integerValue] ? @YES : @NO); writeDic[@"Wireframe Mode"] = ([wireframeOnly integerValue] ? @YES : @NO); writeDic[@"Emulate mjpeg decoder"] = ([mjpegDecoder integerValue] ? @YES : @NO); writeDic[@"Fast mjpeg decoder"] = ([mjpegDecoder15bit integerValue] ? @YES : @NO); writeDic[@"GteAccuracy"] = ([gteAccuracy integerValue] ? @YES : @NO); writeDic[@"Dither Mode"] = @([colorDithering integerValue]); writeDic[kVSync] = ([vSync integerValue] ? @YES : @NO); writeDic[kWindowSize] = NSStringFromSize(NSMakeSize([windowWidth integerValue], [windowHeighth integerValue])); [defaults setObject:writeDic forKey:PrefsKey]; [defaults synchronize]; [self close]; } - (IBAction)reset:(id)sender { NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; [defaults removeObjectForKey:PrefsKey]; [self loadValues]; } - (IBAction)hackToggle:(id)sender { // enable the "hacks" checkboxes BOOL enable = [sender intValue] ? YES : NO; NSArray *views = [hacksMatrix cells]; for (NSControl *control in views) { [control setEnabled:enable]; } } - (void)loadHacksValues { unsigned int hackValues = [(self.keyValues)[kHacks] unsignedIntValue]; [hackEnable setIntegerValue:[(self.keyValues)[kHacksEnable] boolValue]]; // build refs to hacks checkboxes for (NSControl *control in [hacksMatrix cells]) { [control setIntValue:(hackValues >> ([control tag] - 1)) & 1]; } [self hackToggle:hackEnable]; } - (void)loadValues { // set up the window with the values in the .plist PrepFactoryDefaultPreferences(); // in case we're starting anew NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; /* load from preferences */ self.keyValues = [[defaults dictionaryForKey:PrefsKey] mutableCopy]; [self loadHacksValues]; [autoFullScreen setIntegerValue:[keyValues[kAutoFullScreen] boolValue]]; [limitFrameRate setIntegerValue:[keyValues[kFrameLimit] boolValue]]; [fpsCounter setIntegerValue:[keyValues[kFPSCounter] boolValue]]; [scanlineColorWell setColor:[NSUnarchiver unarchiveObjectWithData: keyValues[@"Scanline Color"]]]; [frameSkipping setIntegerValue:[keyValues[kFrameSkipping] boolValue]]; [advancedBlending setIntegerValue:[keyValues[@"Advanced Blending"] boolValue]]; [texFiltering setIntegerValue:[keyValues[@"Texture Filter Level"] integerValue]]; [texEnhancment setIntegerValue:[keyValues[@"Texture Enhancement Level"] integerValue]]; [zMaskClipping setIntegerValue:[keyValues[@"Z Mask Clipping"] integerValue]]; [mjpegDecoder setIntegerValue:[keyValues[@"Emulate mjpeg decoder"] boolValue]]; [mjpegDecoder15bit setIntegerValue:[keyValues[@"Fast mjpeg decoder"] boolValue]]; [drawScanlines setIntegerValue:[keyValues[@"Draw Scanlines"] boolValue]]; [offscreenDrawing selectItemAtIndex:[keyValues[@"Offscreen Drawing Level"] integerValue]]; [advancedBlending setIntegerValue:[keyValues[@"Advanced Blending"] boolValue]]; [opaquePass setIntegerValue:[keyValues[@"Opaque Pass"] boolValue]]; [wireframeOnly setIntegerValue:[keyValues[@"Wireframe Mode"] boolValue]]; [blurEffect setIntegerValue:[keyValues[@"Blur"] boolValue]]; [texColorDepth selectItemAtIndex:[keyValues[@"Texture Color Depth Level"] integerValue]]; [gteAccuracy setIntegerValue:[keyValues[@"GteAccuracy"] boolValue]]; [colorDithering setIntegerValue:[keyValues[@"Dither Mode"] integerValue]]; [scanlineColorWell setEnabled:[keyValues[@"Draw Scanlines"] boolValue]]; [frameBufferEffects selectItemAtIndex:[keyValues[@"Frame Buffer Level"] integerValue]]; [frameBufferAccess selectItemAtIndex:[keyValues[@"Frame Buffer Access"] integerValue]]; [vSync setIntegerValue:[keyValues[kVSync] boolValue]]; [proportionalResize setIntegerValue:[keyValues[@"Proportional Resize"] boolValue]]; NSSize winSize = NSSizeFromString(keyValues[kWindowSize]); [windowWidth setIntegerValue:winSize.width]; [windowHeighth setIntegerValue:winSize.height]; } - (void)awakeFromNib { [[NSColorPanel sharedColorPanel] setShowsAlpha:YES]; // eliminate dumb behavior! // Kludge fix for windowWidth field layout problem on OS X 10.10+ windowWidth.titleWidth = windowWidth.titleWidth + FLT_MIN; } - (void)hacksSheetDidEnd:(NSWindow *)sheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo { NSParameterAssert(sheet == hacksWindow); if (returnCode == NSCancelButton) { //Reset hack preferences. [self loadHacksValues]; } else { unsigned int hackValues = 0; for (NSControl *control in [hacksMatrix cells]) { hackValues |= [control intValue] << ([control tag] - 1); } NSMutableDictionary *writeDic = self.keyValues; writeDic[kHacks] = @(hackValues); writeDic[kHacksEnable] = ([hackEnable integerValue] ? @YES : @NO); } [sheet orderOut:nil]; } - (IBAction)closeHacks:(id)sender { if ([sender tag] == 1) { [NSApp endSheet:hacksWindow returnCode:NSOKButton]; } else { [NSApp endSheet:hacksWindow returnCode:NSCancelButton]; } } - (IBAction)showHacks:(id)sender { [NSApp beginSheet:hacksWindow modalForWindow:[self window] modalDelegate:self didEndSelector:@selector(hacksSheetDidEnd:returnCode:contextInfo:) contextInfo:NULL]; } - (IBAction)toggleCheck:(id)sender { scanlineColorWell.enabled = drawScanlines.integerValue; } @end #import "OSXPlugLocalization.h" PLUGLOCIMP([PluginConfigController class])