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