Following on from my last question, I cannot get Move Extended Memory Block (Function 0Bh)
working in Turbo C 2.01.
The following main.c
contains only the minimum functions: get the XMS driver pointer, call the Move function. xms_move_xmb_internal()
is as bare as I can get it, no variables except the parameters. I couldn't get it working with the XMB handles, so I decided to make sure a conventional->conventional copy worked first.
Compile with tcc -ml -d -G main.c
.
In Dosbox 0.74-2, the call to the XMS driver will either hang indefinitely or crash Dosbox instantly. My other functions (query, freemem, allocation, deallocation, locking and unlocking) work, but not Move. Ethan Brodsky's SB16SND implementation of an XMS wrapper pushes and pops DS around calling the XMS driver pointer but that doesn't have any effect for me if I add it.
I'm aware that in the Large model, far
is redundant but I added it to make sure I wasn't overlooking it.
main.c
:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mem.h>
#include <dos.h>
typedef union
{
struct
{
unsigned int o;
unsigned int s;
} seg_off;
void (far *function_ptr)();
void far *ptr;
unsigned long int offset;
} seg_off_ptr;
seg_off_ptr xms_driver;
int xms_init()
{
union REGS inregs, outregs;
struct SREGS sregs;
inregs.x.ax = 0x4310u;
int86x(0x2Fu, &inregs, &outregs, &sregs);
if (!outregs.h.al) return 0;
xms_driver.seg_off.s = sregs.es;
xms_driver.seg_off.o = outregs.x.bx;
return 1;
}
unsigned int xms_version_implemented()
{
_AX = 0x0000;
(*xms_driver.function_ptr)();
return _AX;
}
void xms_move_xmb_internal(unsigned int ds, unsigned int si)
{
_AX = 0x0B00;
_DS = ds;
_SI = si;
(*xms_driver.function_ptr)();
}
typedef struct _moveparams
{
unsigned long int length;
unsigned int src_handle;
unsigned long int src;
unsigned int dst_handle;
unsigned long int dst;
} moveparams;
void xms_move_xmb
(
unsigned long int length,
unsigned int src_handle,
unsigned long int src,
unsigned int dst_handle,
unsigned long int dst
)
{
moveparams params;
const void far *params_ptr = ¶ms;
params.length = length;
params.src_handle = src_handle;
params.src = src;
params.dst_handle = dst_handle;
params.dst = dst;
xms_move_xmb_internal(FP_SEG(params_ptr), FP_OFF(params_ptr));
}
int main(int argc, char *argv[])
{
int i;
char far *test;
xms_init();
printf("Version %X\r\n", xms_version_implemented());
test = malloc(513);
test[0] = 0;
/* Pattern, 64 XXX then 64 ---. */
for (i = 0; i < (512/4); i++)
{
if (i < 64)
{
strcat(test, "XXX ");
}
else
{
strcat(test, "--- ");
}
}
printf("%s\r\n\r\n", test);
if (1) xms_move_xmb(64ul, 0, (unsigned long)test, 0, (unsigned long)(test + 4*100));
/* Should be equivalent to: */
if (0) memcpy(test + 4*100, test, 64);
printf("%s\r\n\r\n", test);
printf("Did not crash.\r\n");
free(test);
}
The correct output should copy a block of the XXXs into the middle of the ---s.
It's possible that I'm passing the pointer test
into the driver function incorrectly, but I've tried printing the fields of the struct, and printing (and inserting) each individual byte of the params in turn and everything is landing in the correct place.