1
0
Fork 0

different EMS emulation types (ems board style, emm386 extended compatibility),

fixes sound crackling in certain emm386-aware games

Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@3642
This commit is contained in:
Sebastian Strohhäcker 2010-09-26 15:26:46 +00:00
parent 03190a56be
commit 974158842f
4 changed files with 90 additions and 46 deletions

View file

@ -114,6 +114,8 @@ DmaChannel * GetDMAChannel(Bit8u chan);
void CloseSecondDMAController(void);
bool SecondDMAControllerAvailable(void);
void DMA_SetWrapping(Bitu wrap);
static Bit32u dma_wrapping = 0xffff;
#endif

View file

@ -333,7 +333,7 @@ void DOSBOX_Init(void) {
const char* machines[] = {
"hercules", "cga", "tandy", "pcjr", "ega",
"vgaonly", "svga_s3", "svga_et3000", "svga_et4000",
"svga_paradise", "vesa_nolfb", "vesa_oldvbe", 0 };
"svga_paradise", "vesa_nolfb", "vesa_oldvbe", 0 };
secprop=control->AddSection_prop("dosbox",&DOSBOX_RealInit);
Pstring = secprop->Add_path("language",Property::Changeable::Always,"");
Pstring->Set_help("Select another language file.");
@ -654,8 +654,13 @@ void DOSBOX_Init(void) {
Pbool->Set_help("Enable XMS support.");
secprop->AddInitFunction(&EMS_Init,true);//done
Pbool = secprop->Add_bool("ems",Property::Changeable::WhenIdle,true);
Pbool->Set_help("Enable EMS support.");
const char* ems_settings[] = { "true", "emsboard", "emm386", "false", 0};
Pstring = secprop->Add_string("ems",Property::Changeable::WhenIdle,"true");
Pstring->Set_values(ems_settings);
Pstring->Set_help("Enable EMS support. The default (=true) provides the best\n"
"compatibility but certain applications may run better with\n"
"other choices, or require EMS support to be disabled (=false)\n"
"to work at all.");
Pbool = secprop->Add_bool("umb",Property::Changeable::WhenIdle,true);
Pbool->Set_help("Enable UMB support.");

View file

@ -32,6 +32,7 @@
#include "setup.h"
#include "support.h"
#include "cpu.h"
#include "dma.h"
#define EMM_PAGEFRAME 0xE000
#define EMM_PAGEFRAME4K ((EMM_PAGEFRAME*16)/4096)
@ -97,7 +98,8 @@ static Bit16u GEMMIS_seg;
class device_EMM : public DOS_Device {
public:
device_EMM() {
device_EMM(bool is_emm386_avail) {
is_emm386=is_emm386_avail;
SetName("EMMXXXX0");
GEMMIS_seg=0;
}
@ -113,6 +115,7 @@ public:
bool WriteToControlChannel(PhysPt /*bufptr*/,Bit16u /*size*/,Bit16u * /*retcode*/){return true;}
private:
Bit8u cache;
bool is_emm386;
};
bool device_EMM::ReadFromControlChannel(PhysPt bufptr,Bit16u size,Bit16u * retcode) {
@ -125,6 +128,7 @@ bool device_EMM::ReadFromControlChannel(PhysPt bufptr,Bit16u size,Bit16u * retco
*retcode=6;
return true;
case 0x01: {
if (!is_emm386) return false;
if (size!=6) return false;
if (GEMMIS_seg==0) GEMMIS_seg=DOS_GetMemory(0x20);
PhysPt GEMMIS_addr=PhysMake(GEMMIS_seg,0);
@ -181,12 +185,14 @@ bool device_EMM::ReadFromControlChannel(PhysPt bufptr,Bit16u size,Bit16u * retco
return true;
}
case 0x02:
if (!is_emm386) return false;
if (size!=2) return false;
mem_writeb(bufptr+0x00,EMM_VERSION>>4); // version 4
mem_writeb(bufptr+0x01,EMM_MINOR_VERSION);
*retcode=2;
return true;
case 0x03:
if (!is_emm386) return false;
if (EMM_MINOR_VERSION < 0x2d) return false;
if (size!=4) return false;
mem_writew(bufptr+0x00,(Bit16u)(MEM_TotalPages()*4)); // max size (kb)
@ -1262,18 +1268,37 @@ static Bitu INT4B_Handler() {
return CBRET_NONE;
}
Bitu GetEMSType(Section_prop * section) {
Bitu rtype = 0;
std::string emstypestr(section->Get_string("ems"));
if (emstypestr=="true") {
rtype = 1; // mixed mode
} else if (emstypestr=="emsboard") {
rtype = 2;
} else if (emstypestr=="emm386") {
rtype = 3;
} else {
rtype = 0;
}
return rtype;
}
class EMS: public Module_base {
private:
DOS_Device * emm_device;
/* location in protected unfreeable memory where the ems name and callback are
* stored 32 bytes.*/
static Bit16u ems_baseseg;
RealPt old4b_pointer,old67_pointer;
CALLBACK_HandlerObject call_vdma,call_vcpi,call_v86mon;
Bitu call_int67;
Bitu ems_type;
public:
EMS(Section* configuration):Module_base(configuration){
EMS(Section* configuration):Module_base(configuration) {
emm_device=NULL;
ems_type=0;
/* Virtual DMA interrupt callback */
call_vdma.Install(&INT4B_Handler,CB_IRET,"Int 4b vdma");
@ -1283,8 +1308,11 @@ public:
GEMMIS_seg=0;
Section_prop * section=static_cast<Section_prop *>(configuration);
if (!section->Get_bool("ems")) return;
ems_type=GetEMSType(section);
if (ems_type<=0) return;
if (machine==MCH_PCJR) {
ems_type=0;
LOG_MSG("EMS disabled for PCJr machine");
return;
}
@ -1302,8 +1330,8 @@ public:
/* Register the ems device */
//TODO MAYBE put it in the class.
DOS_Device * newdev = new device_EMM();
DOS_AddDevice(newdev);
emm_device = new device_EMM(ems_type!=2);
DOS_AddDevice(emm_device);
/* Clear handle and page tables */
Bitu i;
@ -1323,61 +1351,67 @@ public:
EMM_AllocateSystemHandle(8); // allocate OS-dedicated handle (ems handle zero, 128kb)
if (ems_type==3) {
DMA_SetWrapping(0xffffffff); // emm386-bug that disables dma wrapping
}
if (!ENABLE_VCPI) return;
/* Install a callback that handles VCPI-requests in protected mode requests */
call_vcpi.Install(&VCPI_PM_Handler,CB_IRETD,"VCPI PM");
vcpi.pm_interface=(call_vcpi.Get_callback())*CB_SIZE;
if (ems_type!=2) {
/* Install a callback that handles VCPI-requests in protected mode requests */
call_vcpi.Install(&VCPI_PM_Handler,CB_IRETD,"VCPI PM");
vcpi.pm_interface=(call_vcpi.Get_callback())*CB_SIZE;
/* Initialize private data area and set up descriptor tables */
SetupVCPI();
/* Initialize private data area and set up descriptor tables */
SetupVCPI();
if (!vcpi.enabled) return;
if (!vcpi.enabled) return;
/* Install v86-callback that handles interrupts occuring
in v86 mode, including protection fault exceptions */
call_v86mon.Install(&V86_Monitor,CB_IRET,"V86 Monitor");
/* Install v86-callback that handles interrupts occuring
in v86 mode, including protection fault exceptions */
call_v86mon.Install(&V86_Monitor,CB_IRET,"V86 Monitor");
mem_writeb(vcpi.private_area+0x2e00,(Bit8u)0xFE); //GRP 4
mem_writeb(vcpi.private_area+0x2e01,(Bit8u)0x38); //Extra Callback instruction
mem_writew(vcpi.private_area+0x2e02,call_v86mon.Get_callback()); //The immediate word
mem_writeb(vcpi.private_area+0x2e04,(Bit8u)0x66);
mem_writeb(vcpi.private_area+0x2e05,(Bit8u)0xCF); //A IRETD Instruction
mem_writeb(vcpi.private_area+0x2e00,(Bit8u)0xFE); //GRP 4
mem_writeb(vcpi.private_area+0x2e01,(Bit8u)0x38); //Extra Callback instruction
mem_writew(vcpi.private_area+0x2e02,call_v86mon.Get_callback()); //The immediate word
mem_writeb(vcpi.private_area+0x2e04,(Bit8u)0x66);
mem_writeb(vcpi.private_area+0x2e05,(Bit8u)0xCF); //A IRETD Instruction
/* Testcode only, starts up dosbox in v86-mode */
if (ENABLE_V86_STARTUP) {
/* Prepare V86-task */
CPU_SET_CRX(0, 1);
CPU_LGDT(0xff, vcpi.private_area+0x0000);
CPU_LIDT(0x7ff, vcpi.private_area+0x2000);
if (CPU_LLDT(0x08)) LOG_MSG("VCPI:Could not load LDT");
if (CPU_LTR(0x10)) LOG_MSG("VCPI:Could not load TR");
/* Testcode only, starts up dosbox in v86-mode */
if (ENABLE_V86_STARTUP) {
/* Prepare V86-task */
CPU_SET_CRX(0, 1);
CPU_LGDT(0xff, vcpi.private_area+0x0000);
CPU_LIDT(0x7ff, vcpi.private_area+0x2000);
if (CPU_LLDT(0x08)) LOG_MSG("VCPI:Could not load LDT");
if (CPU_LTR(0x10)) LOG_MSG("VCPI:Could not load TR");
CPU_Push32(SegValue(gs));
CPU_Push32(SegValue(fs));
CPU_Push32(SegValue(ds));
CPU_Push32(SegValue(es));
CPU_Push32(SegValue(ss));
CPU_Push32(0x23002);
CPU_Push32(SegValue(cs));
CPU_Push32(reg_eip&0xffff);
/* Switch to V86-mode */
cpu.cpl=0;
CPU_IRET(true,0);
CPU_Push32(SegValue(gs));
CPU_Push32(SegValue(fs));
CPU_Push32(SegValue(ds));
CPU_Push32(SegValue(es));
CPU_Push32(SegValue(ss));
CPU_Push32(0x23002);
CPU_Push32(SegValue(cs));
CPU_Push32(reg_eip&0xffff);
/* Switch to V86-mode */
cpu.cpl=0;
CPU_IRET(true,0);
}
}
}
~EMS() {
Section_prop * section=static_cast<Section_prop *>(m_configuration);
if (!section->Get_bool("ems")) return;
if (ems_type<=0) return;
/* Undo Biosclearing */
BIOS_ZeroExtendedSize(false);
/* Remove ems device */
device_EMM newdev;
DOS_DelDevice(&newdev);
if (emm_device!=NULL) {
DOS_DelDevice(emm_device);
emm_device=NULL;
}
GEMMIS_seg=0;
/* Remove the emsname and callback hack */

View file

@ -412,6 +412,8 @@ Bitu XMS_Handler(void) {
return CBRET_NONE;
}
Bitu GetEMSType(Section_prop * section);
class XMS: public Module_base {
private:
CALLBACK_HandlerObject callbackhandler;
@ -445,7 +447,8 @@ public:
/* Set up UMB chain */
umb_available=section->Get_bool("umb");
DOS_BuildUMBChain(section->Get_bool("umb"),section->Get_bool("ems"));
bool ems_available = GetEMSType(section)>0;
DOS_BuildUMBChain(section->Get_bool("umb"),ems_available);
}
~XMS(){