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