www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1996/08/01/19:31:04

From: j DOT aldrich6 AT genie DOT com
Message-Id: <199608012323.AA141401825@relay1.geis.com>
Date: Thu, 1 Aug 96 23:15:00 UTC 0000
To: landmark AT vcn DOT bc DOT ca
Cc: djgpp AT delorie DOT com
Mime-Version: 1.0
Subject: Re: Compile Errors

Reply to message 1033519    from LANDMARK AT VCN. on 08/01/96 12:45AM


Warning!  This is an extremely long post!  :)

------------------------------------------------------------

>Hello, i am a newbie to C and DJGPP.
>
>Upon finding and trying to compile this graphics program with DJGPP,
>i have come up with the following errors:
>
>Much help would be appreciated if anyone can help me fix it.

Gack!  The program below is majorly full of all the things you
shouldn't do in DJGPP.  Before you go any further, you should
download the DJGPP FAQ (faq201b.zip) and read it thoroughly.
I also recommend a good C text - you really should learn at
least the basics of debugging before simply posting all your
errors to us.  :)

Firstly, DJGPP is a 32-bit, flat model, protected-mode compiler,
so you don't need or even want MK_FP or any of those other
nasty 16-bit-isms.  Second, the register setting convention your
program uses is a major Borland-ism, and should be avoided
with prejudice.  Most compilers use their own methods of
setting registers and calling interrupts.  Finally, you are including
some of the wrong header files in your program; when you see
"implicit declaration of function so-and-so", you should examine
the docs for that function to see what header file you need.

Now, the critique:

>command-line:
>c:\djgpp\gcc.exe c:\djgpp\include\gfx-1.cc -o c:\djgpp\source\gfx-1.exe -lm
>
[errors deleted]
>
>The program, gfx-1.cc, in c:\djgpp\include

Why in the name of all that's holy did you put that program
in the include directory?  You should set aside a completely
separate directory for your own programs; if you've set
djgpp up correctly there's no problem running it from wherever
you like.

>#include <dos.h>      // MK_FP, geninterrupt()
This is not correct.  Neither of those functions exists at all in DJGPP.

>#include <mem.h>      // memset()
If you look at this header file, you'll see that it is obsolete.  All it
is is a pointer to <stdlib.h>.  memset() is in <string.h>.

>#include <stdio.h>    // printf()
>#include <stdlib.h>   // rand()

Another point to note here is that what you have written is not a
C++ program.  I say this because it doesn't use anything *from*
C++!  I'd really recommend that you learn C before jumping into
more advanced stuff; a proper grounding in the basics is essential.

>void SetMCGA();
>void SetText();
>void Cls(unsigned char Col);
>void Putpixel (int x, int y, unsigned char Col);
>void Putpixel (int x, int y, unsigned char Col);      <---- why declared
twice?
>void TestPutpixel ();

This is not the best or most ANSI way to declare these functions.
They should look like this;

void SetMCGA(void);
void SetText(void);
void Cls(unsigned char);
void Putpixel(int, int, unsigned char);
void TestPutpixel(void);

I suggest you look up your friendly C text for an explanation
of correct function declaration procedures, as well as variable
scope.

>// declare a pointer to the offset of VGA memory
>unsigned char *vga = (unsigned char *) MK_FP(0xA000, 0);

This is just plain WRONG.  Section 10.2 of the FAQ explicitly
states that under DPMI you cannot just access any random
absolute address.  It also describes the correct way to do this.

>void SetMCGA() {
>    _AX = 0x0013;
>    geninterrupt (0x10);
>  }

In djgpp, you use __dpmi_regs to pass register information to
interrupts, and you use int86() or __dpmi_int() from <dpmi.h> to
call those interrupts.

>void Cls(unsigned char Col) {
>    memset(vga, Col, 0xffff);  //"vga" is a pointer to address 0xa0000
>  }

The FAQ describes how to do this properly.

>void TestPutpixel () {
>    int loop1, loop2;
>    for (loop1 = 0, loop1 < 319, loop1++) {
>	for (loop2 = 0, loop2 < 199, loop2++) {
>	    putpixel (loop1, loop2, rand());
>	}
>    }

You need another closing brace here.  You really should line up opening
and closing braces; the way you are doing it virtually guarantees lots
and lots of annoying errors.

You are also making another fundamental error here in assuming
that rand() will return an unsigned char value.  It doesn't.  rand()
returns a number from 0 to RAND_MAX, which is defined in <stdlib.h>
as 2147483647, the maximum value of an int on a *32-bit* compiler.
I know, you can count on the implicit typecasting to unsigned char
when Putpixel is invoked.  Well, don't - it's bad programming.

Here's a corrected version:

void TestPutpixel( void )
{
    int loop1, loop2;

    for (loop1 = 0, loop1 < 319, loop1++)
    {
        for (loop2 = 0, loop2 < 199, loop2++)
        {
            putpixel (loop1, loop2, rand() % 0xff );
        }
    }

    return;      <-- even in a void function it's good to have an explicit
return
}

>void main() {

Argh!  Do I have to go through this again?!?  Please take whatever
disk, manual, or person you got this program from and burn him/her/it
at the stake.  There are only two *correct* ways to define main():

int main( int argc, char **argv )
Use this when you need command-line parameters.

int main( void )
Use this if you don't need command-line parameters.

>    clrscr();
>    SetMCGA();
>    Cls(32);
>    getch();
>    Cls(90);
>    TestPutPixel();

That's 'TestPutpixel()'.  Note the capitalization.  Proofreading your
typing and syntax should be the first thing you do when you debug
a program.

>    SetText();
    return 0;
>}

You need a return in here because main() returns an int to the
operating system.

Hope this helps!

John

- Raw text -


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