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:
parent
03190a56be
commit
974158842f
4 changed files with 90 additions and 46 deletions
|
@ -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
|
||||
|
|
|
@ -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.");
|
||||
|
|
118
src/ints/ems.cpp
118
src/ints/ems.cpp
|
@ -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 */
|
||||
|
|
|
@ -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(){
|
||||
|
|
Loading…
Add table
Reference in a new issue