delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1999/09/03/22:49:47

From: LAPASSET <domixx AT club-internet DOT fr>
Newsgroups: comp.os.msdos.djgpp
Subject: Help MODE X
Date: Thu, 02 Sep 1999 02:50:41 +0200
Organization: Dominique
Lines: 687
Message-ID: <37CDC9E1.28BB3059@club-internet.fr>
NNTP-Posting-Host: montpellier-1-195.club-internet.fr
Mime-Version: 1.0
X-Trace: front3.grolier.fr 936406115 13262 195.36.180.195 (4 Sep 1999 00:48:35 GMT)
NNTP-Posting-Date: 4 Sep 1999 00:48:35 GMT
X-Mailer: Mozilla 4.06 [fr] (Win98; I)
To: djgpp AT delorie DOT com
DJ-Gateway: from newsgroup comp.os.msdos.djgpp
Reply-To: djgpp AT delorie DOT com

hi everyone if someone can help me to convert a file (a tutorial on
modex by Robert Schmidt ) to djgpp (originaly made for borland c)
i have do something, it compiles well ,no errors, but the expected
result is not good !

first this is the original file :
------------------------------------------------------
/*
 * LIB.C v1.2
 *
 * by Robert Schmidt
 * (C)1993 Ztiff Zox Softwear
 *
 * Simple graphics library to accompany the article
 *
 *   INTRODUCTION TO MODE X.
 *
 * This library provides the basic functions for initializing and using
 * unchained (planar) 256-color VGA modes.  Currently supported are:
 *
 * - 320x200
 * - 320x240
 *
 * Functions are provided for:
 *
 * - initializing one of the available modes
 * - setting the start address of the VGA refresh data
 * - setting active and visible display pages
 * - writing and reading a single pixel to/from video memory
 *
 * The library is provided as a demonstration only, and is not claimed
 * to be particularly efficient or suited for any purpose.  It has only
 * been tested with Borland C++ 3.1 by the author.  Comments on success
 * or disaster with other compilers are welcome.
 *
 * This file is public domain.  Do with it whatever you'd like, but
 * please don't distribute it without the article.
 *
 * Thanks go out to various helpful netters who spotted the 0xE7 bug
 * in the set320x240x256() function!
 */


/*
 * We 'require' a large data model simply to get rid of explicit 'far'
 * pointers and compiler specific '_fmemset()' functions and the likes.
 */

#if !defined(__COMPACT__)
# if !defined(__LARGE__)
#  if !defined(__HUGE__)
#   error Large data model required!  Try compiling with 'bcc -ml
lib.c'.
#  endif
# endif
#endif

#include <dos.h>
#include <mem.h>

/*
 * Comment out the following #define if you don't want the testing
main()
 * to be included.
 */

#define TESTING

/*
 * Define the port addresses of some VGA registers.
 */

#define CRTC_ADDR 0x3d4 /* Base port of the CRT Controller (color) */

#define SEQU_ADDR 0x3c4 /* Base port of the Sequencer */
#define GRAC_ADDR 0x3ce /* Base port of the Graphics Controller */


/*
 * Make a far pointer to the VGA graphics buffer segment.  Your compiler

 * might not have the MK_FP macro, but you'll figure something out.
 */

typedef unsigned char UCHAR;
UCHAR *vga = (UCHAR *) MK_FP(0xA000, 0);

/*
 * width and height should specify the mode dimensions.  widthBytes
 * specify the width of a line in addressable bytes.
 */

unsigned width, height, widthBytes;

/*
 * actStart specifies the start of the page being accessed by
 * drawing operations.  visStart specifies the contents of the Screen
 * Start register, i.e. the start of the visible page.
 */

unsigned actStart, visStart;

/*
 * set320x200x256_X()
 * sets mode 13h, then turns it into an unchained (planar), 4-page
 * 320x200x256 mode.
 */

void set320x200x256_X(void)
 {

 union REGS r;

 /* Set VGA BIOS mode 13h: */

 r.x.ax = 0x0013;
 int86(0x10, &r, &r);

 /* Turn off the Chain-4 bit (bit 3 at index 4, port 0x3c4): */

 outport(SEQU_ADDR, 0x0604);

 /* Turn off word mode, by setting the Mode Control register
    of the CRT Controller (index 0x17, port 0x3d4): */

 outport(CRTC_ADDR, 0xE317);

 /* Turn off doubleword mode, by setting the Underline Location
    register (index 0x14, port 0x3d4): */

 outport(CRTC_ADDR, 0x0014);

 /* Clear entire video memory, by selecting all four planes, then
    writing 0 to entire segment. */

 outport(SEQU_ADDR, 0x0F02);
 memset(vga+1, 0, 0xffff); /* stupid size_t exactly 1 too small */
 vga[0] = 0;

 /* Update the global variables to reflect dimensions of this
    mode.  This is needed by most future drawing operations. */

 width   = 320;
 height = 200;

 /* Each byte addresses four pixels, so the width of a scan line
    in *bytes* is one fourth of the number of pixels on a line. */

 widthBytes = width / 4;

 /* By default we want screen refreshing and drawing operations
       to be based at offset 0 in the video segment. */

 actStart = visStart = 0;

 }

