www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1995/04/11/14:45:38

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 <farptr.h> 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 <farptr.h> 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
<cnc AT netcom DOT com> 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 <dpmi.h>
#include <go32.h>
#include <malloc.h>
#include <string.h>

// 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(&regs, 0, sizeof(_go32_dpmi_registers));
	regs.x.ax = 0x0013;
	_go32_dpmi_simulate_int(0x10, &regs);

	// 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

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019