delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1999/11/29/13:51:55

Message-ID: <F77915E7F086D31197F4009027CC81C90DC428@probe-2.as-london.acclaim.com>
From: Shawn Hargreaves <SHargreaves AT acclaimstudios DOT co DOT uk>
To: djgpp AT delorie DOT com
Subject: Re: Newbie tries to plot a pixel and fails :)
Date: Mon, 29 Nov 1999 17:01:03 -0000
MIME-Version: 1.0
X-Mailer: Internet Mail Service (5.5.2650.21)
Reply-To: djgpp AT delorie DOT com

James Migel writes:
> Hi all, I'm trying to work my way through the DJGPP tutorial on 
> the game programming megasite http://perplexed.com/GPMega/

Hmm. Having just had a glance through those docs, I have to say, 
beware! While perhaps not 100% wrong, they are certainly very
misleading: the section about plotting pixels only gives a brief
mention to enabling nearptrs in the text, and then totally ignores
that in the source code examples. In other words, it skips right
over a couple of the more important issues that you need to be
aware of...

For a more complete introduction, try the djgpp User's Guide on
http://www.delorie.com/djgpp/doc/ug/. I can't promise perfection,
but at least all my bits of sample code are complete, and will
work without any further modification :-)

> Is it possible that I have to load a color palette
> before it knows any colors?

It's possible (otherwise you are just relying on your BIOS to have
set the colors, and I wouldn't trust that to always give you the same 
colors on every different machine). But this isn't your problem here.

> fflush(stdin);
> getchar();

Nitpick: flushing stdin probably doesn't do what you expect. This was
used in some old DOS compilers for clearing the input buffer, but
(at least I'm fairly sure, someone please correct me if I'm wrong!)
it doesn't do anything in djgpp. In any case this is certainly not a 
standard feature across different compilers, so it is better to avoid
it.

> union REGS regs;
> regs.x.ax=iMode;
> int86(0x10,&regs,&regs);

Another nitpick: this code will actually work as written, but 
personally I prefer to use __dpmi_int() for such things. The int86()
routine does some emulation to try to keep old real mode DOS programs
working, which limits the number of functions it can support, and
can sometimes have unexpected effects if you didn't realise that it
would do this emulation, so when writing native djgpp code, I think
it is far better to always use __dpmi_int() instead.

> /*global pointer to video buffer*/
> char *pcVideoBuffer=(char *)0xa0000;
[snip]
> pcVideoBuffer[(iy<<8)+(iy<<6)+ix]=cColor;

Here is your real problem: this code is just wrong.

What the tutorial was wanting you to do (but never properly explained)
is to enable the nearptr hack, which is done by calling 
__djgpp_nearptr_enable(), and then adding __djgpp_conventional_base
to your pcVideoBuffer address. For details, see:

	info libc alpha __djgpp_nearptr_enable

Personally I don't like this method very much, though: I think it is
more reliable to use farptr functions for writing to the screen. To
do that, write something like:

	#include <sys/go32.h>
	#include <sys/farptr.h>

	_farpokeb(_dos_ds, 0xA0000 + y*320 + x, color);

Or if you are going to draw many pixels in a row, the faster version:

	_farsetsel(_dos_ds);
	_farnspokeb(0xA0000 + y1*320 + x1, color1);
	_farnspokeb(0xA0000 + y2*320 + x2, color2);
	etc.

btw. that trick of writing (y<<8)+(y<<6) instead of y*320 isn't really
useful with djgpp: the compiler will do that optimisation for you, so
you may as well just write it as a simple multiply: that is less typing,
and easier to read.


	Shawn Hargreaves.

- Raw text -


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