/*
 * setActiveStart() tells our graphics operations which address in video

 * memory should be considered the top left corner.
 */

void setActiveStart(unsigned offset)
 {
 actStart = offset;
 }

/*
 * setVisibleStart() tells the VGA from which byte to fetch the first
 * pixel when starting refresh at the top of the screen.  This version
 * won't look very well in time critical situations (games for
 * instance) as the register outputs are not synchronized with the
 * screen refresh.  This refresh might start when the high byte is
 * set, but before the low byte is set, which produces a bad flicker.
 */

void setVisibleStart(unsigned offset)
 {
 visStart = offset;
 outport(CRTC_ADDR, 0x0C);  /* set high byte */
 outport(CRTC_ADDR+1, visStart >> 8);
 outport(CRTC_ADDR, 0x0D);  /* set low byte */
 outport(CRTC_ADDR+1, visStart & 0xff);
 }

/*
 * setXXXPage() sets the specified page by multiplying the page number
 * with the size of one page at the current resolution, then handing the

 * resulting offset value over to the corresponding setXXXStart()
 * function.  The first page is number 0.
 */

void setActivePage(int page)
 {
 setActiveStart(page * widthBytes * height);
 }

void setVisiblePage(int page)
 {
 setVisibleStart(page * widthBytes * height);
 }

void putPixel_X(int x, int y, UCHAR color)
 {

 /* Each address accesses four neighboring pixels, so set
    Write Plane Enable according to which pixel we want
    to modify.  The plane is determined by the two least
    significant bits of the x-coordinate: */

 outportb(0x3c4, 0x02);
 outportb(0x3c5, 0x01 << (x & 3));

 /* The offset of the pixel into the video segment is
    offset = (width * y + x) / 4, and write the given
    color to the plane we selected above.  Heed the active
    page start selection. */

 vga[(unsigned)(widthBytes * y) + (x / 4) + actStart] = color;

 }

UCHAR getPixel_X(int x, int y)
 {

 /* Select the plane from which we must read the pixel color: */

 outport(GRAC_ADDR, 0x04);
 outport(GRAC_ADDR+1, x & 3);

 return vga[(unsigned)(widthBytes * y) + (x / 4) + actStart];

 }

void set320x240x256_X(void)
 {

 /* Set the unchained version of mode 13h: */

 set320x200x256_X();

 /* Modify the vertical sync polarity bits in the Misc. Output
    Register to achieve square aspect ratio: */

 outportb(0x3C2, 0xE3);

 /* Modify the vertical timing registers to reflect the increased
    vertical resolution, and to center the image as good as
    possible: */

 outport(0x3D4, 0x2C11);  /* turn off write protect */
 outport(0x3D4, 0x0D06);  /* vertical total */
 outport(0x3D4, 0x3E07);  /* overflow register */
 outport(0x3D4, 0xEA10);  /* vertical retrace start */
 outport(0x3D4, 0xAC11);  /* vertical retrace end AND wr.prot */
 outport(0x3D4, 0xDF12);  /* vertical display enable end */
 outport(0x3D4, 0xE715);  /* start vertical blanking */
 outport(0x3D4, 0x0616);  /* end vertical blanking */

 /* Update mode info, so future operations are aware of the
    resolution */

 height = 240;

 }



/*
 * The library testing routines follows below.
 */


#ifdef TESTING

#include <stdio.h>
#include <conio.h>

void set80x25(void)
 {
 union REGS r;
 r.x.ax = 0x0003;
 int86(0x10, &r, &r);
 }

void doTest(void)
 {
 int p, x, y, pages;

 /* This is the way to calculate the number of pages available. */

 pages = 65536L/(widthBytes*height);

 for (p = 0; p < pages; ++p)
  {
  setActivePage(p);

  /* On each page draw a single colored border, and dump the palette
     onto a small square about the middle of the page. */

  for (x = 0; x <= width; ++x)
   {
   putPixel_X(x, 0, p+1);
   putPixel_X(x, height-1, p+1);
   }

  for (y = 0; y <= height; ++y)
   {
   putPixel_X(0, y, p+1);
   putPixel_X(width-1, y, p+1);
   }

  for (x = 0; x < 16; ++x)
   for (y = 0; y < 16; ++y)
    putPixel_X(x+(p+3)*16, y+(p+3)*16, x + y*16);

  }

 /* Each pages will now contain a different image.  Let the user cycle
    through all the pages by pressing a key. */

 for (p = 0; p < pages; ++p)
  {
  setVisiblePage(p);
  getch();
  }

 }


