From: A DOT D DOT Brown AT bradford DOT ac DOT uk Subject: Re: DPMI-safe screen access To: FIXER AT FAXCSL DOT DCRT DOT NIH DOT GOV (Chris Tate) Date: Tue, 11 Apr 1995 12:49:08 +0100 (BST) Cc: djgpp AT sun DOT soe DOT clarkson DOT edu > I've got a program (not written by me) that writes to a text screen by building > temporary buffers, then using bcopy() to blast the data to ScreenPrimary. > Needless to say, this crashes under DPMI (most notably in a DOS box under > Windows). > > Unfortunately, I myself am not familiar with the ins and outs of using the > DPMI-safe dosmemput() or routines, and I'd appreciate any advice > that people might offer me. > > Just how would I go about expressing a text-screen blit as either a dosmemput() > to the right place, or something using the routines, or some other > such approach that works under DPMI? From the FAQ, I'm pretty sure that I'm > going to want to use movedata(), but I'm afraid I need some concrete examples > (I'm not at all used to an architecture that doesn't let you just treat *all* > of memory as one big flat space... :-/ ) Okay, this is how I address the VGA memory from 0xA0000 upwards, and it should be trivial to change it to use B8000 or whatever. It seems to work fine in every configuration I've had available to me. Except in windows where it deletes windows from your hard disk and puts up a message requesting you to not run the program from windows again. (Not really :). (Note - I first saw this method used by Christopher Christenson in his libgame. I've also seen it meantioned by Stu Hull (shull AT bradford DOT ac DOT uk) in his djgpp game programmers faq. Available from x2ftp.oulu.fi:/pub/msdos/programming/docs/gccfaq10.zip) First of all, some time in the initialisation process you need to set up the value of the dos selector. (This is what your 1st 1MB of memory has been remapped to). I make the selector global to a module so that I can refrerence it from my memory copy routine. You also need to set up an buffer which is the size of the video screen for all your drawing, and call the blit routine I'll give in a minute to copy it to video memory. Here's a slightly cut down version of some code that I'm using at the moment. It's in C++, but it should work fine with C if you change the comment style. #include #include #include #include // The selector for the first 1MB of memory static short dos_sel; // A buffer for drawing graphics into before blitting it to the screen intu8 *Screen; // Initialises the graphics mode 320x200, 256 colours void InitialiseGraphics(void) { _go32_dpmi_registers regs; // Change to mode 13h using the video bios call memset(®s, 0, sizeof(_go32_dpmi_registers)); regs.x.ax = 0x0013; _go32_dpmi_simulate_int(0x10, ®s); // Allocate space for the screen buffer if((Screen = malloc(320 * 200)) == NULL) { puts("Sorry, not enough memory is available."); exit(1); } // Set up the selector to conventional memory dos_sel = _go32_conventional_mem_selector(); } // Draws the screen from the offscreen buffer void DrawScreen(void) { asm( " pushw %%es \n" " cld \n" " movw _dos_sel, %%es \n" " rep ; movsw \n" " popw %%es \n" : : "c" (32000), "S" (Screen), "D" (0xA0000) : "%cx", "%si", "%di", "cc" ); } All you do now is draw into Screen as you would do to the video screen and call DrawScreen at the appropriate times. If anyone can see any flaws with what I'm doing, or is having problems understanding the code, then I'll be glad to hear from you. Alistair -- EMAIL: A DOT D DOT Brown AT bradford DOT ac DOT uk