diff options
| author | SND\weimingzhi_cp <SND\weimingzhi_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97> | 2011-02-18 08:58:58 +0000 |
|---|---|---|
| committer | SND\weimingzhi_cp <SND\weimingzhi_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97> | 2011-02-18 08:58:58 +0000 |
| commit | 34cfcc5169cafa8ae9e0d6469e20dc11c122c077 (patch) | |
| tree | 47ddff4f53156e888c370b12c405a6849a9cb2a6 /macosx/plugins/PeopsXgl/macsrc | |
| parent | 394f7a2b4a604dc40cf29f23a7121deb19eed79c (diff) | |
| download | pcsxr-34cfcc5169cafa8ae9e0d6469e20dc11c122c077.tar.gz | |
-(SysBeep)Added Mac OS X port of P.E.Op.S OpenGL plugin. (Patch #8361)
-Fixed help message for Windows. (Issue #8028).
git-svn-id: https://pcsxr.svn.codeplex.com/svn/pcsxr@63522 e17a0e51-4ae3-4d35-97c3-1a29b211df97
Diffstat (limited to 'macosx/plugins/PeopsXgl/macsrc')
| -rw-r--r-- | macosx/plugins/PeopsXgl/macsrc/ExtendedKeys.h | 23 | ||||
| -rw-r--r-- | macosx/plugins/PeopsXgl/macsrc/NetSfPeopsOpenGLPluginConfigController.h | 60 | ||||
| -rw-r--r-- | macosx/plugins/PeopsXgl/macsrc/NetSfPeopsOpenGLPluginConfigController.m | 348 | ||||
| -rw-r--r-- | macosx/plugins/PeopsXgl/macsrc/PluginGLView.h | 47 | ||||
| -rw-r--r-- | macosx/plugins/PeopsXgl/macsrc/PluginGLView.m | 135 | ||||
| -rw-r--r-- | macosx/plugins/PeopsXgl/macsrc/PluginWindow.h | 55 | ||||
| -rw-r--r-- | macosx/plugins/PeopsXgl/macsrc/PluginWindow.m | 155 | ||||
| -rw-r--r-- | macosx/plugins/PeopsXgl/macsrc/PluginWindowController.h | 52 | ||||
| -rw-r--r-- | macosx/plugins/PeopsXgl/macsrc/PluginWindowController.m | 302 | ||||
| -rw-r--r-- | macosx/plugins/PeopsXgl/macsrc/drawgl.m | 234 |
10 files changed, 1411 insertions, 0 deletions
diff --git a/macosx/plugins/PeopsXgl/macsrc/ExtendedKeys.h b/macosx/plugins/PeopsXgl/macsrc/ExtendedKeys.h new file mode 100644 index 00000000..1b6475b8 --- /dev/null +++ b/macosx/plugins/PeopsXgl/macsrc/ExtendedKeys.h @@ -0,0 +1,23 @@ + +#ifndef __EXTENDED_KEYS_H__ +#define __EXTENDED_KEYS_H__ + +enum { + PSX_FREEZE_KEY = 0xFFBE/*XK_F1*/, + PSX_NEXT_FREEZE_SLOT_KEY = 0xFFBF/*XK_F2*/, + PSX_DEFROST_KEY = 0xFFC0/*XK_F3*/, + PSX_SHOW_FREEZE_PIC_KEY = 0xFFC1/*XK_F4*/, + PSX_SIO_ALWAYS_ON_KEY = 0xFFC2/*XK_F5*/, + PSX_BW_MDEC_KEY = 0xFFC3/*XK_F6*/, + PSX_XA_AUDIO_ON_KEY = 0xFFC4/*XK_F7*/, + PSX_SNAPSHOT_KEY = 0xFFC5/*XK_F8*/, + PSX_OPEN_SHELL_KEY = 0xFFC6/*XK_F9*/, + PSX_CLOSE_SHELL_KEY = 0xFFC7/*XK_F10*/, + + PSX_STOP_KEY = 0xFF1B/*XK_Escape*/, + + GPU_FULLSCREEN_KEY = 0x0100, + GPU_FPS_DISPLAY_KEY = 0xFFFF/*XK_Delete*/ +}; + +#endif //__EXTENDED_KEYS_H__ diff --git a/macosx/plugins/PeopsXgl/macsrc/NetSfPeopsOpenGLPluginConfigController.h b/macosx/plugins/PeopsXgl/macsrc/NetSfPeopsOpenGLPluginConfigController.h new file mode 100644 index 00000000..7d3bea7c --- /dev/null +++ b/macosx/plugins/PeopsXgl/macsrc/NetSfPeopsOpenGLPluginConfigController.h @@ -0,0 +1,60 @@ +/* NetSfPeopsSoftGPUPluginConfigController */ +/* All the various stuff needed for configuration is done here, including reading + the preferences and displaying a dialog box for the user +*/ + +#define PluginConfigController NetSfPeopsOpenGLPluginConfigController + +#import <Cocoa/Cocoa.h> + +@interface NetSfPeopsOpenGLPluginConfigController : NSWindowController +{ + // buncha controls. + // most aren't worthy as IBOutlets since the IB interface + // uses bindings to magically set user defaults. + // But you can look at their grandness if you like: + + IBOutlet NSControl *autoFullScreen; + IBOutlet NSPopUpButton *ditherMode; + IBOutlet NSControl *fpsCounter; + IBOutlet NSControl *frameSkipping; + IBOutlet NSControl *hackEnable; + IBOutlet NSView *hacksView; + IBOutlet NSControl *vSync; + + IBOutlet NSControl *proportionalResize; + IBOutlet NSPopUpButton *windowSize; + IBOutlet NSPopUpButton *fullscreenSize; + IBOutlet NSPopUpButton *offscreenDrawing; + + IBOutlet NSPopUpButton *texColorDepth; + IBOutlet NSSlider *texFiltering; + IBOutlet NSSlider *texEnhancment; + + IBOutlet NSPopUpButton *frameBufferEffects; + + + IBOutlet NSControl *drawScanlines; + IBOutlet NSControl *advancedBlending; + IBOutlet NSControl *opaquePass; + IBOutlet NSControl *zMaskClipping; + IBOutlet NSControl *wireframeOnly; + IBOutlet NSControl *blurEffect; + IBOutlet NSControl *mjpegDecoder; + IBOutlet NSControl *mjpegDecoder15bit; + + + + NSMutableDictionary *keyValues; +} +- (IBAction)cancel:(id)sender; +- (IBAction)ok:(id)sender; +- (IBAction)reset:(id)sender; +- (IBAction)hackToggle:(id)sender; + +- (void)loadValues; + +@end + +void PrepFactoryDefaultPreferences(void); + diff --git a/macosx/plugins/PeopsXgl/macsrc/NetSfPeopsOpenGLPluginConfigController.m b/macosx/plugins/PeopsXgl/macsrc/NetSfPeopsOpenGLPluginConfigController.m new file mode 100644 index 00000000..781508be --- /dev/null +++ b/macosx/plugins/PeopsXgl/macsrc/NetSfPeopsOpenGLPluginConfigController.m @@ -0,0 +1,348 @@ + +/* 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 PCSX app, as is + DlgProc() +*/ + +#import "NetSfPeopsOpenGLPluginConfigController.h" +#include "gpu.h" +#include "cfg.h" +#include "menu.h" +#include <OpenGL/gl.h> // bah, "externals.h" thinks include files are for wimps; OpenGL header, in fact, is needed +#include "externals.h" + +#define APP_ID @"net.sf.peops.GpuOpenGLPlugin" +#define PrefsKey APP_ID @" Settings" + +static NetSfPeopsOpenGLPluginConfigController *windowController; +char * pConfigFile=NULL; + +void AboutDlgProc() +{ + // Get parent application instance + NSApplication *app = [NSApplication sharedApplication]; + NSBundle *bundle = [NSBundle bundleWithIdentifier:APP_ID]; + + // Get Credits.rtf + NSString *path = [bundle pathForResource:@"Credits" ofType:@"rtf"]; + NSAttributedString *credits; + if (path) { + credits = [[[NSAttributedString alloc] initWithPath: path + documentAttributes:NULL] autorelease]; + } else { + credits = [[[NSAttributedString alloc] initWithString:@""] autorelease]; + } + + // Get Application Icon + NSImage *icon = [[NSWorkspace sharedWorkspace] iconForFile:[bundle bundlePath]]; + NSSize size = NSMakeSize(64, 64); + [icon setSize:size]; + + [app orderFrontStandardAboutPanelWithOptions:[NSDictionary dictionaryWithObjectsAndKeys: + [bundle objectForInfoDictionaryKey:@"CFBundleName"], @"ApplicationName", + icon, @"ApplicationIcon", + [bundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"], @"ApplicationVersion", + [bundle objectForInfoDictionaryKey:@"CFBundleVersion"], @"Version", + [bundle objectForInfoDictionaryKey:@"NSHumanReadableCopyright"], @"Copyright", + credits, @"Credits", + nil]]; +} + + +void DlgProc() +{ + NSWindow *window; + + PrepFactoryDefaultPreferences(); // Must do here to avoid a "when does such-and-such bind" issue + + if (windowController == nil) { + windowController = [[PluginConfigController alloc] initWithWindowNibName:@"NetSfPeopsOpenGLConfig"]; + } + window = [windowController window]; + + /* load values */ + [windowController loadValues]; + + [window center]; + [window makeKeyAndOrderFront:nil]; +} + + +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 PCSX 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]; + + //tired of wasting time hacking around the "convenience" function + // of registerDefaults, so: + if ([defaults objectForKey:PrefsKey] == nil) + { + // just create default preferences and save them. + + NSDictionary* defaultPrefs = + [[NSDictionary alloc] initWithObjectsAndKeys: + [NSNumber numberWithBool:NO], @"FPS Counter", + [NSNumber numberWithBool:NO], @"Auto Full Screen", + [NSNumber numberWithBool:NO], @"Frame Skipping", + [NSNumber numberWithBool:YES], @"Frame Limit", + [NSNumber numberWithBool:NO], @"VSync", + [NSNumber numberWithBool:NO], @"Enable Hacks", + [NSNumber numberWithInt:0], @"Dither Mode", + [NSNumber numberWithLong:0], @"Hacks", + + [NSNumber numberWithBool:YES], @"Proportional Resize", +// [NSSize stringWithCString: @"default"], @"Fullscreen Resolution", + [NSNumber numberWithInt:2], @"Offscreen Drawing Level", + [NSNumber numberWithInt:0], @"Texture Color Depth Level", + [NSNumber numberWithInt:0], @"Texture Enhancement Level", + [NSNumber numberWithInt:0], @"Texture Filter Level", + [NSNumber numberWithInt:0], @"Frame Buffer Level", + [NSNumber numberWithBool:NO], @"Draw Scanlines", + // nasty: + [NSArchiver archivedDataWithRootObject: [NSColor colorWithCalibratedRed:0 green:0 blue:0 alpha:0.25]], @"Scanline Color", + [NSNumber numberWithBool:NO], @"Advanced Blending", + [NSNumber numberWithBool:NO], @"Opaque Pass", + [NSNumber numberWithBool:NO], @"Blur", + [NSNumber numberWithBool:YES], @"Z Mask Clipping", + [NSNumber numberWithBool:NO], @"Wireframe Mode", + [NSNumber numberWithBool:YES], @"Emulate mjpeg decoder", // helps remove unsightly vertical line in movies + [NSNumber numberWithBool:NO], @"Fast mjpeg decoder", + nil]; + + [defaults setObject: defaultPrefs forKey:PrefsKey]; + [defaults synchronize]; + } + return; +} + +void ReadConfig(void) +{ + // set up PCSX GPU plug's global variables according to user preferences. + // this is called from the PCSX 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 PCSX 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 + +//NOTE this is NOT the "keyValues" member of the controller. Just sayin. + NSDictionary* keyValues = [[NSUserDefaults standardUserDefaults] dictionaryForKey:PrefsKey]; + + + // bind all prefs settings to their PCSX counterparts + // with a little finagling to make it work as expected + iShowFPS = [[keyValues objectForKey:@"FPS Counter"] boolValue]; + + if ([[keyValues objectForKey:@"Frame Limit"] boolValue]){ + bUseFrameLimit = 1; + iFrameLimit = 2; // required + fFrameRate = 60; // required (some number, 60 seems ok) + } + +// Dithering is either on or off in OpenGL plug, but hey + bDrawDither = [[keyValues objectForKey:@"Dither Mode"] intValue]; + + bChangeWinMode = [[keyValues objectForKey:@"Auto Full Screen"] boolValue] ? 2 : 1; + bUseFrameSkip = [[keyValues objectForKey:@"Frame Skipping"] boolValue]; + + bUseFixes = [[keyValues objectForKey:@"Enable Hacks"] boolValue]; + dwCfgFixes = [[keyValues objectForKey:@"Hacks"] longValue]; + + +// we always start out at 800x600 (at least until resizing the window is implemented) + iResX = 800; + iResY = 600; + + iBlurBuffer = [[keyValues objectForKey:@"Blur"] boolValue]; // not noticeable, but doesn't harm + iUseScanLines = [[keyValues objectForKey:@"Draw Scanlines"] boolValue]; // works + NSColor* scanColor = [NSUnarchiver unarchiveObjectWithData: [keyValues objectForKey:@"Scanline Color"]]; + 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 objectForKey:@"Z Mask Clipping"] boolValue]; // works, clips polygons with primitive "Z" buffer + bUseLines = [[keyValues objectForKey:@"Wireframe Mode"] boolValue]; // works, aka "Wireframe" mode + iOffscreenDrawing = [[keyValues objectForKey:@"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 objectForKey:@"Frame Buffer Level"] intValue]; + if (iFrameTexType > 3) iFrameTexType = 3; + if (iFrameTexType < 0) iFrameTexType = 0; + + iTexQuality = [[keyValues objectForKey:@"Texture Color Depth Level"] intValue]; + if (iTexQuality > 4) iTexQuality = 4; + if (iTexQuality < 0) iTexQuality = 0; + +// MAG_FILTER = LINEAR, etc. + iFilterType = [[keyValues objectForKey:@"Texture Filter Level"] intValue]; + if (iFilterType > 2) iFilterType = 2; + 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 objectForKey:@"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 objectForKey:@"Emulate mjpeg decoder"] boolValue]; + bUse15bitMdec = [[keyValues objectForKey:@"Fast mjpeg decoder"] boolValue]; + + + if (iShowFPS) + ulKeybits|=KEY_SHOWFPS; + else + ulKeybits&=~KEY_SHOWFPS; + + // additional checks + if(!iColDepth) iColDepth=32; +#if 0 // was in SoftGPU, not in OpenGL + if(iUseFixes) dwActFixes=dwCfgFixes; + else dwActFixes=0; +#else + dwActFixes=0; // for now... TODO +#endif + + + SetFixes(); + + // need this or you'll be playing at light speed: + if(iFrameLimit==2) SetAutoFrameCap(); + bSkipNextFrame = FALSE; + + szDispBuf[0]=0; + BuildDispMenu(0); +} + +@implementation PluginConfigController + +- (IBAction)cancel:(id)sender +{ + //TODO: the IB bindings have already changed everything to what the + // user clicked on. + // Therefore, "backup" settings should be stored before interaction, + // then restored here. + // IMO, 'cancel' is not needed since the config dialog doesn't launch + // an action when "ok" is clicked. + [self close]; +} + +- (IBAction)ok:(id)sender +{ + +// most everything is taken care of through bindings in Interface Builder. +// note that the IB interface uses NSObjectController (a dict controller) as a proxy to +// NSUserDefaultsController because NSUserDefaultsController can't +// handle dictionaries. Yup, that's what I said. </snark>. + + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + [defaults synchronize]; + +// treat hacks specially: + + unsigned long hackValues = 0; + int i; + NSArray *views = [hacksView subviews]; + for (i=0; i<[views count]; i++) { + NSView *control = [views objectAtIndex:i]; + if ([control isKindOfClass:[NSButton class]]) { + hackValues |= [(NSControl *)control intValue] << ([control tag] - 1); + } + } + + keyValues = [NSMutableDictionary dictionaryWithDictionary: [[NSUserDefaults standardUserDefaults] dictionaryForKey:PrefsKey]]; + + NSMutableDictionary *writeDic = [NSMutableDictionary dictionaryWithDictionary:keyValues]; + [writeDic setObject:[NSNumber numberWithLong:hackValues] forKey:@"Hacks"]; + + // write the preferences with Hacks adjustments + [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; + int i; + NSArray *views = [hacksView subviews]; + + for (i=0; i<[views count]; i++) { + NSView *control = [views objectAtIndex:i]; + if ([control isKindOfClass:[NSButton class]]) { + [(NSControl *)control setEnabled:enable]; + } + } +} + +- (void)loadValues +{ +// set up the window with the values in the .plist + +// all preferences are bound in Interface Builder. +// Though the "hacks settings" is controlled here because it disables/enables the list +// and uses a bit mask + +// Note that in the .nib, an NSObjectController (aka "dict controller") +// is used as a proxy to NSUserDefaults +// because NSUserDefaults is slightly retarded about nested dictionaries +// OK, "Completely" retarded. + + PrepFactoryDefaultPreferences(); // in case we're starting anew + + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + + /* load from preferences */ + keyValues = [NSMutableDictionary dictionaryWithDictionary: [defaults dictionaryForKey:PrefsKey]]; + + unsigned long hackValues = [[keyValues objectForKey:@"Hacks"] longValue]; + + // build refs to hacks checkboxes + int i; + NSArray *views = [hacksView subviews]; + for (i=0; i<[views count]; i++) { + NSView *control = [views objectAtIndex:i]; + if ([control isKindOfClass:[NSButton class]]) { + [(NSControl *)control setIntValue:(hackValues >> ([control tag] - 1)) & 1]; + } + } + + [self hackToggle:hackEnable]; +} + +- (void)awakeFromNib +{ + hacksView = [[hacksView subviews] objectAtIndex:0]; + [[NSColorPanel sharedColorPanel] setShowsAlpha:YES]; // eliminate dumb behavior! +} + +@end diff --git a/macosx/plugins/PeopsXgl/macsrc/PluginGLView.h b/macosx/plugins/PeopsXgl/macsrc/PluginGLView.h new file mode 100644 index 00000000..da780293 --- /dev/null +++ b/macosx/plugins/PeopsXgl/macsrc/PluginGLView.h @@ -0,0 +1,47 @@ +/*************************************************************************** + PluginGLView.h -- a view within game window, rudimentary OpenGL setup + maintainence + PeopsOpenGPU + + Created by Gil Pedersen on Sun April 18 2004. + Copyright (c) 2004 Gil Pedersen. + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#define PluginGLView NetSfPeopsOpenGLGPUPluginGLView + +#import <Cocoa/Cocoa.h> +#import <OpenGL/gl.h> +#include <sys/time.h> + +#define IMAGE_COUNT 2 + +@interface PluginGLView : NSOpenGLView +{ + struct timeval cycle_time; + + NSLock *glLock; // FIXME: wha? + BOOL noDisplay; + BOOL drawBG; + +} + + +- (void)swapBuffer; // I wonder what this does ;-) + +// overrides: +- (id) initWithCoder: (NSCoder *) coder; +- (void)dealloc; +- (BOOL)isOpaque; +- (BOOL)acceptsFirstResponder; +- (void)reshape; + +@end diff --git a/macosx/plugins/PeopsXgl/macsrc/PluginGLView.m b/macosx/plugins/PeopsXgl/macsrc/PluginGLView.m new file mode 100644 index 00000000..feb483a9 --- /dev/null +++ b/macosx/plugins/PeopsXgl/macsrc/PluginGLView.m @@ -0,0 +1,135 @@ +/*************************************************************************** + PluginGLView.m + a view within game window, rudimentary OpenGL setup + maintainence + Also, I clear the gl screen with a beautiful yellow color for + debugging purposes. + + PeopsOpenGLGPU + + Created by Gil Pedersen on Sun April 18 2004. + Copyright (c) 2004 Gil Pedersen. + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#import <OpenGL/gl.h> +#import <OpenGL/glext.h> +#import <OpenGL/glu.h> +//#import <GLUT/glut.h> +//#import <Carbon/Carbon.h> +#import "PluginGLView.h" +#include "externals.h" // for PSXDisplay.disable -- should move it elsewhere really +#undef BOOL + +@implementation PluginGLView + +- (BOOL)isOpaque { return YES; } +- (BOOL)acceptsFirstResponder { return NO; } + + +- (id) initWithCoder: (NSCoder *) coder +{ + // Set up pixel format on creation + // and, well, that's about it. + if ((self = [super initWithCoder:coder]) == nil) + return nil; + + glLock = [[NSLock alloc] init]; + if (nil == glLock) { + [self release]; + return nil; + } + + // Init pixel format attribs + NSOpenGLPixelFormatAttribute attrs[] = + { + NSOpenGLPFAAccelerated, + NSOpenGLPFANoRecovery, + NSOpenGLPFADoubleBuffer, +// NSOpenGLPFASampleBuffers, 1, // For full screen AA when implemented +// NSOpenGLPFASamples, 2, + 0 + }; + + // Get pixel format from OpenGL + NSOpenGLPixelFormat* pixFmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs]; + if (!pixFmt) + { + NSLog(@"No Accelerated OpenGL pixel format found\n"); + + NSOpenGLPixelFormatAttribute attrs2[] = + { + NSOpenGLPFANoRecovery, + 0 + }; + + // Get pixel format from OpenGL + pixFmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs2]; + if (!pixFmt) { + NSLog(@"No OpenGL pixel format found!\n"); + + [self release]; + return nil; + } + } + + [self setPixelFormat:[pixFmt autorelease]]; + + [[self openGLContext] makeCurrentContext]; + + // we're done, dude. + + // Call for a redisplay + noDisplay = YES; // hm, this can be deleted I think + PSXDisplay.Disabled = 1; + [self setNeedsDisplay:true]; + + return self; +} + +- (void)dealloc +{ + [[self openGLContext] makeCurrentContext]; // just in case + [NSOpenGLContext clearCurrentContext]; + [glLock release]; + [super dealloc]; +} + + +- (void)reshape // scrolled, moved or resized +{ + [super reshape]; + + [glLock lock]; // not sure if needed, but hey + [[self openGLContext] makeCurrentContext]; + + NSRect rect = [self bounds]; + rect.size = [self convertSize:rect.size toView:nil]; + glViewport(0.0, 0.0, NSWidth(rect), NSHeight(rect)); + + glClearColor (1.0, 0.5, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + [[self openGLContext] flushBuffer]; + +// [NSOpenGLContext clearCurrentContext]; // this makes bad things happen, so screw it. + [glLock unlock]; + return; +} + +- (void)swapBuffer +{ + // actually not much to do here. + [[self openGLContext] flushBuffer]; + return; + } + + +@end diff --git a/macosx/plugins/PeopsXgl/macsrc/PluginWindow.h b/macosx/plugins/PeopsXgl/macsrc/PluginWindow.h new file mode 100644 index 00000000..06a75546 --- /dev/null +++ b/macosx/plugins/PeopsXgl/macsrc/PluginWindow.h @@ -0,0 +1,55 @@ +/*************************************************************************** + PluginWindow.h - Specialization of the main game window (borderless) + PeopsSoftGPU + + Created by Gil Pedersen on Wed April 21 2004. + Copyright (c) 2004 Gil Pedersen. + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + + /* this is a borderless window that can be dragged about. Also, holds a GLView */ +#import <Cocoa/Cocoa.h> +#import <AppKit/NSMenu.h> + +@interface NetSfPeopsOpenGLGPUPluginWindow : NSWindow +{ + NSWindow* myParent; + NSPoint initialLocation; +} + +- (id) initWithContentRect: (NSRect) contentRect + styleMask: (unsigned int) aStyle + backing: (NSBackingStoreType) bufferingType + defer: (BOOL) flag ; + + +- (BOOL) canBecomeKeyWindow; // to stop the beeping + +- (void) sendEvent:(NSEvent *)theEvent; +- (void) windowDidResize:(NSNotification*)notice; +- (void) windowDidUpdate: (NSNotification*)notice; +- (void) windowDidMove:(NSNotification *)notice; + +- (void) performClose: (id)sender; +- (void) mouseDown:(NSEvent *)theEvent; +- (void) mouseDragged:(NSEvent *)theEvent; + +- (void)keyDown:(NSEvent *)theEvent; +- (void)keyUp:(NSEvent *)theEvent; + +@end + + + +@interface NetSfPeopsOpenGLGPUPluginWindow (NSMenuValidation) +- (BOOL)validateMenuItem:(NSMenuItem*) item; +@end diff --git a/macosx/plugins/PeopsXgl/macsrc/PluginWindow.m b/macosx/plugins/PeopsXgl/macsrc/PluginWindow.m new file mode 100644 index 00000000..feffedec --- /dev/null +++ b/macosx/plugins/PeopsXgl/macsrc/PluginWindow.m @@ -0,0 +1,155 @@ +/*************************************************************************** + PluginWindow.m + PeopsSoftGPU + + Created by Gil Pedersen on Wed April 21 2004. + Copyright (c) 2004 Gil Pedersen. + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#import "PluginWindow.h" +@implementation NetSfPeopsOpenGLGPUPluginWindow +/* +- (BOOL)windowShouldClose:(id)sender +{ + [[NSNotificationCenter defaultCenter] postNotificationName:@"emuWindowDidClose" object:self]; + + return YES; +}*/ + +- (void)sendEvent:(NSEvent *)theEvent +{ + int type = [theEvent type]; + if (type == NSKeyDown || type == NSKeyUp) { + if (type == NSKeyDown && [theEvent keyCode] == 53 /* escape */) { + // reroute to menu event + [[NSApp mainMenu] performKeyEquivalent:theEvent]; + } + + // ignore all key Events + return; + } + + [super sendEvent:theEvent]; +} + +- (id) initWithContentRect: (NSRect) contentRect + styleMask: (unsigned int) aStyle + backing: (NSBackingStoreType) bufferingType + defer: (BOOL) flag +{ + if (self = [super initWithContentRect: contentRect + styleMask: NSBorderlessWindowMask + backing: bufferingType + defer: flag]) + { + return self; + } + + return nil; +} + + + +- (void) windowDidResize:(NSNotification*)notice +{ +} + +- (void) windowDidUpdate: (NSNotification*)notice +{ +} + +- (void)windowDidMove:(NSNotification *)notification +{ + +} + + + +- (BOOL) canBecomeKeyWindow +{ + return YES; +} + +- (void)keyDown:(NSEvent *)theEvent +{ +} + +- (void)keyUp:(NSEvent *)theEvent +{ +} + + +- (BOOL)validateMenuItem:(NSMenuItem*) menuItem +{ +// SEL bleh = [menuItem action]; +// NSLog(@"Validate: %@, action: %@", menuItem, NSStringFromSelector(bleh)); + if ([menuItem action] == @selector(performClose:)) + return YES; + + return NO; + +} + +- (void) performClose: (id)sender +{ + if ([self delegate]){ + // NSLog(@"We have a delegate %@", [self delegate]); + + if ([[self delegate] windowShouldClose:sender]) + [super close]; + } + else { + // hmm, just explode I guess + [super close]; + } +} + +- (void)mouseDown:(NSEvent *)theEvent { + + // Get the mouse location in window coordinates. + initialLocation = [theEvent locationInWindow]; + +} + + + +/* + + Once the user starts dragging the mouse, move the window with it. The window has no title bar for the user to drag (so we have to implement dragging ourselves) + + */ + +- (void)mouseDragged:(NSEvent *)theEvent { + + NSRect screenVisibleFrame = [[NSScreen mainScreen] visibleFrame]; + NSRect windowFrame = [self frame]; + NSPoint newOrigin = windowFrame.origin; + + // Get the mouse location in window coordinates. + NSPoint currentLocation = [theEvent locationInWindow]; + + // Update the origin with the difference between the new mouse location and the old mouse location. + newOrigin.x += (currentLocation.x - initialLocation.x); + newOrigin.y += (currentLocation.y - initialLocation.y); + + // Don't let window get dragged up under the menu bar + if ((newOrigin.y + windowFrame.size.height) > (screenVisibleFrame.origin.y + screenVisibleFrame.size.height)) { + newOrigin.y = screenVisibleFrame.origin.y + (screenVisibleFrame.size.height - windowFrame.size.height); + } + + // Move the window to the new location + [self setFrameOrigin:newOrigin]; + +} + +@end diff --git a/macosx/plugins/PeopsXgl/macsrc/PluginWindowController.h b/macosx/plugins/PeopsXgl/macsrc/PluginWindowController.h new file mode 100644 index 00000000..8ead9fc6 --- /dev/null +++ b/macosx/plugins/PeopsXgl/macsrc/PluginWindowController.h @@ -0,0 +1,52 @@ +/*************************************************************************** + PluginWindowController.h + The big bad boy that controls/creates the game window, the openGLView, and + communicates with PCSX itself + PeopsOpenGPU + + Created by Gil Pedersen on Mon April 11 2004. + Copyright (c) 2004 Gil Pedersen. + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +/* + In truth, this controller should be the ONLY place that glues between the + running PCSX gpu and the mac interface. + ATM, some of the glue is here, some of it in drawgl.m, and a couple + of bits are in the config controller... +*/ + +#define PluginWindowController NetSfPeopsOpenGLGPUPluginWindowController + +#import <Cocoa/Cocoa.h> +#import "PluginGLView.h" + +@class PluginWindowController; + +extern NSWindow *gameWindow; +extern PluginWindowController *gameController; + +@interface PluginWindowController : NSWindowController +{ + IBOutlet NSOpenGLView *glView; + + // NSWindow *fullWindow; + bool inFullscreen; +} + ++ (id)openGameView; +- (PluginGLView *)getOpenGLView; +- (BOOL)fullscreen; +- (void)setFullscreen:(BOOL)flag; +- (void)performFullscreenSwap; +- (void)cureAllIlls; +@end diff --git a/macosx/plugins/PeopsXgl/macsrc/PluginWindowController.m b/macosx/plugins/PeopsXgl/macsrc/PluginWindowController.m new file mode 100644 index 00000000..1ff8c0ac --- /dev/null +++ b/macosx/plugins/PeopsXgl/macsrc/PluginWindowController.m @@ -0,0 +1,302 @@ +/*************************************************************************** + PluginWindowController.m + The big bad boy that controls/creates the game window, the openGLView, and + communicates with PCSX itself + + PeopsOpenGPU + + Created by Gil Pedersen on Tue April 12 2004. + Copyright (c) 2004 Gil Pedersen. + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#import "PluginWindowController.h" +#import "PluginWindow.h" +#import "Carbon/Carbon.h" +#include <OpenGL/gl.h> // OpenGL needed for "externals.h" +#include "externals.h" +#undef BOOL + +// not sure why these aren't class or instance variables... +NSWindow *gameWindow; +PluginWindowController *gameController; +NSRect windowFrame; +NSRect windowDefaultRect; // default window size (needed to go back into window mode) + +@implementation PluginWindowController + ++ (id)openGameView +{ + // create a window for the GPU and return + // the controller that controls it + + if (gameWindow == nil) { + if (gameController == nil) { + gameController = [[PluginWindowController alloc] initWithWindowNibName:@"NetSfPeopsOpenGLGPUInterface"]; + } + gameWindow = [gameController window]; + } + else { + NSLog(@"Well, we have a game window open already, which is kinda bad."); + abort(); + return nil; + } + + [gameWindow setBackgroundColor: [NSColor blackColor]]; + + windowFrame.size.width=iResX; + windowFrame.size.height=iResY; + + + if (windowFrame.size.width != 0) + [gameWindow setFrame:windowFrame display:NO]; + + [gameWindow center]; + windowDefaultRect = [gameWindow frame]; + + [gameWindow makeKeyAndOrderFront:nil]; + [gameController showWindow:nil]; + NSOpenGLView* glInstance = [gameController getOpenGLView]; + [glInstance setFrameSize: windowDefaultRect.size]; + [glInstance reshape]; +// [glView update]; + + CGDirectDisplayID display = (CGDirectDisplayID)[[[[gameWindow screen] deviceDescription] objectForKey:@"NSScreenNumber"] longValue]; + if (CGDisplayIsCaptured(display)) { + [gameController setFullscreen:YES]; + } + + return gameController; +} + +- (PluginGLView *)getOpenGLView +{ + return (PluginGLView *)glView; +} + +- (void) cureAllIlls +{ + // try to reset the GPU without discarding textures, etc. + // when a resize takes place, all hell breaks loose, so + // this is necessarily ugly. + + // all this should be in draw.c, actually + +// needed, but I don't know what it's for... + rRatioRect.left = rRatioRect.top=0; + rRatioRect.right = iResX; + rRatioRect.bottom = iResY; + + [[glView openGLContext] makeCurrentContext]; + + glFlush(); + glFinish(); + + glViewport(rRatioRect.left, // init viewport by ratio rect + iResY-(rRatioRect.top+rRatioRect.bottom), + rRatioRect.right, + rRatioRect.bottom); + + + glScissor(0, 0, iResX, iResY); // init clipping (fullscreen) + glEnable(GL_SCISSOR_TEST); + glMatrixMode(GL_PROJECTION); // init projection with psx resolution + glLoadIdentity(); + glOrtho(0,PSXDisplay.DisplayMode.x, + PSXDisplay.DisplayMode.y, 0, -1, 1); + + CreateScanLines(); +// if(bKeepRatio) SetAspectRatio(); // set ratio + glFlush(); + glFinish(); + + [NSOpenGLContext clearCurrentContext]; + + [glView reshape]; // to get rid of fuglies on screen +// GLinitialize(); // blunt instrument method of setting a proper state. + +} + +- (void)dealloc +{ + + windowFrame = [[self window] frame]; + + [super dealloc]; +} + +// forget keyDownEvents +- (void)keyDown:(NSEvent *)theEvent +{ + // Not required any more +} + +- (void)mouseDown:(NSEvent *)theEvent +{ + if ([self fullscreen]) { + [self setFullscreen:NO]; + } +} + +- (BOOL)fullscreen +{ + return inFullscreen; +} + +- (void)setFullscreen:(BOOL)flag +{ +// this is called by cocoa, not the main PSX thread. +// Messing with the opengl context is a Bad Thing. +// Therefore, just set a global flag, and +// wait around for a frame until +// gpu.c calls fullscreenswap() from +// the right thread + + if ([self fullscreen] == flag) + return; + + if (flag) + bChangeWinMode = 2; + else + bChangeWinMode = 1; + +} + +- (void)performFullscreenSwap +{ + // ah, that's better. We are called from the main PSX thread + // after a screen update, so we're clean. + // bChangeWinMode is a global set from PSX + + int flag = bChangeWinMode - 1; // 1 = go to window, 2 = go to fullscreen + bChangeWinMode = 0; // this is our flag that launched us, so 0 now + + NSWindow *window = [self window]; + NSScreen *screen = [window screen]; + + CGDirectDisplayID display = (CGDirectDisplayID)[[[screen deviceDescription] objectForKey:@"NSScreenNumber"] longValue]; + + NSRect newPlace; + + if (flag){ + [window setLevel: NSScreenSaverWindowLevel]; + newPlace = NSMakeRect(0,0,CGDisplayPixelsWide(display), CGDisplayPixelsHigh(display)); + CGDisplayHideCursor(display); + CGAssociateMouseAndMouseCursorPosition(NO); + } + else{ + [window setLevel: NSNormalWindowLevel]; + newPlace = windowDefaultRect; + CGDisplayShowCursor(display); + CGAssociateMouseAndMouseCursorPosition(YES); + } + + + int proportionalWidth, proportionalHeight; + + [window setFrame:newPlace display:true]; + + // assume square pixel ratio on the monitor + if ((newPlace.size.width*3)/4 <= newPlace.size.height) { // is window skinnier than it needs to be? + proportionalHeight = (newPlace.size.width*3)/4; // then shrink the content height (letterbox) + proportionalWidth = newPlace.size.width; // and conform to width + } else { + proportionalWidth = (newPlace.size.height*4)/3; + proportionalHeight = newPlace.size.height; + } + NSRect fitToWindow = NSMakeRect( + (newPlace.size.width - proportionalWidth)/2, + (newPlace.size.height - proportionalHeight)/2, + proportionalWidth, proportionalHeight); + + [glView setFrame:fitToWindow]; + [glView reshape]; + iResX = proportionalWidth; + iResY = proportionalHeight; + + if (flag) inFullscreen = TRUE; + else inFullscreen = FALSE; + + [self cureAllIlls]; // do some fixin' + return; + +} + +- (BOOL)windowShouldZoom:(NSWindow *)sender toFrame:(NSRect)newFrame +{ + [self setFullscreen:YES]; + + return NO; +} + +- (NSSize)windowWillResize:(NSWindow *)sender toSize:(NSSize)proposedFrameSize +{ + // we don't bother + + return proposedFrameSize; + + if (!(([sender resizeFlags] & NSShiftKeyMask) == NSShiftKeyMask)) { + NSRect oldSize = [sender frame]; + NSRect viewSize = [glView frame]; + + float xDiff = NSWidth(oldSize) - NSWidth(viewSize); + float yDiff = NSHeight(oldSize) - NSHeight(viewSize); + + //if ((proposedFrameSize.height / proposedFrameSize.width) < (3.0/4.0)) + // proposedFrameSize.height = ((proposedFrameSize.width - xDiff) * 3.0) / 4.0 + yDiff; + //else + proposedFrameSize.width = ((proposedFrameSize.height - yDiff) * 4.0) / 3.0 + xDiff; + } + + return proposedFrameSize; +} + +- (void)windowWillMiniaturize:(NSNotification *)aNotification +{ + [[NSNotificationCenter defaultCenter] postNotificationName:@"emuWindowWantPause" object:self]; +} + +- (void)windowDidDeminiaturize:(NSNotification *)aNotification +{ + [[NSNotificationCenter defaultCenter] postNotificationName:@"emuWindowWantResume" object:self]; +} + +//- (void)windowDidBecomeMain:(NSNotification *)aNotification +/*- (void)windowDidBecomeKey:(NSNotification *)aNotification +{ + if (iWindowMode==0) { + [self setFullscreen:YES]; + } +}*/ + +- (BOOL)windowShouldClose:(id)sender +{ +/* if (fullWindow) { + return NO; + } +*/ +// NSLog(@"windowShouldClose: We're closing the window"); + [[NSNotificationCenter defaultCenter] postNotificationName:@"emuWindowDidClose" object:self]; + [gameController autorelease]; + gameController = nil; + gameWindow = nil; + + return YES; +} + +@end + +void ChangeWindowMode(void) +{ + // glue from PSX thread. Globals are already set + [ gameController performFullscreenSwap]; +} diff --git a/macosx/plugins/PeopsXgl/macsrc/drawgl.m b/macosx/plugins/PeopsXgl/macsrc/drawgl.m new file mode 100644 index 00000000..91c7ecbf --- /dev/null +++ b/macosx/plugins/PeopsXgl/macsrc/drawgl.m @@ -0,0 +1,234 @@ +/*************************************************************************** + drawgl.m + an odd set of functions that seem misplaced ATM. + presumably this is the glue to the C GPU plugin stuff + but a much better place might be "PluginWindowController.m" as + gluing is what a controller is made for. + + PeopsOpenGPU + + Created by Gil Pedersen on Sun April 18 2004. + Copyright (c) 2004 Gil Pedersen. + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +#import "PluginWindowController.h" +#import "PluginGLView.h" +#include "ExtendedKeys.h" +#include "externals.h" +#include "draw.h" +#include "gpu.h" +#include "menu.h" + +//////////////////////////////////////////////////////////////////////////////////// +// misc globals +//////////////////////////////////////////////////////////////////////////////////// +#if 0 // globals for OpenGL (vs. SoftGPU) are owned by others... weird +int iResX; +int iResY; +long lLowerpart; +BOOL bIsFirstFrame = TRUE; +BOOL bCheckMask=FALSE; +unsigned short sSetMask=0; +/* unsigned long lSetMask=0; */ +uint32_t sSetMassk=0; +int iDesktopCol=16; +int iShowFPS=0; +int iWinSize; +int iUseScanLines=0; +int iUseNoStretchBlt=0; +int iFastFwd=0; +int iDebugMode=0; +int iFVDisplay=0; +PSXPoint_t ptCursorPoint[8]; +unsigned short usCursorActive=0; +char * Xpixels; +char * pCaptionText; +#endif + + +extern BOOL bCheckMask; +extern BOOL bIsFirstFrame; +extern int iShowFPS; +extern unsigned short sSetMask; +extern int iUseScanLines; +extern unsigned short usCursorActive; + + + +int iResX; +int iResY; +long lLowerpart; + +uint32_t sSetMassk=0; +int iDesktopCol=16; +int iWinSize; +int iUseNoStretchBlt=0; +int iFastFwd=0; +int iDebugMode=0; +int iFVDisplay=0; +PSXPoint_t ptCursorPoint[8]; +char * Xpixels; +char * pCaptionText; + + + + +//static PluginWindowController *windowController; +// static is BAD NEWS if user uses other plug ins +PluginGLView *glView; + +//////////////////////////////////////////////////////////////////////// + +void DoBufferSwap(void) // SWAP BUFFERS +{ +#if 1 + [glView swapBuffer]; +#else + static long long lastTickCount = -1; + static int skipCount = 0; + long long microTickCount; + long deltaTime; + + Microseconds((struct UnsignedWide *)µTickCount); + deltaTime = (long)(microTickCount - lastTickCount); + if (deltaTime <= (PSXDisplay.PAL ? 1000000/50 : 100000000 / 5994) || + skipCount >= 3) { + skipCount = 0; + [glView swapBuffer]; + } else { + skipCount++; + } + NSLog(@"count: %i", deltaTime); + lastTickCount = microTickCount; +#endif +} + + +//////////////////////////////////////////////////////////////////////// + +void DoClearScreenBuffer(void) // CLEAR DX BUFFER +{ + // clear the screen, and DON'T flush it + [glView clearBuffer:NO]; +} + + +//////////////////////////////////////////////////////////////////////// + +void DoClearFrontBuffer(void) // CLEAR DX BUFFER +{ + // clear the screen, and flush it + [glView clearBuffer:YES]; +} + +//////////////////////////////////////////////////////////////////////// + +unsigned long ulInitDisplay(void) // OPEN GAME WINDOW +{ + bUsingTWin=FALSE; + +// InitMenu(); // This function does nothing + + bIsFirstFrame = FALSE; + + if(iShowFPS) + { + //iShowFPS=0; + ulKeybits|=KEY_SHOWFPS; + szDispBuf[0]=0; + BuildDispMenu(0); + } + + PluginWindowController *windowController = [PluginWindowController openGameView]; + glView = [windowController getOpenGLView]; + + [[windowController window] setTitle:[NSString stringWithCString:pCaptionText]]; + + return (unsigned long)[windowController window]; +} + + +//////////////////////////////////////////////////////////////////////// + +void CloseDisplay(void) +{ + if (gameController) { + [gameController close]; + [gameController release]; + gameController = nil; + gameWindow = nil; + } +} + +void BringContextForward(void) +{ + [[glView openGLContext] makeCurrentContext]; +} + +void SendContextBack(void) +{ + [NSOpenGLContext clearCurrentContext]; +} + +void SetVSync(long myValue) +{ + long DoItMyFriend = myValue; + [[glView openGLContext] setValues: &DoItMyFriend forParameter: NSOpenGLCPSwapInterval]; + +} +//////////////////////////////////////////////////////////////////////// + +/* taken care of in menu.c +void CreatePic(unsigned char * pMem) +{ +} +*/ + +/////////////////////////////////////////////////////////////////////////////////////// + +/* taken care of in menu.c +void DestroyPic(void) +{ +} +*/ + +/////////////////////////////////////////////////////////////////////////////////////// +/* taken care of in menu.c +void DisplayPic(void) +{ +} +*/ + +/////////////////////////////////////////////////////////////////////////////////////// + +void ShowGpuPic(void) +{ + // this is the default implementation... +} + +/////////////////////////////////////////////////////////////////////////////////////// + +void ShowTextGpuPic(void) +{ + // this is the default implementation... +} + + +void HandleKey(int keycode) +{ + switch (keycode) { + case GPU_FULLSCREEN_KEY: + [gameController setFullscreen:![gameController fullscreen]]; + break; + } +} |