/*
 * Library test (program) entry point.
 */

int main(void)
 {
 puts("First, have a look at the 320x200 mode.  I will draw some
rubbish");
 puts("on all of the four pages, then let you cycle through them by");
 puts("hitting a key on each page.");
 puts("Press a key when ready...");
 getch();

 set320x200x256_X();
 doTest();

 set80x25();
 puts("Then, check out Mode X, 320x240 with 3 (and a half) pages.");
 puts("Press a key when ready...");
 getch();

 set320x240x256_X();
 doTest();

 set80x25();
 puts("Where to next?  It's your move!");
 return 0;
 }

#endif
---------------------------------------------------------------
and now my try to convert it to djgpp :
--------------------------------------------------------------
#include <dos.h>
#include <mem.h>
#include <stdlib.h>
#include <sys/nearptr.h>
#include <go32.h> /* for _dos_ds */
#include <string.h>
#include <stdio.h>
#include <conio.h>
#include <pc.h>

#define TESTING

/*
 * Define the port addresses of some VGA registers.
 */

#define CRTC_ADDR 0x3d4 /* Base port of the CRT Controller (color) */

#define SEQU_ADDR 0x3c4 /* Base port of the Sequencer */
#define GRAC_ADDR 0x3ce /* Base port of the Graphics Controller */


/*
 * Make a far pointer to the VGA graphics buffer segment.  Your compiler

 * might not have the MK_FP macro, but you'll figure something out.
 */

typedef unsigned char UCHAR;
typedef unsigned short USHORT;

char  *vga = (char  *)0xa0000;

/*
 * width and height should specify the mode dimensions.  widthBytes
 * specify the width of a line in addressable bytes.
 */

unsigned width, height, widthBytes;

/*
 * actStart specifies the start of the page being accessed by
 * drawing operations.  visStart specifies the contents of the Screen
 * Start register, i.e. the start of the visible page.
 */

unsigned actStart, visStart;

/*
 * set320x200x256_X()
 * sets mode 13h, then turns it into an unchained (planar), 4-page
 * 320x200x256 mode.
 */

void set320x200x256_X(void)
 {

 union REGS r;

 /* Set VGA BIOS mode 13h: */

 r.x.ax = 0x0013;
 int86(0x10, &r, &r);

 /* Turn off the Chain-4 bit (bit 3 at index 4, port 0x3c4): */

        outportb(SEQU_ADDR, (unsigned char)0x0604);

 /* Turn off word mode, by setting the Mode Control register
    of the CRT Controller (index 0x17, port 0x3d4): */

        outportb(CRTC_ADDR,(unsigned char)0xE317);

 /* Turn off doubleword mode, by setting the Underline Location
    register (index 0x14, port 0x3d4): */

        outportb(CRTC_ADDR, (unsigned char)0x0014);

 /* Clear entire video memory, by selecting all four planes, then
    writing 0 to entire segment. */

        outportb(SEQU_ADDR, (unsigned char)0x0F02);
 memset(vga+1, 0, 0xffff); /* stupid size_t exactly 1 too small */
 vga[0] = 0;

 /* Update the global variables to reflect dimensions of this
    mode.  This is needed by most future drawing operations. */

 width   = 320;
 height = 200;

 /* Each byte addresses four pixels, so the width of a scan line
    in *bytes* is one fourth of the number of pixels on a line. */

 widthBytes = width / 4;

 /* By default we want screen refreshing and drawing operations
       to be based at offset 0 in the video segment. */

 actStart = visStart = 0;

 }

/*
 * setActiveStart() tells our graphics operations which address in video

 * memory should be considered the top left corner.
 */

void setActiveStart(unsigned offset)
 {
 actStart = offset;
 }

/*
 * setVisibleStart() tells the VGA from which byte to fetch the first
 * pixel when starting refresh at the top of the screen.  This version
 * won't look very well in time critical situations (games for
 * instance) as the register outputs are not synchronized with the
 * screen refresh.  This refresh might start when the high byte is
 * set, but before the low byte is set, which produces a bad flicker.
 */

void setVisibleStart(unsigned offset)
 {
 visStart = offset;
        outportb(CRTC_ADDR, (unsigned char)0x0C);               /* set
high byte */
        outportb(CRTC_ADDR+1, (unsigned char)visStart >> 8);
        outportb(CRTC_ADDR, (unsigned char)0x0D);               /* set
low byte */
        outportb(CRTC_ADDR+1, (unsigned char)visStart & 0xff);
 }

/*
 * setXXXPage() sets the specified page by multiplying the page number
 * with the size of one page at the current resolution, then handing the

 * resulting offset value over to the corresponding setXXXStart()
 * function.  The first page is number 0.
 */

void setActivePage(int page)
 {
 setActiveStart(page * widthBytes * height);
 }

void setVisiblePage(int page)
 {
 setVisibleStart(page * widthBytes * height);
 }

void putPixel_X(int x, int y, UCHAR color)
 {

 /* Each address accesses four neighboring pixels, so set
    Write Plane Enable according to which pixel we want
    to modify.  The plane is determined by the two least
    significant bits of the x-coordinate: */

        outportb(0x3c4, (unsigned char)0x02);
        outportb(0x3c5, (unsigned char)0x01 << (x & 3));

 /* The offset of the pixel into the video segment is
    offset = (width * y + x) / 4, and write the given
    color to the plane we selected above.  Heed the active
    page start selection. */

       // vga[(unsigned)(widthBytes * y) + (x / 4) + actStart] = color;
       vga[(widthBytes * y) + (x / 4) + actStart] = color;
 }


void set320x240x256_X(void)
 {

 /* Set the unchained version of mode 13h: */

 set320x200x256_X();

 /* Modify the vertical sync polarity bits in the Misc. Output
    Register to achieve square aspect ratio: */

        outportb(0x3C2, (unsigned char)0xE3);

 /* Modify the vertical timing registers to reflect the increased
    vertical resolution, and to center the image as good as
    possible: */

        outportb(0x3D4, (unsigned char)0x2C11);         /* turn off
write protect */
        outportb(0x3D4, (unsigned char)0x0D06);         /* vertical
total */
        outportb(0x3D4, (unsigned char)0x3E07);         /* overflow
register */
        outportb(0x3D4, (unsigned char)0xEA10);         /* vertical
retrace start */
        outportb(0x3D4, (unsigned char)0xAC11);         /* vertical
retrace end AND wr.prot */
        outportb(0x3D4, (unsigned char)0xDF12);         /* vertical
display enable end */
        outportb(0x3D4, (unsigned char)0xE715);         /* start
vertical blanking */
        outportb(0x3D4, (unsigned char)0x0616);         /* end vertical
blanking */

 /* Update mode info, so future operations are aware of the
    resolution */

 height = 240;

 }



/*
 * The library testing routines follows below.
 */


#ifdef TESTING


void set80x25(void)
 {
 union REGS r;
 r.x.ax = 0x0003;
 int86(0x10, &r, &r);
 }

void doTest(void)
 {
 int p, x, y, pages;

 /* This is the way to calculate the number of pages available. */

 pages = 65536L/(widthBytes*height);

        for (p = 0; p < pages; ++p)
                {
                setActivePage(p);
                 setActivePage(0);
  /* On each page draw a single colored border, and dump the palette
     onto a small square about the middle of the page. */

                for (x = 0; x <= width; ++x)
   {
                        putPixel_X(x, 0, p+1);
                        putPixel_X(x, height-1, p+1);
   }

                for (y = 0; y <= height; ++y)
                        {
                        putPixel_X(0, y, p+1);
                        putPixel_X(width-1, y, p+1);
                        }

                for (x = 0; x < 16; ++x)
                        for (y = 0; y < 16; ++y)
                                putPixel_X(x+(p+3)*16, y+(p+3)*16, x +
y*16);

                }

 /* Each pages will now contain a different image.  Let the user cycle
    through all the pages by pressing a key. */

 for (p = 0; p < pages; ++p)
  {
  setVisiblePage(p);
  getch();
  }

 }


/*
 * Library test (program) entry point.
 */

int main(void)
 {
        __djgpp_nearptr_enable();
        vga += __djgpp_conventional_base;


        puts("First, have a look at the 320x200 mode.  I will draw some
rubbish");
 puts("on all of the four pages, then let you cycle through them by");
 puts("hitting a key on each page.");
 puts("Press a key when ready...");
 getch();



 set320x200x256_X();
 doTest();

 set80x25();
 puts("Then, check out Mode X, 320x240 with 3 (and a half) pages.");
 puts("Press a key when ready...");
 getch();


        set320x240x256_X();
        doTest();

 set80x25();
 puts("Where to next?  It's your move!");

         __djgpp_nearptr_disable();
        return 0;
 }

#endif
-------------------------------------
that's it , if someone could help me, i think my fakes are in this
outportb fonction, but i'm not sure.
tanks
Domi
domixx AT club-internet DOT fr

- Raw text -


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