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