DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/dosbox.cpp
00001 /*
00002  *  Copyright (C) 2002-2015  The DOSBox Team
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017  */
00018 
00019 /* NTS: Valgrind hunting shows memory leak from C++ new operator somewhere
00020  *      with the JACK library indirectly invoked by SDL audio. Can we resolve
00021  *      that too eventually? */
00022 
00023 /* NTS: Valgrind hunting also shows one of the section INIT functions (I can't
00024  *      yet tell which one because the stack trace doesn't show it) is allocating
00025  *      something and is not freeing it. */
00026 
00027 /* NTS: Valgrind hunting has a moderate to high signal-to-noise ratio because
00028  *      of memory leaks (lazy memory allocation) from other libraries in the
00029  *      system, including:
00030  *
00031  *         ncurses
00032  *         libSDL
00033  *         libX11 and libXCB
00034  *         libasound (ALSA sound library)
00035  *         PulseAudio library calls
00036  *         JACK library calls
00037  *         libdl (the dlopen/dlclose functions allocate something and never free it)
00038  *         and a whole bunch of unidentified malloc calls without a matching free.
00039  *
00040  *      On my dev system, a reported leak of 450KB (77KB possibly lost + 384KB still reachable
00041  *      according to Valgrind) is normal.
00042  *
00043  *      Now you ask: why do I care so much about Valgrind, memory leaks, and cleaning
00044  *      up the code? The less spurious memory leaks, the easier it is to identify
00045  *      actual leaks among the noise and to patch them up. Thus, "valgrind hunting" --J.C. */
00046 
00047 #include <stdlib.h>
00048 #include <stdarg.h>
00049 #include <stdio.h>
00050 #include <string.h>
00051 #include <ctime>
00052 #include <unistd.h>
00053 #include "dosbox.h"
00054 #include "debug.h"
00055 #include "cpu.h"
00056 #include "video.h"
00057 #include "pic.h"
00058 #include "cpu.h"
00059 #include "ide.h"
00060 #include "callback.h"
00061 #include "inout.h"
00062 #include "mixer.h"
00063 #include "timer.h"
00064 #include "dos_inc.h"
00065 #include "setup.h"
00066 #include "control.h"
00067 #include "cross.h"
00068 #include "programs.h"
00069 #include "support.h"
00070 #include "mapper.h"
00071 #include "ints/int10.h"
00072 #include "menu.h"
00073 #include "render.h"
00074 #include "pci_bus.h"
00075 #include "parport.h"
00076 #include "clockdomain.h"
00077 
00078 #ifdef WIN32
00079 #define WIN32_LEAN_AND_MEAN
00080 #include <windows.h>
00081 #endif
00082 
00083 #include <list>
00084 
00085 /*===================================TODO: Move to it's own file==============================*/
00086 #if defined(__SSE__) && !defined(_M_AMD64)
00087 bool sse2_available = false;
00088 
00089 # ifdef __GNUC__
00090 #  define cpuid(func,ax,bx,cx,dx)\
00091     __asm__ __volatile__ ("cpuid":\
00092     "=a" (ax), "=b" (bx), "=c" (cx), "=d" (dx) : "a" (func));
00093 # endif /* __GNUC__ */
00094 
00095 # if defined(_MSC_VER)
00096 #  define cpuid(func,a,b,c,d)\
00097     __asm mov eax, func\
00098     __asm cpuid\
00099     __asm mov a, eax\
00100     __asm mov b, ebx\
00101     __asm mov c, ecx\
00102     __asm mov d, edx
00103 # endif /* _MSC_VER */
00104 
00105 void CheckSSESupport()
00106 {
00107 #if defined (__GNUC__) || (_MSC_VER)
00108     Bitu a, b, c, d;
00109     cpuid(1, a, b, c, d);
00110     sse2_available = ((d >> 26) & 1)?true:false;
00111 #endif
00112 }
00113 #endif
00114 /*=============================================================================*/
00115 
00116 extern void         GFX_SetTitle(Bit32s cycles,Bits frameskip,Bits timing,bool paused);
00117 
00118 extern Bitu         frames;
00119 extern Bitu         cycle_count;
00120 extern bool         sse2_available;
00121 extern bool         dynamic_dos_kernel_alloc;
00122 extern Bitu         DOS_PRIVATE_SEGMENT_Size;
00123 extern bool         VGA_BIOS_dont_duplicate_CGA_first_half;
00124 extern bool         VIDEO_BIOS_always_carry_14_high_font;
00125 extern bool         VIDEO_BIOS_always_carry_16_high_font;
00126 extern bool         VIDEO_BIOS_enable_CGA_8x8_second_half;
00127 extern bool         allow_more_than_640kb;
00128 
00129 bool                dos_con_use_int16_to_detect_input = true;
00130 
00131 bool                dbg_zero_on_dos_allocmem = true;
00132 bool                dbg_zero_on_xms_allocmem = true;
00133 bool                dbg_zero_on_ems_allocmem = true;
00134 
00135 /* the exact frequency of the NTSC color subcarrier ~3.579545454...MHz or 315/88 */
00136 /* see: http://en.wikipedia.org/wiki/Colorburst */
00137 #define             NTSC_COLOR_SUBCARRIER_NUM       (315000000ULL)
00138 #define             NTSC_COLOR_SUBCARRIER_DEN       (88ULL)
00139 
00140 /* PCI bus clock
00141  * Usual setting: 100MHz / 3 = 33.333MHz
00142  *                 90MHz / 3 = 30.000MHz */
00143 ClockDomain         clockdom_PCI_BCLK(100000000,3);     /* MASTER 100MHz / 3 = 33.33333MHz */
00144 
00145 /* ISA bus OSC clock (14.31818MHz), using a crystal that is 4x the NTSC subcarrier frequency 3.5795454..MHz */
00146 ClockDomain         clockdom_ISA_OSC(NTSC_COLOR_SUBCARRIER_NUM*4,NTSC_COLOR_SUBCARRIER_DEN);
00147 
00148 /* ISA bus clock (varies between 4.77MHz to 8.333MHz)
00149  * PC/XT: ISA oscillator clock (14.31818MHz / 3) = 4.77MHz
00150  * Some systems keep CPU synchronous to bus clock: 4.77MHz, 6MHz, 8MHz, 8.333MHz
00151  * Later systems: 25MHz / 3 = 8.333MHz
00152  *                33MHz / 4 = 8.333MHz
00153  * PCI bus systems: PCI bus clock 33MHz / 4 = 8.333MHz (especially Intel chipsets according to PIIX datasheets) */
00154 ClockDomain         clockdom_ISA_BCLK(25000000,3);      /* MASTER 25000000Hz / 3 = 8.333333MHz */
00155 
00156 Config*             control;
00157 MachineType         machine;
00158 bool                PS1AudioCard;       // Perhaps have PS1 as a machine type...?
00159 SVGACards           svgaCard;
00160 bool                SDLNetInited;
00161 Bit32s              ticksDone;
00162 Bit32u              ticksScheduled;
00163 bool                ticksLocked;
00164 bool                mono_cga=false;
00165 bool                ignore_opcode_63 = true;
00166 int             dynamic_core_cache_block_size = 32;
00167 Bitu                VGA_BIOS_Size_override = 0;
00168 Bitu                VGA_BIOS_SEG = 0xC000;
00169 Bitu                VGA_BIOS_SEG_END = 0xC800;
00170 Bitu                VGA_BIOS_Size = 0x8000;
00171 
00172 static Bit32u           ticksRemain;
00173 static Bit32u           ticksLast;
00174 static Bit32u           ticksLastFramecounter;
00175 static Bit32u           ticksLastRTcounter;
00176 static double           ticksLastRTtime;
00177 static Bit32u           ticksAdded;
00178 static Bit32u           Ticks = 0;
00179 extern double           rtdelta;
00180 static LoopHandler*     loop;
00181 
00182 /* The whole load of startups for all the subfunctions */
00183 void                LOG_StartUp(void);
00184 void                MEM_Init(Section *);
00185 void                ISAPNP_Cfg_Init(Section *);
00186 void                ROMBIOS_Init(Section *);
00187 void                CALLBACK_Init(Section*);
00188 void                PROGRAMS_Init(Section*);
00189 void                RENDER_Init(Section*);
00190 void                VGA_VsyncInit(Section*);
00191 void                VGA_Init(Section*);
00192 void                DOS_Init(Section*);
00193 void                CPU_Init(Section*);
00194 #if C_FPU
00195 void                FPU_Init(Section*);
00196 #endif
00197 void                DMA_Init(Section*);
00198 void                MIXER_Init(Section*);
00199 void                MIDI_Init(Section*);
00200 void                HARDWARE_Init(Section*);
00201 void                PCIBUS_Init(Section*);
00202 void                PCI_Init(Section*);
00203 void                VOODOO_Init(Section*);
00204 
00205 void                IDE_Primary_Init(Section*);
00206 void                IDE_Secondary_Init(Section*);
00207 void                IDE_Tertiary_Init(Section*);
00208 void                IDE_Quaternary_Init(Section*);
00209 void                IDE_Quinternary_Init(Section*);
00210 void                IDE_Sexternary_Init(Section*);
00211 void                IDE_Septernary_Init(Section*);
00212 void                IDE_Octernary_Init(Section*);
00213 
00214 void                FDC_Primary_Init(Section*);
00215 
00216 void                KEYBOARD_Init(Section*);    //TODO This should setup INT 16 too but ok ;)
00217 void                JOYSTICK_Init(Section*);
00218 void                MOUSE_Init(Section*);
00219 void                SBLASTER_Init(Section*);
00220 void                GUS_Init(Section*);
00221 void                MPU401_Init(Section*);
00222 void                PCSPEAKER_Init(Section*);
00223 void                TANDYSOUND_Init(Section*);
00224 void                DISNEY_Init(Section*);
00225 void                PS1SOUND_Init(Section*);
00226 void                INNOVA_Init(Section*);
00227 void                SERIAL_Init(Section*); 
00228 void                DONGLE_Init(Section*);
00229 #if C_IPX
00230 void                IPX_Init(Section*);
00231 #endif
00232 void                SID_Init(Section* sec);
00233 void                PIC_Init(Section*);
00234 void                TIMER_Init(Section*);
00235 void                BIOS_Init(Section*);
00236 void                DEBUG_Init(Section*);
00237 void                CMOS_Init(Section*);
00238 void                MSCDEX_Init(Section*);
00239 void                DRIVES_Init(Section*);
00240 void                CDROM_Image_Init(Section*);
00241 void                EMS_Init(Section*);
00242 void                XMS_Init(Section*);
00243 void                DOS_KeyboardLayout_Init(Section*);
00244 void                AUTOEXEC_Init(Section*);
00245 void                INT10_Init(Section*);
00246 #if C_NE2000
00247 void                NE2K_Init(Section* sec);
00248 #endif
00249 
00250 signed long long time_to_clockdom(ClockDomain &src,double t) {
00251     signed long long lt = (signed long long)t;
00252 
00253     lt *= (signed long long)src.freq;
00254     lt /= (signed long long)src.freq_div;
00255     return lt;
00256 }
00257 
00258 unsigned long long update_clockdom_from_now(ClockDomain &dst) {
00259     signed long long s;
00260 
00261     /* PIC_Ticks (if I read the code correctly) is millisecond ticks, units of 1/1000 seconds.
00262      * PIC_TickIndexND() units of submillisecond time in units of 1/CPU_CycleMax. */
00263     s  = (signed long long)((unsigned long long)PIC_Ticks * (unsigned long long)dst.freq);
00264     s += (signed long long)(((unsigned long long)PIC_TickIndexND() * (unsigned long long)dst.freq) / (unsigned long long)CPU_CycleMax);
00265     /* convert down to frequency counts, not freq x 1000 */
00266     s /= (signed long long)(1000ULL * (unsigned long long)dst.freq_div);
00267 
00268     /* guard against time going backwards slightly (as PIC_TickIndexND() will do sometimes by tiny amounts) */
00269     if (dst.counter < (unsigned long long)s) dst.counter = (unsigned long long)s;
00270 
00271     return dst.counter;
00272 }
00273 
00274 /* for ISA components that rely on dividing down from OSC */
00275 unsigned long long update_ISA_OSC_clock() {
00276     return update_clockdom_from_now(clockdom_ISA_OSC);
00277 }
00278 
00279 /* for ISA components */
00280 unsigned long long update_ISA_BCLK_clock() {
00281     return update_clockdom_from_now(clockdom_ISA_BCLK);
00282 }
00283 
00284 /* for PCI components */
00285 unsigned long long update_PCI_BCLK_clock() {
00286     return update_clockdom_from_now(clockdom_PCI_BCLK);
00287 }
00288 
00289 #include "paging.h"
00290 
00291 extern bool rom_bios_vptable_enable;
00292 extern bool rom_bios_8x8_cga_font;
00293 extern bool allow_port_92_reset;
00294 extern bool allow_keyb_reset;
00295 
00296 extern bool DOSBox_Paused();
00297 
00298 static Bitu Normal_Loop(void) {
00299     bool saved_allow = dosbox_allow_nonrecursive_page_fault;
00300     Bit32u ticksNew;
00301     Bits ret;
00302 
00303     if (!menu.hidecycles || menu.showrt) { /* sdlmain.cpp/render.cpp doesn't even maintain the frames count when hiding cycles! */
00304         ticksNew = GetTicks();
00305         if (ticksNew >= Ticks) {
00306             Bit32u interval = ticksNew - ticksLastFramecounter;
00307             double rtnow = PIC_FullIndex();
00308 
00309             if (interval == 0) interval = 1; // avoid divide by zero
00310 
00311             rtdelta = rtnow - ticksLastRTtime;
00312             rtdelta = (rtdelta * 1000) / interval;
00313 
00314             ticksLastRTtime = rtnow;
00315             ticksLastFramecounter = Ticks;
00316             Ticks = ticksNew + 500;     // next update in 500ms
00317             frames = (frames * 1000) / interval; // compensate for interval, be more exact (FIXME: so can we adjust for fractional frame rates)
00318             GFX_SetTitle(CPU_CycleMax,-1,-1,false);
00319             frames = 0;
00320         }
00321     }
00322 
00323     try {
00324         while (1) {
00325             if (PIC_RunQueue()) {
00326                 /* now is the time to check for the NMI (Non-maskable interrupt) */
00327                 CPU_Check_NMI();
00328 
00329                 saved_allow = dosbox_allow_nonrecursive_page_fault;
00330                 dosbox_allow_nonrecursive_page_fault = true;
00331                 ret = (*cpudecoder)();
00332                 dosbox_allow_nonrecursive_page_fault = saved_allow;
00333 
00334                 if (GCC_UNLIKELY(ret<0))
00335                     return 1;
00336 
00337                 if (ret>0) {
00338                     if (GCC_UNLIKELY(ret >= CB_MAX))
00339                         return 0;
00340 
00341                     dosbox_allow_nonrecursive_page_fault = false;
00342                     Bitu blah = (*CallBack_Handlers[ret])();
00343                     dosbox_allow_nonrecursive_page_fault = saved_allow;
00344                     if (GCC_UNLIKELY(blah > 0U))
00345                         return blah;
00346                 }
00347 #if C_DEBUG
00348                 if (DEBUG_ExitLoop())
00349                     return 0;
00350 #endif
00351             } else {
00352                 GFX_Events();
00353                 if (DOSBox_Paused() == false && ticksRemain > 0) {
00354                     TIMER_AddTick();
00355                     ticksRemain--;
00356                 } else {
00357                     goto increaseticks;
00358                 }
00359             }
00360         }
00361 increaseticks:
00362         if (GCC_UNLIKELY(ticksLocked)) {
00363             ticksRemain=5;
00364             /* Reset any auto cycle guessing for this frame */
00365             ticksLast = GetTicks();
00366             ticksAdded = 0;
00367             ticksDone = 0;
00368             ticksScheduled = 0;
00369         } else {
00370             ticksNew=GetTicks();
00371             ticksScheduled += ticksAdded;
00372             if (ticksNew > ticksLast) {
00373                 ticksRemain = ticksNew-ticksLast;
00374                 ticksLast = ticksNew;
00375                 ticksDone += (Bit32s)ticksRemain;
00376                 if ( ticksRemain > 20 ) {
00377                     ticksRemain = 20;
00378                 }
00379                 ticksAdded = ticksRemain;
00380                 if (CPU_CycleAutoAdjust && !CPU_SkipCycleAutoAdjust) {
00381                     if (ticksScheduled >= 250 || ticksDone >= 250 || (ticksAdded > 15 && ticksScheduled >= 5) ) {
00382                         if(ticksDone < 1) ticksDone = 1; // Protect against div by zero
00383                         /* ratio we are aiming for is around 90% usage*/
00384                         Bit32s ratio = (ticksScheduled * (CPU_CyclePercUsed*90*1024/100/100)) / ticksDone;
00385                         Bit32s new_cmax = CPU_CycleMax;
00386                         Bit64s cproc = (Bit64s)CPU_CycleMax * (Bit64s)ticksScheduled;
00387                         if (cproc > 0) {
00388                             /* ignore the cycles added due to the IO delay code in order
00389                                to have smoother auto cycle adjustments */
00390                             double ratioremoved = (double) CPU_IODelayRemoved / (double) cproc;
00391                             if (ratioremoved < 1.0) {
00392                                 ratio = (Bit32s)((double)ratio * (1 - ratioremoved));
00393                                 /* Don't allow very high ratio which can cause us to lock as we don't scale down
00394                                  * for very low ratios. High ratio might result because of timing resolution */
00395                                 if (ticksScheduled >= 250 && ticksDone < 10 && ratio > 20480) 
00396                                     ratio = 20480;
00397                                 Bit64s cmax_scaled = (Bit64s)CPU_CycleMax * (Bit64s)ratio;
00398                                 /* The auto cycle code seems reliable enough to disable the fast cut back code.
00399                                  * This should improve the fluency of complex games.
00400                                  if (ratio <= 1024) 
00401                                  new_cmax = (Bit32s)(cmax_scaled / (Bit64s)1024);
00402                                  else 
00403                                  */
00404                                 new_cmax = (Bit32s)(1 + (CPU_CycleMax >> 1) + cmax_scaled / (Bit64s)2048);
00405                             }
00406                         }
00407 
00408                         if (new_cmax<CPU_CYCLES_LOWER_LIMIT)
00409                             new_cmax=CPU_CYCLES_LOWER_LIMIT;
00410 
00411                         /*
00412                            LOG_MSG("cyclelog: current %6d   cmax %6d   ratio  %5d  done %3d   sched %3d",
00413                            CPU_CycleMax,
00414                            new_cmax,
00415                            ratio,
00416                            ticksDone,
00417                            ticksScheduled);
00418                            */  
00419                         /* ratios below 1% are considered to be dropouts due to
00420                            temporary load imbalance, the cycles adjusting is skipped */
00421                         if (ratio>10) {
00422                             /* ratios below 12% along with a large time since the last update
00423                                has taken place are most likely caused by heavy load through a
00424                                different application, the cycles adjusting is skipped as well */
00425                             if ((ratio>120) || (ticksDone<700)) {
00426                                 CPU_CycleMax = new_cmax;
00427                                 if (CPU_CycleLimit > 0) {
00428                                     if (CPU_CycleMax>CPU_CycleLimit) CPU_CycleMax = CPU_CycleLimit;
00429                                 }
00430                             }
00431                         }
00432                         CPU_IODelayRemoved = 0;
00433                         ticksDone = 0;
00434                         ticksScheduled = 0;
00435                     } else if (ticksAdded > 15) {
00436                         /* ticksAdded > 15 but ticksScheduled < 5, lower the cycles
00437                            but do not reset the scheduled/done ticks to take them into
00438                            account during the next auto cycle adjustment */
00439                         CPU_CycleMax /= 3;
00440                         if (CPU_CycleMax < CPU_CYCLES_LOWER_LIMIT)
00441                             CPU_CycleMax = CPU_CYCLES_LOWER_LIMIT;
00442                     }
00443                 }
00444             } else {
00445                 ticksAdded = 0;
00446                 SDL_Delay(1);
00447                 ticksDone -= (Bit32s)((Bit32u)(GetTicks() - ticksNew));
00448                 if (ticksDone < 0)
00449                     ticksDone = 0;
00450             }
00451         }
00452     }
00453     catch (GuestPageFaultException &pf) {
00454         Bitu FillFlags(void);
00455 
00456         ret = 0;
00457         FillFlags();
00458         dosbox_allow_nonrecursive_page_fault = false;
00459         CPU_Exception(EXCEPTION_PF,pf.faultcode);
00460         dosbox_allow_nonrecursive_page_fault = saved_allow;
00461     }
00462     catch (int x) {
00463         dosbox_allow_nonrecursive_page_fault = saved_allow;
00464         if (x == 4/*CMOS shutdown*/) {
00465             ret = 0;
00466 //          LOG_MSG("CMOS shutdown reset acknowledged");
00467         }
00468         else {
00469             throw;
00470         }
00471     }
00472 
00473     return 0;
00474 }
00475 
00476 LoopHandler *DOSBOX_GetLoop(void) {
00477     return loop;
00478 }
00479 
00480 void DOSBOX_SetLoop(LoopHandler * handler) {
00481     loop=handler;
00482 }
00483 
00484 void DOSBOX_SetNormalLoop() {
00485     loop=Normal_Loop;
00486 }
00487 
00488 void DOSBOX_RunMachine(void){
00489     Bitu ret;
00490     do {
00491         ret=(*loop)();
00492     } while (!ret);
00493 }
00494 
00495 static void DOSBOX_UnlockSpeed( bool pressed ) {
00496     static bool autoadjust = false;
00497     if (pressed) {
00498         LOG_MSG("Fast Forward ON");
00499         ticksLocked = true;
00500         if (CPU_CycleAutoAdjust) {
00501             autoadjust = true;
00502             CPU_CycleAutoAdjust = false;
00503             CPU_CycleMax /= 3;
00504             if (CPU_CycleMax<1000) CPU_CycleMax=1000;
00505         }
00506     } else {
00507         LOG_MSG("Fast Forward OFF");
00508         ticksLocked = false;
00509         if (autoadjust) {
00510             autoadjust = false;
00511             CPU_CycleAutoAdjust = true;
00512         }
00513     }
00514     GFX_SetTitle(-1,-1,-1,false);
00515 }
00516 
00517 void DOSBOX_UnlockSpeed2( bool pressed ) {
00518     if (pressed) {
00519         ticksLocked =! ticksLocked;
00520         DOSBOX_UnlockSpeed(ticksLocked?true:false);
00521 
00522         /* make sure the menu item keeps up with our state */
00523         mainMenu.get_item("mapper_speedlock2").check(ticksLocked).refresh_item(mainMenu);
00524     }
00525 }
00526 
00527 void notifyError(const std::string& message)
00528 {
00529 #ifdef WIN32
00530     ::MessageBox(0, message.c_str(), "Error", 0);
00531 #endif
00532     LOG_MSG("%s",message.c_str());
00533 }
00534 
00535 /* TODO: move to utility header */
00536 #ifdef _MSC_VER /* Microsoft C++ does not have strtoull */
00537 # if _MSC_VER < 1800 /* But Visual Studio 2013 apparently does (http://www.vogons.org/viewtopic.php?f=41&t=31881&sid=49ff69ebc0459ed6523f5a250daa4d8c&start=400#p355770) */
00538 unsigned long long strtoull(const char *s,char **endptr,int base) {
00539     return _strtoui64(s,endptr,base); /* pfff... whatever Microsoft */
00540 }
00541 # endif
00542 #endif
00543 
00544 /* utility function. rename as appropriate and move to utility collection */
00545 void parse_busclk_setting_str(ClockDomain *cd,const char *s) {
00546     const char *d;
00547 
00548     /* we're expecting an integer, a float, or an integer ratio */
00549     d = strchr(s,'/');
00550     if (d != NULL) { /* it has a slash therefore an integer ratio */
00551         unsigned long long num,den;
00552 
00553         while (*d == ' ' || *d == '/') d++;
00554         num = strtoull(s,NULL,0);
00555         den = strtoull(d,NULL,0);
00556         if (num >= 1ULL && den >= 1ULL) cd->set_frequency(num,den);
00557     }
00558     else {
00559         d = strchr(s,'.');
00560         if (d != NULL) { /* it has a dot, floating point */
00561             double f = atof(s);
00562             unsigned long long fi = (unsigned long long)floor((f*1000000)+0.5);
00563             unsigned long long den = 1000000;
00564 
00565             while (den > 1ULL) {
00566                 if ((fi%10ULL) == 0) {
00567                     den /= 10ULL;
00568                     fi /= 10ULL;
00569                 }
00570                 else {
00571                     break;
00572                 }
00573             }
00574 
00575             if (fi >= 1ULL) cd->set_frequency(fi,den);
00576         }
00577         else {
00578             unsigned long long f = strtoull(s,NULL,10);
00579             if (f >= 1ULL) cd->set_frequency(f,1);
00580         }
00581     }
00582 }
00583 
00584 unsigned int dosbox_shell_env_size = 0;
00585 
00586 void clocktree_build_conversion_list();
00587 
00588 void Null_Init(Section *sec) {
00589         (void)sec;
00590 }
00591 
00592 extern Bit8u cga_comp;
00593 extern bool new_cga;
00594 
00595 bool dpi_aware_enable = true;
00596 
00597 std::string dosbox_title;
00598 
00599 void DOSBOX_InitTickLoop() {
00600     LOG(LOG_MISC,LOG_DEBUG)("Initializing tick loop management");
00601 
00602     ticksRemain = 0;
00603     ticksLocked = false;
00604     ticksLastRTtime = 0;
00605     ticksLast = GetTicks();
00606     ticksLastRTcounter = GetTicks();
00607     ticksLastFramecounter = GetTicks();
00608     DOSBOX_SetLoop(&Normal_Loop);
00609 }
00610 
00611 void Init_VGABIOS() {
00612     Section_prop *section = static_cast<Section_prop *>(control->GetSection("dosbox"));
00613     assert(section != NULL);
00614 
00615     if (IS_PC98_ARCH) {
00616         VGA_BIOS_Size = 0;
00617         return;
00618     }
00619 
00620     // log
00621     LOG(LOG_MISC,LOG_DEBUG)("Init_VGABIOS: Initializing VGA BIOS and parsing it's settings");
00622 
00623     // mem init must have already happened.
00624     // We can remove this once the device callout system is in place.
00625     assert(MemBase != NULL);
00626 
00627     VGA_BIOS_Size_override = (Bitu)section->Get_int("vga bios size override");
00628     if (VGA_BIOS_Size_override > 0) VGA_BIOS_Size_override = (VGA_BIOS_Size_override+0x7FFU)&(~0xFFFU);
00629 
00630     VGA_BIOS_dont_duplicate_CGA_first_half = section->Get_bool("video bios dont duplicate cga first half rom font");
00631     VIDEO_BIOS_always_carry_14_high_font = section->Get_bool("video bios always offer 14-pixel high rom font");
00632     VIDEO_BIOS_always_carry_16_high_font = section->Get_bool("video bios always offer 16-pixel high rom font");
00633     VIDEO_BIOS_enable_CGA_8x8_second_half = section->Get_bool("video bios enable cga second half rom font");
00634     /* NTS: mainline compatible mapping demands the 8x8 CGA font */
00635     rom_bios_8x8_cga_font = section->Get_bool("rom bios 8x8 CGA font");
00636     rom_bios_vptable_enable = section->Get_bool("rom bios video parameter table");
00637 
00638     /* sanity check */
00639     if (VGA_BIOS_dont_duplicate_CGA_first_half && !rom_bios_8x8_cga_font) /* can't point at the BIOS copy if it's not there */
00640         VGA_BIOS_dont_duplicate_CGA_first_half = false;
00641 
00642     if (VGA_BIOS_Size_override >= 512 && VGA_BIOS_Size_override <= 65536)
00643         VGA_BIOS_Size = (VGA_BIOS_Size_override + 0x7FFU) & (~0xFFFU);
00644     else if (IS_VGA_ARCH)
00645         VGA_BIOS_Size = 0x3000; /* <- Experimentation shows the S3 emulation can fit in 12KB, doesn't need all 32KB */
00646     else if (machine == MCH_EGA) {
00647         if (VIDEO_BIOS_always_carry_16_high_font)
00648             VGA_BIOS_Size = 0x3000;
00649         else
00650             VGA_BIOS_Size = 0x2000;
00651     }
00652     else {
00653         if (VIDEO_BIOS_always_carry_16_high_font && VIDEO_BIOS_always_carry_14_high_font)
00654             VGA_BIOS_Size = 0x3000;
00655         else if (VIDEO_BIOS_always_carry_16_high_font || VIDEO_BIOS_always_carry_14_high_font)
00656             VGA_BIOS_Size = 0x2000;
00657         else
00658             VGA_BIOS_Size = 0;
00659     }
00660     VGA_BIOS_SEG = 0xC000;
00661     VGA_BIOS_SEG_END = (VGA_BIOS_SEG + (VGA_BIOS_Size >> 4));
00662 
00663     /* clear for VGA BIOS (FIXME: Why does Project Angel like our BIOS when we memset() here, but don't like it if we memset() in the INT 10 ROM setup routine?) */
00664     if (VGA_BIOS_Size != 0)
00665         memset((char*)MemBase+0xC0000,0x00,VGA_BIOS_Size);
00666 }
00667 
00668 void DOSBOX_RealInit() {
00669     DOSBoxMenu::item *item;
00670 
00671     LOG(LOG_MISC,LOG_DEBUG)("DOSBOX_RealInit: loading settings and initializing");
00672 
00673     MAPPER_AddHandler(DOSBOX_UnlockSpeed, MK_rightarrow, MMODHOST,"speedlock","Speedlock");
00674     {
00675         MAPPER_AddHandler(DOSBOX_UnlockSpeed2, MK_nothing, 0, "speedlock2", "Speedlock2", &item);
00676         item->set_description("Toggle emulation speed, to allow running faster than realtime (fast forward)");
00677         item->set_text("Turbo (Fast Forward)");
00678     }
00679 
00680     Section_prop *section = static_cast<Section_prop *>(control->GetSection("dosbox"));
00681     assert(section != NULL);
00682 
00683     // boot-time option whether or not to report ourself as "DPI aware" to Windows so the
00684     // DWM doesn't upscale our window for backwards compat.
00685     dpi_aware_enable = section->Get_bool("dpi aware");
00686 
00687     // TODO: allow change at any time. in fact if it were possible for DOSBox-X configuration
00688     //       schema code to attach event callbacks when a setting changes, we would set one
00689     //       on the title= setting now to auto-update the titlebar when this changes.
00690     dosbox_title = section->Get_string("title");
00691 
00692     // TODO: these should be parsed by DOS kernel at startup
00693     dosbox_shell_env_size = (unsigned int)section->Get_int("shell environment size");
00694 
00695     // TODO: a bit of a challenge: if we put it in the ROM area as mainline DOSBox does then the init
00696     //       needs to read this from the BIOS where it can map the memory appropriately. if the allocation
00697     //       is dynamic and the private area is down at the base of memory like real DOS, then the BIOS
00698     //       should ignore it and the DOS kernel should parse it. If we're going to put it into upper
00699     //       areas as well, then we should also consider making it look like adapter ROM at startup
00700     //       so it can be enumerated properly by DOS programs scanning the ROM area.
00701     /* private area size param in bytes. round up to nearest paragraph */
00702     DOS_PRIVATE_SEGMENT_Size = (Bitu)((section->Get_int("private area size") + 8) / 16);
00703 
00704     // TODO: these should be parsed by BIOS startup
00705     allow_more_than_640kb = section->Get_bool("allow more than 640kb base memory");
00706 
00707     // TODO: should be parsed by motherboard emulation
00708     allow_port_92_reset = section->Get_bool("allow port 92 reset");
00709 
00710     // CGA/EGA/VGA-specific
00711     extern unsigned char vga_p3da_undefined_bits;
00712     vga_p3da_undefined_bits = (unsigned char)section->Get_hex("vga 3da undefined bits");
00713 
00714     // TODO: should be parsed by motherboard emulation or lower level equiv..?
00715     std::string cmd_machine;
00716     if (control->cmdline->FindString("-machine",cmd_machine,true)){
00717         //update value in config (else no matching against suggested values
00718         section->HandleInputline(std::string("machine=") + cmd_machine);
00719     }
00720 
00721     // TODO: should be parsed by...? perhaps at some point we support machine= for backwards compat
00722     //       but translate it into two separate params that specify what machine vs what video hardware.
00723     //       or better yet as envisioned, a possible dosbox.conf schema that allows a machine with no
00724     //       base video of it's own, and then to specify an ISA or PCI card attached to the bus that
00725     //       provides video.
00726     std::string mtype(section->Get_string("machine"));
00727     svgaCard = SVGA_None; 
00728     machine = MCH_VGA;
00729     int10.vesa_nolfb = false;
00730     int10.vesa_oldvbe = false;
00731     if      (mtype == "cga")           { machine = MCH_CGA; mono_cga = false; }
00732     else if (mtype == "cga_mono")      { machine = MCH_CGA; mono_cga = true; }
00733     else if (mtype == "cga_rgb")       { machine = MCH_CGA; mono_cga = false; cga_comp = 2; }
00734     else if (mtype == "cga_composite") { machine = MCH_CGA; mono_cga = false; cga_comp = 1; new_cga = false; }
00735     else if (mtype == "cga_composite2"){ machine = MCH_CGA; mono_cga = false; cga_comp = 1; new_cga = true; }
00736     else if (mtype == "tandy")         { machine = MCH_TANDY; }
00737     else if (mtype == "pcjr")          { machine = MCH_PCJR; }
00738     else if (mtype == "hercules")      { machine = MCH_HERC; }
00739     else if (mtype == "ega")           { machine = MCH_EGA; }
00740     else if (mtype == "svga_s3")       { svgaCard = SVGA_S3Trio; }
00741     else if (mtype == "vesa_nolfb")    { svgaCard = SVGA_S3Trio; int10.vesa_nolfb = true;}
00742     else if (mtype == "vesa_oldvbe")   { svgaCard = SVGA_S3Trio; int10.vesa_oldvbe = true;}
00743     else if (mtype == "svga_et4000")   { svgaCard = SVGA_TsengET4K; }
00744     else if (mtype == "svga_et3000")   { svgaCard = SVGA_TsengET3K; }
00745     else if (mtype == "svga_paradise") { svgaCard = SVGA_ParadisePVGA1A; }
00746     else if (mtype == "vgaonly")       { svgaCard = SVGA_None; }
00747     else if (mtype == "amstrad")       { machine = MCH_AMSTRAD; }
00748     else if (mtype == "pc98")          { machine = MCH_PC98; }
00749     else if (mtype == "pc9801")        { machine = MCH_PC98; } /* Future differentiation */
00750     else if (mtype == "pc9821")        { machine = MCH_PC98; } /* Future differentiation */
00751 
00752     else if (mtype == "fm_towns")      { machine = MCH_FM_TOWNS; }
00753 
00754     else E_Exit("DOSBOX:Unknown machine type %s",mtype.c_str());
00755 
00756     // TODO: should be parsed by motherboard emulation
00757     std::string isabclk = section->Get_string("isa bus clock");
00758     if (isabclk == "std8.3")
00759         clockdom_ISA_BCLK.set_frequency(25000000,3);    /* 25MHz / 3 = 8.333MHz, early 386 systems did this, became an industry standard "norm" afterwards */
00760     else if (isabclk == "std8")
00761         clockdom_ISA_BCLK.set_frequency(8000000,1); /* 8Mhz */
00762     else if (isabclk == "std6")
00763         clockdom_ISA_BCLK.set_frequency(6000000,1); /* 6MHz */
00764     else if (isabclk == "std4.77")
00765         clockdom_ISA_BCLK.set_frequency(clockdom_ISA_OSC.freq,clockdom_ISA_OSC.freq_div*3LL); /* 14.31818MHz / 3 = 4.77MHz */
00766     else if (isabclk == "oc10")
00767         clockdom_ISA_BCLK.set_frequency(10000000,1);    /* 10MHz */
00768     else if (isabclk == "oc12")
00769         clockdom_ISA_BCLK.set_frequency(12000000,1);    /* 12MHz */
00770     else if (isabclk == "oc15")
00771         clockdom_ISA_BCLK.set_frequency(15000000,1);    /* 15MHz */
00772     else if (isabclk == "oc16")
00773         clockdom_ISA_BCLK.set_frequency(16000000,1);    /* 16MHz */
00774     else
00775         parse_busclk_setting_str(&clockdom_ISA_BCLK,isabclk.c_str());
00776 
00777     std::string pcibclk = section->Get_string("pci bus clock");
00778     if (pcibclk == "std33.3")
00779         clockdom_PCI_BCLK.set_frequency(100000000,3);   /* 100MHz / 3 = 33.333MHz, VERY common PCI speed */
00780     else if (pcibclk == "std30")
00781         clockdom_PCI_BCLK.set_frequency(30000000,1);    /* 30Mhz */
00782     else if (pcibclk == "std25")
00783         clockdom_PCI_BCLK.set_frequency(25000000,1);    /* 25MHz */
00784     else
00785         parse_busclk_setting_str(&clockdom_PCI_BCLK,pcibclk.c_str());
00786 
00787     clockdom_ISA_OSC.set_name("ISA OSC");
00788     clockdom_ISA_BCLK.set_name("ISA BCLK");
00789     clockdom_PCI_BCLK.set_name("PCI BCLK");
00790 
00791     // FM TOWNS is stub!!!
00792     if (IS_FM_TOWNS) E_Exit("FM Towns emulation not yet implemented");
00793 }
00794 
00795 void DOSBOX_SetupConfigSections(void) {
00796     Prop_int* Pint;
00797     Prop_hex* Phex;
00798     Prop_bool* Pbool;
00799     Prop_string* Pstring;
00800     Prop_double* Pdouble;
00801     Prop_multival* Pmulti;
00802     Section_prop * secprop;
00803     Prop_multival_remain* Pmulti_remain;
00804 
00805     // Some frequently used option sets
00806     const char* vsyncrate[] = { "%u", 0 };
00807     const char* force[] = { "", "forced", 0 };
00808     const char* cyclest[] = { "auto","fixed","max","%u",0 };
00809     const char* mputypes[] = { "intelligent", "uart", "none", 0 };
00810     const char* vsyncmode[] = { "off", "on" ,"force", "host", 0 };
00811     const char* captureformats[] = { "default", "avi-zmbv", "mpegts-h264", 0 };
00812     const char* blocksizes[] = {"1024", "2048", "4096", "8192", "512", "256", 0};
00813     const char* capturechromaformats[] = { "auto", "4:4:4", "4:2:2", "4:2:0", 0};
00814     const char* auxdevices[] = {"none","2button","3button","intellimouse","intellimouse45",0};
00815     const char* cputype_values[] = {"auto", "8086", "8086_prefetch", "80186", "80186_prefetch", "286", "286_prefetch", "386", "386_prefetch", "486", "486_prefetch", "pentium", "pentium_mmx", "ppro_slow", 0};
00816     const char* rates[] = {  "44100", "48000", "32000","22050", "16000", "11025", "8000", "49716", 0 };
00817     const char* oplrates[] = {   "44100", "49716", "48000", "32000","22050", "16000", "11025", "8000", 0 };
00818     const char* devices[] = { "default", "win32", "alsa", "oss", "coreaudio", "coremidi", "mt32", "synth", "timidity", "none", 0}; // FIXME: add some way to offer the actually available choices.
00819     const char* apmbiosversions[] = { "auto", "1.0", "1.1", "1.2", 0 };
00820     const char *mt32log[] = {"off", "on",0};
00821     const char *mt32thread[] = {"off", "on",0};
00822     const char *mt32ReverseStereo[] = {"off", "on",0};
00823     const char *mt32DACModes[] = {"0", "1", "2", "3", "auto",0};
00824     const char *mt32reverbModes[] = {"0", "1", "2", "3", "auto",0};
00825     const char *mt32reverbTimes[] = {"0", "1", "2", "3", "4", "5", "6", "7",0};
00826     const char *mt32reverbLevels[] = {"0", "1", "2", "3", "4", "5", "6", "7",0};
00827     const char* gustypes[] = { "classic", "classic37", "max", "interwave", 0 };
00828     const char* sbtypes[] = { "sb1", "sb2", "sbpro1", "sbpro2", "sb16", "sb16vibra", "gb", "ess688", "reveal_sc400", "none", 0 };
00829     const char* oplmodes[]={ "auto", "cms", "opl2", "dualopl2", "opl3", "none", "hardware", "hardwaregb", 0};
00830     const char* serials[] = { "dummy", "disabled", "modem", "nullmodem", "serialmouse", "directserial", "log", 0 };
00831     const char* acpi_rsd_ptr_settings[] = { "auto", "bios", "ebda", 0 };
00832     const char* cpm_compat_modes[] = { "auto", "off", "msdos2", "msdos5", "direct", 0 };
00833     const char* dosv_settings[] = { "off", "japanese", "chinese", "korean", 0 };
00834     const char* acpisettings[] = { "off", "1.0", "1.0b", "2.0", "2.0a", "2.0b", "2.0c", "3.0", "3.0a", "3.0b", "4.0", "4.0a", "5.0", "5.0a", "6.0", 0 };
00835     const char* guspantables[] = { "old", "accurate", "default", 0 };
00836     const char *sidbaseno[] = { "240", "220", "260", "280", "2a0", "2c0", "2e0", "300", 0 };
00837     const char* joytypes[] = { "auto", "2axis", "4axis", "4axis_2", "fcs", "ch", "none",0};
00838     const char* joydeadzone[] = { "0.26", 0 };
00839     const char* joyresponse[] = { "1.0", 0 };
00840     const char* iosgus[] = { "240", "220", "260", "280", "2a0", "2c0", "2e0", "300", "210", "230", "250", 0 };
00841     const char* ios[] = { "220", "240", "260", "280", "2a0", "2c0", "2e0", "300", 0 };
00842     const char* ems_settings[] = { "true", "emsboard", "emm386", "false", 0};
00843     const char* irqsgus[] = { "5", "3", "7", "9", "10", "11", "12", 0 };
00844     const char* irqssb[] = { "7", "5", "3", "9", "10", "11", "12", 0 };
00845     const char* dmasgus[] = { "3", "0", "1", "5", "6", "7", 0 };
00846     const char* dmassb[] = { "1", "5", "0", "3", "6", "7", 0 };
00847     const char* oplemus[] = { "default", "compat", "fast", "nuked", 0 };
00848     const char *qualityno[] = { "0", "1", "2", "3", 0 };
00849     const char* tandys[] = { "auto", "on", "off", 0};
00850     const char* ps1opt[] = { "on", "off", 0};
00851     const char* truefalseautoopt[] = { "true", "false", "1", "0", "auto", 0};
00852     const char* pc98fmboards[] = { "auto", "off", "false", "board26k", "board86", "board86c", 0};
00853     const char* pc98videomodeopt[] = { "", "24khz", "31khz", "15khz", 0};
00854     const char* aspectmodes[] = { "false", "true", "0", "1", "yes", "no", "nearest", "bilinear", 0};
00855     const char *vga_ac_mapping_settings[] = { "", "auto", "4x4", "4low", "first16", 0 };
00856 
00857     const char* irqssbhack[] = {
00858         "none", "cs_equ_ds", 0
00859     };
00860 
00861     /* Setup all the different modules making up DOSBox */
00862     const char* machines[] = {
00863         "hercules", "cga", "cga_mono", "cga_rgb", "cga_composite", "cga_composite2", "tandy", "pcjr", "ega",
00864         "vgaonly", "svga_s3", "svga_et3000", "svga_et4000",
00865         "svga_paradise", "vesa_nolfb", "vesa_oldvbe", "amstrad", "pc98", "pc9801", "pc9821",
00866 
00867         "fm_towns", // STUB
00868 
00869         0 };
00870 
00871     const char* scalers[] = { 
00872         "none", "normal2x", "normal3x", "normal4x", "normal5x",
00873 #if RENDER_USE_ADVANCED_SCALERS>2
00874         "advmame2x", "advmame3x", "advinterp2x", "advinterp3x", "hq2x", "hq3x", "2xsai", "super2xsai", "supereagle",
00875 #endif
00876 #if RENDER_USE_ADVANCED_SCALERS>0
00877         "tv2x", "tv3x", "rgb2x", "rgb3x", "scan2x", "scan3x",
00878 #endif
00879         "hardware_none", "hardware2x", "hardware3x", "hardware4x", "hardware5x",
00880 #if C_XBRZ
00881         "xbrz", "xbrz_bilinear",
00882 #endif
00883         0 };
00884 
00885     const char* cores[] = { "auto",
00886 #if (C_DYNAMIC_X86)
00887         "dynamic",
00888 #endif
00889         "normal", "full", "simple", 0 };
00890 
00891     const char* voodoo_settings[] = {
00892         "false",
00893         "software",
00894 #if C_OPENGL
00895         "opengl",
00896 #endif
00897         "auto",
00898         0
00899     };
00900 
00901 #if defined(__SSE__) && !defined(_M_AMD64)
00902     CheckSSESupport();
00903 #endif
00904     SDLNetInited = false;
00905 
00906     secprop=control->AddSection_prop("dosbox",&Null_Init);
00907     Pstring = secprop->Add_path("language",Property::Changeable::Always,"");
00908     Pstring->Set_help("Select another language file.");
00909 
00910     Pstring = secprop->Add_path("title",Property::Changeable::Always,"");
00911     Pstring->Set_help("Additional text to place in the title bar of the window");
00912 
00913     Pbool = secprop->Add_bool("dpi aware",Property::Changeable::OnlyAtStart,true);
00914     Pbool->Set_help("Set this option (on by default) to indicate to your OS that DOSBox is DPI aware.\n"
00915             "If it is not set, Windows Vista/7/8/10 and higher may upscale the DOSBox window\n"
00916             "on higher resolution monitors which is probably not what you want.");
00917 
00918     Pbool = secprop->Add_bool("keyboard hook", Property::Changeable::Always, false);
00919     Pbool->Set_help("Use keyboard hook (currently only on Windows) to catch special keys and synchronize the keyboard LEDs with the host");
00920 
00921     // STUB OPTION, NOT YET FULLY IMPLEMENTED
00922     Pbool = secprop->Add_bool("weitek",Property::Changeable::WhenIdle,false);
00923     Pbool->Set_help("If set, emulate the Weitek coprocessor. This option only has effect if cputype=386 or cputype=486.");
00924 
00925     Pbool = secprop->Add_bool("bochs debug port e9",Property::Changeable::WhenIdle,false);
00926     Pbool->Set_help("If set, emulate Bochs debug port E9h. ASCII text written to this I/O port is assumed to be debug output, and logged.");
00927 
00928     Pstring = secprop->Add_string("machine",Property::Changeable::OnlyAtStart,"svga_s3");
00929     Pstring->Set_values(machines);
00930     Pstring->Set_help("The type of machine DOSBox tries to emulate.");
00931 
00932     Phex = secprop->Add_hex("svga lfb base", Property::Changeable::OnlyAtStart, 0);
00933     Phex->Set_help("If nonzero, define the physical memory address of the linear framebuffer.");
00934 
00935     Pint = secprop->Add_int("vmemdelay", Property::Changeable::WhenIdle,0);
00936     Pint->SetMinMax(-1,100000);
00937     Pint->Set_help( "VGA Memory I/O delay in nanoseconds. Set to -1 to use default, 0 to disable.\n"
00938             "Default off. Enable this option (-1 or nonzero) if you are running a game or\n"
00939             "demo that needs slower VGA memory (like that of older ISA hardware) to work properly.\n"
00940             "If your game is not sensitive to VGA RAM I/O speed, then turning on this option\n"
00941             "will do nothing but cause a significant drop in frame rate which is probably not\n"
00942             "what you want. Recommended values -1, 0 to 2000.");
00943 
00944     Pint = secprop->Add_int("vmemsize", Property::Changeable::WhenIdle,2);
00945     Pint->SetMinMax(0,8);
00946     Pint->Set_help(
00947         "Amount of video memory in megabytes.\n"
00948         "  The maximum resolution and color depth the svga_s3 will be able to display\n"
00949         "  is determined by this value.\n "
00950         "  0: 512k (800x600  at 256 colors)\n"
00951         "  1: 1024x768  at 256 colors or 800x600  at 64k colors\n"
00952         "  2: 1600x1200 at 256 colors or 1024x768 at 64k colors or 640x480 at 16M colors\n"
00953         "  4: 1600x1200 at 64k colors or 1024x768 at 16M colors\n"
00954         "  8: up to 1600x1200 at 16M colors\n"
00955         "For build engine games, use more memory than in the list above so it can\n"
00956         "use triple buffering and thus won't flicker.\n"
00957         );
00958 
00959     Pint = secprop->Add_int("vmemsizekb", Property::Changeable::WhenIdle,0);
00960     Pint->SetMinMax(0,8);
00961     Pint->Set_help(
00962         "Amount of video memory in kilobytes, in addition to vmemsize");
00963 
00964     Pstring = secprop->Add_path("captures",Property::Changeable::Always,"capture");
00965     Pstring->Set_help("Directory where things like wave, midi, screenshot get captured.");
00966 
00967     Pstring = secprop->Add_string("capture chroma format", Property::Changeable::OnlyAtStart,"auto");
00968     Pstring->Set_values(capturechromaformats);
00969     Pstring->Set_help("Chroma format to use when capturing to H.264. 'auto' picks the best quality option.\n"
00970             "4:4:4       Chroma is at full resolution. This provides the best quality, however not widely supported by editing software.\n"
00971             "4:2:2       Chroma is at half horizontal resolution.\n"
00972             "4:2:0       Chroma is at quarter resolution, which may cause minor color smearing.\n"
00973             "            However, this chroma format is most likely to be compatible with video editing software.");
00974 
00975     Pstring = secprop->Add_string("capture format", Property::Changeable::OnlyAtStart,"default");
00976     Pstring->Set_values(captureformats);
00977     Pstring->Set_help("Capture format to use when capturing video. The availability of the format depends on how DOSBox-X was compiled.\n"
00978             "default                     Use compiled-in default (avi-zmbv)\n"
00979             "avi-zmbv                    Use DOSBox-style AVI + ZMBV codec with PCM audio\n"
00980             "mpegts-h264                 Use MPEG transport stream + H.264 + AAC audio. Resolution & refresh rate changes can be contained\n"
00981             "                            within one file with this choice, however not all software can support mid-stream format changes.");
00982 
00983     Pint = secprop->Add_int("shell environment size",Property::Changeable::OnlyAtStart,0);
00984     Pint->SetMinMax(0,65280);
00985     Pint->Set_help("Size of the initial DOSBox shell environment block, in bytes. This does not affect the environment block of sub-processes spawned from the shell.\n"
00986             "This option has no effect unless dynamic kernel allocation is enabled.");
00987 
00988     Pint = secprop->Add_int("private area size",Property::Changeable::OnlyAtStart,32768); // DOSBox mainline compatible 32KB region
00989     Pint->SetMinMax(16,128*1024);
00990     Pint->Set_help("Set DOSBox-X private memory area size. This area contains private memory structures used by the DOS kernel.\n"
00991             "It is discarded when you boot into another OS. Mainline DOSBox uses 32KB. Testing shows that it is possible\n"
00992             "to run DOSBox with as little as 4KB. If DOSBox-X aborts with error \"not enough memory for internal tables\"\n"
00993             "then you need to increase this value.");
00994 
00995     // NOTE: This will be revised as I test the DOSLIB code against more VGA/SVGA hardware!
00996     Pstring = secprop->Add_string("vga attribute controller mapping",Property::Changeable::WhenIdle,"auto");
00997     Pstring->Set_values(vga_ac_mapping_settings);
00998     Pstring->Set_help(
00999             "This affects how the attribute controller maps colors, especially in 256-color mode.\n"
01000             "Some SVGA cards handle the attribute controller palette differently than most SVGA cards.\n"
01001             "  auto                         Automatically pick the mapping based on the SVGA chipset.\n"
01002             "  4x4                          Split into two 4-bit nibbles, map through AC, recombine. This is standard VGA behavior including clone SVGA cards.\n"
01003             "  4low                         Split into two 4-bit nibbles, remap only the low 4 bits, recombine. This is standard ET4000 behavior.\n"
01004             "\n"
01005             "NOTES:\n"
01006             "  Demoscene executable 'COPPER.EXE' requires the '4low' behavior in order to display line-fading effects\n"
01007             "  (including scrolling credits) correctly, else those parts of the demo show up as a blank screen.\n"
01008             "  \n"
01009             "  4low behavior is default for ET4000 emulation.");
01010 
01011     // TODO: At some point, I would like to make "mask" the default instead of "fast"
01012     Pstring = secprop->Add_string("a20",Property::Changeable::WhenIdle,"fast");
01013     Pstring->Set_help("A20 gate emulation mode.\n"
01014               "The on/off/on_fake/off_fake options are intended for testing and debugging DOS development,\n"
01015               "or to emulate obscure hardware, or to work around potential extended memory problems with DOS programs.\n"
01016               "on_fake/off_fake are intended to test whether a program carries out a memory test to ensure the A20\n"
01017               "gate is set as intended (as HIMEM.SYS does). If it goes by the gate bit alone, it WILL crash.\n"
01018               "This parameter is also changeable from the builtin A20GATE command.\n"
01019               "  fast                         Emulate A20 gating by remapping the first 64KB @ 1MB boundary (fast, mainline DOSBox behavior)\n"
01020               "  mask                         Emulate A20 gating by masking memory I/O address (accurate)\n"
01021               "  off                          Lock A20 gate off (Software/OS cannot enable A20)\n"
01022               "  on                           Lock A20 gate on (Software/OS cannot disable A20)\n"
01023               "  off_fake                     Lock A20 gate off but allow bit to toggle (hope your DOS game tests the HMA!)\n"
01024               "  on_fake                      Lock A20 gate on but allow bit to toggle");
01025 
01026     Pbool = secprop->Add_bool("turn off a20 gate on boot",Property::Changeable::WhenIdle,true);
01027     Pbool->Set_help("If enabled, A20 gate is switched off when booting a guest OS.\n"
01028                     "Enabled by default. Recommended for MS-DOS when HIMEM.SYS is not installed in the guest OS.\n"
01029                     "If disabled, and MS-DOS does not load HIMEM.SYS, programs and features that rely on the 1MB wraparound will fail.");
01030 
01031     Pstring = secprop->Add_string("isa bus clock",Property::Changeable::WhenIdle,"std8.3");
01032     Pstring->Set_help("ISA BCLK frequency, used to emulate I/O delay.\n"
01033               "WARNING: In future revisions, PCI/motherboard chipset emulation will allow the guest OS/program to alter this value at runtime.\n"
01034               "  std8.3                       8.333MHz (typical 386-class or higher)\n"
01035               "  std8                         8MHz\n"
01036               "  std6                         6MHz\n"
01037               "  std4.77                      4.77MHz (precisely 1/3 x 14.31818MHz). Bus frequency of older PC/XT systems.\n"
01038               "  oc10                         10MHz\n"
01039               "  oc12                         12MHz\n"
01040               "  oc15                         15MHz\n"
01041               "  oc16                         16MHz\n"
01042               "  <integer or float>           Any integer or floating point value will be used as the clock frequency in Hz\n"
01043               "  <integer/integer ratio>      If a ratio is given (num/den), the ratio will be used as the clock frequency");
01044 
01045     Pstring = secprop->Add_string("pci bus clock",Property::Changeable::WhenIdle,"std33.3");
01046     Pstring->Set_help("PCI bus frequency, used to emulate I/O delay.\n"
01047               "WARNING: In future revisions, PCI/motherboard chipset emulation will allow the guest OS/program to alter this value at runtime.\n"
01048               "  std33.3                      33.333MHz (very common setting on motherboards)\n"
01049               "  std30                        30MHz (some older mid-1990's Pentium systems)\n"
01050               "  std25                        25MHz\n"
01051               "  <integer or float>           Any integer or floating point value will be used as the clock frequency in Hz\n"
01052               "  <integer/integer ratio>      If a ratio is given (num/den), the ratio will be used as the clock frequency");
01053 
01054     Pstring = secprop->Add_string("call binary on reset",Property::Changeable::WhenIdle,"");
01055     Pstring->Set_help("If set, this is the path of a binary blob to load into the ROM BIOS area and execute immediately after CPU reset.\n"
01056                       "It will be executed before the BIOS POST routine, only ONCE. The binary blob is expected either to IRET or to\n"
01057                       "jump directly to F000:FFF0 to return control to the BIOS.\n"
01058                       "This can be used for x86 assembly language experiments and automated testing against the CPU emulation.");
01059 
01060     Pstring = secprop->Add_string("call binary on boot",Property::Changeable::WhenIdle,"");
01061     Pstring->Set_help("If set, this is the path of a binary blob to load into the ROM BIOS area and execute immediately before booting the DOS system.\n"
01062                       "This can be used for x86 assembly language experiments and automated testing against the CPU emulation.");
01063 
01064     Pint = secprop->Add_int("rom bios allocation max",Property::Changeable::OnlyAtStart,0);
01065     Pint->SetMinMax(0,128);
01066     Pint->Set_help("Maximum size (top down from 1MB) allowed for ROM BIOS dynamic allocation in KB");
01067 
01068     Pint = secprop->Add_int("rom bios minimum size",Property::Changeable::OnlyAtStart,0);
01069     Pint->SetMinMax(0,128);
01070     Pint->Set_help("Once ROM BIOS layout is finalized, trim total region down to a minimum amount in KB");
01071 
01072     Pint = secprop->Add_int("irq delay ns", Property::Changeable::WhenIdle,-1);
01073     Pint->SetMinMax(-1,100000);
01074     Pint->Set_help( "IRQ delay in nanoseconds. Set to -1 to use default, 0 to disable.\n"
01075                     "This is a more precise version of the irqdelay= setting.\n"
01076                     "There are some old DOS games and demos that have race conditions with IRQs that need a nonzero value here to work properly.");
01077 
01078     Pint = secprop->Add_int("iodelay", Property::Changeable::WhenIdle,-1);
01079     Pint->SetMinMax(-1,100000);
01080     Pint->Set_help( "I/O delay in nanoseconds for I/O port access. Set to -1 to use default, 0 to disable.\n"
01081             "A value of 1000 (1us) is recommended for ISA bus type delays. If your game\n"
01082             "or demo is not sensitive to I/O port and ISA bus timing, you can turn this option off\n"
01083             "(set to 0) to increase game performance.");
01084 
01085     Pint = secprop->Add_int("iodelay16", Property::Changeable::WhenIdle,-1);
01086     Pint->SetMinMax(-1,100000);
01087     Pint->Set_help( "I/O delay for 16-bit transfers. -1 to use default, 0 to disable.");
01088 
01089     Pint = secprop->Add_int("iodelay32", Property::Changeable::WhenIdle,-1);
01090     Pint->SetMinMax(-1,100000);
01091     Pint->Set_help( "I/O delay for 32-bit transfers. -1 to use default, 0 to disable.");
01092 
01093     // STUB OPTION, NOT YET FULLY IMPLEMENTED
01094     Pstring = secprop->Add_string("acpi", Property::Changeable::OnlyAtStart,"off");
01095     Pstring->Set_values(acpisettings);
01096     Pstring->Set_help("ACPI emulation, and what version of the specification to follow.\n"
01097             "WARNING: This option is very experimental at this time and should not be enabled unless you're willing to accept the consequences.\n"
01098             "         Intended for use with ACPI-aware OSes including Linux and Windows 98/ME. This option will also slightly reduce available\n"
01099             "         system memory to make room for the ACPI tables, just as real BIOSes do, and reserve an IRQ for ACPI functions.");
01100 
01101     // STUB OPTION, NOT YET FULLY IMPLEMENTED
01102     Pstring = secprop->Add_string("acpi rsd ptr location", Property::Changeable::OnlyAtStart,"auto");
01103     Pstring->Set_values(acpi_rsd_ptr_settings);
01104     Pstring->Set_help("Where to store the Root System Description Pointer structure. You can have it stored in the ROM BIOS area, or the Extended Bios Data Area.");
01105 
01106     // STUB OPTION, NOT YET FULLY IMPLEMENTED
01107     Pint = secprop->Add_int("acpi sci irq", Property::Changeable::WhenIdle,-1);
01108     Pint->Set_help("IRQ to assign as ACPI system control interrupt. set to -1 to automatically assign.");
01109 
01110     // STUB OPTION, NOT YET FULLY IMPLEMENTED
01111     Phex = secprop->Add_hex("acpi iobase",Property::Changeable::WhenIdle,0);
01112     Phex->Set_help("I/O port base for the ACPI device Power Management registers. Set to 0 for automatic assignment.");
01113 
01114     // STUB OPTION, NOT YET FULLY IMPLEMENTED
01115     Pint = secprop->Add_int("acpi reserved size", Property::Changeable::WhenIdle,0);
01116     Pint->Set_help("Amount of memory at top to reserve for ACPI structures and tables. Set to 0 for automatic assignment.");
01117 
01118     Pint = secprop->Add_int("memsize", Property::Changeable::WhenIdle,16);
01119     Pint->SetMinMax(1,511);
01120     Pint->Set_help(
01121         "Amount of memory DOSBox has in megabytes.\n"
01122         "  This value is best left at its default to avoid problems with some games,\n"
01123         "  though few games might require a higher value.\n"
01124         "  There is generally no speed advantage when raising this value.\n"
01125         "  Programs that use 286 protected mode like Windows 3.0 in Standard Mode may crash with more than 15MB.");
01126 
01127     Pint = secprop->Add_int("memsizekb", Property::Changeable::WhenIdle,0);
01128     Pint->SetMinMax(0,524288);
01129     Pint->Set_help(
01130         "Amount of memory DOSBox has in kilobytes.\n"
01131         "  This value should normally be set to 0.\n"
01132         "  If nonzero, it is added to the memsize parameter.\n"
01133         "  Finer grained control of total memory may be useful in\n"
01134         "  emulating ancient DOS machines with less than 640KB of\n"
01135         "  RAM or early 386 systems with odd extended memory sizes.");
01136 
01137     Pint = secprop->Add_int("dos mem limit", Property::Changeable::WhenIdle,0);
01138     Pint->SetMinMax(0,1023);
01139     Pint->Set_help( "Limit DOS conventional memory to this amount. Does not affect extended memory.\n"
01140             "Setting this option to a value in the range 636-639 can be used to simulate modern BIOSes\n"
01141             "that maintain an EBDA (Extended BIOS Data Area) at the top of conventional memory.\n"
01142             "You may also play with this option for diagnostic purposes or to stress test DOS programs in limited memory setups.\n"
01143             "\n"
01144             "A few DOS games & demos require this option to be set:\n"
01145             "     Majic 12 \"Show\": If UMBs are enabled, set this option to 639 to avoid MCB chain corruption error.");
01146 
01147     Pbool = secprop->Add_bool("isa memory hole at 512kb",Property::Changeable::WhenIdle,false);
01148     Pbool->Set_help("If set, emulate an ISA memory hole at the 512KB to 640KB area (0x80000-0x9FFFF).");
01149 
01150     Pint = secprop->Add_int("memalias", Property::Changeable::WhenIdle,0);
01151     Pint->SetMinMax(0,32);
01152     Pint->Set_help(
01153         "Memory aliasing emulation, in number of valid address bits.\n"
01154         ". Many 386/486 class motherboards and processors prior to 1995\n"
01155         "  suffered from memory aliasing for various technical reasons. If the software you are\n"
01156         "  trying to run assumes aliasing, or otherwise plays cheap tricks with paging,\n"
01157         "  enabling this option can help. Note that enabling this option can cause slight performance degredation. Set to 0 to disable.\n"
01158         "  Recommended values when enabled:\n"
01159         "    24: 16MB aliasing. Common on 386SX systems (CPU had 24 external address bits)\n"
01160         "        or 386DX and 486 systems where the CPU communicated directly with the ISA bus (A24-A31 tied off)\n"
01161         "    26: 64MB aliasing. Some 486s had only 26 external address bits, some motherboards tied off A26-A31");
01162 
01163     Pstring = secprop->Add_string("pc-98 fm board",Property::Changeable::Always,"auto");
01164     Pstring->Set_values(pc98fmboards);
01165     Pstring->Set_help("In PC-98 mode, selects the FM music board to emulate.");
01166 
01167     Pint = secprop->Add_int("pc-98 fm board irq", Property::Changeable::WhenIdle,0);
01168     Pint->Set_help("If set, helps to determine the IRQ of the FM board. A setting of zero means to auto-determine the IRQ.");
01169 
01170     Phex = secprop->Add_hex("pc-98 fm board io port", Property::Changeable::WhenIdle,0);
01171     Phex->Set_help("If set, helps to determine the base I/O port of the FM board. A setting of zero means to auto-determine the port number.");
01172 
01173     Pbool = secprop->Add_bool("pc-98 sound bios",Property::Changeable::WhenIdle,false);
01174     Pbool->Set_help("Set Sound BIOS enabled bit in MEMSW 4 for some games that require it.\n"
01175                     "TODO: Real emulation of PC-9801-26K/86 Sound BIOS");
01176 
01177     Pbool = secprop->Add_bool("pc-98 buffer page flip",Property::Changeable::WhenIdle,false);
01178     Pbool->Set_help("If set, the game's request to page flip will be delayed to vertical retrace, which can eliminate tearline artifacts.\n"
01179                     "Note that this is NOT the behavior of actual hardware. This option is provided for the user's preference.");
01180 
01181     Pbool = secprop->Add_bool("pc-98 enable 16-color",Property::Changeable::WhenIdle,true);
01182     Pbool->Set_help("Allow 16-color graphics mode if set, disable if not set");
01183 
01184     Pbool = secprop->Add_bool("pc-98 enable grcg",Property::Changeable::WhenIdle,true);
01185     Pbool->Set_help("Allow GRCG graphics functions if set, disable if not set");
01186 
01187     Pbool = secprop->Add_bool("pc-98 enable egc",Property::Changeable::WhenIdle,true);
01188     Pbool->Set_help("Allow EGC graphics functions if set, disable if not set");
01189 
01190     Pbool = secprop->Add_bool("pc-98 start gdc at 5mhz",Property::Changeable::WhenIdle,false);
01191     Pbool->Set_help("Start GDC at 5MHz if set, 2.5MHz if clear. May be required for some games.");
01192 
01193     Pbool = secprop->Add_bool("pc-98 allow scanline effect",Property::Changeable::WhenIdle,true);
01194     Pbool->Set_help("If set, PC-98 emulation will allow the DOS application to enable the 'scanline effect'\n"
01195                     "in 200-line graphics modes upconverted to 400-line raster display. When enabled, odd\n"
01196                     "numbered scanlines are blanked instead of doubled");
01197 
01198     Pstring = secprop->Add_string("pc-98 video mode",Property::Changeable::WhenIdle,"");
01199     Pstring->Set_values(pc98videomodeopt);
01200     Pstring->Set_help("Specify the preferred PC-98 video mode.\n"
01201                       "Valid values are 15, 24, or 31 for each specific horizontal refresh rate on the platform.\n"
01202                       "24khz is default and best supported at this time.\n"
01203                       "15khz is not implemented at this time.\n"
01204                       "31khz is experimental at this time.");
01205 
01206     Pint = secprop->Add_int("pc-98 timer master frequency", Property::Changeable::WhenIdle,0);
01207     Pint->SetMinMax(0,2457600);
01208     Pint->Set_help("8254 timer clock frequency (NEC PC-98). Depending on the CPU frequency the clock frequency is one of two common values.\n"
01209                    "If your setting is neither of the below the closest appropriate value will be chosen.\n"
01210                    "This setting affects the master clock rate that DOS applications must divide down from to program the timer\n"
01211                    "at the correct rate, which affects timer interrupt, PC speaker, and the COM1 RS-232C serial port baud rate.\n"
01212                    "8MHz is treated as an alias for 4MHz and 10MHz is treated as an alias for 5MHz.\n"
01213                    "    0: Use default (auto)\n"
01214                    "    4: 1.996MHz (as if 4MHz or multiple thereof CPU clock)\n"
01215                    "    5: 2.457MHz (as if 5MHz or multiple thereof CPU clock)");
01216 
01217     Pint = secprop->Add_int("pc-98 allow 4 display partition graphics", Property::Changeable::WhenIdle,-1);
01218     Pint->SetMinMax(-1,1);
01219     Pint->Set_help("According to NEC graphics controller documentation, graphics mode is supposed to support only\n"
01220                    "2 display partitions. Some games rely on hardware flaws that allowed 4 partitions.\n"
01221                    "   -1: Default (choose automatically)\n"
01222                    "    0: Disable\n"
01223                    "    1: Enable");
01224 
01225     Pbool = secprop->Add_bool("pc-98 force ibm keyboard layout",Property::Changeable::WhenIdle,false);
01226     Pbool->Set_help("Force to use a default keyboard layout like IBM US-English for PC-98 emulation.\n"
01227                     "Will only work with apps and games using BIOS for keyboard.");
01228 
01229     Pint = secprop->Add_int("vga bios size override", Property::Changeable::WhenIdle,0);
01230     Pint->SetMinMax(512,65536);
01231     Pint->Set_help("VGA BIOS size override. Override the size of the VGA BIOS (normally 32KB in compatible or 12KB in non-compatible).");
01232 
01233     Pbool = secprop->Add_bool("video bios dont duplicate cga first half rom font",Property::Changeable::WhenIdle,false);
01234     Pbool->Set_help("If set, save 4KB of EGA/VGA ROM space by pointing to the copy in the ROM BIOS of the first 128 chars");
01235 
01236     Pbool = secprop->Add_bool("video bios always offer 14-pixel high rom font",Property::Changeable::WhenIdle,false);
01237     Pbool->Set_help("If set, video BIOS will always carry the 14-pixel ROM font. If clear, 14-pixel rom font will not be offered except for EGA/VGA emulation.");
01238 
01239     Pbool = secprop->Add_bool("video bios always offer 16-pixel high rom font",Property::Changeable::WhenIdle,false);
01240     Pbool->Set_help("If set, video BIOS will always carry the 16-pixel ROM font. If clear, 16-pixel rom font will not be offered except for VGA emulation.");
01241 
01242     Pbool = secprop->Add_bool("video bios enable cga second half rom font",Property::Changeable::WhenIdle,true);
01243     Pbool->Set_help("If set, and emulating CGA/PCjr/Tandy, automatically provide the second half of the 8x8 ROM font.\n"
01244             "This setting is ignored for EGA/VGA emulation. If not set, you will need a utility like GRAFTABL.COM to load the second half of the ROM font for graphics.\n"
01245             "NOTE: if you disable the 14 & 16 pixel high font AND the second half when machine=cga, you will disable video bios completely.");
01246 
01247     Pstring = secprop->Add_string("forcerate",Property::Changeable::Always,"");
01248     Pstring->Set_help("Force the VGA framerate to a specific value(ntsc, pal, or specific hz), no matter what");
01249 
01250     Pbool = secprop->Add_bool("sierra ramdac",Property::Changeable::WhenIdle,true);
01251     Pbool->Set_help("Whether or not to emulate a Sierra or compatible RAMDAC at port 3C6h-3C9h.\n"
01252             "Some DOS games expect to access port 3C6h to enable highcolor/truecolor SVGA modes on older chipsets.\n"
01253             "Disable if you wish to emulate SVGA hardware that lacks a RAMDAC or (depending on the chipset) does\n"
01254             "not emulate a RAMDAC that is accessible through port 3C6h. This option has no effect for non-VGA video hardware.");
01255 
01256     Pbool = secprop->Add_bool("sierra ramdac lock 565",Property::Changeable::WhenIdle,false);
01257     Pbool->Set_help("When emulating High Sierra highcolor RAMDAC, assume 5:6:5 at all times if set. Else,\n"
01258             "bit 6 of the DAC command selects between 5:5:5 and 5:6:5. Set this option for demos or\n"
01259             "games that got the command byte wrong (MFX Transgrassion 2) or any other demo that is\n"
01260             "not rendering highcolor 16bpp correctly.");
01261 
01262     Pbool = secprop->Add_bool("page flip debug line",Property::Changeable::Always,false);
01263     Pbool->Set_help("VGA debugging switch. If set, an inverse line will be drawn on the exact scanline that the CRTC display offset registers were written.\n"
01264             "This can be used to help diagnose whether or not the DOS game is page flipping properly according to vertical retrace if the display on-screen is flickering.");
01265 
01266     Pbool = secprop->Add_bool("vertical retrace poll debug line",Property::Changeable::Always,false);
01267     Pbool->Set_help("VGA debugging switch. If set, an inverse green dotted line will be drawn on the exact scanline that the CRTC status port (0x3DA) was read.\n"
01268             "This can be used to help diagnose whether the DOS game is propertly waiting for vertical retrace.");
01269 
01270     Pbool = secprop->Add_bool("cgasnow",Property::Changeable::WhenIdle,true);
01271     Pbool->Set_help("When machine=cga, determines whether or not to emulate CGA snow in 80x25 text mode");
01272 
01273     Phex = secprop->Add_hex("vga 3da undefined bits",Property::Changeable::WhenIdle,0);
01274     Phex->Set_help("VGA status port 3BA/3DAh only defines bits 0 and 3. This setting allows you to assign a bit pattern to the undefined bits.\n"
01275                    "The purpose of this hack is to deal with demos that read and handle port 3DAh in ways that might crash if all are zero.\n"
01276                    "By default, this value is zero.");
01277 
01278     Pbool = secprop->Add_bool("unmask timer on int 10 setmode",Property::Changeable::OnlyAtStart,false);
01279     Pbool->Set_help("If set, INT 10h will unmask IRQ 0 (timer) when setting video modes.");
01280 
01281     Pbool = secprop->Add_bool("unmask keyboard on int 16 read",Property::Changeable::OnlyAtStart,false);
01282     Pbool->Set_help("If set, INT 16h will unmask IRQ 1 (keyboard) when asked to read keyboard input.");
01283 
01284     Pbool = secprop->Add_bool("int16 keyboard polling undocumented cf behavior",Property::Changeable::OnlyAtStart,false);
01285     Pbool->Set_help("If set, INT 16h function AH=01h will also set/clear the carry flag depending on whether input was available.\n"
01286                     "There are some old DOS games and demos that rely on this behavior to sense keyboard input, and this behavior\n"
01287                     "has been verified to occur on some old (early 90s) BIOSes.");
01288 
01289     Pbool = secprop->Add_bool("allow port 92 reset",Property::Changeable::OnlyAtStart,true);
01290     Pbool->Set_help("If set (default), allow the application to reset the CPU through port 92h");
01291 
01292     Pbool = secprop->Add_bool("enable port 92",Property::Changeable::WhenIdle,true);
01293     Pbool->Set_help("Emulate port 92h (PS/2 system control port A). If you want to emulate a system that pre-dates the PS/2, set to 0.");
01294 
01295     Pbool = secprop->Add_bool("enable 1st dma controller",Property::Changeable::WhenIdle,true);
01296     Pbool->Set_help("Emulate 1st (AT) DMA controller (default). Set to 0 if you wish to emulate a system that lacks DMA (PCjr and some Tandy systems)");
01297 
01298     Pbool = secprop->Add_bool("enable 2nd dma controller",Property::Changeable::WhenIdle,true);
01299     Pbool->Set_help("Emulate 2nd (AT) DMA controller (default). Set to 0 if you wish to emulate a PC/XT system without 16-bit DMA.\n"
01300             "Note: mainline DOSBox automatically disables 16-bit DMA when machine=cga or machine=hercules, while DOSBox-X does not.");
01301 
01302     Pbool = secprop->Add_bool("allow dma address decrement",Property::Changeable::WhenIdle,true);
01303     Pbool->Set_help("If set, allow increment & decrement modes as specified in the 8237 datasheet.\n"
01304             "If clear, always increment the address (as if to emulate clone 8237 implementations that skipped the inc/dec bit).");
01305 
01306     Pstring = secprop->Add_string("enable 128k capable 16-bit dma", Property::Changeable::OnlyAtStart,"auto");
01307     Pstring->Set_values(truefalseautoopt);
01308     Pstring->Set_help("If true, DMA controller emulation models ISA hardware that permits 16-bit DMA to span 128KB.\n"
01309                     "If false, DMA controller emulation models PCI hardware that limits 16-bit DMA to 64KB boundaries.\n"
01310                     "If auto, the choice is made according to other factors in hardware emulation");
01311 
01312     Pbool = secprop->Add_bool("enable dma extra page registers",Property::Changeable::WhenIdle,true);
01313     Pbool->Set_help("If set, emulate the extra page registers (I/O ports 0x80, 0x84-0x86, 0x88, 0x8C-0x8E), like actual hardware.\n"
01314             "Note that mainline DOSBox behavior is to NOT emulate these registers.");
01315 
01316     Pbool = secprop->Add_bool("dma page registers write-only",Property::Changeable::WhenIdle,false);
01317     Pbool->Set_help("Normally (on AT hardware) the DMA page registers are read/write. Set this option if you want to emulate PC/XT hardware where the page registers are write-only.");
01318 
01319     Pbool = secprop->Add_bool("enable slave pic",Property::Changeable::WhenIdle,true);
01320     Pbool->Set_help("Enable slave PIC (IRQ 8-15). Set this to 0 if you want to emulate a PC/XT type arrangement with IRQ 0-7 and no IRQ 2 cascade.");
01321 
01322     Pbool = secprop->Add_bool("enable pc nmi mask",Property::Changeable::WhenIdle,true);
01323     Pbool->Set_help("Enable PC/XT style NMI mask register (0xA0). Note that this option conflicts with the secondary PIC and will be ignored if the slave PIC is enabled.");
01324 
01325     Pbool = secprop->Add_bool("rom bios 8x8 CGA font",Property::Changeable::Always,true);
01326     Pbool->Set_help("If set, or mainline compatible bios mapping, a legacy 8x8 CGA font (first 128 characters) is stored at 0xF000:0xFA6E. DOS programs that do not use INT 10h to locate fonts might require that font to be located there.");
01327 
01328     Pbool = secprop->Add_bool("rom bios video parameter table",Property::Changeable::Always,true);
01329     Pbool->Set_help("If set, or mainline compatible bios mapping, DOSBox will emulate the video parameter table and assign that to INT 1Dh. If clear, table will not be provided.");
01330 
01331     Pbool = secprop->Add_bool("allow more than 640kb base memory",Property::Changeable::Always,false);
01332     Pbool->Set_help("If set, and space is available, allow conventional memory to extend past 640KB.\n"
01333             "For example, if machine=cga, conventional memory can extend out to 0xB800 and provide up to 736KB of RAM.\n"
01334             "This allows you to emulate PC/XT style memory extensions.");
01335 
01336     /* should be set to zero unless for very specific demos:
01337      *  - "Melvindale" by MFX (1996): Set this to 2, the nightmarish visual rendering code appears to draw 2 scanlines
01338      *    upward from the VESA linear framebuffer base we return, causing DOSBox to emit warnings about illegal read/writes
01339      *    from 0xBFFFF000-0xBFFFFFFF (just before the base of the framebuffer at 0xC0000000). It also has the effect of
01340      *    properly centering the picture on the screen. I suppose it's a miracle the demo didn't crash people's computers
01341      *    writing to undefined areas like that. */
01342     Pint = secprop->Add_int("vesa lfb base scanline adjust",Property::Changeable::WhenIdle,0);
01343     Pint->Set_help("If non-zero, the VESA BIOS will report the linear framebuffer offset by this many scanlines.\n"
01344             "This does not affect the linear framebuffer's location. It only affects the linear framebuffer\n"
01345             "location reported by the VESA BIOS. Set to nonzero for DOS games with sloppy VESA graphics pointer management.\n"
01346             "    MFX \"Melvindale\" (1996): Set this option to 2 to center the picture properly.");
01347 
01348     /* If set, all VESA BIOS modes map 128KB of video RAM at A0000-BFFFF even though VESA BIOS emulation
01349      * reports a 64KB window. Some demos like the 1996 Wired report
01350      * (ftp.scene.org/pub/parties/1995/wired95/misc/e-w95rep.zip) assume they can write past the window
01351      * by spilling into B0000 without bank switching. */
01352     Pbool = secprop->Add_bool("vesa map non-lfb modes to 128kb region",Property::Changeable::Always,false);
01353     Pbool->Set_help("If set, VESA BIOS SVGA modes will be set to map 128KB of video memory to A0000-BFFFF instead of\n"
01354                     "64KB at A0000-AFFFF. This does not affect the SVGA window size or granularity.\n"
01355                     "Some games or demoscene productions assume that they can render into the next SVGA window/bank\n"
01356                     "by writing to video memory beyond the current SVGA window address and will not appear correctly\n"
01357                     "without this option.");
01358 
01359     Pbool = secprop->Add_bool("allow hpel effects",Property::Changeable::Always,false);
01360     Pbool->Set_help("If set, allow the DOS demo or program to change the horizontal pel (panning) register per scanline.\n"
01361             "Some early DOS demos use this to create waving or sinus effects on the picture. Not very many VGA\n"
01362             "chipsets allow this, so far, only ATI chipsets are known to support this effect. Disabled by default.");
01363 
01364     Pbool = secprop->Add_bool("allow hretrace effects",Property::Changeable::Always,false);
01365     Pbool->Set_help("If set, allow the DOS demo or program to make the picture wavy by playing with the 'start horizontal"
01366             "retrace' register of the CRTC during the active picture. Some early DOS demos (Copper by Surprise!"
01367             "productions) need this option set for some demo effects to work. Disabled by default.");
01368 
01369     Pdouble = secprop->Add_double("hretrace effect weight",Property::Changeable::Always,4.0);
01370     Pdouble->Set_help("If emulating hretrace effects, this parameter adds 'weight' to the offset to smooth it out.\n"
01371             "the larger the number, the more averaging is applied. This is intended to emulate the inertia\n"
01372             "of the electron beam in a CRT monitor");
01373 
01374     Pint = secprop->Add_int("vesa modelist cap",Property::Changeable::Always,0);
01375     Pint->Set_help("IF nonzero, the VESA modelist is capped so that it contains no more than the specified number of video modes.\n"
01376             "Set this option to a value between 8 to 32 if the DOS application has problems with long modelists or a fixed\n"
01377             "buffer for querying modes. Such programs may crash if given the entire modelist supported by DOSBox-X.\n"
01378             "  Warcraft II by Blizzard ................ Set to a value between 8 and 16. This game has a fixed buffer that it\n"
01379             "                                           reads the modelist into. DOSBox-X's normal modelist is too long and\n"
01380             "                                           the game will overrun the buffer and crash without this setting.");
01381 
01382     Pint = secprop->Add_int("vesa modelist width limit",Property::Changeable::Always,0);
01383     Pint->Set_help("IF nonzero, VESA modes with horizontal resolution higher than the specified pixel count will not be listed.\n"
01384             "This is another way the modelist can be capped for DOS applications that have trouble with long modelists.");
01385 
01386     Pint = secprop->Add_int("vesa modelist height limit",Property::Changeable::Always,0);
01387     Pint->Set_help("IF nonzero, VESA modes with vertical resolution higher than the specified pixel count will not be listed.\n"
01388             "This is another way the modelist can be capped for DOS applications that have trouble with long modelists.");
01389 
01390     Pbool = secprop->Add_bool("vesa vbe 1.2 modes are 32bpp",Property::Changeable::Always,true);
01391     Pbool->Set_help("If set, truecolor (16M color) VESA BIOS modes in the 0x100-0x11F range are 32bpp. If clear, they are 24bpp.\n"
01392             "Some DOS games and demos assume one bit depth or the other and do not enumerate VESA BIOS modes, which is why this\n"
01393             "option exists.");
01394 
01395     Pbool = secprop->Add_bool("allow low resolution vesa modes",Property::Changeable::Always,true);
01396     Pbool->Set_help("If set, allow low resolution VESA modes (320x200x16/24/32bpp and so on). You could set this to false to simulate\n"
01397             "SVGA hardware with a BIOS that does not support the lowres modes for testing purposes.");
01398 
01399     Pbool = secprop->Add_bool("allow 32bpp vesa modes",Property::Changeable::Always,true);
01400     Pbool->Set_help("If the DOS game or demo has problems with 32bpp VESA modes, set to 'false'");
01401 
01402     Pbool = secprop->Add_bool("allow 24bpp vesa modes",Property::Changeable::Always,true);
01403     Pbool->Set_help("If the DOS game or demo has problems with 24bpp VESA modes, set to 'false'");
01404 
01405     Pbool = secprop->Add_bool("allow 16bpp vesa modes",Property::Changeable::Always,true);
01406     Pbool->Set_help("If the DOS game or demo has problems with 16bpp VESA modes, set to 'false'");
01407 
01408     Pbool = secprop->Add_bool("allow 15bpp vesa modes",Property::Changeable::Always,true);
01409     Pbool->Set_help("If the DOS game or demo has problems with 15bpp VESA modes, set to 'false'");
01410 
01411     Pbool = secprop->Add_bool("allow 8bpp vesa modes",Property::Changeable::Always,true);
01412     Pbool->Set_help("If the DOS game or demo has problems with 8bpp VESA modes, set to 'false'");
01413 
01414     Pbool = secprop->Add_bool("allow 4bpp vesa modes",Property::Changeable::Always,true);
01415     Pbool->Set_help("If the DOS game or demo has problems with 4bpp VESA modes, set to 'false'");
01416 
01417     Pbool = secprop->Add_bool("allow tty vesa modes",Property::Changeable::Always,true);
01418     Pbool->Set_help("If the DOS game or demo has problems with text VESA modes, set to 'false'");
01419 
01420     Pbool = secprop->Add_bool("double-buffered line compare",Property::Changeable::Always,false);
01421     Pbool->Set_help("This setting affects the VGA Line Compare register. Set to false (default value) to emulate most VGA behavior\n"
01422             "Set to true for the value to latch once at the start of the frame.");
01423 
01424     Pbool = secprop->Add_bool("ignore vblank wraparound",Property::Changeable::Always,false);
01425     Pbool->Set_help("DOSBox-X can handle active display properly if games or demos reprogram vertical blanking to end in the active picture area.\n"
01426             "If the wraparound handling prevents the game from displaying properly, set this to false. Out of bounds vblank values will be ignored.\n");
01427 
01428     Pbool = secprop->Add_bool("enable vga resize delay",Property::Changeable::Always,false);
01429     Pbool->Set_help("If the DOS game you are running relies on certain VGA raster tricks that affect active display area, enable this option.\n"
01430             "This adds a delay between VGA mode changes and window updates. It also means that if you are capturing a demo or game,\n"
01431             "that your capture will also show a few garbled frames at any point mode changes occur, which is why this option is disabled\n"
01432             "by default. If you intend to run certain DOS games and demos like DoWhackaDo, enable this option.");
01433 
01434     Pbool = secprop->Add_bool("resize only on vga active display width increase",Property::Changeable::Always,false);
01435     Pbool->Set_help("If set, changes to the Display End register of the CRTC do not trigger DOSBox to resize it's window\n"
01436             "IF the value written is less than the current value. Some demos like DoWhackaDo need this option set\n"
01437             "because of the way it's raster effects work. If the DOSBox window rapidly changes size during a demo\n"
01438             "try setting this option. Else, leave it turned off. Changes to other VGA CRTC registers will trigger\n"
01439             "a DOSBox mode change as normal regardless of this setting.");
01440 
01441     Pbool = secprop->Add_bool("enable pci bus",Property::Changeable::OnlyAtStart,true);
01442     Pbool->Set_help("Enable PCI bus emulation");
01443 
01444     Pbool = secprop->Add_bool("vga palette update on full load",Property::Changeable::Always,true);
01445     Pbool->Set_help("If set, all three bytes of the palette entry must be loaded before taking the color,\n"
01446                     "which is fairly typical SVGA behavior. If not set, partial changes are allowed.");
01447 
01448     Pbool = secprop->Add_bool("ignore odd-even mode in non-cga modes",Property::Changeable::Always,false);
01449     Pbool->Set_help("Some demoscene productions use VGA Mode X but accidentally enable odd/even mode.\n"
01450                     "Setting this option can correct for that and render the demo properly.\n"
01451                     "This option forces VGA emulation to ignore odd/even mode except in text and CGA modes.");
01452 
01453     secprop=control->AddSection_prop("render",&Null_Init,true);
01454     Pint = secprop->Add_int("frameskip",Property::Changeable::Always,0);
01455     Pint->SetMinMax(0,10);
01456     Pint->Set_help("How many frames DOSBox skips before drawing one.");
01457 
01458     Pstring = secprop->Add_string("aspect", Property::Changeable::Always, "false");
01459     Pstring->Set_values(aspectmodes);
01460     Pstring->Set_help(
01461         "Aspect ratio correction mode. Can be set to the following values:\n"
01462         "  'false' (default):\n"
01463         "      'direct3d'/opengl outputs: image is simply scaled to full window/fullscreen size, possibly resulting in disproportional image\n"
01464         "      'surface' output: it does no aspect ratio correction (default), resulting in disproportional images if VGA mode pixel ratio is not 4:3\n"
01465         "  'true':\n"
01466         "      'direct3d'/opengl outputs: uses output driver functions to scale / pad image with black bars, correcting output to proportional 4:3 image\n"
01467         "          In most cases image degradation should not be noticeable (it all depends on the video adapter and how much the image is upscaled).\n"
01468         "          Should have none to negligible impact on performance, mostly being done in hardware\n"
01469         "      'surface' output: inherits old DOSBox aspect ratio correction method (adjusting rendered image line count to correct output to 4:3 ratio)\n"
01470         "          Due to source image manipulation this mode does not mix well with scalers, i.e. multiline scalers like hq2x/hq3x will work poorly\n"
01471         "          Slightly degrades visual image quality. Has a tiny impact on performance"
01472 #if C_XBRZ
01473         "\n"
01474         "          When using xBRZ scaler with 'surface' output, aspect ratio correction is done by the scaler itself, so none of the above apply"
01475 #endif
01476 #if C_SURFACE_POSTRENDER_ASPECT
01477         "\n"
01478         "  'nearest':\n"
01479         "      'direct3d'/opengl outputs: not available, fallbacks to 'true' mode automatically\n"
01480         "      'surface' output: scaler friendly aspect ratio correction, works by rescaling rendered image using nearest neighbor scaler\n"
01481         "          Complex scalers work. Image quality is on par with 'true' mode (and better with scalers). More CPU intensive than 'true' mode\n"
01482 #if C_XBRZ
01483         "          When using xBRZ scaler with 'surface' output, aspect ratio correction is done by the scaler itself, so it fallbacks to 'true' mode\n"
01484 #endif
01485         "  'bilinear':\n"
01486         "      'direct3d'/opengl outputs: not available, fallbacks to 'true' mode automatically\n"
01487         "      'surface' output: scaler friendly aspect ratio correction, works by rescaling rendered image using bilinear scaler\n"
01488         "          Complex scalers work. Image quality is much better, should be on par with using 'direct3d' output + 'true' mode\n"
01489         "          Very CPU intensive, high end CPU may be required"
01490 #if C_XBRZ
01491         "\n"
01492         "          When using xBRZ scaler with 'surface' output, aspect ratio correction is done by the scaler itself, so it fallbacks to 'true' mode"
01493 #endif
01494 #endif
01495     );
01496 
01497     Pbool = secprop->Add_bool("char9",Property::Changeable::Always,true);
01498     Pbool->Set_help("Allow 9-pixel wide text mode fonts.");
01499 
01500     /* NTS: In the original code borrowed from yhkong, this was named "multiscan". All it really does is disable
01501      *      the doublescan down-rezzing DOSBox normally does with 320x240 graphics so that you get the full rendition of what a VGA output would emit. */
01502     Pbool = secprop->Add_bool("doublescan",Property::Changeable::Always,true);
01503     Pbool->Set_help("If set, doublescanned output emits two scanlines for each source line, in the\n"
01504             "same manner as the actual VGA output (320x200 is rendered as 640x400 for example).\n"
01505             "If clear, doublescanned output is rendered at the native source resolution (320x200 as 320x200).\n"
01506             "This affects the raster PRIOR to the software or hardware scalers. Choose wisely.\n");
01507 
01508     Pmulti = secprop->Add_multi("scaler",Property::Changeable::Always," ");
01509     Pmulti->SetValue("normal2x",/*init*/true);
01510     Pmulti->Set_help("Scaler used to enlarge/enhance low resolution modes. If 'forced' is appended,\n"
01511                      "then the scaler will be used even if the result might not be desired.");
01512     Pstring = Pmulti->GetSection()->Add_string("type",Property::Changeable::Always,"normal2x");
01513     Pstring->Set_values(scalers);
01514 
01515     Pstring = Pmulti->GetSection()->Add_string("force",Property::Changeable::Always,"");
01516     Pstring->Set_values(force);
01517 
01518 #if C_XBRZ
01519     Pint = secprop->Add_int("xbrz slice",Property::Changeable::OnlyAtStart,16);
01520     Pint->SetMinMax(1,1024);
01521     Pint->Set_help("Number of screen lines to process in single xBRZ scaler taskset task, affects xBRZ performance, 16 is the default");
01522 
01523     Pint = secprop->Add_int("xbrz fixed scale factor",Property::Changeable::OnlyAtStart, 0);
01524     Pint->SetMinMax(0,6);
01525     Pint->Set_help("To use fixed xBRZ scale factor (i.e. to attune performance), set it to 2-6, 0 - use automatic calculation (default)");
01526 
01527     Pint = secprop->Add_int("xbrz max scale factor",Property::Changeable::OnlyAtStart, 0);
01528     Pint->SetMinMax(0,6);
01529     Pint->Set_help("To cap maximum xBRZ scale factor used (i.e. to attune performance), set it to 2-6, 0 - use scaler allowed maximum (default)");
01530 #endif
01531 
01532     Pbool = secprop->Add_bool("autofit",Property::Changeable::Always,true);
01533     Pbool->Set_help(
01534         "Best fits image to window\n"
01535         "- Intended for output=direct3d, fullresolution=original, aspect=true");
01536 
01537 
01538     secprop=control->AddSection_prop("vsync",&Null_Init,true);//done
01539 
01540     Pstring = secprop->Add_string("vsyncmode",Property::Changeable::WhenIdle,"off");
01541     Pstring->Set_values(vsyncmode);
01542     Pstring->Set_help("Synchronize vsync timing to the host display. Requires calibration within dosbox.");
01543     Pstring = secprop->Add_string("vsyncrate",Property::Changeable::WhenIdle,"75");
01544     Pstring->Set_values(vsyncrate);
01545     Pstring->Set_help("Vsync rate used if vsync is enabled. Ignored if vsyncmode is set to host (win32).");
01546 
01547     secprop=control->AddSection_prop("cpu",&Null_Init,true);//done
01548     Pstring = secprop->Add_string("core",Property::Changeable::WhenIdle,"auto");
01549     Pstring->Set_values(cores);
01550     Pstring->Set_help("CPU Core used in emulation. auto will switch to dynamic if available and appropriate.\n"
01551             "WARNING: Do not use dynamic or auto setting core with Windows 95 or other preemptive\n"
01552             "multitasking OSes with protected mode paging, you should use the normal core instead.");
01553 
01554     Pbool = secprop->Add_bool("fpu",Property::Changeable::Always,true);
01555     Pbool->Set_help("Enable FPU emulation");
01556 
01557     Pbool = secprop->Add_bool("segment limits",Property::Changeable::Always,true);
01558     Pbool->Set_help("Enforce segment limits");
01559 
01560     Pbool = secprop->Add_bool("double fault",Property::Changeable::Always,true);
01561     Pbool->Set_help("Emulate double fault exception");
01562 
01563     Pbool = secprop->Add_bool("reset on triple fault",Property::Changeable::Always,true);
01564     Pbool->Set_help("Reset CPU on triple fault condition (failure to handle double fault)");
01565 
01566     Pbool = secprop->Add_bool("always report double fault",Property::Changeable::Always,false);
01567     Pbool->Set_help("Always report (to log file) double faults if set. Else, a double fault is reported only once. Set this option for debugging purposes.");
01568 
01569     Pbool = secprop->Add_bool("always report triple fault",Property::Changeable::Always,false);
01570     Pbool->Set_help("Always report (to log file) triple faults if set. Else, a triple fault is reported only once. Set this option for debugging purposes.");
01571 
01572     Pbool = secprop->Add_bool("enable msr",Property::Changeable::Always,true);
01573     Pbool->Set_help("Allow RDMSR/WRMSR instructions. This option is only meaningful when cputype=pentium.\n"
01574             "WARNING: Leaving this option enabled while installing Windows 95/98/ME can cause crashes.");
01575 
01576     Pbool = secprop->Add_bool("enable cmpxchg8b",Property::Changeable::Always,true);
01577     Pbool->Set_help("Enable Pentium CMPXCHG8B instruction. Enable this explicitly if using software that uses this instruction.\n"
01578             "You must enable this option to run Windows ME because portions of the kernel rely on this instruction.");
01579 
01580     Pbool = secprop->Add_bool("ignore undefined msr",Property::Changeable::Always,false);
01581     Pbool->Set_help("Ignore RDMSR/WRMSR on undefined registers. Normally the CPU will fire an Invalid Opcode exception in that case.\n"
01582             "This option is off by default, enable if using software or drivers that assumes the presence of\n"
01583             "certain MSR registers without checking. If you are using certain versions of the 3Dfx glide drivers for MS-DOS\n"
01584             "you will need to set this to TRUE as 3Dfx appears to have coded GLIDE2.OVL to assume the presence\n"
01585             "of Pentium Pro/Pentium II MTRR registers.\n"
01586             "WARNING: Leaving this option enabled while installing Windows 95/98/ME can cause crashes.");
01587 
01588     /* NTS: This setting is honored by all cpu cores except dynamic core */
01589     Pint = secprop->Add_int("interruptible rep string op",Property::Changeable::Always,-1);
01590     Pint->SetMinMax(-1,65536);
01591     Pint->Set_help("if nonzero, REP string instructions (LODS/MOVS/STOS/INS/OUTS) are interruptible (by interrupts or other events).\n"
01592             "if zero, REP string instructions are carried out in full before processing events and interrupts.\n"
01593             "Set to -1 for a reasonable default setting based on cpu type and other configuration.\n"
01594             "A setting of 0 can improve emulation speed at the expense of emulation accuracy.\n"
01595             "A nonzero setting (1-8) may be needed for DOS games and demos that use the IRQ 0 interrupt to play digitized samples\n"
01596             "while doing VGA palette animation at the same time (use case of REP OUTS), where the non-interruptible version\n"
01597             "would cause an audible drop in audio pitch.");
01598 
01599     Pint = secprop->Add_int("dynamic core cache block size",Property::Changeable::Always,32);
01600     Pint->SetMinMax(1,65536);
01601     Pint->Set_help("dynamic core cache block size. default value is 32. change this value carefully.\n"
01602             "according to forum discussion, setting this to 1 can aid debugging, however doing so\n"
01603             "also causes problems with 32-bit protected mode DOS games and reduces the performance\n"
01604             "of the dynamic core.\n");
01605 
01606     Pstring = secprop->Add_string("cputype",Property::Changeable::Always,"auto");
01607     Pstring->Set_values(cputype_values);
01608     Pstring->Set_help("CPU Type used in emulation. auto emulates a 486 which tolerates Pentium instructions.");
01609 
01610     Pmulti_remain = secprop->Add_multiremain("cycles",Property::Changeable::Always," ");
01611     Pmulti_remain->Set_help(
01612         "Amount of instructions DOSBox tries to emulate each millisecond.\n"
01613         "Setting this value too high results in sound dropouts and lags.\n"
01614         "Cycles can be set in 3 ways:\n"
01615         "  'auto'          tries to guess what a game needs.\n"
01616         "                  It usually works, but can fail for certain games.\n"
01617         "  'fixed #number' will set a fixed amount of cycles. This is what you usually\n"
01618         "                  need if 'auto' fails (Example: fixed 4000).\n"
01619         "  'max'           will allocate as much cycles as your computer is able to\n"
01620         "                  handle.");
01621 
01622     Pstring = Pmulti_remain->GetSection()->Add_string("type",Property::Changeable::Always,"auto");
01623     Pmulti_remain->SetValue("auto",/*init*/true);
01624     Pstring->Set_values(cyclest);
01625 
01626     Pstring = Pmulti_remain->GetSection()->Add_string("parameters",Property::Changeable::Always,"");
01627     
01628     Pint = secprop->Add_int("cycleup",Property::Changeable::Always,10);
01629     Pint->SetMinMax(1,1000000);
01630     Pint->Set_help("Amount of cycles to decrease/increase with keycombos.(CTRL-F11/CTRL-F12)");
01631 
01632     Pint = secprop->Add_int("cycledown",Property::Changeable::Always,20);
01633     Pint->SetMinMax(1,1000000);
01634     Pint->Set_help("Setting it lower than 100 will be a percentage.");
01635 
01636     Pbool = secprop->Add_bool("use dynamic core with paging on",Property::Changeable::Always,false);
01637     Pbool->Set_help("Dynamic core is NOT compatible with the way page faults in the guest are handled in DosBox-X.\n"
01638             "Windows 9x may crash with paging on if dynamic core is enabled. Enable at your own risk.\n");
01639             
01640     Pbool = secprop->Add_bool("ignore opcode 63",Property::Changeable::Always,true);
01641     Pbool->Set_help("When debugging, do not report illegal opcode 0x63.\n"
01642             "Enable this option to ignore spurious errors while debugging from within Windows 3.1/9x/ME");
01643 
01644     Pbool = secprop->Add_bool("apmbios",Property::Changeable::WhenIdle,true);
01645     Pbool->Set_help("Emulate Advanced Power Management BIOS calls");
01646 
01647     Pbool = secprop->Add_bool("apmbios pnp",Property::Changeable::WhenIdle,false);
01648     Pbool->Set_help("If emulating ISA PnP BIOS, announce APM BIOS in PnP enumeration.\n"
01649             "Warning: this can cause Windows 95 OSR2 and later to enumerate the APM BIOS twice and cause problems.");
01650 
01651     Pstring = secprop->Add_string("apmbios version",Property::Changeable::WhenIdle,"auto");
01652     Pstring->Set_values(apmbiosversions);
01653     Pstring->Set_help("What version of the APM BIOS specification to emulate.\n"
01654             "You will need at least APM BIOS v1.1 for emulation to work with Windows 95/98/ME");
01655 
01656     Pbool = secprop->Add_bool("apmbios allow realmode",Property::Changeable::WhenIdle,true);
01657     Pbool->Set_help("Allow guest OS to connect from real mode.");
01658 
01659     Pbool = secprop->Add_bool("apmbios allow 16-bit protected mode",Property::Changeable::WhenIdle,true);
01660     Pbool->Set_help("Allow guest OS to connect from 16-bit protected mode.");
01661 
01662     Pbool = secprop->Add_bool("apmbios allow 32-bit protected mode",Property::Changeable::WhenIdle,true);
01663     Pbool->Set_help("Allow guest OS to connect from 32-bit protected mode.\n"
01664             "If you want power management in Windows 95/98/ME (beyond using the APM to shutdown the computer) you MUST enable this option.\n"
01665             "Windows 95/98/ME does not support the 16-bit real and protected mode APM BIOS entry points.\n"
01666             "Please note at this time that 32-bit APM is unstable under Windows ME");
01667 
01668     Pbool = secprop->Add_bool("integration device",Property::Changeable::WhenIdle,false);
01669     Pbool->Set_help("Enable DOSBox integration I/O device. This can be used by the guest OS to match mouse pointer position, for example. EXPERIMENTAL!");
01670 
01671     Pbool = secprop->Add_bool("integration device pnp",Property::Changeable::WhenIdle,false);
01672     Pbool->Set_help("List DOSBox integration I/O device as part of ISA PnP enumeration. This has no purpose yet.");
01673 
01674     Pbool = secprop->Add_bool("isapnpbios",Property::Changeable::WhenIdle,true);
01675     Pbool->Set_help("Emulate ISA Plug & Play BIOS. Enable if using DOSBox to run a PnP aware DOS program or if booting Windows 9x.\n"
01676             "Do not disable if Windows 9x is configured around PnP devices, you will likely confuse it.");
01677 
01678     Pbool = secprop->Add_bool("realbig16",Property::Changeable::WhenIdle,false);
01679     Pbool->Set_help("Allow the B (big) bit in real mode. If set, allow the DOS program to set the B bit,\n"
01680         "then jump to realmode with B still set (aka Huge Unreal mode). Needed for Project Angel.");
01681 
01682     secprop=control->AddSection_prop("keyboard",&Null_Init);
01683     Pbool = secprop->Add_bool("aux",Property::Changeable::OnlyAtStart,true);
01684     Pbool->Set_help("Enable emulation of the 8042 auxiliary port. PS/2 mouse emulation requires this to be enabled.\n"
01685             "You should enable this if you will be running Windows ME or any other OS that does not use the BIOS to receive mouse events.");
01686 
01687     Pbool = secprop->Add_bool("allow output port reset",Property::Changeable::OnlyAtStart,true);
01688     Pbool->Set_help("If set (default), allow the application to reset the CPU through the keyboard controller.\n"
01689             "This option is required to allow Windows ME to reboot properly, whereas Windows 9x and earlier\n"
01690             "will reboot without this option using INT 19h");
01691 
01692     Pstring = secprop->Add_string("auxdevice",Property::Changeable::OnlyAtStart,"intellimouse");
01693     Pstring->Set_values(auxdevices);
01694     Pstring->Set_help("Type of PS/2 mouse attached to the AUX port");
01695 
01696     secprop=control->AddSection_prop("pci",&Null_Init,false); //PCI bus
01697 
01698     Pstring = secprop->Add_string("voodoo",Property::Changeable::WhenIdle,"auto");
01699     Pstring->Set_values(voodoo_settings);
01700     Pstring->Set_help("Enable VOODOO support.");
01701 
01702     secprop=control->AddSection_prop("mixer",&Null_Init);
01703     Pbool = secprop->Add_bool("nosound",Property::Changeable::OnlyAtStart,false);
01704     Pbool->Set_help("Enable silent mode, sound is still emulated though.");
01705 
01706     Pbool = secprop->Add_bool("sample accurate",Property::Changeable::OnlyAtStart,false);
01707     Pbool->Set_help("Enable sample accurate mixing, at the expense of some emulation performance. Enable this option for DOS games and demos that\n"
01708             "require such accuracy for correct Tandy/OPL output including digitized speech. This option can also help eliminate minor\n"
01709             "errors in Gravis Ultrasound emulation that result in random echo/attenuation effects.");
01710 
01711     Pbool = secprop->Add_bool("swapstereo",Property::Changeable::OnlyAtStart,false); 
01712     Pbool->Set_help("Swaps the left and right stereo channels."); 
01713 
01714     Pint = secprop->Add_int("rate",Property::Changeable::OnlyAtStart,44100);
01715     Pint->Set_values(rates);
01716     Pint->Set_help("Mixer sample rate, setting any device's rate higher than this will probably lower their sound quality.");
01717 
01718     Pint = secprop->Add_int("blocksize",Property::Changeable::OnlyAtStart,1024);
01719     Pint->Set_values(blocksizes);
01720     Pint->Set_help("Mixer block size, larger blocks might help sound stuttering but sound will also be more lagged.");
01721 
01722     Pint = secprop->Add_int("prebuffer",Property::Changeable::OnlyAtStart,20);
01723     Pint->SetMinMax(0,100);
01724     Pint->Set_help("How many milliseconds of data to keep on top of the blocksize.");
01725 
01726     secprop=control->AddSection_prop("midi",&Null_Init,true);//done
01727 
01728     Pstring = secprop->Add_string("mpu401",Property::Changeable::WhenIdle,"intelligent");
01729     Pstring->Set_values(mputypes);
01730     Pstring->Set_help("Type of MPU-401 to emulate.");
01731 
01732     Pstring = secprop->Add_string("mididevice",Property::Changeable::WhenIdle,"default");
01733     Pstring->Set_values(devices);
01734     Pstring->Set_help("Device that will receive the MIDI data from MPU-401.");
01735 
01736     Pstring = secprop->Add_string("midiconfig",Property::Changeable::WhenIdle,"");
01737     Pstring->Set_help("Special configuration options for the device driver. This is usually the id of the device you want to use.\n"
01738                       "  or in the case of coreaudio or synth, you can specify a soundfont here.\n"
01739                       "  When using a Roland MT-32 rev. 0 as midi output device, some games may require a delay in order to prevent 'buffer overflow' issues.\n"
01740                       "  In that case, add 'delaysysex', for example: midiconfig=2 delaysysex\n"
01741                       "  See the README/Manual for more details.");
01742 
01743     Pint = secprop->Add_int("samplerate",Property::Changeable::WhenIdle,44100);
01744     Pint->Set_values(rates);
01745     Pint->Set_help("Sample rate for MIDI synthesizer, if applicable.");
01746     
01747     Pint = secprop->Add_int("mpuirq",Property::Changeable::WhenIdle,-1);
01748     Pint->SetMinMax(-1,15);
01749     Pint->Set_help("MPU-401 IRQ. -1 to automatically choose.");
01750 
01751     Pstring = secprop->Add_string("mt32.reverse.stereo",Property::Changeable::WhenIdle,"off");
01752     Pstring->Set_values(mt32ReverseStereo);
01753     Pstring->Set_help("Reverse stereo channels for MT-32 output");
01754 
01755     Pstring = secprop->Add_string("mt32.verbose",Property::Changeable::WhenIdle,"off");
01756     Pstring->Set_values(mt32log);
01757     Pstring->Set_help("MT-32 debug logging");
01758 
01759     Pstring = secprop->Add_string("mt32.thread",Property::Changeable::WhenIdle,"off");
01760     Pstring->Set_values(mt32thread);
01761     Pstring->Set_help("MT-32 rendering in separate thread");
01762 
01763     Pstring = secprop->Add_string("mt32.dac",Property::Changeable::WhenIdle,"auto");
01764     Pstring->Set_values(mt32DACModes);
01765     Pstring->Set_help("MT-32 DAC input emulation mode\n"
01766         "Nice = 0 - default\n"
01767         "Produces samples at double the volume, without tricks.\n"
01768         "Higher quality than the real devices\n\n"
01769 
01770         "Pure = 1\n"
01771         "Produces samples that exactly match the bits output from the emulated LA32.\n"
01772         "Nicer overdrive characteristics than the DAC hacks (it simply clips samples within range)\n"
01773         "Much less likely to overdrive than any other mode.\n"
01774         "Half the volume of any of the other modes, meaning its volume relative to the reverb\n"
01775         "output when mixed together directly will sound wrong. So, reverb level must be lowered.\n"
01776         "Perfect for developers while debugging :)\n\n"
01777 
01778         "GENERATION1 = 2\n"
01779         "Re-orders the LA32 output bits as in early generation MT-32s (according to Wikipedia).\n"
01780         "Bit order at DAC (where each number represents the original LA32 output bit number, and XX means the bit is always low):\n"
01781         "15 13 12 11 10 09 08 07 06 05 04 03 02 01 00 XX\n\n"
01782 
01783         "GENERATION2 = 3\n"
01784         "Re-orders the LA32 output bits as in later geneerations (personally confirmed on my CM-32L - KG).\n"
01785         "Bit order at DAC (where each number represents the original LA32 output bit number):\n"
01786         "15 13 12 11 10 09 08 07 06 05 04 03 02 01 00 14\n");
01787 
01788     Pstring = secprop->Add_string("mt32.reverb.mode",Property::Changeable::WhenIdle,"auto");
01789     Pstring->Set_values(mt32reverbModes);
01790     Pstring->Set_help("MT-32 reverb mode");
01791 
01792     Pint = secprop->Add_int("mt32.reverb.time",Property::Changeable::WhenIdle,5);
01793     Pint->Set_values(mt32reverbTimes);
01794     Pint->Set_help("MT-32 reverb decaying time"); 
01795 
01796     Pint = secprop->Add_int("mt32.reverb.level",Property::Changeable::WhenIdle,3);
01797     Pint->Set_values(mt32reverbLevels);
01798     Pint->Set_help("MT-32 reverb level");
01799 
01800     Pint = secprop->Add_int("mt32.partials",Property::Changeable::WhenIdle,32);
01801     Pint->SetMinMax(0,256);
01802     Pint->Set_help("MT-32 max partials allowed (0-256)");
01803 
01804     secprop=control->AddSection_prop("debug",&Null_Init);
01805 
01806     secprop=control->AddSection_prop("sblaster",&Null_Init,true);//done
01807     
01808     Pstring = secprop->Add_string("sbtype",Property::Changeable::WhenIdle,"sb16");
01809     Pstring->Set_values(sbtypes);
01810     Pstring->Set_help("Type of Soundblaster to emulate. gb is Gameblaster.");
01811 
01812     Phex = secprop->Add_hex("sbbase",Property::Changeable::WhenIdle,0x220);
01813     Phex->Set_values(ios);
01814     Phex->Set_help("The IO address of the soundblaster.");
01815 
01816     Pint = secprop->Add_int("irq",Property::Changeable::WhenIdle,7);
01817     Pint->Set_values(irqssb);
01818     Pint->Set_help("The IRQ number of the soundblaster. Set to -1 to start DOSBox with the IRQ unassigned");
01819 
01820     Pint = secprop->Add_int("mindma",Property::Changeable::OnlyAtStart,-1);
01821     Pint->Set_help( "Minimum DMA transfer left to increase attention across DSP blocks, in milliseconds. Set to -1 for default.\n"
01822             "There are some DOS games/demos that use single-cycle DSP playback in their music tracker and they micromanage\n"
01823             "the DMA transfer per block poorly in a way that causes popping and artifacts. Setting this option to 0 for\n"
01824             "such DOS applications may reduce audible popping and artifacts.");
01825 
01826     /* Sound Blaster IRQ hacks.
01827      *
01828      * These hacks reduce emulation accuracy but can be set to work around bugs or mistakes in some old
01829      * games and demos related to handling the Sound Blaster IRQ.
01830      *
01831      * - Saga by Dust (1993):
01832      *     Sound Blaster support has a fatal flaw in that the Sound Blaster interrupt handler it installs assumes
01833      *     DS == CS. It uses the DS register to read local variables needed to manage the Sound Blaster card but
01834      *     it makes no attempt to push DS and then load the DS segment value it needs. While the demo may seem to
01835      *     run normally at first, eventually the interrupt is fired at just the right time to catch the demo in
01836      *     the middle of it's graphics routines (DS=A000). Since the ISR uses DS to load the Sound Blaster DSP
01837      *     I/O port, it reads some random value from *video RAM* and then hangs in a loop waiting for that I/O
01838      *     port to clear bit 7! Setting 'cs_equ_ds' works around that bug by instructing PIC emulation not to
01839      *     fire the interrupt unless segment registers CS and DS match. */
01840     Pstring = secprop->Add_string("irq hack",Property::Changeable::WhenIdle,"none");
01841     Pstring->Set_values(irqssbhack);
01842     Pstring->Set_help("Specify a hack related to the Sound Blaster IRQ to avoid crashes in a handful of games and demos.\n"
01843             "    none                   Emulate IRQs normally\n"
01844             "    cs_equ_ds              Do not fire IRQ unless two CPU segment registers match: CS == DS. Read Dosbox-X Wiki or source code for details.");
01845 
01846     Pint = secprop->Add_int("dma",Property::Changeable::WhenIdle,1);
01847     Pint->Set_values(dmassb);
01848     Pint->Set_help("The DMA number of the soundblaster. Set to -1 to start DOSBox with the IRQ unassigned");
01849 
01850     Pint = secprop->Add_int("hdma",Property::Changeable::WhenIdle,5);
01851     Pint->Set_values(dmassb);
01852     Pint->Set_help("The High DMA number of the soundblaster. Set to -1 to start DOSBox with the IRQ unassigned");
01853 
01854     Pbool = secprop->Add_bool("pic unmask irq",Property::Changeable::WhenIdle,false);
01855     Pbool->Set_help("Start the DOS virtual machine with the sound blaster IRQ already unmasked at the PIC.\n"
01856             "Some early DOS games/demos that support Sound Blaster expect the IRQ to fire but make\n"
01857             "no attempt to unmask the IRQ. If audio cuts out no matter what IRQ you try, then try\n"
01858             "setting this option.\n"
01859             "Option is needed for:\n"
01860             "   Public NMI \"jump\" demo (1992)");
01861 
01862     Pbool = secprop->Add_bool("enable speaker",Property::Changeable::WhenIdle,false);
01863     Pbool->Set_help("Start the DOS virtual machine with the sound blaster speaker enabled.\n"
01864                     "Sound Blaster Pro and older cards have a speaker disable/enable command.\n"
01865                     "Normally the card boots up with the speaker disabled. If a DOS game or demo\n"
01866                     "attempts to play without enabling the speaker, set this option to true to\n"
01867                     "compensate. This setting has no meaning if emulating a Sound Blaster 16 card.");
01868 
01869     Pbool = secprop->Add_bool("enable asp",Property::Changeable::WhenIdle,false);
01870     Pbool->Set_help("If set, emulate the presence of the Sound Blaster 16 Advanced Sound Processor/Creative Sound Processor chip.\n"
01871             "NOTE: This only emulates it's presence and the basic DSP commands to communicate with it. Actual ASP/CSP functions are not yet implemented.");
01872 
01873     Pbool = secprop->Add_bool("disable filtering",Property::Changeable::WhenIdle,false);
01874     Pbool->Set_help("By default DOSBox-X filters Sound Blaster output to emulate lowpass filters and analog output limitations.\n"
01875             "Set this option to true to disable filtering. Note that doing so disables emulation of the Sound Blaster Pro\n"
01876             "output filter and ESS AudioDrive lowpass filter.");
01877 
01878     Pbool = secprop->Add_bool("dsp write buffer status must return 0x7f or 0xff",Property::Changeable::WhenIdle,false);
01879     Pbool->Set_help("If set, force port 22Ch (DSP write buffer status) to return 0x7F or 0xFF. If not set, the port\n"
01880             "may return 0x7F or 0xFF depending on what type of Sound Blaster is being emulated.\n"
01881             "Set this option for some early DOS demos that make that assumption about port 22Ch.\n"
01882             "Option is needed for:\n"
01883             "   Overload by Hysteria (1992) - Audio will crackle/saturate (8-bit overflow) except when sbtype=sb16");
01884 
01885     Pbool = secprop->Add_bool("pre-set sbpro stereo",Property::Changeable::WhenIdle,false);
01886     Pbool->Set_help("Start the DOS virtual machine with the Sound Blaster Pro stereo bit set (in the mixer).\n"
01887             "A few demos support Sound Blaster Pro but forget to set this bit.\n"
01888             "Option is needed for:\n"
01889             "   Inconexia by Iguana (1993)");
01890 
01891     Pbool = secprop->Add_bool("sbmixer",Property::Changeable::WhenIdle,true);
01892     Pbool->Set_help("Allow the soundblaster mixer to modify the DOSBox mixer.");
01893 
01894     Pstring = secprop->Add_string("oplmode",Property::Changeable::WhenIdle,"auto");
01895     Pstring->Set_values(oplmodes);
01896     Pstring->Set_help("Type of OPL emulation. On 'auto' the mode is determined by sblaster type.\n"
01897         "To emulate Adlib, set sbtype=none and oplmode=opl2. To emulate a Game Blaster, set\n"
01898         "sbtype=none and oplmode=cms");
01899 
01900     Pbool = secprop->Add_bool("adlib force timer overflow on detect",Property::Changeable::WhenIdle,true);
01901     Pbool->Set_help("If set, Adlib/OPL emulation will signal 'overflow' on timers after 50 I/O reads.\n"
01902             "This is a temporary hack to work around timing bugs noted in DOSBox-X. Certain\n"
01903             "games (Wolfenstein 3D) poll the Adlib status port a fixed number of times assuming\n"
01904             "that the poll loop takes long enough for the Adlib timer to run out. If the game\n"
01905             "cannot reliably detect Adlib at higher cycles counts, but can reliably detect at\n"
01906             "lower cycles counts, set this option.\n"
01907             "NOTE: Technically this decreases emulation accuracy, however it also reflects the\n"
01908             "      fact that DOSBox-X's I/O timing code needs some work to better match the\n"
01909             "      slowness of the ISA bus per I/O read in consideration of DOS games. So this\n"
01910             "      option is ON by default.");
01911     /* NTS: The reason I mention Wolfenstein 3D is that it seems coded not to probe for Sound Blaster unless it
01912      *      first detects the Adlib at port 0x388. No Adlib, no Sound Blaster. */
01913     /* ^ NTS: To see what I mean, download Wolf3d source code, look at ID_SD.C line 1585 (Adlib detection routine).
01914      *        Note it sets Timer 1, then reads port 388h 100 times before reading status to detect whether the
01915      *        timer "overflowed" (fairly typical Adlib detection code).
01916      *        Some quick math: 8333333Hz ISA BCLK / 6 cycles per read (3 wait states) = 1388888 reads/second possible
01917      *                         100 I/O reads * (1 / 1388888) = 72us */ 
01918 
01919     Pstring = secprop->Add_string("oplemu",Property::Changeable::WhenIdle,"default");
01920     Pstring->Set_values(oplemus);
01921     Pstring->Set_help("Provider for the OPL emulation. compat might provide better quality (see oplrate as well).");
01922 
01923     Pint = secprop->Add_int("oplrate",Property::Changeable::WhenIdle,44100);
01924     Pint->Set_values(oplrates);
01925     Pint->Set_help("Sample rate of OPL music emulation. Use 49716 for highest quality (set the mixer rate accordingly).");
01926 
01927     Phex = secprop->Add_hex("hardwarebase",Property::Changeable::WhenIdle,0x220);
01928     Phex->Set_help("base address of the real hardware soundblaster:\n"\
01929         "210,220,230,240,250,260,280");
01930 
01931     Pbool = secprop->Add_bool("force dsp auto-init",Property::Changeable::WhenIdle,false);
01932     Pbool->Set_help("Treat all single-cycle DSP commands as auto-init to keep playback going.\n"
01933             "This option is a workaround for DOS games or demos that use single-cycle DSP playback commands and\n"
01934             "have problems with missing the Sound Blaster IRQ under load. Do not enable unless you need this workaround.\n"
01935             "Needed for:\n"
01936             "  - Extreme \"lunatic\" demo (1993)");
01937 
01938     Pbool = secprop->Add_bool("force goldplay",Property::Changeable::WhenIdle,false);
01939     Pbool->Set_help("Always render Sound Blaster output sample-at-a-time. Testing option. You probably don't want to enable this.");
01940 
01941     Pbool = secprop->Add_bool("goldplay",Property::Changeable::WhenIdle,true);
01942     Pbool->Set_help("Enable goldplay emulation.");
01943 
01944     Pbool = secprop->Add_bool("goldplay stereo",Property::Changeable::WhenIdle,true);
01945     Pbool->Set_help("Enable workaround for goldplay stereo playback. Many DOS demos using this technique\n"
01946             "don't seem to know they need to double the frequency when programming the DSP time constant for Pro stereo output.\n"
01947             "If stereo playback seems to have artifacts consider enabling this option. For accurate emulation of Sound Blaster\n"
01948             "hardware, disable this option.");
01949 
01950     Pstring = secprop->Add_string("dsp require interrupt acknowledge",Property::Changeable::WhenIdle,"auto");
01951     Pstring->Set_help("If set, the DSP will halt DMA playback until IRQ acknowledgement occurs even in auto-init mode (SB16 behavior).\n"
01952             "If clear, IRQ acknowledgement will have no effect on auto-init playback (SB Pro and earlier & clone behavior)\n"
01953             "If set to 'auto' then behavior is determined by sbtype= setting.\n"
01954             "This is a setting for hardware accuracy in emulation. If audio briefly plays then stops then your DOS game\n"
01955             "and it's not using IRQ (but using DMA), try setting this option to 'false'");
01956 
01957     Pint = secprop->Add_int("dsp write busy delay",Property::Changeable::WhenIdle,-1);
01958     Pint->Set_help("Amount of time in nanoseconds the DSP chip signals 'busy' after writing to the DSP (port 2xCh). Set to -1 to use card-specific defaults.\n"
01959             "WARNING: Setting the value too high (above 20000ns) may have detrimental effects to DOS games that use IRQ 0 and DSP command 0x10 to play audio.\n"
01960             "         Setting the value way too high (above 1000000ns) can cause significant lag in DOS games.");
01961 
01962     Pbool = secprop->Add_bool("blaster environment variable",Property::Changeable::WhenIdle,true);
01963     Pbool->Set_help("Whether or not to set the BLASTER environment variable automatically at startup");
01964 
01965     Pbool = secprop->Add_bool("sample rate limits",Property::Changeable::WhenIdle,true);
01966     Pbool->Set_help("If set (default), limit DSP sample rate to what real hardware is limited to");
01967 
01968     /* recommended for:
01969      *   1992 demo "overload" (if set, Sound Blaster support can run at 24KHz without causing demo to hang in the IRQ 0 timer)
01970      *   1993 demo "xmas 93" (superiority complex) because the demo's Sound Blaster mode writes at the timer interrupt rate without polling the DSP to check busy state */
01971     Pbool = secprop->Add_bool("instant direct dac",Property::Changeable::WhenIdle,false);
01972     Pbool->Set_help("If set, direct DAC output commands are instantaneous. This option is intended as a quick fix for\n"
01973             "games or demos that play direct DAC music/sound from the IRQ 0 timer who a) write the DSP command\n"
01974             "and data without polling the DSP to ensure it's ready or b) can get locked into the IRQ 0 handler\n"
01975             "waiting for DSP status when instructed to play at or beyond the DSP's maximum direct DAC sample rate.\n"
01976             "This fix allows broken Sound Blaster code to work and should not be enabled unless necessary.");
01977 
01978     /* accuracy emulation: SB16 does not honor SBPro stereo bit in the mixer */
01979     Pbool = secprop->Add_bool("stereo control with sbpro only",Property::Changeable::WhenIdle,true);
01980     Pbool->Set_help("Default on. If set, Sound Blaster Pro stereo is not available when emulating sb16 or sb16vibra.\n"
01981             "If clear, sb16 emulation will honor the sbpro stereo bit. Note that Creative SB16 cards do not\n"
01982             "honor the stereo bit, and this option allows DOSBox emulate that fact. Accuracy setting.");
01983 
01984     /* NTS: It turns out (SB16 at least) the DSP will periodically set bit 7 (busy) by itself at some
01985      *      clock rate even if it's idle. Casual testing on an old Pentium system with a ViBRA shows
01986      *      it's possible to see both 0x7F and 0xFF come back if you repeatedly type "i 22c" in DOS
01987      *      DEBUG.EXE.  FIXME: At what clock rate and duty cycle does this happen? */
01988     Pint = secprop->Add_int("dsp busy cycle rate",Property::Changeable::WhenIdle,-1/*default*/);
01989     Pint->Set_help("Sound Blaster 16 DSP chips appear to go busy periodically at some high clock rate\n"
01990             "whether the DSP is actually doing anything for the system or not. This is an accuracy\n"
01991             "option for Sound Blaster emulation. If this option is nonzero, it will be interpreted\n"
01992             "as the busy cycle rate in Hz. If zero, busy cycle will not be emulated. If -1, sound\n"
01993             "blaster emulation will automatically choose a setting based on the sbtype= setting");
01994 
01995     Pint = secprop->Add_int("dsp busy cycle always",Property::Changeable::WhenIdle,-1/*default*/);
01996     Pint->Set_help("If set, the DSP busy cycle always happens. If clear, DSP busy cycle only happens when\n"
01997             "audio playback is running. Default setting is to pick according to the sound card.");
01998 
01999     Pint = secprop->Add_int("dsp busy cycle duty",Property::Changeable::WhenIdle,-1/*default*/);
02000     Pint->Set_help("If emulating SB16 busy cycle, this value (0 to 100) controls the duty cycle of the busy cycle.\n"
02001             "If this option is set to -1, Sound Blaster emulation will choose a value automatically according\n"
02002             "to sbtype=. If 0, busy cycle emulation is disabled.");
02003 
02004     /* NTS: Confirmed: My Sound Blaster 2.0 (at least) mirrors the DSP on port 22Ch and 22Dh. This option
02005      *      will only take effect with sbtype sb1 and sb2, so make it enabled by default. Accuracy setting. */
02006     Pbool = secprop->Add_bool("io port aliasing",Property::Changeable::WhenIdle,true);
02007     Pbool->Set_help("If set, Sound Blaster ports alias by not decoding the LSB of the I/O port.\n"
02008             "This option only applies when sbtype is set to sb1 or sb2 (not SBPro or SB16).\n"
02009             "This is a hack for the Electromotive Force 'Internal Damage' demo which apparently\n"
02010             "relies on this behavior for Sound Blaster output and should be enabled for accuracy in emulation.");
02011 
02012     secprop=control->AddSection_prop("gus",&Null_Init,true); //done
02013     Pbool = secprop->Add_bool("gus",Property::Changeable::WhenIdle,false);  
02014     Pbool->Set_help("Enable the Gravis Ultrasound emulation.");
02015 
02016     Pbool = secprop->Add_bool("autoamp",Property::Changeable::WhenIdle,false);
02017     Pbool->Set_help("If set, GF1 output will reduce in volume automatically if the sum of all channels exceeds full volume.\n"
02018                     "If not set, then loud music will clip to full volume just as it would on real hardware.\n"
02019                     "Enable this option for loud music if you want a more pleasing rendition without saturation and distortion.");
02020 
02021     Pbool = secprop->Add_bool("unmask dma",Property::Changeable::WhenIdle,false);
02022     Pbool->Set_help("Start the DOS virtual machine with the DMA channel already unmasked at the controller.\n"
02023             "Use this for DOS applications that expect to operate the GUS but forget to unmask the DMA channel.");
02024 
02025     Pbool = secprop->Add_bool("pic unmask irq",Property::Changeable::WhenIdle,false);
02026     Pbool->Set_help("Start the DOS virtual machine with the GUS IRQ already unmasked at the PIC.");
02027 
02028     Pbool = secprop->Add_bool("startup initialized",Property::Changeable::WhenIdle,false);
02029     Pbool->Set_help("If set, start the GF1 in a fully initialized state (as if ULTRINIT had been run).\n"
02030                     "If clear, leave the card in an uninitialized state (as if cold boot).\n"
02031                     "Some DOS games or demoscene productions will hang or fail to use the Ultrasound hardware\n"
02032                     "because they assume the card is initialized and their hardware detect does not fully initialize the card.");
02033 
02034     Pbool = secprop->Add_bool("dma enable on dma control polling",Property::Changeable::WhenIdle,false);
02035     Pbool->Set_help("If set, automatically enable GUS DMA transfer bit in specific cases when the DMA control register is being polled.\n"
02036                     "THIS IS A HACK. Some games and demoscene productions need this hack to avoid hanging while uploading sample data\n"
02037                     "to the Gravis Ultrasound due to bugs in their implementation.");
02038 
02039     Pbool = secprop->Add_bool("clear dma tc irq if excess polling",Property::Changeable::WhenIdle,false);
02040     Pbool->Set_help("If the DOS application is seen polling the IRQ status register rapidly, automatically clear the DMA TC IRQ status.\n"
02041             "This is a hack that should only be used with DOS applications that need it to avoid bugs in their GUS support code.\n"
02042             "Needed for:\n"
02043             "  Warcraft II by Blizzard ............. if using GUS for music and sound, set this option to prevent the game from\n"
02044             "                                        hanging when you click on the buttons in the main menu.");
02045 
02046     /* some DOS demos, especially where the programmers wrote their own tracker, forget to set "master IRQ enable" on the GUS,
02047      * and then wonder why music isn't playing. prior to some GUS bugfixes they happend to work anyway because DOSBox also
02048      * ignored master IRQ enable. you can restore that buggy behavior here.
02049      *
02050      * DOS games & demos that need this:
02051      *   - "Juice" by Psychic Link (writes 0x300 to GUS reset which only enables DAC and takes card out of reset, does not enable IRQ) */
02052     Pbool = secprop->Add_bool("force master irq enable",Property::Changeable::WhenIdle,false);
02053     Pbool->Set_help("Set this option if a DOS game or demo initializes the GUS but is unable to play any music.\n"
02054             "Usually the cause is buggy GUS support that resets the GUS but fails to set the Master IRQ enable bit.");
02055 
02056     Pstring = secprop->Add_string("gus panning table",Property::Changeable::WhenIdle,"default");
02057     Pstring->Set_values(guspantables);
02058     Pstring->Set_help("Controls which table or equation is used for the Gravis Ultrasound panning emulation.\n"
02059             "accurate emulation attempts to better reflect how the actual hardware handles panning,\n"
02060             "while the old emulation uses a simpler idealistic mapping.");
02061 
02062     Pint = secprop->Add_int("gusrate",Property::Changeable::WhenIdle,44100);
02063     Pint->Set_values(rates);
02064     Pint->Set_help("Sample rate of Ultrasound emulation.");
02065 
02066     Pbool = secprop->Add_bool("gus fixed render rate",Property::Changeable::WhenIdle,false);
02067     Pbool->Set_help("If set, Gravis Ultrasound audio output is rendered at a fixed sample rate specified by 'gusrate'. This can provide better quality than real hardware,\n"
02068             "if desired. Else, Gravis Ultrasound emulation will change the sample rate of it's output according to the number of active channels, just like real hardware.\n"
02069             "Note: DOSBox-X defaults to 'false', while mainline DOSBox SVN is currently hardcoded to render as if this setting is 'true'.");
02070 
02071     Pint = secprop->Add_int("gusmemsize",Property::Changeable::WhenIdle,-1);
02072     Pint->SetMinMax(-1,1024);
02073     Pint->Set_help("Amount of RAM on the Gravis Ultrasound in KB. Set to -1 for default.");
02074 
02075     Phex = secprop->Add_hex("gusbase",Property::Changeable::WhenIdle,0x240);
02076     Phex->Set_values(iosgus);
02077     Phex->Set_help("The IO base address of the Gravis Ultrasound.");
02078 
02079     Pint = secprop->Add_int("gusirq",Property::Changeable::WhenIdle,5);
02080     Pint->Set_values(irqsgus);
02081     Pint->Set_help("The IRQ number of the Gravis Ultrasound.");
02082 
02083     Pint = secprop->Add_int("gusdma",Property::Changeable::WhenIdle,3);
02084     Pint->Set_values(dmasgus);
02085     Pint->Set_help("The DMA channel of the Gravis Ultrasound.");
02086     
02087     Pstring = secprop->Add_string("gustype",Property::Changeable::WhenIdle,"classic");
02088     Pstring->Set_values(gustypes);
02089     Pstring->Set_help(  "Type of Gravis Ultrasound to emulate.\n"
02090                 "classic             Original Gravis Ultrasound chipset\n"
02091                 "classic37           Original Gravis Ultrasound with ICS Mixer (rev 3.7)\n"
02092                 "max                 Gravis Ultrasound MAX emulation (with CS4231 codec)\n"
02093                 "interwave           Gravis Ultrasound Plug & Play (interwave)");
02094 
02095     Pstring = secprop->Add_string("ultradir",Property::Changeable::WhenIdle,"C:\\ULTRASND");
02096     Pstring->Set_help(
02097         "Path to Ultrasound directory. In this directory\n"
02098         "there should be a MIDI directory that contains\n"
02099         "the patch files for GUS playback. Patch sets used\n"
02100         "with Timidity should work fine.");
02101 
02102     secprop = control->AddSection_prop("innova",&Null_Init,true);//done
02103     Pbool = secprop->Add_bool("innova",Property::Changeable::WhenIdle,false);
02104     Pbool->Set_help("Enable the Innovation SSI-2001 emulation.");
02105     Pint = secprop->Add_int("samplerate",Property::Changeable::WhenIdle,22050);
02106     Pint->Set_values(rates);
02107     Pint->Set_help("Sample rate of Innovation SSI-2001 emulation");
02108     Phex = secprop->Add_hex("sidbase",Property::Changeable::WhenIdle,0x280);
02109     Phex->Set_values(sidbaseno);
02110     Phex->Set_help("SID base port (typically 280h).");
02111     Pint = secprop->Add_int("quality",Property::Changeable::WhenIdle,0);
02112     Pint->Set_values(qualityno);
02113     Pint->Set_help("Set SID emulation quality level (0 to 3).");
02114 
02115     secprop = control->AddSection_prop("speaker",&Null_Init,true);//done
02116     Pbool = secprop->Add_bool("pcspeaker",Property::Changeable::WhenIdle,true);
02117     Pbool->Set_help("Enable PC-Speaker emulation.");
02118 
02119     Pint = secprop->Add_int("initial frequency",Property::Changeable::WhenIdle,-1);
02120     Pint->Set_help("PC speaker PIT timer is programmed to this frequency on startup. If the DOS game\n"
02121             "or demo causes a long audible beep at startup (leaving the gate open) try setting\n"
02122             "this option to 0 to silence the PC speaker until reprogrammed by the demo.\n"
02123             "Set to 0 for some early Abaddon demos including \"Torso\" and \"Cycling\".");
02124 
02125     Pint = secprop->Add_int("pcrate",Property::Changeable::WhenIdle,44100);
02126     Pint->Set_values(rates);
02127     Pint->Set_help("Sample rate of the PC-Speaker sound generation.");
02128 
02129     Pstring = secprop->Add_string("tandy",Property::Changeable::WhenIdle,"auto");
02130     Pstring->Set_values(tandys);
02131     Pstring->Set_help("Enable Tandy Sound System emulation. For 'auto', emulation is present only if machine is set to 'tandy'.");
02132     
02133     Pint = secprop->Add_int("tandyrate",Property::Changeable::WhenIdle,44100);
02134     Pint->Set_values(rates);
02135     Pint->Set_help("Sample rate of the Tandy 3-Voice generation.");
02136     
02137     Pbool = secprop->Add_bool("disney",Property::Changeable::WhenIdle,false);
02138     Pbool->Set_help("Enable Disney Sound Source emulation. (Covox Voice Master and Speech Thing compatible).");
02139     Pstring = secprop->Add_string("ps1audio",Property::Changeable::WhenIdle,"off");
02140     Pstring->Set_values(ps1opt);
02141     Pstring->Set_help("Enable PS1 audio emulation.");
02142     Pint = secprop->Add_int("ps1audiorate",Property::Changeable::OnlyAtStart,22050);
02143     Pint->Set_values(rates);
02144     Pint->Set_help("Sample rate of the PS1 audio emulation.");
02145 
02146     secprop=control->AddSection_prop("joystick",&Null_Init,false);//done
02147     Pstring = secprop->Add_string("joysticktype",Property::Changeable::WhenIdle,"auto");
02148     Pstring->Set_values(joytypes);
02149     Pstring->Set_help(
02150         "Type of joystick to emulate: auto (default), none,\n"
02151         "2axis (supports two joysticks),\n"
02152         "4axis (supports one joystick, first joystick used),\n"
02153         "4axis_2 (supports one joystick, second joystick used),\n"
02154         "fcs (Thrustmaster), ch (CH Flightstick).\n"
02155         "none disables joystick emulation.\n"
02156         "auto chooses emulation depending on real joystick(s).\n"
02157         "(Remember to reset dosbox's mapperfile if you saved it earlier)");
02158 
02159     Pbool = secprop->Add_bool("timed",Property::Changeable::WhenIdle,true);
02160     Pbool->Set_help("enable timed intervals for axis. Experiment with this option, if your joystick drifts (away).");
02161 
02162     Pbool = secprop->Add_bool("autofire",Property::Changeable::WhenIdle,false);
02163     Pbool->Set_help("continuously fires as long as you keep the button pressed.");
02164     
02165     Pbool = secprop->Add_bool("swap34",Property::Changeable::WhenIdle,false);
02166     Pbool->Set_help("swap the 3rd and the 4th axis. can be useful for certain joysticks.");
02167 
02168     Pbool = secprop->Add_bool("buttonwrap",Property::Changeable::WhenIdle,false);
02169     Pbool->Set_help("enable button wrapping at the number of emulated buttons.");
02170 
02171         /*improved joystick
02172          * each axis has its own deadzone and response
02173          * each axis index can be remapped, e.g. fix poor driver mappings
02174          */
02175 
02176         /* logical axes settings*/
02177         std::vector<int> sticks = { 2, 1 };
02178         for (auto i = 0u; i < sticks.size(); i++)
02179         {
02180                 const auto count = sticks[i];
02181                 for (auto j = 0; j < count; j++)
02182                 {
02183                         const auto joy = std::to_string(i + 1);
02184                         const auto stick = std::to_string(j + 1);
02185                         const auto name = "joy" + joy + "deadzone" + stick;
02186                         const auto help = "deadzone for joystick " + joy + " thumbstick " + stick + ".";
02187                         Pdouble = secprop->Add_double(name, Property::Changeable::WhenIdle, 0.25);
02188                         Pdouble->SetMinMax(0.0, 1.0);
02189                         Pdouble->Set_help(help);
02190                 }
02191         }
02192         for (auto i = 0u; i < sticks.size(); i++)
02193         {
02194                 const auto count = sticks[i];
02195                 for (auto j = 0; j < count; j++)
02196                 {
02197                         const auto joy = std::to_string(i + 1);
02198                         const auto stick = std::to_string(j + 1);
02199                         const auto name = "joy" + joy + "response" + stick;
02200                         const auto help = "response for joystick " + joy + " thumbstick " + stick + ".";
02201                         Pdouble = secprop->Add_double(name, Property::Changeable::WhenIdle, 1.0);
02202                         Pdouble->SetMinMax(-5.0, 5.0);
02203                         Pdouble->Set_help(help);
02204                 }
02205         }
02206 
02207         const auto joysticks = 2;
02208         const auto axes = 8;
02209         for (auto i = 0; i < joysticks; i++)
02210         {
02211                 for (auto j = 0; j < axes; j++)
02212                 {
02213                         const auto joy = std::to_string(i + 1);
02214                         const auto axis = std::to_string(j);
02215                         const auto propname = "joy" + joy + "axis" + axis;
02216                         Pint = secprop->Add_int(propname, Property::Changeable::WhenIdle, j);
02217                         Pint->SetMinMax(0, axes - 1);
02218                         const auto help = "axis for joystick " + joy + " axis " + axis + ".";
02219                         Pint->Set_help(help);
02220                 }
02221         }
02222         /*physical axes settings*/
02223         secprop = control->AddSection_prop("mapper", &Null_Init, true);
02224 
02225         const auto directions = 2;
02226         for (auto i = 0; i < joysticks; i++)
02227         {
02228                 for (auto j = 0; j < axes; j++)
02229                 {
02230                         for (auto k = 0; k < directions; k++)
02231                         {
02232                                 const auto joy = std::to_string(i + 1);
02233                                 const auto axis = std::to_string(j);
02234                                 const auto dir = k == 0 ? "-" : "+";
02235                                 const auto name = "joy" + joy + "deadzone" + axis + dir;
02236                                 Pdouble = secprop->Add_double(name, Property::Changeable::WhenIdle, 0.6);
02237                                 Pdouble->SetMinMax(0.0, 1.0);
02238                                 const auto help = "deadzone for joystick " + joy + " axis " + axis + dir;
02239                                 Pdouble->Set_help(help);
02240                         }
02241                 }
02242         }
02243 
02244 
02245     secprop=control->AddSection_prop("serial",&Null_Init,true);
02246    
02247     Pmulti_remain = secprop->Add_multiremain("serial1",Property::Changeable::WhenIdle," ");
02248     Pstring = Pmulti_remain->GetSection()->Add_string("type",Property::Changeable::WhenIdle,"dummy");
02249     Pmulti_remain->SetValue("dummy",/*init*/true);
02250     Pstring->Set_values(serials);
02251     Pstring = Pmulti_remain->GetSection()->Add_string("parameters",Property::Changeable::WhenIdle,"");
02252     Pmulti_remain->Set_help(
02253         "set type of device connected to com port.\n"
02254         "Can be disabled, dummy, modem, nullmodem, directserial.\n"
02255         "Additional parameters must be in the same line in the form of\n"
02256         "parameter:value. Parameter for all types is irq (optional).\n"
02257         "for directserial: realport (required), rxdelay (optional).\n"
02258         "                 (realport:COM1 realport:ttyS0).\n"
02259         "for modem: listenport (optional).\n"
02260         "for nullmodem: server, rxdelay, txdelay, telnet, usedtr,\n"
02261         "               transparent, port, inhsocket, nonlocal (all optional).\n"
02262         "               connections are limited to localhost unless you specify nonlocal:1\n"
02263         "Example: serial1=modem listenport:5000");
02264 
02265     Pmulti_remain = secprop->Add_multiremain("serial2",Property::Changeable::WhenIdle," ");
02266     Pstring = Pmulti_remain->GetSection()->Add_string("type",Property::Changeable::WhenIdle,"dummy");
02267     Pmulti_remain->SetValue("dummy",/*init*/true);
02268     Pstring->Set_values(serials);
02269     Pstring = Pmulti_remain->GetSection()->Add_string("parameters",Property::Changeable::WhenIdle,"");
02270     Pmulti_remain->Set_help("see serial1");
02271 
02272     Pmulti_remain = secprop->Add_multiremain("serial3",Property::Changeable::WhenIdle," ");
02273     Pstring = Pmulti_remain->GetSection()->Add_string("type",Property::Changeable::WhenIdle,"disabled");
02274     Pmulti_remain->SetValue("disabled",/*init*/true);
02275     Pstring->Set_values(serials);
02276     Pstring = Pmulti_remain->GetSection()->Add_string("parameters",Property::Changeable::WhenIdle,"");
02277     Pmulti_remain->Set_help("see serial1");
02278 
02279     Pmulti_remain = secprop->Add_multiremain("serial4",Property::Changeable::WhenIdle," ");
02280     Pstring = Pmulti_remain->GetSection()->Add_string("type",Property::Changeable::WhenIdle,"disabled");
02281     Pmulti_remain->SetValue("disabled",/*init*/true);
02282     Pstring->Set_values(serials);
02283     Pstring = Pmulti_remain->GetSection()->Add_string("parameters",Property::Changeable::WhenIdle,"");
02284     Pmulti_remain->Set_help("see serial1");
02285 
02286     // parallel ports
02287     secprop=control->AddSection_prop("parallel",&Null_Init,true);
02288     Pstring = secprop->Add_string("parallel1",Property::Changeable::WhenIdle,"disabled");
02289     Pstring->Set_help(
02290             "parallel1-3 -- set type of device connected to lpt port.\n"
02291             "Can be:\n"
02292             "   reallpt (direct parallel port passthrough),\n"
02293             "   file (records data to a file or passes it to a device),\n"
02294             "   printer (virtual dot-matrix printer, see [printer] section)\n"
02295             "       disney (attach Disney Sound Source emulation to this port)\n"
02296             "Additional parameters must be in the same line in the form of\n"
02297             "parameter:value.\n"
02298             "  for reallpt:\n"
02299             "  Windows:\n"
02300             "    realbase (the base address of your real parallel port).\n"
02301             "      Default: 378\n"
02302             "    ecpbase (base address of the ECP registers, optional).\n"
02303             "  Linux: realport (the parallel port device i.e. /dev/parport0).\n"
02304             "  for file: \n"
02305             "    dev:<devname> (i.e. dev:lpt1) to forward data to a device,\n"
02306             "    or append:<file> appends data to the specified file.\n"
02307             "    Without the above parameters data is written to files in the capture dir.\n"
02308             "    Additional parameters: timeout:<milliseconds> = how long to wait before\n"
02309             "    closing the file on inactivity (default:500), addFF to add a formfeed when\n"
02310             "    closing, addLF to add a linefeed if the app doesn't, cp:<codepage number>\n"
02311             "    to perform codepage translation, i.e. cp:437\n"
02312             "  for printer:\n"
02313             "    printer still has it's own configuration section above."
02314     );
02315     Pstring = secprop->Add_string("parallel2",Property::Changeable::WhenIdle,"disabled");
02316     Pstring->Set_help("see parallel1");
02317     Pstring = secprop->Add_string("parallel3",Property::Changeable::WhenIdle,"disabled");
02318     Pstring->Set_help("see parallel1");
02319 
02320     Pbool = secprop->Add_bool("dongle",Property::Changeable::WhenIdle,false);
02321     Pbool->Set_help("Enable dongle");
02322 
02323     /* All the DOS Related stuff, which will eventually start up in the shell */
02324     secprop=control->AddSection_prop("dos",&Null_Init,false);//done
02325     Pbool = secprop->Add_bool("xms",Property::Changeable::WhenIdle,true);
02326     Pbool->Set_help("Enable XMS support.");
02327 
02328     Pbool = secprop->Add_bool("hma",Property::Changeable::WhenIdle,true);
02329     Pbool->Set_help("Report through XMS that HMA exists (not necessarily available)");
02330 
02331     Pbool = secprop->Add_bool("hma allow reservation",Property::Changeable::WhenIdle,true);
02332     Pbool->Set_help("Allow TSR and application (anything other than the DOS kernel) to request control of the HMA.\n"
02333             "They will not be able to request control however if the DOS kernel is configured to occupy the HMA (DOS=HIGH)");
02334 
02335     Pint = secprop->Add_int("hard drive data rate limit",Property::Changeable::WhenIdle,-1);
02336     Pint->Set_help("Slow down (limit) hard disk throughput. This setting controls the limit in bytes/second.\n"
02337                    "Set to 0 to disable the limit, or -1 to use a reasonable default.");
02338 
02339     Pint = secprop->Add_int("hma minimum allocation",Property::Changeable::WhenIdle,0);
02340     Pint->Set_help("Minimum allocation size for HMA in bytes (equivalent to /HMAMIN= parameter).");
02341 
02342     Pbool = secprop->Add_bool("log console",Property::Changeable::WhenIdle,false);
02343     Pbool->Set_help("If set, log DOS CON output to the log file.");
02344 
02345     Pbool = secprop->Add_bool("dos in hma",Property::Changeable::WhenIdle,true);
02346     Pbool->Set_help("Report that DOS occupies HMA (equiv. DOS=HIGH)");
02347 
02348     Pint = secprop->Add_int("dos sda size",Property::Changeable::WhenIdle,0);
02349     Pint->Set_help("SDA (swappable data area) size, in bytes. Set to 0 to use a reasonable default.");
02350 
02351     Pint = secprop->Add_int("hma free space",Property::Changeable::WhenIdle,34*1024); /* default 34KB (TODO: How much does MS-DOS 5.0 usually occupy?) */
02352     Pint->Set_help("Controls the amount of free space available in HMA. This setting is not meaningful unless the\n"
02353             "DOS kernel occupies HMA and the emulated DOS version is at least 5.0.");
02354 
02355     Pstring = secprop->Add_string("cpm compatibility mode",Property::Changeable::WhenIdle,"auto");
02356     Pstring->Set_values(cpm_compat_modes);
02357     Pstring->Set_help(
02358             "This controls how the DOS kernel sets up the CP/M compatibility code in the PSP segment.\n"
02359             "Several options are provided to emulate one of several undocumented behaviors related to the CP/M entry point.\n"
02360             "If set to auto, DOSBox-X will pick the best option to allow it to work properly.\n"
02361             "Unless set to 'off', this option will require the DOS kernel to occupy the first 256 bytes of the HMA memory area\n"
02362             "to prevent crashes when the A20 gate is switched on.\n"
02363             "   auto      Pick the best option\n"
02364             "   off       Turn off the CP/M entry point (program will abort if called)\n"
02365             "   msdos2    MS-DOS 2.x behavior, offset field also doubles as data segment size\n"
02366             "   msdos5    MS-DOS 5.x behavior, entry point becomes one of two fixed addresses\n"
02367             "   direct    Non-standard behavior, encode the CALL FAR directly to the entry point rather than indirectly");
02368 
02369     Pbool = secprop->Add_bool("share",Property::Changeable::WhenIdle,true);
02370     Pbool->Set_help("Report SHARE.EXE as resident. Does not actually emulate SHARE functions.");
02371 
02372     // bugfix for "Digital Dream" DOS demo that displays a "peace to hackers" message if it thinks it's being debugged.
02373     Pbool = secprop->Add_bool("write plain iretf for debug interrupts",Property::Changeable::WhenIdle,true);
02374     Pbool->Set_help("If true (default), the DOS kernel will create an alternate interrupt handler for debug interrupts INT 1 and INT 3\n"
02375             "that contain ONLY an IRETF instruction. If false, INT 1 and INT 3 will use the same default interrupt handler in\n"
02376             "the DOS kernel, which contains a callback instruction followed by IRETF. Some DOS games/demos assume they are being\n"
02377             "debugged if the debug interrupts point to anything other than an IRETF instruction. Set this option to false if\n"
02378             "you need notification that INT 1/INT 3 was not handled.");
02379 
02380     Phex = secprop->Add_hex("minimum dos initial private segment", Property::Changeable::WhenIdle,0);
02381     Phex->Set_help("In non-mainline mapping mode, where DOS structures are allocated from base memory, this sets the\n"
02382             "minimum segment value. Recommended value is 0x70. You may reduce the value down to 0x50 if freeing\n"
02383             "up more memory is important. Set to 0 for default.");
02384 
02385     Phex = secprop->Add_hex("minimum mcb segment", Property::Changeable::WhenIdle,0);
02386     Phex->Set_help("Minimum segment value to begin memory allocation from, in hexadecimal. Set to 0 for default.\n"
02387             "You can increase available DOS memory by reducing this value down to as low as 0x51, however\n"
02388             "setting it to low can cause some DOS programs to crash or run erratically, and some DOS games\n"
02389             "and demos to cause intermittent static noises when using Sound Blaster output. DOS programs\n"
02390             "compressed with Microsoft EXEPACK will not run if the minimum MCB segment is below 64KB.");
02391 
02392     Phex = secprop->Add_hex("minimum mcb free", Property::Changeable::WhenIdle,0);
02393     Phex->Set_help("Minimum free segment value to leave free. At startup, the DOS kernel will allocate memory\n"
02394                    "up to this point. This can be used to deal with EXEPACK issues or DOS programs that cannot\n"
02395                    "be loaded too low in memory. This differs from 'minimum mcb segment' in that this affects\n"
02396                    "the lowest free block instead of the starting point of the mcb chain.");
02397 
02398     // TODO: Enable by default WHEN the 'SD' signature becomes valid, and a valid device list within
02399     //       is emulated properly.
02400     Pbool = secprop->Add_bool("enable dummy device mcb",Property::Changeable::OnlyAtStart,false);
02401     Pbool->Set_help("If set (default), allocate a fake device MCB at the base of conventional memory.\n"
02402             "Clearing this option can reclaim a small amount of conventional memory at the expense of\n"
02403             "some minor DOS compatibility.");
02404 
02405     Pint = secprop->Add_int("maximum environment block size on exec", Property::Changeable::WhenIdle,-1);
02406     Pint->SetMinMax(-1,65535);
02407     Pint->Set_help("Maximum environment block size to copy for child processes. Set to -1 for default.");
02408 
02409     Pint = secprop->Add_int("additional environment block size on exec", Property::Changeable::WhenIdle,-1);
02410     Pint->SetMinMax(-1,65535);
02411     Pint->Set_help("When executing a program, compute the size of the parent block then add this amount to allow for a few additional variables.\n"
02412             "If the subprocesses will never add/modify the environment block, you can free up a few additional bytes by setting this to 0.\n"
02413             "Set to -1 for default setting.");
02414 
02415     // DEPRECATED, REMOVE
02416     Pbool = secprop->Add_bool("enable a20 on windows init",Property::Changeable::OnlyAtStart,false);
02417     Pbool->Set_help("If set, DOSBox will enable the A20 gate when Windows 3.1/9x broadcasts the INIT message\n"
02418             "at startup. Windows 3.1 appears to make assumptions at some key points on startup about\n"
02419             "A20 that don't quite hold up and cause Windows 3.1 to crash when you set A20 emulation\n"
02420             "to a20=mask as opposed to a20=fast. This option is enabled by default.");
02421 
02422     Pbool = secprop->Add_bool("zero memory on xms memory allocation",Property::Changeable::OnlyAtStart,false);
02423     Pbool->Set_help("If set, memory returned by XMS allocation call is zeroed first. This is NOT what\n"
02424             "DOS actually does, but if set, can help certain DOS games and demos cope with problems\n"
02425             "related to uninitialized variables in extended memory. When enabled this option may\n"
02426             "incur a slight to moderate performance penalty.");
02427 
02428     Pstring = secprop->Add_string("dosv",Property::Changeable::WhenIdle,"off");
02429     Pstring->Set_values(dosv_settings);
02430     Pstring->Set_help("Enable DOS/V emulation and specify which version to emulate. This option is intended for\n"
02431             "use with games or software originating from Asia that use the double byte character set\n"
02432             "encodings and the DOS/V extensions to display Japanese, Chinese, or Korean text.\n"
02433             "Note that enabling DOS/V replaces 80x25 text mode (INT 10h mode 3) with a EGA/VGA graphics\n"
02434             "mode that emulates text mode to display the characters and may be incompatible with non-Asian\n"
02435             "software that assumes direct access to the text mode via segment 0xB800.\n"
02436             "WARNING: This option is very experimental at this time.");
02437 
02438     Pstring = secprop->Add_string("ems",Property::Changeable::WhenIdle,"true");
02439     Pstring->Set_values(ems_settings);
02440     Pstring->Set_help("Enable EMS support. The default (=true) provides the best\n"
02441         "compatibility but certain applications may run better with\n"
02442         "other choices, or require EMS support to be disabled (=false)\n"
02443         "to work at all.");
02444 
02445     Pbool = secprop->Add_bool("vcpi",Property::Changeable::OnlyAtStart,true);
02446     Pbool->Set_help("If set and expanded memory is enabled, also emulate VCPI.");
02447 
02448     Pbool = secprop->Add_bool("unmask timer on disk io",Property::Changeable::OnlyAtStart,false);
02449     Pbool->Set_help("If set, INT 21h emulation will unmask IRQ 0 (timer interrupt) when the application opens/closes/reads/writes files.");
02450 
02451     Pbool = secprop->Add_bool("zero int 67h if no ems",Property::Changeable::OnlyAtStart,true);
02452     Pbool->Set_help("If ems=false, leave interrupt vector 67h zeroed out (default true).\n"
02453             "This is a workaround for games or demos that try to detect EMS by whether or not INT 67h is 0000:0000 rather than a proper test.\n"
02454             "This option also affects whether INT 67h is zeroed when booting a guest OS");
02455 
02456     /* FIXME: The vm86 monitor in src/ints/ems.cpp is not very stable! Option is default OFF until stabilized! */
02457     Pbool = secprop->Add_bool("emm386 startup active",Property::Changeable::OnlyAtStart,false);
02458     Pbool->Set_help("If set and expanded memory is set to emulate emm386, start the DOS machine with EMM386.EXE active\n"
02459             "(running the 16-bit DOS environment from within Virtual 8086 mode). If you will be running anything\n"
02460             "that involves a DOS extender you will also need to enable the VCPI interface as well.");
02461 
02462     Pbool = secprop->Add_bool("zero memory on ems memory allocation",Property::Changeable::OnlyAtStart,false);
02463     Pbool->Set_help("If set, memory returned by EMS allocation call is zeroed first. This is NOT what\n"
02464             "DOS actually does, but if set, can help certain DOS games and demos cope with problems\n"
02465             "related to uninitialized variables in expanded memory. When enabled this option may\n"
02466             "incur a slight to moderate performance penalty.");
02467 
02468     Pint = secprop->Add_int("ems system handle memory size",Property::Changeable::WhenIdle,384);
02469     Pint->Set_help("Amount of memory associated with system handle, in KB");
02470 
02471     Pbool = secprop->Add_bool("ems system handle on even megabyte",Property::Changeable::WhenIdle,false);
02472     Pbool->Set_help("If set, try to allocate the EMM system handle on an even megabyte.\n"
02473             "If the DOS game or demo fiddles with the A20 gate while using EMM386.EXE emulation in virtual 8086 mode, setting this option may help prevent crashes.\n"
02474             "However, forcing allocation on an even megabyte will also cause some extended memory fragmentation and reduce the\n"
02475             "overall amount of extended memory available to the DOS game depending on whether it expects large contiguous chunks\n"
02476             "of extended memory.");
02477 
02478     Pbool = secprop->Add_bool("umb",Property::Changeable::WhenIdle,true);
02479     Pbool->Set_help("Enable UMB support.");
02480 
02481     Phex = secprop->Add_hex("umb start",Property::Changeable::OnlyAtStart,0); /* <- (0=auto) 0xD000 is mainline DOSBox compatible behavior */
02482     Phex->Set_help("UMB region starting segment");
02483 
02484     Phex = secprop->Add_hex("umb end",Property::Changeable::OnlyAtStart,0); /* <- (0=auto) 0xEFFF is mainline DOSBox compatible (where base=0xD000 and size=0x2000) */
02485     Phex->Set_help("UMB region last segment");
02486 
02487     Pbool = secprop->Add_bool("kernel allocation in umb",Property::Changeable::OnlyAtStart,false);
02488     Pbool->Set_help("If set, dynamic kernel allocation=1, and private area in umb=1, all kernel structures will be allocated from the private area in UMB.\n"
02489             "If you intend to run Windows 3.1 in DOSBox, you must set this option to false else Windows 3.1 will not start.");
02490 
02491     Pbool = secprop->Add_bool("keep umb on boot",Property::Changeable::OnlyAtStart,false);
02492     Pbool->Set_help("If emulating UMBs, keep the UMB around after boot (Mainline DOSBox behavior). If clear, UMB is unmapped when you boot an operating system.");
02493 
02494     Pbool = secprop->Add_bool("keep private area on boot",Property::Changeable::OnlyAtStart,false);
02495     Pbool->Set_help("If set, keep the DOSBox private area around after boot (Mainline DOSBox behavior). If clear, unmap and discard the private area when you boot an operating system.");
02496 
02497     Pbool = secprop->Add_bool("private area in umb",Property::Changeable::WhenIdle,true);
02498     Pbool->Set_help("If set, keep private DOS segment in upper memory block, usually segment 0xC800 (Mainline DOSBox behavior)\n"
02499             "If clear, place private DOS segment at the base of system memory (just below the MCB)");
02500 
02501     Pstring = secprop->Add_string("ver",Property::Changeable::WhenIdle,"");
02502     Pstring->Set_help("Set DOS version. Specify as major.minor format. A single number is treated as the major version (LFN patch compat). Common settings are:\n"
02503             "auto (or unset)                  Pick a DOS kernel version automatically\n"
02504             "3.3                              MS-DOS 3.3 emulation (not tested!)\n"
02505             "5.0                              MS-DOS 5.0 emulation (recommended for DOS gaming)\n"
02506             "6.22                             MS-DOS 6.22 emulation\n"
02507             "7.0                              Windows 95 (pure DOS mode) emulation\n");
02508 
02509     Pbool = secprop->Add_bool("automount",Property::Changeable::WhenIdle,true);
02510     Pbool->Set_help("Enable automatic mount.");
02511 
02512     Pbool = secprop->Add_bool("int33",Property::Changeable::WhenIdle,true);
02513     Pbool->Set_help("Enable INT 33H (mouse) support.");
02514 
02515     Pbool = secprop->Add_bool("int 13 extensions",Property::Changeable::WhenIdle,true);
02516     Pbool->Set_help("Enable INT 13h extensions (functions 0x40-0x48). You will need this enabled if the virtual hard drive image is 8.4GB or larger.");
02517 
02518     Pbool = secprop->Add_bool("biosps2",Property::Changeable::OnlyAtStart,true);
02519     Pbool->Set_help("Emulate BIOS INT 15h PS/2 mouse services\n"
02520         "Note that some OS's like Microsoft Windows neither use INT 33h nor\n"
02521         "probe the AUX port directly and depend on this BIOS interface exclusively\n"
02522         "for PS/2 mouse support. In other cases there is no harm in leaving this enabled");
02523 
02524     /* bugfix for Yodel "mayday" demo */
02525     /* TODO: Set this option to default to "true" if it turns out most BIOSes unmask the IRQ during INT 15h AH=86 WAIT */
02526     Pbool = secprop->Add_bool("int15 wait force unmask irq",Property::Changeable::OnlyAtStart,true);
02527     Pbool->Set_help("Some demos or games mistakingly use INT 15h AH=0x86 (WAIT) while leaving the IRQs needed for it masked.\n"
02528             "If this option is set (by default), the necessary IRQs will be unmasked when INT 15 AH=0x86 is used so that the game or demo does not hang.");
02529 
02530     Pbool = secprop->Add_bool("int15 mouse callback does not preserve registers",Property::Changeable::OnlyAtStart,false);
02531     Pbool->Set_help("Set to true if the guest OS or DOS program assigns an INT 15h mouse callback,\n"
02532             "but does not properly preserve CPU registers. Diagnostic function only (default off).");
02533 
02534     Pstring = secprop->Add_string("keyboardlayout",Property::Changeable::WhenIdle, "auto");
02535     Pstring->Set_help("Language code of the keyboard layout (or none).");
02536 
02537     Pbool = secprop->Add_bool("dbcs",Property::Changeable::OnlyAtStart,true);
02538     Pbool->Set_help("Enable DBCS table.\n"
02539             "CAUTION: Some software will crash without the DBCS table, including the Open Watcom installer.\n");
02540 
02541     Pbool = secprop->Add_bool("filenamechar",Property::Changeable::OnlyAtStart,true);
02542     Pbool->Set_help("Enable filename char table");
02543 
02544     Pbool = secprop->Add_bool("collating and uppercase",Property::Changeable::OnlyAtStart,true);
02545     Pbool->Set_help("Enable collating and uppercase table");
02546 
02547     Pint = secprop->Add_int("files",Property::Changeable::OnlyAtStart,127);
02548     Pint->Set_help("Number of file handles available to DOS programs. (equivalent to \"files=\" in config.sys)");
02549 
02550     // DEPRECATED, REMOVE
02551     Pbool = secprop->Add_bool("con device use int 16h to detect keyboard input",Property::Changeable::OnlyAtStart,true);
02552     Pbool->Set_help("If set, use INT 16h to detect keyboard input (MS-DOS 6.22 behavior). If clear, detect keyboard input by\n"
02553             "peeking into the BIOS keyboard buffer (Mainline DOSBox behavior). You will need to set this\n"
02554             "option for programs that hook INT 16h to handle keyboard input ahead of the DOS console.\n"
02555             "Microsoft Scandisk needs this option to respond to keyboard input correctly.");
02556 
02557     Pbool = secprop->Add_bool("zero memory on int 21h memory allocation",Property::Changeable::OnlyAtStart,false);
02558     Pbool->Set_help("If set, memory returned by the INT 21h allocation call is zeroed first. This is NOT what\n"
02559             "DOS actually does, but if set, can help certain DOS games and demos cope with problems\n"
02560             "related to uninitialized variables in the data or stack segment. If you intend to run a\n"
02561             "game or demo known to have this problem (Second Unreal, for example), set to true, else\n"
02562             "set to false. When enabled this option may incur a slight to moderate performance penalty.");
02563 
02564     secprop=control->AddSection_prop("ipx",&Null_Init,true);
02565     Pbool = secprop->Add_bool("ipx",Property::Changeable::WhenIdle, false);
02566     Pbool->Set_help("Enable ipx over UDP/IP emulation.");
02567 
02568     secprop=control->AddSection_prop("ne2000",&Null_Init,true);
02569     MSG_Add("NE2000_CONFIGFILE_HELP",
02570         "macaddr -- The physical address the emulator will use on your network.\n"
02571         "           If you have multiple DOSBoxes running on your network,\n"
02572         "           this has to be changed. Modify the last three number blocks.\n"
02573         "           I.e. AC:DE:48:88:99:AB.\n"
02574         "realnic -- Specifies which of your network interfaces is used.\n"
02575         "           Write \'list\' here to see the list of devices in the\n"
02576         "           Status Window. Then make your choice and put either the\n"
02577         "           interface number (2 or something) or a part of your adapters\n"
02578         "           name, e.g. VIA here.\n"
02579 
02580     );
02581 
02582     Pbool = secprop->Add_bool("ne2000", Property::Changeable::WhenIdle, false);
02583     Pbool->Set_help("Enable Ethernet passthrough. Requires [Win]Pcap.");
02584 
02585     Phex = secprop->Add_hex("nicbase", Property::Changeable::WhenIdle, 0x300);
02586     Phex->Set_help("The base address of the NE2000 board.");
02587 
02588     Pint = secprop->Add_int("nicirq", Property::Changeable::WhenIdle, 3);
02589     Pint->Set_help("The interrupt it uses. Note serial2 uses IRQ3 as default.");
02590 
02591     Pstring = secprop->Add_string("macaddr", Property::Changeable::WhenIdle,"AC:DE:48:88:99:AA");
02592     Pstring->Set_help("The physical address the emulator will use on your network.\n"
02593         "If you have multiple DOSBoxes running on your network,\n"
02594         "this has to be changed for each. AC:DE:48 is an address range reserved for\n"
02595         "private use, so modify the last three number blocks.\n"
02596         "I.e. AC:DE:48:88:99:AB.");
02597 
02598     /* TODO: Change default to "nat" and then begin implementing support for emulating
02599      *       an ethernet connection with DOSBox-X as a NAT/firewall between the guest
02600      *       and the OS. Sort of like "NAT" mode in VirtualBox. When that works, we
02601      *       can then compile NE2000 support with and without libpcap/winpcap support. */
02602     Pstring = secprop->Add_string("realnic", Property::Changeable::WhenIdle,"list");
02603     Pstring->Set_help("Specifies which of your network interfaces is used.\n"
02604         "Write \'list\' here to see the list of devices in the\n"
02605         "Status Window. Then make your choice and put either the\n"
02606         "interface number (2 or something) or a part of your adapters\n"
02607         "name, e.g. VIA here.");
02608 
02609     /* floppy controller emulation options and setup */
02610     secprop=control->AddSection_prop("fdc, primary",&Null_Init,false);
02611 
02612     /* Primary FDC on by default, secondary is not. Most PCs have only one floppy controller. */
02613     Pbool = secprop->Add_bool("enable",Property::Changeable::OnlyAtStart,false);
02614     Pbool->Set_help("Enable floppy controller interface");
02615 
02616     Pbool = secprop->Add_bool("pnp",Property::Changeable::OnlyAtStart,true);
02617     Pbool->Set_help("List floppy controller in ISA PnP BIOS enumeration");
02618 
02619     Pint = secprop->Add_int("irq",Property::Changeable::WhenIdle,0/*use FDC default*/);
02620     Pint->Set_help("IRQ used by floppy controller. Set to 0 for default.\n"
02621         "WARNING: Setting the IRQ to non-standard values will not work unless the guest OS is using the ISA PnP BIOS to detect the floppy controller.\n"
02622         "         Setting the IRQ to one already occupied by another device or IDE controller will trigger \"resource conflict\" errors in Windows 95.\n"
02623         "         Normally, floppy controllers use IRQ 6.");
02624 
02625     Phex = secprop->Add_hex("io",Property::Changeable::WhenIdle,0/*use FDC default*/);
02626     Phex->Set_help("Base I/O port for floppy controller. Set to 0 for default.\n"
02627         "WARNING: Setting the I/O port to non-standard values will not work unless the guest OS is using the ISA PnP BIOS to detect the IDE controller.\n"
02628         "         Standard I/O ports are 3F0 and 370.");
02629 
02630     Pint = secprop->Add_int("dma",Property::Changeable::WhenIdle,-1/*use FDC default*/);
02631     Pint->Set_help("DMA channel for floppy controller. Set to -1 for default.\n"
02632         "WARNING: Setting the DMA channel to non-standard values will not work unless the guest OS is using the ISA PnP BIOS to detect the IDE controller.\n"
02633         "         Standard DMA channel is 2.");
02634 
02635     Pbool = secprop->Add_bool("int13fakev86io",Property::Changeable::WhenIdle,false);
02636     Pbool->Set_help(
02637         "If set, and int13fakeio is set, certain INT 13h commands will\n"
02638         "cause floppy emulation to issue fake CPU I/O traps (GPF) in\n"
02639         "virtual 8086 mode and a fake IRQ signal. you must enable this option\n"
02640         "if you want 32-bit floppy access in Windows 95 to work with DOSBox.");
02641 
02642     Pbool = secprop->Add_bool("instant mode",Property::Changeable::WhenIdle,false);
02643     Pbool->Set_help(
02644         "If set, all floppy operations are 'instantaneous', they are carried\n"
02645         "out without any delay. Real hardware of course has motor, command\n"
02646         "and data I/O delays and so this option is off by default for realistic\n"
02647         "emulation.");
02648 
02649     Pbool = secprop->Add_bool("auto-attach to int 13h",Property::Changeable::WhenIdle,true);
02650     Pbool->Set_help(
02651         "If set, DOSBox-X will automatically attach a disk image as being\n"
02652         "inserted into a floppy drive attached to the controller when imgmount is used\n"
02653         "to mount a disk image to drive 0/1 or A/B. If not set, you must specify\n"
02654         "the -fdc option to imgmount to attach drive A/B to the floppy controller\n"
02655         "manually. You must use the -fdc option regardless if loading floppies into\n"
02656         "drives attached to any other FDC than the primary controller");
02657 
02658     /* FIXME: From http://wiki.osdev.org/Floppy_Disk_Controller#Configure
02659      *
02660      *    "The three modes are PC-AT mode, PS/2 mode, and Model 30 mode. The most likely mode ... is model 30 mode.
02661      *    You may find some pre-1996 Pentium machines using PS/2 mode. You can ignore PC-AT mode."
02662      *
02663      *    What? What the fuck are you talking about?
02664      *
02665      *    "AT mode" seems to imply the presense of port 3F7. PS/2 mode seems to imply the presense of 3F0-3F1 and 3F7.
02666      *    A Toshiba laptop (Satellite Pro 465CDX) has port 3F7 but not 3F0-3F1. By other documentation I've found, that
02667      *    means this laptop (which came out late 1997) is running in AT mode! There's plenty of hardware running in both
02668      *    PS/2 and AT mode, even some very old stuff in my pile of junk dating back to 1990!
02669      *
02670      *    Somehow I think this information is as correct as their ATAPI programming docs on how to read CD-ROM
02671      *    sectors: it's a start but it's mostly wrong. Hopefully DOSLIB will shed light on what the real differences
02672      *    are and what is most common. --J.C. */
02673     Pstring = secprop->Add_string("mode",Property::Changeable::WhenIdle,"ps2");
02674     Pstring->Set_help(
02675         "Floppy controller mode. What the controller acts like.\n"
02676         "  ps2                          PS/2 mode (most common)\n"
02677         "  ps2_model30                  PS/2 model 30\n"
02678         "  at                           AT mode\n"
02679         "  xt                           PC/XT mode");
02680 
02681     /* FIXME: Not yet implemented. Future plans */
02682     Pstring = secprop->Add_string("chip",Property::Changeable::WhenIdle,"82077aa");
02683     Pstring->Set_help(
02684         "Floppy controller chipset\n"
02685         "  82077aa                      Intel 82077AA chipset\n"
02686         "  82072                        Intel 82072 chipset\n"
02687         "  nec_uPD765                   NEC uPD765 chipset\n"
02688         "  none                         No chipset (For PC/XT mode)");
02689 
02690     /* IDE emulation options and setup */
02691     for (size_t i=0;i < MAX_IDE_CONTROLLERS;i++) {
02692         secprop=control->AddSection_prop(ide_names[i],&Null_Init,false);//done
02693 
02694         /* Primary and Secondary are on by default, Teritary and Quaternary are off by default.
02695          * Throughout the life of the IDE interface it was far more common for a PC to have just
02696          * a Primary and Secondary interface */
02697         Pbool = secprop->Add_bool("enable",Property::Changeable::OnlyAtStart,(i < 2) ? true : false);
02698         if (i == 0) Pbool->Set_help("Enable IDE interface");
02699 
02700         Pbool = secprop->Add_bool("pnp",Property::Changeable::OnlyAtStart,true);
02701         if (i == 0) Pbool->Set_help("List IDE device in ISA PnP BIOS enumeration");
02702 
02703         Pint = secprop->Add_int("irq",Property::Changeable::WhenIdle,0/*use IDE default*/);
02704         if (i == 0) Pint->Set_help("IRQ used by IDE controller. Set to 0 for default.\n"
02705                 "WARNING: Setting the IRQ to non-standard values will not work unless the guest OS is using the ISA PnP BIOS to detect the IDE controller.\n"
02706                 "         Setting the IRQ to one already occupied by another device or IDE controller will trigger \"resource conflict\" errors in Windows 95.\n"
02707                 "         Using IRQ 9, 12, 13, or IRQ 2-7 may cause problems with MS-DOS CD-ROM drivers.");
02708 
02709         Phex = secprop->Add_hex("io",Property::Changeable::WhenIdle,0/*use IDE default*/);
02710         if (i == 0) Pint->Set_help("Base I/O port for IDE controller. Set to 0 for default.\n"
02711                 "WARNING: Setting the I/O port to non-standard values will not work unless the guest OS is using the ISA PnP BIOS to detect the IDE controller.\n"
02712                 "         Using any port other than 1F0, 170, 1E8 or 168 can prevent MS-DOS CD-ROM drivers from detecting the IDE controller.");
02713 
02714         Phex = secprop->Add_hex("altio",Property::Changeable::WhenIdle,0/*use IDE default*/);
02715         if (i == 0) Pint->Set_help("Alternate I/O port for IDE controller (alt status, etc). Set to 0 for default.\n"
02716                 "WARNING: Setting the I/O port to non-standard values will not work unless the guest OS is using the ISA PnP BIOS to detect the IDE controller.\n"
02717                 "         For best compatability set this value to io+0x206, for example, io=1F0 altio=3F6.\n"
02718                 "         The primary IDE controller will not claim port 3F7 if the primary floppy controller is enabled due to I/O port overlap in the 3F0-3F7 range.");
02719 
02720         Pbool = secprop->Add_bool("int13fakeio",Property::Changeable::WhenIdle,false);
02721         if (i == 0) Pbool->Set_help(
02722                 "If set, force IDE state change on certain INT 13h commands.\n"
02723                 "IDE registers will be changed as if BIOS had carried out the action.\n"
02724                 "If you are running Windows 3.11 or Windows 3.11 Windows for Workgroups\n"
02725                 "you must enable this option (and use -reservecyl 1) if you want 32-bit\n"
02726                 "disk access to work correctly in DOSBox.");
02727 
02728         Pbool = secprop->Add_bool("int13fakev86io",Property::Changeable::WhenIdle,false);
02729         if (i == 0) Pbool->Set_help(
02730                 "If set, and int13fakeio is set, certain INT 13h commands will\n"
02731                 "cause IDE emulation to issue fake CPU I/O traps (GPF) in\n"
02732                 "virtual 8086 mode and a fake IRQ signal. you must enable this option\n"
02733                 "if you want 32-bit disk access in Windows 95 to work with DOSBox.");
02734 
02735         Pbool = secprop->Add_bool("enable pio32",Property::Changeable::WhenIdle,false);
02736         if (i == 0) Pbool->Set_help(
02737                 "If set, 32-bit I/O reads and writes are handled directly (much like PCI IDE implementations)\n"
02738                 "If clear, 32-bit I/O will be handled as if two 16-bit I/O (much like ISA IDE implementations)");
02739 
02740         Pbool = secprop->Add_bool("ignore pio32",Property::Changeable::WhenIdle,false);
02741         if (i == 0) Pbool->Set_help(
02742                 "If 32-bit I/O is enabled, attempts to read/write 32-bit I/O will be ignored entirely.\n"
02743                 "In this way, you can have DOSBox emulate one of the strange quirks of 1995-1997 era\n"
02744                 "laptop hardware");
02745 
02746         Pint = secprop->Add_int("cd-rom spinup time",Property::Changeable::WhenIdle,0/*use IDE or CD-ROM default*/);
02747         if (i == 0) Pint->Set_help("Emulated CD-ROM time in ms to spin up if CD is stationary.\n"
02748                 "Set to 0 to use controller or CD-ROM drive-specific default.");
02749 
02750         Pint = secprop->Add_int("cd-rom spindown timeout",Property::Changeable::WhenIdle,0/*use IDE or CD-ROM default*/);
02751         if (i == 0) Pint->Set_help("Emulated CD-ROM time in ms that drive will spin down automatically when not in use\n"
02752                 "Set to 0 to use controller or CD-ROM drive-specific default.");
02753 
02754         Pint = secprop->Add_int("cd-rom insertion delay",Property::Changeable::WhenIdle,0/*use IDE or CD-ROM default*/);
02755         if (i == 0) Pint->Set_help("Emulated CD-ROM time in ms that drive will report \"medium not present\"\n"
02756                 "to emulate the time it takes for someone to take out a CD and insert a new one when\n"
02757                 "DOSBox is instructed to swap or change CDs.\n"
02758                 "When running Windows 95 or higher a delay of 4000ms is recommended to ensure that\n"
02759                 "auto-insert notification triggers properly.\n"
02760                 "Set to 0 to use controller or CD-ROM drive-specific default.");
02761     }
02762 
02763     //TODO ?
02764     control->AddSection_line("autoexec",&Null_Init);
02765     MSG_Add("AUTOEXEC_CONFIGFILE_HELP",
02766         "Lines in this section will be run at startup.\n"
02767         "You can put your MOUNT lines here.\n"
02768     );
02769     MSG_Add("CONFIGFILE_INTRO",
02770             "# This is the configuration file for DOSBox %s. (Please use the latest version of DOSBox)\n"
02771             "# Lines starting with a # are comment lines and are ignored by DOSBox.\n"
02772             "# They are used to (briefly) document the effect of each option.\n"
02773         "# To write out ALL options, use command 'config -all' with -wc or -writeconf options.\n");
02774     MSG_Add("CONFIG_SUGGESTED_VALUES", "Possible values");
02775 }
02776 
02777 int utf8_encode(char **ptr,char *fence,uint32_t code) {
02778     int uchar_size=1;
02779     char *p = *ptr;
02780 
02781     if (!p) return UTF8ERR_NO_ROOM;
02782     if (code >= (uint32_t)0x80000000UL) return UTF8ERR_INVALID;
02783     if (p >= fence) return UTF8ERR_NO_ROOM;
02784 
02785     if (code >= 0x4000000) uchar_size = 6;
02786     else if (code >= 0x200000) uchar_size = 5;
02787     else if (code >= 0x10000) uchar_size = 4;
02788     else if (code >= 0x800) uchar_size = 3;
02789     else if (code >= 0x80) uchar_size = 2;
02790 
02791     if ((p+uchar_size) > fence) return UTF8ERR_NO_ROOM;
02792 
02793     switch (uchar_size) {
02794         case 1: *p++ = (char)code;
02795             break;
02796         case 2: *p++ = (char)(0xC0 | (code >> 6));
02797             *p++ = (char)(0x80 | (code & 0x3F));
02798             break;
02799         case 3: *p++ = (char)(0xE0 | (code >> 12));
02800             *p++ = (char)(0x80 | ((code >> 6) & 0x3F));
02801             *p++ = (char)(0x80 | (code & 0x3F));
02802             break;
02803         case 4: *p++ = (char)(0xF0 | (code >> 18));
02804             *p++ = (char)(0x80 | ((code >> 12) & 0x3F));
02805             *p++ = (char)(0x80 | ((code >> 6) & 0x3F));
02806             *p++ = (char)(0x80 | (code & 0x3F));
02807             break;
02808         case 5: *p++ = (char)(0xF8 | (code >> 24));
02809             *p++ = (char)(0x80 | ((code >> 18) & 0x3F));
02810             *p++ = (char)(0x80 | ((code >> 12) & 0x3F));
02811             *p++ = (char)(0x80 | ((code >> 6) & 0x3F));
02812             *p++ = (char)(0x80 | (code & 0x3F));
02813             break;
02814         case 6: *p++ = (char)(0xFC | (code >> 30));
02815             *p++ = (char)(0x80 | ((code >> 24) & 0x3F));
02816             *p++ = (char)(0x80 | ((code >> 18) & 0x3F));
02817             *p++ = (char)(0x80 | ((code >> 12) & 0x3F));
02818             *p++ = (char)(0x80 | ((code >> 6) & 0x3F));
02819             *p++ = (char)(0x80 | (code & 0x3F));
02820             break;
02821     };
02822 
02823     *ptr = p;
02824     return 0;
02825 }
02826 
02827 int utf8_decode(const char **ptr,const char *fence) {
02828     const char *p = *ptr;
02829     int uchar_size=1;
02830     int ret = 0,c;
02831 
02832     if (!p) return UTF8ERR_NO_ROOM;
02833     if (p >= fence) return UTF8ERR_NO_ROOM;
02834 
02835     ret = (unsigned char)(*p);
02836     if (ret >= 0xFE) { p++; return UTF8ERR_INVALID; }
02837     else if (ret >= 0xFC) uchar_size=6;
02838     else if (ret >= 0xF8) uchar_size=5;
02839     else if (ret >= 0xF0) uchar_size=4;
02840     else if (ret >= 0xE0) uchar_size=3;
02841     else if (ret >= 0xC0) uchar_size=2;
02842     else if (ret >= 0x80) { p++; return UTF8ERR_INVALID; }
02843 
02844     if ((p+uchar_size) > fence)
02845         return UTF8ERR_NO_ROOM;
02846 
02847     switch (uchar_size) {
02848         case 1: p++;
02849             break;
02850         case 2: ret = (ret&0x1F)<<6; p++;
02851             c = (unsigned char)(*p++); if ((c&0xC0) != 0x80) return UTF8ERR_INVALID;
02852             ret |= c&0x3F;
02853             break;
02854         case 3: ret = (ret&0xF)<<12; p++;
02855             c = (unsigned char)(*p++); if ((c&0xC0) != 0x80) return UTF8ERR_INVALID;
02856             ret |= (c&0x3F)<<6;
02857             c = (unsigned char)(*p++); if ((c&0xC0) != 0x80) return UTF8ERR_INVALID;
02858             ret |= c&0x3F;
02859             break;
02860         case 4: ret = (ret&0x7)<<18; p++;
02861             c = (unsigned char)(*p++); if ((c&0xC0) != 0x80) return UTF8ERR_INVALID;
02862             ret |= (c&0x3F)<<12;
02863             c = (unsigned char)(*p++); if ((c&0xC0) != 0x80) return UTF8ERR_INVALID;
02864             ret |= (c&0x3F)<<6;
02865             c = (unsigned char)(*p++); if ((c&0xC0) != 0x80) return UTF8ERR_INVALID;
02866             ret |= c&0x3F;
02867             break;
02868         case 5: ret = (ret&0x3)<<24; p++;
02869             c = (unsigned char)(*p++); if ((c&0xC0) != 0x80) return UTF8ERR_INVALID;
02870             ret |= (c&0x3F)<<18;
02871             c = (unsigned char)(*p++); if ((c&0xC0) != 0x80) return UTF8ERR_INVALID;
02872             ret |= (c&0x3F)<<12;
02873             c = (unsigned char)(*p++); if ((c&0xC0) != 0x80) return UTF8ERR_INVALID;
02874             ret |= (c&0x3F)<<6;
02875             c = (unsigned char)(*p++); if ((c&0xC0) != 0x80) return UTF8ERR_INVALID;
02876             ret |= c&0x3F;
02877             break;
02878         case 6: ret = (ret&0x1)<<30; p++;
02879             c = (unsigned char)(*p++); if ((c&0xC0) != 0x80) return UTF8ERR_INVALID;
02880             ret |= (c&0x3F)<<24;
02881             c = (unsigned char)(*p++); if ((c&0xC0) != 0x80) return UTF8ERR_INVALID;
02882             ret |= (c&0x3F)<<18;
02883             c = (unsigned char)(*p++); if ((c&0xC0) != 0x80) return UTF8ERR_INVALID;
02884             ret |= (c&0x3F)<<12;
02885             c = (unsigned char)(*p++); if ((c&0xC0) != 0x80) return UTF8ERR_INVALID;
02886             ret |= (c&0x3F)<<6;
02887             c = (unsigned char)(*p++); if ((c&0xC0) != 0x80) return UTF8ERR_INVALID;
02888             ret |= c&0x3F;
02889             break;
02890     };
02891 
02892     *ptr = p;
02893     return ret;
02894 }
02895 
02896 int utf16le_encode(char **ptr,char *fence,uint32_t code) {
02897     char *p = *ptr;
02898 
02899     if (!p) return UTF8ERR_NO_ROOM;
02900     if (code > 0x10FFFF) return UTF8ERR_INVALID;
02901     if (code > 0xFFFF) { /* UTF-16 surrogate pair */
02902         uint32_t lo = (code - 0x10000) & 0x3FF;
02903         uint32_t hi = ((code - 0x10000) >> 10) & 0x3FF;
02904         if ((p+2+2) > fence) return UTF8ERR_NO_ROOM;
02905         *p++ = (char)( (hi+0xD800)       & 0xFF);
02906         *p++ = (char)(((hi+0xD800) >> 8) & 0xFF);
02907         *p++ = (char)( (lo+0xDC00)       & 0xFF);
02908         *p++ = (char)(((lo+0xDC00) >> 8) & 0xFF);
02909     }
02910     else if ((code&0xF800) == 0xD800) { /* do not allow accidental surrogate pairs (0xD800-0xDFFF) */
02911         return UTF8ERR_INVALID;
02912     }
02913     else {
02914         if ((p+2) > fence) return UTF8ERR_NO_ROOM;
02915         *p++ = (char)( code       & 0xFF);
02916         *p++ = (char)((code >> 8) & 0xFF);
02917     }
02918 
02919     *ptr = p;
02920     return 0;
02921 }
02922 
02923 int utf16le_decode(const char **ptr,const char *fence) {
02924     const char *p = *ptr;
02925     unsigned int ret,b=2;
02926 
02927     if (!p) return UTF8ERR_NO_ROOM;
02928     if ((p+1) >= fence) return UTF8ERR_NO_ROOM;
02929 
02930     ret = (unsigned char)p[0];
02931     ret |= ((unsigned int)((unsigned char)p[1])) << 8;
02932     if (ret >= 0xD800U && ret <= 0xDBFFU)
02933         b=4;
02934     else if (ret >= 0xDC00U && ret <= 0xDFFFU)
02935         { p++; return UTF8ERR_INVALID; }
02936 
02937     if ((p+b) > fence)
02938         return UTF8ERR_NO_ROOM;
02939 
02940     p += 2;
02941     if (ret >= 0xD800U && ret <= 0xDBFFU) {
02942         /* decode surrogate pair */
02943         unsigned int hi = ret & 0x3FFU;
02944         unsigned int lo = (unsigned char)p[0];
02945         lo |= ((unsigned int)((unsigned char)p[1])) << 8;
02946         p += 2;
02947         if (lo < 0xDC00U || lo > 0xDFFFU) return UTF8ERR_INVALID;
02948         lo &= 0x3FFU;
02949         ret = ((hi << 10U) | lo) + 0x10000U;
02950     }
02951 
02952     *ptr = p;
02953     return (int)ret;
02954 }
02955