|
|
1.1 root 1: /*
2: Hatari - PrefsController.m
3:
4: This file is distributed under the GNU Public License, version 2 or at
5: your option any later version. Read the file gpl.txt for details.
6:
7: Preferences window controller implementation file
8:
9: Feb-Mar 2006, Sébastien Molines - Created
10: */
11:
12: // TODO: Set the default paths to MacOS-friendly values
13: // TODO: Move hardcoded string to localizable resources (e.g. string "Reset the emulator?")
14:
15:
16: #import "PrefsController.h"
17: #import "Shared.h"
18:
19: #include "main.h"
20: #include "configuration.h"
21: #include "dialog.h"
22: #include "file.h"
23: #include "floppy.h"
24: #include "screen.h"
25: #include "sdlgui.h"
26:
27: // Macros to transfer data between Cocoa controls and Hatari data structures
28: #define EXPORT_TEXTFIELD(nstextfield, target) GuiOsx_ExportPathString([nstextfield stringValue], target, sizeof((target)))
29: #define EXPORT_SWITCH(nsbutton, target) target = ([(nsbutton) state] == NSOnState)
30: #define EXPORT_RADIO(nsmatrix, target) target = [[(nsmatrix) selectedCell] tag]
31: #define EXPORT_DROPDOWN(nspopupbutton, target) target = [[(nspopupbutton) selectedItem] tag]
32: #define IMPORT_TEXTFIELD(nstextfield, source) [(nstextfield) setStringValue:[[NSString stringWithCString:(source)] stringByAbbreviatingWithTildeInPath]]
33: #define IMPORT_SWITCH(nsbutton, source) [(nsbutton) setState:((source))? NSOnState : NSOffState]
34: #define IMPORT_RADIO(nsmatrix, source) [(nsmatrix) selectCellWithTag:(source)]
35: #define IMPORT_DROPDOWN(nspopupbutton, source) [(nspopupbutton) selectItemAtIndex:[(nspopupbutton) indexOfItemWithTag:(source)]]
36:
37: // Keys to be listed in the Joysticks dropdowns
38: SDLKey Preferences_KeysForJoysticks[] =
39: {
40: SDLK_BACKSPACE,
41: SDLK_TAB,
42: SDLK_CLEAR,
43: SDLK_RETURN,
44: SDLK_PAUSE,
45: SDLK_ESCAPE,
46: SDLK_SPACE,
47: SDLK_EXCLAIM,
48: SDLK_QUOTEDBL,
49: SDLK_HASH,
50: SDLK_DOLLAR,
51: SDLK_AMPERSAND,
52: SDLK_QUOTE,
53: SDLK_LEFTPAREN,
54: SDLK_RIGHTPAREN,
55: SDLK_ASTERISK,
56: SDLK_PLUS,
57: SDLK_COMMA,
58: SDLK_MINUS,
59: SDLK_PERIOD,
60: SDLK_SLASH,
61: SDLK_0,
62: SDLK_1,
63: SDLK_2,
64: SDLK_3,
65: SDLK_4,
66: SDLK_5,
67: SDLK_6,
68: SDLK_7,
69: SDLK_8,
70: SDLK_9,
71: SDLK_COLON,
72: SDLK_SEMICOLON,
73: SDLK_LESS,
74: SDLK_EQUALS,
75: SDLK_GREATER,
76: SDLK_QUESTION,
77: SDLK_AT,
78: SDLK_LEFTBRACKET,
79: SDLK_BACKSLASH,
80: SDLK_RIGHTBRACKET,
81: SDLK_CARET,
82: SDLK_UNDERSCORE,
83: SDLK_BACKQUOTE,
84: SDLK_a,
85: SDLK_b,
86: SDLK_c,
87: SDLK_d,
88: SDLK_e,
89: SDLK_f,
90: SDLK_g,
91: SDLK_h,
92: SDLK_i,
93: SDLK_j,
94: SDLK_k,
95: SDLK_l,
96: SDLK_m,
97: SDLK_n,
98: SDLK_o,
99: SDLK_p,
100: SDLK_q,
101: SDLK_r,
102: SDLK_s,
103: SDLK_t,
104: SDLK_u,
105: SDLK_v,
106: SDLK_w,
107: SDLK_x,
108: SDLK_y,
109: SDLK_z,
110: SDLK_DELETE,
111: SDLK_KP0,
112: SDLK_KP1,
113: SDLK_KP2,
114: SDLK_KP3,
115: SDLK_KP4,
116: SDLK_KP5,
117: SDLK_KP6,
118: SDLK_KP7,
119: SDLK_KP8,
120: SDLK_KP9,
121: SDLK_KP_PERIOD,
122: SDLK_KP_DIVIDE,
123: SDLK_KP_MULTIPLY,
124: SDLK_KP_MINUS,
125: SDLK_KP_PLUS,
126: SDLK_KP_ENTER,
127: SDLK_KP_EQUALS,
128: SDLK_UP,
129: SDLK_DOWN,
130: SDLK_RIGHT,
131: SDLK_LEFT,
132: SDLK_INSERT,
133: SDLK_HOME,
134: SDLK_END,
135: SDLK_PAGEUP,
136: SDLK_PAGEDOWN,
137: SDLK_F1,
138: SDLK_F2,
139: SDLK_F3,
140: SDLK_F4,
141: SDLK_F5,
142: SDLK_F6,
143: SDLK_F7,
144: SDLK_F8,
145: SDLK_F9,
146: SDLK_F10,
147: SDLK_F11,
148: SDLK_F12,
149: SDLK_F13,
150: SDLK_F14,
151: SDLK_F15,
152: SDLK_NUMLOCK,
153: SDLK_CAPSLOCK,
154: SDLK_SCROLLOCK,
155: SDLK_RSHIFT,
156: SDLK_LSHIFT,
157: SDLK_RCTRL,
158: SDLK_LCTRL,
159: SDLK_RALT,
160: SDLK_LALT,
161: SDLK_RMETA,
162: SDLK_LMETA,
163: SDLK_LSUPER,
164: SDLK_RSUPER,
165: SDLK_MODE,
166: SDLK_COMPOSE,
167: SDLK_HELP,
168: SDLK_PRINT,
169: SDLK_SYSREQ,
170: SDLK_BREAK,
171: SDLK_MENU,
172: SDLK_POWER,
173: SDLK_EURO,
174: SDLK_UNDO
175: };
176:
177: size_t Preferences_cKeysForJoysticks = sizeof(Preferences_KeysForJoysticks) / sizeof(Preferences_KeysForJoysticks[0]);
178:
179:
180: @implementation PrefsController
181:
182:
183: /*-----------------------------------------------------------------------*/
184: /*
185: Helper method for Choose buttons
186: Returns: TRUE is the user selected a path, FALSE if he/she aborted
187: */
188: - (BOOL)choosePathForControl:(NSTextField*)textField chooseDirectories:(bool)chooseDirectories defaultInitialDir:(NSString*)defaultInitialDir
189: {
190: // Create and configure an OpenPanel
191: NSOpenPanel *openPanel = [NSOpenPanel openPanel];
192: [openPanel setCanChooseDirectories: chooseDirectories];
193: [openPanel setCanChooseFiles: !chooseDirectories];
194:
195: NSString *directoryToOpen;
196: NSString *fileToPreselect;
197: NSString *oldPath = [textField stringValue];
198: if ((oldPath != nil) && ([oldPath length] > 0))
199: {
200: // There is existing path: we will open its directory with its file pre-selected.
201: directoryToOpen = [oldPath stringByDeletingLastPathComponent];
202: fileToPreselect = [oldPath lastPathComponent];
203: }
204: else
205: {
206: // Currently no path: we will open the user's directory with no file selected.
207: directoryToOpen = [defaultInitialDir stringByExpandingTildeInPath];
208: fileToPreselect = nil;
209: }
210:
211: // Run the OpenPanel, then check if the user clicked OK and selected at least one file
212: if ( (NSOKButton == [openPanel runModalForDirectory:directoryToOpen file:fileToPreselect types:nil] )
213: && ([[openPanel filenames] count] > 0) )
214: {
215: // Get the path to the selected file
216: NSString *path = [[openPanel filenames] objectAtIndex:0];
217:
218: // Set the control to it (abbreviated if possible)
219: [textField setStringValue:[path stringByAbbreviatingWithTildeInPath]];
220:
221: // Signal completion
222: return TRUE;
223: }
224:
225: // Signal that the selection was aborted
226: return FALSE;
227: }
228:
229:
230: /*-----------------------------------------------------------------------*/
231: /*
232: Helper method to insert a floppy image
233: TODO: Add code to restrict to known file types
234: */
235: - (void)insertFloppyImageIntoDrive:(int)drive forTextField:(NSTextField*)floppyTextField
236: {
237: if ([self choosePathForControl:floppyTextField chooseDirectories:FALSE defaultInitialDir:[defaultImagesLocation stringValue]])
238: {
239: // Get the full path to the selected file
240: NSString *path = [[floppyTextField stringValue] stringByExpandingTildeInPath];
241:
242: // Make a non-const C string out of it
243: const char* constSzPath = [path cString];
244: size_t cbPath = strlen(constSzPath) + 1;
245: char szPath[cbPath];
246: strncpy(szPath, constSzPath, cbPath);
247:
248: // Insert the floppy image at this path
249: Floppy_InsertDiskIntoDrive(drive, szPath);
250: }
251: }
252:
253:
254: /*-----------------------------------------------------------------------*/
255: /*
256: Helper function to convert display bits to a display mode number
257: */
258: int DisplayModeFromFlags(BOOL zoomSTLowRes, BOOL force8bpp)
259: {
260: if (zoomSTLowRes)
261: {
262: return (force8bpp)? DISPLAYMODE_LOWCOL_HIGHRES : DISPLAYMODE_HICOL_HIGHRES;
263: }
264: else
265: {
266: return (force8bpp)? DISPLAYMODE_LOWCOL_LOWRES : DISPLAYMODE_HICOL_LOWRES;
267: }
268: }
269:
270:
271: /*-----------------------------------------------------------------------*/
272: /*
273: Helper function to convert a display mode number to display bits
274: */
275: void DisplayModeToFlags(int chosenDisplayMode, BOOL *pZoomSTLowRes, BOOL *pForce8bpp)
276: {
277: *pZoomSTLowRes = ( (chosenDisplayMode == DISPLAYMODE_LOWCOL_HIGHRES)
278: ||(chosenDisplayMode == DISPLAYMODE_HICOL_HIGHRES) );
279:
280: *pForce8bpp = ( (chosenDisplayMode == DISPLAYMODE_LOWCOL_LOWRES)
281: ||(chosenDisplayMode == DISPLAYMODE_LOWCOL_HIGHRES) );
282: }
283:
284:
285: /*-----------------------------------------------------------------------*/
286: /*
287: Methods for all the "Choose" buttons
288: */
289: - (IBAction)chooseCartridgeImage:(id)sender;
290: {
291: [self choosePathForControl: cartridgeImage chooseDirectories:FALSE defaultInitialDir:@"~"];
292: }
293:
294: - (IBAction)chooseDefaultImagesLocation:(id)sender
295: {
296: [self choosePathForControl: defaultImagesLocation chooseDirectories:TRUE defaultInitialDir:@"~"];
297: }
298:
299: - (IBAction)chooseFloppyImageA:(id)sender
300: {
301: [self insertFloppyImageIntoDrive:0 forTextField: floppyImageA];
302: }
303:
304: - (IBAction)chooseFloppyImageB:(id)sender
305: {
306: [self insertFloppyImageIntoDrive:1 forTextField: floppyImageB];
307: }
308:
309: - (IBAction)chooseGemdosImage:(id)sender
310: {
311: [self choosePathForControl: gemdosImage chooseDirectories:TRUE defaultInitialDir:@"~"];
312: }
313:
314: - (IBAction)chooseHdImage:(id)sender
315: {
316: [self choosePathForControl: hdImage chooseDirectories:FALSE defaultInitialDir:@"~"];
317: }
318:
319: - (IBAction)chooseKeyboardMappingFile:(id)sender
320: {
321: [self choosePathForControl: keyboardMappingFile chooseDirectories:FALSE defaultInitialDir:@"~"];
322: }
323:
324: - (IBAction)chooseMidiOutputFile:(id)sender
325: {
326: [self choosePathForControl: writeMidiToFile chooseDirectories:FALSE defaultInitialDir:@"~"];
327: }
328:
329: - (IBAction)choosePrintToFile:(id)sender
330: {
331: [self choosePathForControl: printToFile chooseDirectories:FALSE defaultInitialDir:@"~"];
332: }
333:
334: - (IBAction)chooseRS232InputFile:(id)sender
335: {
336: [self choosePathForControl: readRS232FromFile chooseDirectories:FALSE defaultInitialDir:@"~"];
337: }
338:
339: - (IBAction)chooseRS232OutputFile:(id)sender
340: {
341: [self choosePathForControl: writeRS232ToFile chooseDirectories:FALSE defaultInitialDir:@"~"];
342: }
343:
344: - (IBAction)chooseTosImage:(id)sender;
345: {
346: [self choosePathForControl: tosImage chooseDirectories:FALSE defaultInitialDir:@"~"];
347: }
348:
349:
350: /*-----------------------------------------------------------------------*/
351: /*
352: Methods for the "Eject" buttons
353: */
354: - (IBAction)ejectFloppyA:(id)sender
355: {
356: Floppy_EjectDiskFromDrive(0, FALSE);
357:
358: // Refresh the control
359: [floppyImageA setStringValue:@""];
360: }
361:
362: - (IBAction)ejectFloppyB:(id)sender
363: {
364: Floppy_EjectDiskFromDrive(1, FALSE);
365:
366: // Refresh the control
367: [floppyImageB setStringValue:@""];
368: }
369:
370: - (IBAction)ejectGemdosImage:(id)sender
371: {
372: // Clear the control. Later. saveAllControls will set the DialogParams accordingly to signal this is ejected
373: [gemdosImage setStringValue:@""];
374: }
375:
376: - (IBAction)ejectHdImage:(id)sender
377: {
378: // Clear the control. Later. saveAllControls will set the DialogParams accordingly to signal this is ejected
379: [hdImage setStringValue:@""];
380: }
381:
382:
383: /*-----------------------------------------------------------------------*/
384: /*
385: Methods for the "Load Config" and "Save Config" buttons
386: */
387: - (IBAction)loadConfig:(id)sender
388: {
389: // Load the config into DialogParams
390: Dialog_LoadParams();
391:
392: // Refresh all the controls to match DialogParams
393: [self setAllControls];
394: }
395:
396: - (IBAction)saveConfig:(id)sender
397: {
398: // Update the DialogParams from the controls
399: [self saveAllControls];
400:
401: // Save the DialogParams to the config file
402: Dialog_SaveParams();
403: }
404:
405:
406: /*-----------------------------------------------------------------------*/
407: /*
408: Commits and closes
409: */
410: - (IBAction)commitAndClose:(id)sender
411: {
412: BOOL applyChanges = TRUE;
413:
414: // The user clicked OK
415: [self saveAllControls];
416:
417: // If a reset is required, ask the user first
418: if (Dialog_DoNeedReset())
419: {
420: applyChanges = ( 0 == NSRunAlertPanel (@"Reset the emulator?",
421: @"The emulator must be reset in order to apply your changes.\nAll current work will be lost.",
422: @"Don't reset", @"Reset", nil) );
423: }
424:
425: // Commit the new configuration
426: if (applyChanges)
427: {
428: Dialog_CopyDialogParamsToConfiguration(FALSE);
429: }
430:
431: // Close the window
432: [window close];
433: }
434:
435: - (void)initKeysDropDown:(NSPopUpButton*)dropDown
436: {
437: [dropDown removeAllItems];
438: int i;
439: for (i = 0; i < Preferences_cKeysForJoysticks; i++)
440: {
441: SDLKey key = Preferences_KeysForJoysticks[i];
442: const char* szKeyName = SDL_GetKeyName(key);
443: [dropDown addItemWithTitle:[[NSString stringWithCString:szKeyName] capitalizedString]];
444: [[dropDown lastItem] setTag:key];
445: }
446: }
447:
448:
449: /*-----------------------------------------------------------------------*/
450: /*
451: Displays the Preferences dialog
452: */
453: - (IBAction)loadPrefs:(id)sender
454: {
455: if (!bInitialized)
456: {
457: // Note: These inits cannot be done in awakeFromNib as by this time SDL is not yet initialized.
458:
459: // Fill the keyboard dropdowns
460: [self initKeysDropDown:joystickUp];
461: [self initKeysDropDown:joystickRight];
462: [self initKeysDropDown:joystickDown];
463: [self initKeysDropDown:joystickLeft];
464: [self initKeysDropDown:joystickFire];
465:
466: // Get and store the number of real joysticks
467: cRealJoysticks = SDL_NumJoysticks();
468:
469: // Fill the real joysticks dropdown, if any are available
470: if (cRealJoysticks > 0)
471: {
472: [realJoystick removeAllItems];
473: int i;
474: for (i = 0; i < cRealJoysticks; i++)
475: {
476: const char* szJoystickName = SDL_JoystickName(i);
477: [realJoystick addItemWithTitle:[[NSString stringWithCString:szJoystickName] capitalizedString]];
478: [[realJoystick lastItem] setTag:i];
479: }
480: }
481: else // No real joysticks: Disable the controls
482: {
483: [[joystickMode cellWithTag:1] setEnabled:FALSE];
484: [realJoystick setEnabled:FALSE];
485: }
486:
487: bInitialized = TRUE;
488: }
489:
490:
491: // Copy configuration settings to DialogParams (which we will only commit back to the configuration settings if choosing OK)
492: DialogParams = ConfigureParams;
493:
494: [self setAllControls];
495:
496: // Display the window
497: [[ModalWrapper alloc] runModal:window];
498: }
499:
500:
501: /*-----------------------------------------------------------------------*/
502: /*
503: Updates the controls following a change in the joystick selection
504: */
505: - (IBAction)changeViewedJoystick:(id)sender
506: {
507: // Save the pre-joystick controls, as we are about to change them
508: [self saveJoystickControls];
509:
510: // Refresh the per-joystick controls
511: [self setJoystickControls];
512:
513: // Update the controls' enabled states
514: [self updateEnabledStates:self];
515: }
516:
517:
518: /*-----------------------------------------------------------------------*/
519: /*
520: Initializes all controls
521: */
522: - (void)setAllControls
523: {
524: // Get the display mode flags
525: BOOL bZoomSTLowRes, bForce8bpp;
526: DisplayModeToFlags(DialogParams.Screen.ChosenDisplayMode, &bZoomSTLowRes, &bForce8bpp);
527:
528: // Import the floppy paths into their controls.
529: // Note: Floppy images are exposed in the prefs dialog, however they aren't stored with the prefs and won't need to be saved on exit.
530: IMPORT_TEXTFIELD(floppyImageA, EmulationDrives[0].szFileName);
531: IMPORT_TEXTFIELD(floppyImageB, EmulationDrives[1].szFileName);
532:
533: // Import all the preferences into their controls
534: IMPORT_SWITCH(autoInsertB, DialogParams.DiskImage.bAutoInsertDiskB);
535: IMPORT_SWITCH(blitter, DialogParams.System.bBlitter);
536: IMPORT_SWITCH(bootFromHD, DialogParams.HardDisk.bBootFromHardDisk);
537: IMPORT_SWITCH(captureOnChange, DialogParams.Screen.bCaptureChange);
538: IMPORT_TEXTFIELD(cartridgeImage, DialogParams.Rom.szCartridgeImageFileName);
539: IMPORT_RADIO(colorDepth, DialogParams.Screen.nVdiColors);
540: IMPORT_SWITCH(compatibleCpu, DialogParams.System.bCompatibleCpu);
541: IMPORT_RADIO(cpuClock, DialogParams.System.nCpuFreq);
542: IMPORT_RADIO(cpuType, DialogParams.System.nCpuLevel);
543: IMPORT_TEXTFIELD(defaultImagesLocation, DialogParams.DiskImage.szDiskImageDirectory);
544: IMPORT_SWITCH(enableMidi, DialogParams.Midi.bEnableMidi);
545: IMPORT_SWITCH(enablePrinter, DialogParams.Printer.bEnablePrinting);
546: IMPORT_SWITCH(enableRS232, DialogParams.RS232.bEnableRS232);
547: IMPORT_SWITCH(enableSound, DialogParams.Sound.bEnableSound);
548: IMPORT_SWITCH(force8bpp, bForce8bpp);
549: IMPORT_SWITCH(frameSkip, DialogParams.Screen.bFrameSkip);
550: IMPORT_SWITCH(interleaved, DialogParams.Screen.bInterleavedScreen);
551: IMPORT_RADIO(keyboardMapping, DialogParams.Keyboard.nKeymapType);
552: IMPORT_TEXTFIELD(keyboardMappingFile, DialogParams.Keyboard.szMappingFileName);
553: IMPORT_RADIO(machineType, DialogParams.System.nMachineType);
554: IMPORT_RADIO(monitor, DialogParams.Screen.bUseHighRes);
555: IMPORT_SWITCH(patchTimerD, DialogParams.System.bPatchTimerD);
556: IMPORT_RADIO(playbackQuality, DialogParams.Sound.nPlaybackQuality);
557: IMPORT_TEXTFIELD(printToFile, DialogParams.Printer.szPrintToFileName);
558: IMPORT_RADIO(ramSize, DialogParams.Memory.nMemorySize);
559: IMPORT_TEXTFIELD(readRS232FromFile, DialogParams.RS232.szInFileName);
560: IMPORT_SWITCH(realTime, DialogParams.System.bRealTimeClock);
561: IMPORT_RADIO(resolution, DialogParams.Screen.nVdiResolution);
562: IMPORT_SWITCH(slowFDC, DialogParams.System.bSlowFDC);
563: IMPORT_TEXTFIELD(tosImage, DialogParams.Rom.szTosImageFileName);
564: IMPORT_SWITCH(useBorders, DialogParams.Screen.bAllowOverscan);
565: IMPORT_SWITCH(useVDIResolution, DialogParams.Screen.bUseExtVdiResolutions);
566: IMPORT_TEXTFIELD(writeMidiToFile, DialogParams.Midi.szMidiOutFileName);
567: IMPORT_RADIO(writeProtection, DialogParams.DiskImage.nWriteProtection);
568: IMPORT_TEXTFIELD(writeRS232ToFile, DialogParams.RS232.szOutFileName);
569: IMPORT_SWITCH(zoomSTLowRes, bZoomSTLowRes);
570:
571: // If the HD flag is set, load the HD path, otherwise make it blank
572: if (DialogParams.HardDisk.bUseHardDiskImage)
573: {
574: IMPORT_TEXTFIELD(hdImage, DialogParams.HardDisk.szHardDiskImage);
575: }
576: else
577: {
578: [hdImage setStringValue:@""];
579: }
580:
581: // If the Gemdos flag is set, load the Gemdos path, otherwise make it blank
582: if (DialogParams.HardDisk.bUseHardDiskDirectories)
583: {
584: IMPORT_TEXTFIELD(gemdosImage, DialogParams.HardDisk.szHardDiskDirectories[0]);
585: }
586: else
587: {
588: [gemdosImage setStringValue:@""];
589: }
590:
591: // Set the per-joystick controls
592: [self setJoystickControls];
593:
594: // Update the controls' enabled states
595: [self updateEnabledStates:self];
596: }
597:
598:
599: /*-----------------------------------------------------------------------*/
600: /*
601: Updates the enabled states of controls who depend on other controls
602: */
603: - (IBAction)updateEnabledStates:(id)sender
604: {
605: // Joystick key controls are only enabled if "Use keyboard" is selected
606: int nJoystickMode;
607: EXPORT_RADIO(joystickMode, nJoystickMode);
608: BOOL bUsingKeyboard = (nJoystickMode == JOYSTICK_KEYBOARD);
609: [joystickUp setEnabled:bUsingKeyboard];
610: [joystickRight setEnabled:bUsingKeyboard];
611: [joystickDown setEnabled:bUsingKeyboard];
612: [joystickLeft setEnabled:bUsingKeyboard];
613: [joystickFire setEnabled:bUsingKeyboard];
614:
615: // Resolution and colour depth depend on Extended GEM VDI resolution
616: BOOL bUsingVDI;
617: EXPORT_SWITCH(useVDIResolution, bUsingVDI);
618: [resolution setEnabled:bUsingVDI];
619: [colorDepth setEnabled:bUsingVDI];
620:
621: // Playback quality depends on enable sound
622: BOOL bSoundEnabled;
623: EXPORT_SWITCH(enableSound, bSoundEnabled);
624: [playbackQuality setEnabled:bSoundEnabled];
625: }
626:
627:
628: /*-----------------------------------------------------------------------*/
629: /*
630: Updates the joystick controls to match the new joystick selection
631: */
632: - (void)setJoystickControls
633: {
634: // Get and persist the ID of the newly selected joystick
635: EXPORT_DROPDOWN(currentJoystick, nCurrentJoystick);
636:
637: // Data validation: If the JoyID is out of bounds, correct it and, if set to use real joystick, change to disabled
638: if ( (DialogParams.Joysticks.Joy[nCurrentJoystick].nJoyId < 0)
639: || (DialogParams.Joysticks.Joy[nCurrentJoystick].nJoyId >= cRealJoysticks) )
640: {
641: DialogParams.Joysticks.Joy[nCurrentJoystick].nJoyId = 0;
642: if (DialogParams.Joysticks.Joy[nCurrentJoystick].nJoystickMode == JOYSTICK_REALSTICK)
643: {
644: DialogParams.Joysticks.Joy[nCurrentJoystick].nJoystickMode = JOYSTICK_DISABLED;
645: }
646: }
647:
648: // Don't change the realJoystick dropdown if none is available (to keep "(None available)" selected)
649: if (cRealJoysticks > 0)
650: {
651: IMPORT_DROPDOWN(realJoystick, DialogParams.Joysticks.Joy[nCurrentJoystick].nJoyId);
652: }
653:
654: IMPORT_RADIO(joystickMode, DialogParams.Joysticks.Joy[nCurrentJoystick].nJoystickMode);
655: IMPORT_DROPDOWN(joystickUp, DialogParams.Joysticks.Joy[nCurrentJoystick].nKeyCodeUp);
656: IMPORT_DROPDOWN(joystickRight, DialogParams.Joysticks.Joy[nCurrentJoystick].nKeyCodeRight);
657: IMPORT_DROPDOWN(joystickDown, DialogParams.Joysticks.Joy[nCurrentJoystick].nKeyCodeDown);
658: IMPORT_DROPDOWN(joystickLeft, DialogParams.Joysticks.Joy[nCurrentJoystick].nKeyCodeLeft);
659: IMPORT_DROPDOWN(joystickFire, DialogParams.Joysticks.Joy[nCurrentJoystick].nKeyCodeFire);
660: IMPORT_SWITCH(enableAutoFire, DialogParams.Joysticks.Joy[nCurrentJoystick].bEnableAutoFire);
661: }
662:
663:
664: /*-----------------------------------------------------------------------*/
665: /*
666: Saves the setting for the joystick currently being viewed
667: */
668: - (void)saveJoystickControls
669: {
670: EXPORT_RADIO(joystickMode, DialogParams.Joysticks.Joy[nCurrentJoystick].nJoystickMode);
671: EXPORT_DROPDOWN(realJoystick, DialogParams.Joysticks.Joy[nCurrentJoystick].nJoyId);
672: EXPORT_DROPDOWN(joystickUp, DialogParams.Joysticks.Joy[nCurrentJoystick].nKeyCodeUp);
673: EXPORT_DROPDOWN(joystickRight, DialogParams.Joysticks.Joy[nCurrentJoystick].nKeyCodeRight);
674: EXPORT_DROPDOWN(joystickDown, DialogParams.Joysticks.Joy[nCurrentJoystick].nKeyCodeDown);
675: EXPORT_DROPDOWN(joystickLeft, DialogParams.Joysticks.Joy[nCurrentJoystick].nKeyCodeLeft);
676: EXPORT_DROPDOWN(joystickFire, DialogParams.Joysticks.Joy[nCurrentJoystick].nKeyCodeFire);
677: EXPORT_SWITCH(enableAutoFire, DialogParams.Joysticks.Joy[nCurrentJoystick].bEnableAutoFire);
678: }
679:
680:
681: /*-----------------------------------------------------------------------*/
682: /*
683: Saves the settings for all controls
684: */
685: - (void)saveAllControls
686: {
687: BOOL bZoomSTLowRes, bForce8bpp;
688:
689: // Export the preference controls into their vars
690: EXPORT_SWITCH(autoInsertB, DialogParams.DiskImage.bAutoInsertDiskB);
691: EXPORT_SWITCH(blitter, DialogParams.System.bBlitter);
692: EXPORT_SWITCH(bootFromHD, DialogParams.HardDisk.bBootFromHardDisk);
693: EXPORT_SWITCH(captureOnChange, DialogParams.Screen.bCaptureChange);
694: EXPORT_TEXTFIELD(cartridgeImage, DialogParams.Rom.szCartridgeImageFileName);
695: EXPORT_RADIO(colorDepth, DialogParams.Screen.nVdiColors);
696: EXPORT_SWITCH(compatibleCpu, DialogParams.System.bCompatibleCpu);
697: EXPORT_RADIO(cpuClock, DialogParams.System.nCpuFreq);
698: EXPORT_RADIO(cpuType, DialogParams.System.nCpuLevel);
699: EXPORT_TEXTFIELD(defaultImagesLocation, DialogParams.DiskImage.szDiskImageDirectory);
700: EXPORT_SWITCH(enableMidi, DialogParams.Midi.bEnableMidi);
701: EXPORT_SWITCH(enablePrinter, DialogParams.Printer.bEnablePrinting);
702: EXPORT_SWITCH(enableRS232, DialogParams.RS232.bEnableRS232);
703: EXPORT_SWITCH(enableSound, DialogParams.Sound.bEnableSound);
704: EXPORT_SWITCH(force8bpp, bForce8bpp);
705: EXPORT_SWITCH(frameSkip, DialogParams.Screen.bFrameSkip);
706: EXPORT_SWITCH(interleaved, DialogParams.Screen.bInterleavedScreen);
707: EXPORT_RADIO(keyboardMapping, DialogParams.Keyboard.nKeymapType);
708: EXPORT_TEXTFIELD(keyboardMappingFile, DialogParams.Keyboard.szMappingFileName);
709: EXPORT_RADIO(machineType, DialogParams.System.nMachineType);
710: EXPORT_RADIO(monitor, DialogParams.Screen.bUseHighRes);
711: EXPORT_SWITCH(patchTimerD, DialogParams.System.bPatchTimerD);
712: EXPORT_RADIO(playbackQuality, DialogParams.Sound.nPlaybackQuality);
713: EXPORT_TEXTFIELD(printToFile, DialogParams.Printer.szPrintToFileName);
714: EXPORT_RADIO(ramSize, DialogParams.Memory.nMemorySize);
715: EXPORT_TEXTFIELD(readRS232FromFile, DialogParams.RS232.szInFileName);
716: EXPORT_SWITCH(realTime, DialogParams.System.bRealTimeClock);
717: EXPORT_RADIO(resolution, DialogParams.Screen.nVdiResolution);
718: EXPORT_SWITCH(slowFDC, DialogParams.System.bSlowFDC);
719: EXPORT_TEXTFIELD(tosImage, DialogParams.Rom.szTosImageFileName);
720: EXPORT_SWITCH(useBorders, DialogParams.Screen.bAllowOverscan);
721: EXPORT_SWITCH(useVDIResolution, DialogParams.Screen.bUseExtVdiResolutions);
722: EXPORT_TEXTFIELD(writeMidiToFile, DialogParams.Midi.szMidiOutFileName);
723: EXPORT_RADIO(writeProtection, DialogParams.DiskImage.nWriteProtection);
724: EXPORT_TEXTFIELD(writeRS232ToFile, DialogParams.RS232.szOutFileName);
725: EXPORT_SWITCH(zoomSTLowRes, bZoomSTLowRes);
726:
727: // Set the display mode based on the display flags
728: DialogParams.Screen.ChosenDisplayMode = DisplayModeFromFlags(bZoomSTLowRes, bForce8bpp);
729:
730: // Define the HD flag, and export the HD path if one is selected
731: if ([[hdImage stringValue] length] > 0)
732: {
733: EXPORT_TEXTFIELD(hdImage, DialogParams.HardDisk.szHardDiskImage);
734: DialogParams.HardDisk.bUseHardDiskImage = TRUE;
735: }
736: else
737: {
738: DialogParams.HardDisk.bUseHardDiskImage = FALSE;
739: }
740:
741: // Define the Gemdos flag, and export the Gemdos path if one is selected
742: if ([[gemdosImage stringValue] length] > 0)
743: {
744: EXPORT_TEXTFIELD(gemdosImage, DialogParams.HardDisk.szHardDiskDirectories[0]);
745: DialogParams.HardDisk.bUseHardDiskDirectories = TRUE;
746: }
747: else
748: {
749: DialogParams.HardDisk.bUseHardDiskDirectories = FALSE;
750: }
751:
752: // Save the per-joystick controls
753: [self saveJoystickControls];
754: }
755:
756: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.