BCC2GRX - Interfacing Borland based graphics programs to LIBGRX
Copyright (C) 1993-97 by Hartmut Schirmer
Copyright (C) 2002 by Dimitar Zhekov
This library is now part of the GRX graphics library.
Contact : grx@gnu.de
1. Introduction and overview
-----------------------------------------------------------------------------
The BCC2GRX was created to allow users of LIBGRX to compile graphics
programs written for Borland-C++ and Turbo-C graphics interface. C code
can be directly compiled and linked with BCC2GRX.
Using LIBGRX based graphics gives you some advantages :
- 32 bit linear memory model (except for Turbo-C and BCC / DOS)
- high resolution and high color graphics modes supported
- easy way to support new graphics adapters
- LIBGRX and BCC2GRX are free software
- most ported applications run faster
The current BCC2GRX (v2.3) does only a few error checks since it is
assumed the program was extensively tested before porting it to GRX.
BCC2GRX is not a convenient platform to develop new BGI programs. Of
course you should use native LIBGRX in such cases!
2. Differences between BGI and BCC2GRX
-----------------------------------------------------------------------------
BCC2GRX is based on LIBGRX instead of using an .bgi driver. This
introduces some differences compared with the Borland GI. The (known)
differences are listed below.
- Most LIBGRX platforms are 32 bit. An int will take 4 bytes instead of
2 with Turbo-C and BCC for DOS. If you need a 16 bit integer, change
the definition from int to short which is 16 bit on all systems.
- WHITE is a function not constant with BCC2GRX. This may cause
problems in switch () statements.
(You may use
#define WHITE 15
#include <libbcc.h>
to improve compatibility.)
- BCC2GRX can not use .bgi drivers. Installing an user driver and the
register(far)bgidriver will always cause an error.
- registerfarbgifont() and registerbgifont() are the same. Both take a
void* to the character font (whole file with header !)
- initgraph()/detectgraph() work slightly different. See below for
details.
- getmodenames() and other functions may be called before initgraph()
- character files won't be flushed at closegraph()
- NOT_PUT isn't supported.
- some constants may differ in value
- BCC2GRX's outtext() and outtextxy() do correct clipping
- some graphics primitives slightly differ in behaviour between BGI and
LIBGRX. Eg. the "saucer" in bccbgi.c putimage()/getimage() demo
looks a little different.
- the BCC2GRX header file is <libbcc.h>. You must change the #include
statements since BCC2GRX is incompatible with <graphics.h>. For
programs compatible with both Borland GI and BCC2GRX, conditional
compilation may be used:
#if defined(__MSDOS__) && defined(__TURBOC__)
# include <graphics.h>
#else
# include <libbcc.h>
#endif
and such programs should be linked with the respective library,
either Borland or GRX (but not both).
- the color constants like REG, GREEN, etc. won't work in graphics
modes with more than 256 colors. Use _ega_color(RED),
_ega_color(GREEN), etc to get the right colors
3. Some useful internals of BCC2GRX
-----------------------------------------------------------------------------
Since LIBGRX provides a flexible and powerful set of graphics primitives,
some of the basic routines are defined within bccgrx.h using "__inline__
static" functions when using a GNU-C compiler. It compiles these functions
like macros, but you can refer to their addresses. There is one exeption to
this rule: When compiling code based on a pascal program, a macro is used
for getaspectratio since the pascal and C graphics interfaces use different
calling types.
BGI has something called a 'viewport'. There are two very different
behaviors depending on the clipping flag:
If clipping is on, one introduces something like a subscreen where
(nearly) all drawing operations are done.
Otherwise the origin of the drawing coordinate system is shifted from
the top left corner to some other point on screen.
BCC2GRX always adds the origin shift to all operations. If clipping is
requested, GrSetClipBox() is called and LIBGRX restricts drawing to the
selected subscreen.
One may wonder why BCC2GRX has it's own drawpoly() function instead of
using the LIBGRX function. In BGI a polygon isn't really a polygon but may
be a union of several unconnected closed polygons. In more detail:
If the start point of a polygon is reached again, the next point
is the start point of a new polygon. No connection line is drawn.
So one may draw several closed polygons at once. I don't know whether this
behavior of the BGI is a bug or a feature, but BCC2GRX is at least
compatible ...
4. initgraph()/detectgraph()/closegraph()
-----------------------------------------------------------------------------
It's recommended to use something like the following code to
initialize the graphics interface :
int gd, gm, err;
gd = DETECT; /* or detectgraph(&gd,&gm); */
initgraph(&gd,&gm,PATH_TO_CHR_FILES);
err = graphresult();
if (err != grOk) ...
This code sets up the default graphics mode defined in the GO32 or GRX20DRV
environment variable. This code will work with Borland and GRX based BGI
code without change. BCC2GRX will treat all gd values as 'DETECT' and set
up the GRX default graphics mode.
BCC2GRX provides two new functions to select the graphics mode:
void set_BGI_mode(int *graphdriver, int *graphmode);
and
void set_BGI_mode_whc(int *graphdriver, int *graphmode,
int width, int height, int colors);
If your code requires one of the standard BGI modes, use set_BGI_mode()
with BCC2GRX:
gd = VGA; gm = VGAHI;
#ifdef __GNUC__
set_BGI_mode( &gd, &gm);
#endif
initgraph( &gd, &gm, "");
All resolutions including the SVGA modes may be set up by calling the
set_BGI_mode_whc() function:
#ifdef __GNUC__
set_BGI_mode_whc( &gd, &gm, 640, 480, 1<<24);
#else
/* BCC stuff invoking a SVGA mode, needs nonstd BGI driver */
#endif
initgraph( &gd, &gm, "");
The BCC2GRX requests the desired resolution from LIBGRX by calling
GrSetMode( GR_width_height_color_graphics, ...)
If there is no such mode in the current driver, a related one may be set up
by LIBGRX. If you program needs a special resolution (say eg. Hercules
720x348) you should check getmaxx() and getmaxy() after initgraph().
Please note that
- set_BGI_mode(HERCMONO, HERCMONOHI) uses 720x350x16 on VGA cards,
- all drivers != NATIVE_GRX behave like DETECT with BCC2GRX,
- set_BGI_mode[_whc]() sets up local variables used by initgraph() and
setgraphmode(). You may change the resolution after initgraph() done
by
gd = DETECT;
initgraph(&gd, &gm, "");
/* Default graphics mode */
....
#if defined(__TURBOC__) && defined(__MSDOS__)
/* Borland GI stuff to set up 1024x768x256 mode */
gm = ... ;
#else
set_BGI_mode_whc(&gd, &gm, 1024, 768, 256);
#endif
setgraphmode( gm);
/* Now in 1024x768x256 mode */
Starting with BCC2GRX v2.0 there are new functions:
getmodemaxcolor(int mode), getmodemaxx(int mode), getmodemaxy(int mode)
which may be called at any time, even before initgraph(). A program may
require true rgb support (32k colors or more) and at least 800x600 pixels.
The new getmodemax*() functions may be used for flexible setup:
int gd=DETECT, gm;
#if defined(__BCC2GRX__) && (__BCC2GRX__>=0x200)
#define XR 800
#define YR 600
#define CR (1<<15)
int lo,hi,x=0,y=0,c=0,i;
detectgraph(&gd,&gm);
getmoderange(gd, &lo, &hi); gm=-1;
for (i=hi;i>=lo;--i)
if (getmodemaxcolor(i)>=CR) {
if (getmodemaxx(i)==XR && getmodemaxy(i)==YR) {
gm = i; /* enough colors and exact geometry */
break; /* ==> done */
}
if (getmodemaxx(i)>=XR && getmodemaxy(i)>=YR)
gm = i;
} else break; /* no success */
if (gm<0) {
puts("Sorry, no sufficient video mode available\n");
exit(1);
}
#undef XR
#undef YR
#undef CR
#endif
initgraph(&gd,&gm,"");
The above example exploits the BCC2GRX ordering of modes:
less colors first, less total pixel count earlier, or
decide by horizontal width
Eg.:
640x480x16 // 16 < 256 available colors
320x200x256 // 64000 < 128000 total pixel
640x200x256 // 128000 < 172800 total pixel
360x480x256 // 360 < 480 horizontal pixel
480x360x256 // 172800 < 480000 total pixel
800x600x256 // 256 < 16M available colors
640x480x16M
closegraph() doesn't free any allocated memory (eg. vector fonts).
The paging routines setactivepage() and setvisualpage() are functional for
GRX v2 base BCC2GRX. Just call set_BGI_mode_pages() before calling
initgraph():
set_BGI_mode_pages(2); /* 1 or 2 valid ! */
initgraph(...);
if (graphresult() == grOk && get_BGI_mode_pages() > 1) {
/* Do cool paging stuff */
}
You can't check paging without switching into graphics mode!
Translating BCC modes by set_BGI_mode() will disable paging!
5. Using fonts
------------------------------------------------------------------------------
The BCC2GRX v1.2 or newer can link vector fonts into the .exe file.
The standard fonts are in the libbcc*.a:
_bold_font, _euro_font, _goth_font, _lcom_font
_litt_font, _sans_font, _scri_font, _simp_font
_trip_font, _tscr_font
Call registerbgifont() to enable font usage:
registerbgifont( &_bold_font);
registerbgifont( &_euro_font);
registerbgifont( &_goth_font);
registerbgifont( &_lcom_font);
registerbgifont( &_litt_font);
registerbgifont( &_sans_font);
registerbgifont( &_scri_font);
registerbgifont( &_simp_font);
registerbgifont( &_trip_font);
registerbgifont( &_tscr_font);
Of course you can also link non standard fonts:
- copy the .chr file(s) to bcc2grx/src
- goto bcc2grx and type 'make'
- add
extern int _<font_name>_font;
registerbgifont( &_<font_name>_font);
to your source
The actual BCC2GRX handels the 11 standard and up to 10 user fonts. If you
need more user fonts, you should change the definition of LastUserFont in
text.c!
Starting with BCC2GRX v1.2 you can also use the LIBGRX bitmapped fonts.
Just get a font handle and set the new text style. Eg. you may want to use
the 8x16 VGA font in high resolution graphics:
font_handle = installuserfont( "pc8x16.fnt");
settextstyle( font_handle, HORIZ_DIR, 1);
See test/ttext.c for more examples.
Please note that GRX 2.x can't scale bitmap fonts at drawing level any
longer. Before drawing a magnified DEFAULT_FONT, BCC2GRX will first set up
the required new font and keeps a pointer for later use. Due to this, you
might notice a slight delay the first time you request a magnified font.
The new GRX 2.x may use Borland vector fonts as native fonts. Managing the
resulting bitmap fonts would use much more memory than linking the font
rendering code twice, so I decided not to use the GRX font API.
Every font will be loaded only once and stay in (virtual) memory until the
program terminates. If this behaviour doesn't work with your program (eg.
something like a font editor) or you get short of memory loading hundreds
of fonts, please tell me about.
8. What's new in this release?
-----------------------------------------------------------------------------
New copyright terms: same license as the rest of GRX.
Updated for GRX 1.03 / .vdr drivers / 64K && 16M color modes
More robust library internal function naming
BLACK now is a constant
Several (minor) bug fixes
Updated for GRX v2
libbcc.h won't include GRX stuff any more
added version control __BCC2GRX__
Linux support
setactivepage()/setvisualpage() with GRX v2
For a more complete list of changes and new features check src/changes.
9. LIBGRX 2.4.5 and later
-----------------------------------------------------------------------------
Starting with LIBGRX 2.4.5, BCC2GRX supports Turbo-C and BCC. The
documentation has been updated accordingly.