diff --git a/contrib/windows/installer/dosbox-x.reference.setup.conf b/contrib/windows/installer/dosbox-x.reference.setup.conf index c6ce12f7c..fa8774aaf 100644 --- a/contrib/windows/installer/dosbox-x.reference.setup.conf +++ b/contrib/windows/installer/dosbox-x.reference.setup.conf @@ -1707,6 +1707,7 @@ timeout = 0 # lfn: Enable long filename support. If set to auto (default), it is enabled if the reported DOS version is at least 7.0. # If set to autostart, the builtin VER command won't activate/disactivate LFN support according to the reported DOS version. # Possible values: true, false, 1, 0, auto, autostart. +# autoa20fix: If set (default), DOSBox-X will automatically re-run the executable with the A20 gate disabled if it failed with the "Packed file is corrupt" error. # autoloadfix: If set (default), DOSBox-X will automatically re-run the executable with LOADFIX if it failed with the "Packed file is corrupt" error. # automount: Enable automatic drive mounting in Windows. # automountall: Automatically mount all available Windows drives at start. @@ -1801,6 +1802,7 @@ umb = true quick reboot = false ver = lfn = auto +autoa20fix = true autoloadfix = true automount = true automountall = false diff --git a/dosbox-x.reference.conf b/dosbox-x.reference.conf index 3a2ae49f6..1a27ea594 100644 --- a/dosbox-x.reference.conf +++ b/dosbox-x.reference.conf @@ -624,6 +624,7 @@ timeout = 0 # lfn: Enable long filename support. If set to auto (default), it is enabled if the reported DOS version is at least 7.0. # If set to autostart, the builtin VER command won't activate/disactivate LFN support according to the reported DOS version. # Possible values: true, false, 1, 0, auto, autostart. +# autoa20fix: If set (default), DOSBox-X will automatically re-run the executable with the A20 gate disabled if it failed with the "Packed file is corrupt" error. # autoloadfix: If set (default), DOSBox-X will automatically re-run the executable with LOADFIX if it failed with the "Packed file is corrupt" error. # automount: Enable automatic drive mounting in Windows. # automountall: Automatically mount all available Windows drives at start. @@ -651,6 +652,7 @@ umb = true quick reboot = false ver = lfn = auto +autoa20fix = true autoloadfix = true automount = true automountall = false diff --git a/dosbox-x.reference.full.conf b/dosbox-x.reference.full.conf index a6609a3c0..b03893f17 100644 --- a/dosbox-x.reference.full.conf +++ b/dosbox-x.reference.full.conf @@ -1707,6 +1707,7 @@ timeout = 0 # lfn: Enable long filename support. If set to auto (default), it is enabled if the reported DOS version is at least 7.0. # If set to autostart, the builtin VER command won't activate/disactivate LFN support according to the reported DOS version. # Possible values: true, false, 1, 0, auto, autostart. +# autoa20fix: If set (default), DOSBox-X will automatically re-run the executable with the A20 gate disabled if it failed with the "Packed file is corrupt" error. # autoloadfix: If set (default), DOSBox-X will automatically re-run the executable with LOADFIX if it failed with the "Packed file is corrupt" error. # automount: Enable automatic drive mounting in Windows. # automountall: Automatically mount all available Windows drives at start. @@ -1801,6 +1802,7 @@ private area in umb = true quick reboot = false ver = lfn = auto +autoa20fix = true autoloadfix = true automount = true automountall = false diff --git a/src/dos/dos.cpp b/src/dos/dos.cpp index 65ccedc2c..3e70bc61e 100644 --- a/src/dos/dos.cpp +++ b/src/dos/dos.cpp @@ -379,8 +379,10 @@ static inline void overhead() { #define BCD2BIN(x) ((((unsigned int)(x) >> 4u) * 10u) + ((x) & 0x0fu)) #define BIN2BCD(x) ((((x) / 10u) << 4u) + (x) % 10u) extern bool date_host_forced; +extern bool dos_a20_disable_on_exec; static Bitu DOS_21Handler(void); +void XMS_DOS_LocalA20DisableIfNotEnabled(void); void DOS_Int21_7139(char *name1, const char *name2); void DOS_Int21_713a(char *name1, const char *name2); void DOS_Int21_713b(char *name1, const char *name2); @@ -1610,6 +1612,13 @@ static Bitu DOS_21Handler(void) { case 0x4b: /* EXEC Load and/or execute program */ { MEM_StrCopy(SegPhys(ds)+reg_dx,name1,DOSNAMEBUF); + + /* A20 hack for EXEPACK'd executables */ + if (dos_a20_disable_on_exec) { + XMS_DOS_LocalA20DisableIfNotEnabled(); + dos_a20_disable_on_exec=false; + } + LOG(LOG_EXEC,LOG_NORMAL)("Execute %s %d",name1,reg_al); if (!DOS_Execute(name1,SegPhys(es)+reg_bx,reg_al)) { reg_ax=dos.errorcode; diff --git a/src/dosbox.cpp b/src/dosbox.cpp index 8f10e0de6..fe990db46 100644 --- a/src/dosbox.cpp +++ b/src/dosbox.cpp @@ -3660,6 +3660,10 @@ void DOSBOX_SetupConfigSections(void) { "If set to autostart, the builtin VER command won't activate/disactivate LFN support according to the reported DOS version."); Pstring->SetBasic(true); + Pbool = secprop->Add_bool("autoa20fix",Property::Changeable::WhenIdle,true); + Pbool->Set_help("If set (default), DOSBox-X will automatically re-run the executable with the A20 gate disabled if it failed with the \"Packed file is corrupt\" error."); + Pbool->SetBasic(true); + Pbool = secprop->Add_bool("autoloadfix",Property::Changeable::WhenIdle,true); Pbool->Set_help("If set (default), DOSBox-X will automatically re-run the executable with LOADFIX if it failed with the \"Packed file is corrupt\" error."); Pbool->SetBasic(true); diff --git a/src/ints/xms.cpp b/src/ints/xms.cpp index 3601ce98e..461b28857 100644 --- a/src/ints/xms.cpp +++ b/src/ints/xms.cpp @@ -398,6 +398,15 @@ Bitu XMS_LocalDisableA20(void) { return 0; } +void XMS_DOS_LocalA20DisableIfNotEnabled(void) { + /* This is one of two hacks to deal with EXEPACK'd executables loaded too low */ + if (XMS_GetEnabledA20()) { + LOG(LOG_DOSMISC,LOG_DEBUG)("Temporarily disabling A20 gate. As a hack this will FORCE local A20 enable to zero (from count=%d)",xms_local_enable_count); + xms_local_enable_count = 1; + XMS_LocalDisableA20(); + } +} + void XMS_DOS_LocalA20EnableIfNotEnabled(void) { /* Confirmed MS-DOS behavior if DOS=HIGH */ if (!XMS_GetEnabledA20()) { diff --git a/src/shell/shell_misc.cpp b/src/shell/shell_misc.cpp index d098a7e25..0b34e1010 100644 --- a/src/shell/shell_misc.cpp +++ b/src/shell/shell_misc.cpp @@ -747,6 +747,7 @@ void DOS_Shell::InputCommand(char * line) { ProcessCmdLineEnvVarStitution(line); } +void XMS_DOS_LocalA20DisableIfNotEnabled(void); /* WARNING: Substitution is carried out in-place! * Buffer pointed to by "line" must be at least CMD_MAXLINE+1 bytes long! */ @@ -885,6 +886,7 @@ overflow: std::string full_arguments = ""; intptr_t hret=0; +bool dos_a20_disable_on_exec=false; bool infix=false, winautorun=false; extern bool packerr, reqwin, startwait, startquiet, ctrlbrk, mountwarning; #if defined (WIN32) && !defined(HX_DOS) @@ -1145,7 +1147,15 @@ continue_1: reg_eip=oldeip; SegSet16(cs,oldcs); #endif - if (packerr&&!infix&&sec->Get_bool("autoloadfix")) { + if (packerr&&!infix&&sec->Get_bool("autoa20fix")) { + WriteOut("\r\n\033[41;1m\033[1;37;1mDOSBox-X\033[0m Failed to load the executable\r\n\033[41;1m\033[37;1mDOSBox-X\033[0m Now try again with A20 disable...\r\n"); + infix=true; + dos_a20_disable_on_exec=true; + Execute(name, args); + dos_a20_disable_on_exec=false; + infix=false; + } + else if (packerr&&!infix&&sec->Get_bool("autoloadfix")) { uint16_t segment; uint16_t blocks = (uint16_t)(64*1024/16); if (DOS_AllocateMemory(&segment,&blocks)) {