|
|
1.1 root 1: /*
2: Hatari - change.c
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: This code handles run-time configuration changes. We keep all our
8: configuration details in a structure called 'ConfigureParams'. Before
9: doing he changes, a backup copy is done of this structure. When
10: the changes are done, these are compared to see whether emulator
1.1.1.2 root 11: needs to be rebooted
1.1 root 12: */
1.1.1.2 root 13: const char Change_fileid[] = "Hatari change.c : " __DATE__ " " __TIME__;
1.1 root 14:
15: #include <ctype.h>
16: #include "main.h"
17: #include "configuration.h"
18: #include "audio.h"
19: #include "change.h"
20: #include "dialog.h"
21: #include "floppy.h"
22: #include "gemdos.h"
23: #include "hdc.h"
1.1.1.3 root 24: #include "ide.h"
1.1 root 25: #include "ioMem.h"
26: #include "joy.h"
27: #include "keymap.h"
28: #include "m68000.h"
1.1.1.2 root 29: #include "midi.h"
1.1 root 30: #include "options.h"
31: #include "printer.h"
32: #include "reset.h"
33: #include "rs232.h"
34: #include "screen.h"
35: #include "sound.h"
36: #include "statusbar.h"
37: #include "tos.h"
38: #include "vdi.h"
39: #include "video.h"
40: #include "hatari-glue.h"
41: #if ENABLE_DSP_EMU
42: # include "falcon/dsp.h"
43: #endif
44:
1.1.1.5 root 45: #define DEBUG 0
46: #if DEBUG
47: #define Dprintf(a) printf(a)
48: #else
49: #define Dprintf(a)
50: #endif
1.1 root 51:
52: /*-----------------------------------------------------------------------*/
53: /**
54: * Check if user needs to be warned that changes will take place after reset.
1.1.1.3 root 55: * Return true if wants to reset.
1.1 root 56: */
57: bool Change_DoNeedReset(CNF_PARAMS *current, CNF_PARAMS *changed)
58: {
59: /* Did we change monitor type? If so, must reset */
60: if (current->Screen.nMonitorType != changed->Screen.nMonitorType
61: && (changed->System.nMachineType == MACHINE_FALCON
62: || current->Screen.nMonitorType == MONITOR_TYPE_MONO
63: || changed->Screen.nMonitorType == MONITOR_TYPE_MONO))
1.1.1.3 root 64: return true;
1.1 root 65:
66: /* Did change to GEM VDI display? */
67: if (current->Screen.bUseExtVdiResolutions != changed->Screen.bUseExtVdiResolutions)
1.1.1.3 root 68: return true;
1.1 root 69:
70: /* Did change GEM resolution or color depth? */
71: if (changed->Screen.bUseExtVdiResolutions &&
72: (current->Screen.nVdiWidth != changed->Screen.nVdiWidth
73: || current->Screen.nVdiHeight != changed->Screen.nVdiHeight
74: || current->Screen.nVdiColors != changed->Screen.nVdiColors))
1.1.1.3 root 75: return true;
1.1 root 76:
77: /* Did change TOS ROM image? */
78: if (strcmp(changed->Rom.szTosImageFileName, current->Rom.szTosImageFileName))
1.1.1.3 root 79: return true;
1.1 root 80:
1.1.1.3 root 81: /* Did change ACSI hard disk image? */
1.1 root 82: if (changed->HardDisk.bUseHardDiskImage != current->HardDisk.bUseHardDiskImage
83: || (strcmp(changed->HardDisk.szHardDiskImage, current->HardDisk.szHardDiskImage)
84: && changed->HardDisk.bUseHardDiskImage))
1.1.1.3 root 85: return true;
86:
1.1.1.4 root 87: /* Did change IDE master hard disk image? */
88: if (changed->HardDisk.bUseIdeMasterHardDiskImage != current->HardDisk.bUseIdeMasterHardDiskImage
89: || strcmp(changed->HardDisk.szIdeMasterHardDiskImage, current->HardDisk.szIdeMasterHardDiskImage))
90: return true;
91:
92: /* Did change IDE slave hard disk image? */
93: if (changed->HardDisk.bUseIdeSlaveHardDiskImage != current->HardDisk.bUseIdeSlaveHardDiskImage
94: || strcmp(changed->HardDisk.szIdeSlaveHardDiskImage, current->HardDisk.szIdeSlaveHardDiskImage))
1.1.1.3 root 95: return true;
1.1 root 96:
97: /* Did change GEMDOS drive? */
98: if (changed->HardDisk.bUseHardDiskDirectories != current->HardDisk.bUseHardDiskDirectories
99: || (strcmp(changed->HardDisk.szHardDiskDirectories[0], current->HardDisk.szHardDiskDirectories[0])
100: && changed->HardDisk.bUseHardDiskDirectories))
1.1.1.3 root 101: return true;
1.1 root 102:
103: /* Did change machine type? */
104: if (changed->System.nMachineType != current->System.nMachineType)
1.1.1.3 root 105: return true;
1.1 root 106:
1.1.1.5 root 107: #if ENABLE_DSP_EMU
108: /* enabling DSP needs reset (disabling it not) */
109: if (current->System.nDSPType != DSP_TYPE_EMU &&
110: changed->System.nDSPType == DSP_TYPE_EMU)
111: {
112: return true;
113: }
114: #endif
115:
116: #if ENABLE_WINUAE_CPU
1.1.1.6 root 117: /* Did change CPU address mode? */
118: if (changed->System.bAddressSpace24 != current->System.bAddressSpace24)
119: return true;
120:
1.1.1.5 root 121: /* Did change CPU prefetch mode? */
122: if (changed->System.bCompatibleCpu != current->System.bCompatibleCpu)
123: return true;
124:
125: /* Did change CPU cycle exact? */
126: if (changed->System.bCycleExactCpu != current->System.bCycleExactCpu)
127: return true;
128:
129: /* Did change MMU? */
130: if (changed->System.bMMU != current->System.bMMU)
131: return true;
1.1.1.7 ! root 132:
! 133: /* Did change FPU? */
! 134: if (changed->System.n_FPUType != current->System.n_FPUType)
! 135: return true;
1.1.1.5 root 136: #endif
137:
1.1 root 138: /* Did change size of memory? */
139: if (current->Memory.nMemorySize != changed->Memory.nMemorySize)
1.1.1.3 root 140: return true;
1.1 root 141:
1.1.1.3 root 142: return false;
1.1 root 143: }
144:
145:
146: /*-----------------------------------------------------------------------*/
147: /**
148: * Copy details back to configuration and perform reset.
149: */
150: void Change_CopyChangedParamsToConfiguration(CNF_PARAMS *current, CNF_PARAMS *changed, bool bForceReset)
151: {
152: bool NeedReset;
1.1.1.3 root 153: bool bReInitGemdosDrive = false;
154: bool bReInitAcsiEmu = false;
155: bool bReInitIDEEmu = false;
156: bool bReInitIoMem = false;
157: bool bScreenModeChange = false;
158: bool bReInitMidi = false;
1.1.1.7 ! root 159: bool bReInitPrinter = false;
1.1 root 160: bool bFloppyInsert[MAX_FLOPPYDRIVES];
161: int i;
162:
1.1.1.5 root 163: Dprintf("Changes for:\n");
1.1 root 164: /* Do we need to warn user that changes will only take effect after reset? */
165: if (bForceReset)
166: NeedReset = bForceReset;
167: else
168: NeedReset = Change_DoNeedReset(current, changed);
169:
170: /* Do need to change resolution? Need if change display/overscan settings
171: * (if switch between Colour/Mono cause reset later) or toggle statusbar
172: */
173: if (!NeedReset &&
174: (changed->Screen.nForceBpp != current->Screen.nForceBpp
1.1.1.4 root 175: || changed->Screen.bAspectCorrect != current->Screen.bAspectCorrect
176: || changed->Screen.nMaxWidth != current->Screen.nMaxWidth
177: || changed->Screen.nMaxHeight != current->Screen.nMaxHeight
1.1 root 178: || changed->Screen.bAllowOverscan != current->Screen.bAllowOverscan
179: || changed->Screen.bShowStatusbar != current->Screen.bShowStatusbar))
180: {
1.1.1.5 root 181: Dprintf("- screenmode>\n");
1.1.1.3 root 182: bScreenModeChange = true;
1.1 root 183: }
184:
185: /* Did set new printer parameters? */
186: if (changed->Printer.bEnablePrinting != current->Printer.bEnablePrinting
187: || strcmp(changed->Printer.szPrintToFileName,current->Printer.szPrintToFileName))
188: {
1.1.1.5 root 189: Dprintf("- printer>\n");
1.1.1.7 ! root 190: Printer_UnInit();
! 191: bReInitPrinter = true;
1.1 root 192: }
193:
194: /* Did set new RS232 parameters? */
195: if (changed->RS232.bEnableRS232 != current->RS232.bEnableRS232
196: || strcmp(changed->RS232.szOutFileName, current->RS232.szOutFileName)
197: || strcmp(changed->RS232.szInFileName, current->RS232.szInFileName))
198: {
1.1.1.5 root 199: Dprintf("- RS-232>\n");
1.1 root 200: RS232_UnInit();
201: }
202:
203: /* Did stop sound? Or change playback Hz. If so, also stop sound recording */
1.1.1.3 root 204: if (!changed->Sound.bEnableSound || changed->Sound.nPlaybackFreq != current->Sound.nPlaybackFreq)
1.1 root 205: {
1.1.1.5 root 206: Dprintf("- sound>\n");
1.1 root 207: if (Sound_AreWeRecording())
208: Sound_EndRecording();
209: Audio_UnInit();
210: }
211:
212: /* Did change floppy (images)? */
213: for (i = 0; i < MAX_FLOPPYDRIVES; i++)
214: {
215: /*
216: Log_Printf(LOG_DEBUG, "Old and new disk %c:\n\t%s\n\t%s", 'A'+i,
217: current->DiskImage.szDiskFileName[i],
218: changed->DiskImage.szDiskFileName[i]);
219: */
220: if (strcmp(changed->DiskImage.szDiskFileName[i],
221: current->DiskImage.szDiskFileName[i])
222: || strcmp(changed->DiskImage.szDiskZipPath[i],
223: current->DiskImage.szDiskZipPath[i]))
1.1.1.3 root 224: bFloppyInsert[i] = true;
1.1 root 225: else
1.1.1.3 root 226: bFloppyInsert[i] = false;
1.1 root 227: }
228:
229: /* Did change GEMDOS drive? */
230: if (changed->HardDisk.bUseHardDiskDirectories != current->HardDisk.bUseHardDiskDirectories
231: || (strcmp(changed->HardDisk.szHardDiskDirectories[0], current->HardDisk.szHardDiskDirectories[0])
232: && changed->HardDisk.bUseHardDiskDirectories))
233: {
1.1.1.5 root 234: Dprintf("- gemdos HD>\n");
1.1 root 235: GemDOS_UnInitDrives();
1.1.1.3 root 236: bReInitGemdosDrive = true;
1.1 root 237: }
238:
239: /* Did change HD image? */
240: if (changed->HardDisk.bUseHardDiskImage != current->HardDisk.bUseHardDiskImage
241: || (strcmp(changed->HardDisk.szHardDiskImage, current->HardDisk.szHardDiskImage)
242: && changed->HardDisk.bUseHardDiskImage))
243: {
1.1.1.5 root 244: Dprintf("- HD image>\n");
1.1 root 245: HDC_UnInit();
1.1.1.3 root 246: bReInitAcsiEmu = true;
247: }
248:
1.1.1.4 root 249: /* Did change IDE HD master image? */
250: if (changed->HardDisk.bUseIdeMasterHardDiskImage != current->HardDisk.bUseIdeMasterHardDiskImage
251: || (strcmp(changed->HardDisk.szIdeMasterHardDiskImage, current->HardDisk.szIdeMasterHardDiskImage)
252: && changed->HardDisk.bUseIdeMasterHardDiskImage))
253: {
1.1.1.5 root 254: Dprintf("- IDE master>\n");
1.1.1.4 root 255: Ide_UnInit();
256: bReInitIDEEmu = true;
257: }
258:
259: /* Did change IDE HD slave image? */
260: if (changed->HardDisk.bUseIdeSlaveHardDiskImage != current->HardDisk.bUseIdeSlaveHardDiskImage
261: || (strcmp(changed->HardDisk.szIdeSlaveHardDiskImage, current->HardDisk.szIdeSlaveHardDiskImage)
262: && changed->HardDisk.bUseIdeSlaveHardDiskImage))
1.1.1.3 root 263: {
1.1.1.5 root 264: Dprintf("- IDE slave>\n");
1.1.1.3 root 265: Ide_UnInit();
266: bReInitIDEEmu = true;
1.1 root 267: }
268:
269: /* Did change blitter, rtc or system type? */
270: if (changed->System.bBlitter != current->System.bBlitter
271: #if ENABLE_DSP_EMU
272: || changed->System.nDSPType != current->System.nDSPType
273: #endif
274: || changed->System.bRealTimeClock != current->System.bRealTimeClock
275: || changed->System.nMachineType != current->System.nMachineType)
276: {
1.1.1.5 root 277: Dprintf("- blitter/rtc/dsp/machine>\n");
1.1 root 278: IoMem_UnInit();
1.1.1.3 root 279: bReInitIoMem = true;
1.1 root 280: }
281:
282: #if ENABLE_DSP_EMU
283: /* Disabled DSP? */
1.1.1.3 root 284: if (current->System.nDSPType == DSP_TYPE_EMU &&
285: changed->System.nDSPType != DSP_TYPE_EMU)
1.1 root 286: {
1.1.1.5 root 287: Dprintf("- DSP>\n");
1.1 root 288: DSP_UnInit();
289: }
290: #endif
291:
1.1.1.2 root 292: /* Did change MIDI settings? */
293: if (current->Midi.bEnableMidi != changed->Midi.bEnableMidi
294: || ((strcmp(changed->Midi.sMidiOutFileName, current->Midi.sMidiOutFileName)
295: || strcmp(changed->Midi.sMidiInFileName, current->Midi.sMidiInFileName))
296: && changed->Midi.bEnableMidi))
297: {
1.1.1.5 root 298: Dprintf("- midi>\n");
1.1.1.2 root 299: Midi_UnInit();
300: bReInitMidi = true;
301: }
302:
1.1 root 303: /* Copy details to configuration,
304: * so it can be saved out or set on reset
305: */
306: if (changed != &ConfigureParams)
307: {
308: ConfigureParams = *changed;
309: }
310:
311: /* Copy details to global, if we reset copy them all */
312: Configuration_Apply(NeedReset);
313:
314: #if ENABLE_DSP_EMU
1.1.1.3 root 315: if (current->System.nDSPType != DSP_TYPE_EMU &&
316: changed->System.nDSPType == DSP_TYPE_EMU)
1.1 root 317: {
1.1.1.5 root 318: Dprintf("- DSP<\n");
1.1 root 319: DSP_Init();
320: }
321: #endif
322:
323: /* Set keyboard remap file */
324: if (ConfigureParams.Keyboard.nKeymapType == KEYMAP_LOADED)
1.1.1.5 root 325: {
326: Dprintf("- keymap<\n");
1.1 root 327: Keymap_LoadRemapFile(ConfigureParams.Keyboard.szMappingFileName);
1.1.1.5 root 328: }
1.1 root 329:
330: /* Mount a new HD image: */
331: if (bReInitAcsiEmu && ConfigureParams.HardDisk.bUseHardDiskImage)
332: {
1.1.1.5 root 333: Dprintf("- HD<\n");
1.1.1.4 root 334: HDC_Init();
1.1 root 335: }
336:
1.1.1.4 root 337: /* Mount a new IDE HD master or slave image: */
338: if (bReInitIDEEmu && (ConfigureParams.HardDisk.bUseIdeMasterHardDiskImage || ConfigureParams.HardDisk.bUseIdeSlaveHardDiskImage))
1.1.1.3 root 339: {
1.1.1.5 root 340: Dprintf("- IDE<\n");
1.1.1.3 root 341: Ide_Init();
342: }
343:
1.1 root 344: /* Insert floppies? */
345: for (i = 0; i < MAX_FLOPPYDRIVES; i++)
346: {
347: if (bFloppyInsert[i])
1.1.1.5 root 348: {
349: Dprintf("- floppy<\n");
1.1 root 350: Floppy_InsertDiskIntoDrive(i);
1.1.1.5 root 351: }
1.1 root 352: }
353:
354: /* Mount a new GEMDOS drive? */
355: if (bReInitGemdosDrive && ConfigureParams.HardDisk.bUseHardDiskDirectories)
356: {
1.1.1.5 root 357: Dprintf("- gemdos HD<\n");
1.1 root 358: GemDOS_InitDrives();
359: }
360:
361: /* Restart audio sub system if necessary: */
362: if (ConfigureParams.Sound.bEnableSound && !bSoundWorking)
363: {
1.1.1.5 root 364: Dprintf("- audio<\n");
1.1 root 365: Audio_Init();
366: }
367:
368: /* Re-initialize the RS232 emulation: */
1.1.1.7 ! root 369: if (ConfigureParams.RS232.bEnableRS232)
1.1 root 370: {
1.1.1.5 root 371: Dprintf("- RS-232<\n");
1.1 root 372: RS232_Init();
373: }
374:
375: /* Re-init IO memory map? */
376: if (bReInitIoMem)
377: {
1.1.1.5 root 378: Dprintf("- IO mem<\n");
1.1 root 379: IoMem_Init();
380: }
381:
1.1.1.7 ! root 382: /* Re-init Printer emulation? */
! 383: if (bReInitPrinter)
! 384: {
! 385: Dprintf("- printer<\n");
! 386: Printer_Init();
! 387: }
! 388:
1.1.1.2 root 389: /* Re-init MIDI emulation? */
390: if (bReInitMidi)
391: {
1.1.1.5 root 392: Dprintf("- midi<\n");
1.1.1.2 root 393: Midi_Init();
394: }
395:
1.1 root 396: /* Force things associated with screen change */
397: if (bScreenModeChange)
398: {
1.1.1.5 root 399: Dprintf("- screenmode<\n");
1.1 root 400: Screen_ModeChanged();
401: }
402:
403: /* Do we need to perform reset? */
404: if (NeedReset)
405: {
1.1.1.5 root 406: Dprintf("- reset\n");
1.1 root 407: Reset_Cold();
408: }
409:
410: /* Go into/return from full screen if flagged */
411: if (!bInFullScreen && ConfigureParams.Screen.bFullScreen)
412: Screen_EnterFullScreen();
413: else if (bInFullScreen && !ConfigureParams.Screen.bFullScreen)
414: Screen_ReturnFromFullScreen();
1.1.1.4 root 415:
416: /* update statusbar info (CPU, MHz, mem etc) */
417: Statusbar_UpdateInfo();
1.1.1.5 root 418: Dprintf("done.\n");
1.1 root 419: }
420:
421:
422: /*-----------------------------------------------------------------------*/
423: /**
424: * Change given Hatari options
1.1.1.3 root 425: * Return false if parsing failed, true otherwise
1.1 root 426: */
427: static bool Change_Options(int argc, const char *argv[])
428: {
429: bool bOK;
430: CNF_PARAMS current;
431:
1.1.1.3 root 432: Main_PauseEmulation(false);
1.1 root 433:
434: /* get configuration changes */
435: current = ConfigureParams;
436: ConfigureParams.Screen.bFullScreen = bInFullScreen;
437: bOK = Opt_ParseParameters(argc, argv);
438:
439: /* Check if reset is required and ask user if he really wants to continue */
440: if (bOK && Change_DoNeedReset(¤t, &ConfigureParams)
1.1.1.5 root 441: && current.Log.nAlertDlgLogLevel > LOG_FATAL) {
1.1 root 442: bOK = DlgAlert_Query("The emulated system must be "
443: "reset to apply these changes. "
444: "Apply changes now and reset "
445: "the emulator?");
446: }
447: /* Copy details to configuration */
448: if (bOK) {
1.1.1.3 root 449: Change_CopyChangedParamsToConfiguration(¤t, &ConfigureParams, false);
1.1 root 450: } else {
451: ConfigureParams = current;
452: }
453:
454: Main_UnPauseEmulation();
455: return bOK;
456: }
457:
458:
459: /*-----------------------------------------------------------------------*/
460: /**
1.1.1.7 ! root 461: * Parse given command line and change Hatari options accordingly.
! 462: * Given string must be stripped and not empty.
1.1.1.3 root 463: * Return false if parsing failed or there were no args, true otherwise
1.1 root 464: */
465: bool Change_ApplyCommandline(char *cmdline)
466: {
467: int i, argc, inarg;
468: const char **argv;
469: bool ret;
470:
471: /* count args */
472: inarg = argc = 0;
473: for (i = 0; cmdline[i]; i++)
474: {
1.1.1.7 ! root 475: if (isspace(cmdline[i]) && cmdline[i-1] != '\\')
1.1 root 476: {
477: inarg = 0;
478: continue;
479: }
480: if (!inarg)
481: {
482: inarg++;
483: argc++;
484: }
485: }
486: if (!argc)
487: {
1.1.1.3 root 488: return false;
1.1 root 489: }
490: /* 2 = "hatari" + NULL */
491: argv = malloc((argc+2) * sizeof(char*));
492: if (!argv)
493: {
494: perror("command line alloc");
1.1.1.3 root 495: return false;
1.1 root 496: }
497:
498: /* parse them to array */
499: fprintf(stderr, "Command line with '%d' arguments:\n", argc);
500: inarg = argc = 0;
501: argv[argc++] = "hatari";
502: for (i = 0; cmdline[i]; i++)
503: {
504: if (isspace(cmdline[i]))
505: {
1.1.1.7 ! root 506: if (cmdline[i-1] != '\\')
1.1 root 507: {
1.1.1.7 ! root 508: cmdline[i] = '\0';
! 509: if (inarg)
! 510: {
! 511: fprintf(stderr, "- '%s'\n", argv[argc-1]);
! 512: }
! 513: inarg = 0;
! 514: continue;
! 515: }
! 516: else
! 517: {
! 518: /* remove quote for space */
! 519: memcpy(cmdline+i-1, cmdline+i, strlen(cmdline+i)+1);
! 520: i--;
1.1 root 521: }
522: }
523: if (!inarg)
524: {
525: argv[argc++] = &(cmdline[i]);
526: inarg++;
527: }
528: }
529: if (inarg)
530: {
531: fprintf(stderr, "- '%s'\n", argv[argc-1]);
532: }
533: argv[argc] = NULL;
534:
535: /* do args */
536: ret = Change_Options(argc, argv);
1.1.1.3 root 537: free((void *)argv);
1.1 root 538: return ret;
539: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.