Reply 100 of 406, by Baron von Riedesel
crazii wrote on 2023-02-06, 03:05:That's cool! is it possible detect & switch to the module at runtime (support QEMM & the module both)? I was thinking about support different EMMs but not yet starting that. Sine this module almost have the same API like QEMM so I guess only tiny portion need to be adjusted, like detection/entry point and such.
Yes, it's dynamic. The adaption ( in qemm.c, function QEMM_GetVersion() ) is a bit hackish, though, because a real INT 2F has to be executed, not a simulated one. This can surely be improved by someone better aquainted with DJGPP peculiarities
unsigned int result = _dos_open("QEMM386$", O_RDONLY, &fd);
// if(result != 0)
// return 0;
uint32_t entryfar = 0;
//ioctl - read from character device control channel
DPMI_REG r = {0};
if ( result == 0 ) {
int count = ioctl(fd, DOS_RCVDATA, 4, &entryfar);
_dos_close(fd);
if(count != 4)
return 0;
r.w.cs = entryfar>>16;
r.w.ip = entryfar&0xFFFF;
} else {
/* getting the entry point of QPIEMU is non-trivial in protected-mode, since
* the int 2Fh must be executed as interrupt ( not just "simulated" ). Here
* a small ( 3 bytes ) helper proc is constructed on the fly, at 0040:00D0,
* which is the INT 2Fh, followed by an RETF.
*/
asm(
"push ds \n\t"
"push $0x40 \n\t"
"pop ds \n\t"
"mov $0xd0, bx \n\t"
"mov $0xcb2fcd, (bx) \n\t"
"pop ds \n\t"
);
r.w.ax = 0x1684;
r.w.bx = 0x4354;
r.w.sp = 0; r.w.ss = 0;
r.w.cs = 0x40;
r.w.ip = 0xd0;
if( DPMI_CallRealModeRETF( &r) != 0 || (r.w.ax & 0xff))
return 0;
r.w.ip = r.w.di;
r.w.cs = r.w.es;
}
r.h.ah = 0x03;
QEMM_EntryIP = r.w.ip;
QEMM_EntryCS = r.w.cs;