
                   The WATCOM C/C++ Game Programmer's FAQ
 
 
||        ||   ||   |||||||| ||||    ||||      ||  ||    cccc  /
||        ||  ||||     ||   ||  ||  ||  ||    ||||||||  cc    /
||        || ||  ||    ||  ||      ||    ||  || |||| ||  cccc/
||        || ||  ||    ||  ||      ||    ||  ||  ||  ||     /
 ||  ||  || ||    ||   ||  ||      ||    || ||   ||   ||   /
 || |||| || ||||||||   ||  ||      ||    || ||   ||   ||  /  cccc   +   +
  |||||||| ||      ||  ||   ||  ||  ||  ||  ||   ||   ||    cc     +++ +++
   ||  ||  ||      ||  ||    ||||    ||||   ||   ||   ||     cccc   +   +
 
                             Game Programmer's
 
 
   ***********************   *******               **************
   ***********************  *********            *******    *******
   ********                ***********         *******         *******
   ********               *************        *******         *******
   *****************     ******* *******       *******         *******
   *****************    *******   *******      *******         *******
   ********            *******     *******     *******         *******
   ********           *********************    *******    ************
   ********          ***********************     *******************
   ********         *******           *******       *********************
                                                                    *******
 
Created October 23, 1994 by Lee A. Lorenz
Version 0.7
 
==============================================================================
HISTORY:
 
 Version    Date            Description
---------+----------+--------------------------------------------------------
  0.5    | 10/23/94 | Initial version, skimpy, yes, but at least here it is!
         |          | Not much, just to get it started. I will add to it, but
         |          | others could add to it as well...
---------+----------+--------------------------------------------------------
  0.6    | 10/24/94 | A little more added.
---------+----------+--------------------------------------------------------
  0.7    | 10/29/94 | Table of Contents added (uses Line#, though).
---------+----------+--------------------------------------------------------
 
==============================================================================
 
                             Table Of Contents
                                                            Line Numbers
Data sizes in protected mode.....................................110
MK_FP doesn't work the same......................................128
Hooking Interrupts...............................................151
Finding WATCOM files (FTP sites, BBS)............................197
Libraries for WATCOM C/C++32.....................................218
Problems linking non-WATCOM object files.........................249
Using Inline assembly............................................285
Books for WATCOM C/C++32.........................................319
DOS extenders for WATCOM C/C++32.................................325
Differences in using assembly....................................345
Using DPMI.......................................................359
Accessing VESA BIOS functions....................................367
Trying to recompile other source code............................390
 
==============================================================================
 
Well, since the "Betrayal" at Borland, and WATCOM's strategic pricing of
WATCOM C/C++ version 10.0, many users unfamiliar with protected mode
programming have been posting alot of questions. The purpose of this FAQ
is to clear up many of those questions. For now, I will concentrate on the
specifics of programming WATCOM C/C++ (9.5 or 10.0) in protected (or 32-bit)
mode, using the DOS/4GW Dos Extender from Rational Systems.
 
    To begin this FAQ, I'd like to outline my own reasons for switching to
WATCOM's C/C++ compiler.
    I've been a longtime Borland C/C++ user, in fact, I was a registered
user from version 1.0 on up to 3.1. About two years ago, the need for a
good 32-bit compiler began surfacing with my growing requirements for
memory and the complications of segmented programming became apparent.
    In November of 1993, Borland released version 4.0- but while it was
advertised as a "32-bit" compiler, this was only true of Windows
programming. Other disturbing things happened- Borland announced that
they would not support TurboVision, they withdrew the DOS IDE, they
seperated TASM, to make it an additional purchase. Still, I was reassured by
Borland (via Paul Gross himself on CompuServe) that Borland might still
upgrade the package to include better DOS tools (including 32-bit
development). Until they did that, the appearance was that Borland was saying
that DOS development was DEAD AND BURIED.
    I waited... and waited... until I saw an ad in Dr.Dobb's Journal for
the PowerPak in June of 1994. Great... but when I called to upgrade my
Borland C/C++ to 4.0 and order the PowerPak (now $199+$99 for powerpak),
the operators didn't even know about it! Even worse was after a few days,
they told me it *MIGHT* ship in July, but they weren't sure!
    That was when I saw WATCOM's ad, advertising the special $199 price. I
called The Programmer's Shop and ordered it. They told me 10.0 wasn't
shipping yet, HOWEVER, they would send me version 9.5. Cool. Better still,
while the $199 price did not include printed manuals (CD-ROM docs), the
9.5 sent to me *DID* have all of the manuals.
    Well, now I'm a convert... it doesn't hurt that one of the hottest
PC games ever, DOOM, was written using WATCOM C/C++ and the DOS/4GW
extender, as well as many other leading games (X-COM, Indy Car Racing).
My next task was to port many of my libraries over to WATCOM C, luckily,
I had dabbled with the DJGPP release of GNU C/C++, a freeware 32-bit C
compiler, so I had a bit of code already converted.
 
-------------------------------------------------------------------------------
 
Now for the questions:
 
-------------------------------------------------------------------------------
 
Q. My structures appear to be all messed up. Loading from files directly into
   the structures gets "shifted" and the wrong values show up. What's
   happening?
 
A. Well, if you have declared "int" in your structures, bear in mind that
   the size of the int has CHANGED. You need to change them to "short".
 
    TYPE            Size in 16-bit compiler         Size in 32-bit compiler
    char              8 bits  (1 byte)                 8 bits  (1 byte)
    int              16 bits  (2 bytes)               32 bits  (4 bytes)
    short            16 bits  (2 bytes)               16 bits  (2 bytes)
    long             32 bits  (4 bytes)               32 bits  (4 bytes)
 
   Thus, use "short" and "long" where the size of the data is specifically
   required.
 
-------------------------------------------------------------------------------
 
Q. How come this doesn't work anymore for accessing video memory:
 
    unsigned char far *ScrPtr;
 
    ScrPtr=MK_FP(0xa000,0);
 
A. Well, that's because memory is no longer segmented. In 32-bit mode, we use
   "selectors" wich refer to chunks of memory defined in GDTs (Global
   Descriptor Tables). In DOS/4GW, the "default" selector maps the first
   megabyte of memory (your traditional DOS memory) to the first linear
   megabyte of addresses. In short, the screen memory for graphics is located
   at 0x000a0000 through 0x000affff. So, our program needs the following:
 
    unsigned char *ScrPtr;               /* No "far" required here */
 
    ScrPtr=(unsigned char *)0x0a0000;
 
   The reason the call to MK_FP() is allowed, is that there will be cases where
   you need "far" pointers, as in the case of DPMI calls (see below). In this
   case, a selector is a 16-bit value and the offset if a 32-bit value.
 
-------------------------------------------------------------------------------
 
Q. I don't understand "bimodal" interrupts, how am I going to hook into INT9
   to capture keys with my own keyhandler?
 
A. The interrupt mechanism for protected mode is quite complicated. When an
   interrupt is called, it may call one of TWO possible routines, either a
   "Real-mode" routine or a "Protected-mode" routine, depending on which
   state the CPU was in. To deal with this, DOS/4GW has a feature known as
   "auto-passup/auto-passdown". Simply put, if the interrupt function is
   defined for Real-mode, and not in Protected-mode, and the interrupt is
   called in protected mode, DOS/4GW will pass it "down" to the Real-mode
   function.
    Now the kicker... if you define a Protected-mode function for that
   interrupt, DOS/4GW will pass all interrupts occuring in Real-mode *UP*
   to Protected-mode!
    There is a price to pay for this feature, speed. There is a little bit of
   overhead involved. In many cases, this is not a problem, so attempt this
   method first before trying a bimodal interrupt.
    Here is a shell of implementing an IRQ handler:
 
 
    void (__interrupt __far *OldISR)();
 
    void interrupt ISR_0( void )
    {
        /* Your code here... */
    }
 
    void main(void)
    {
            :               :
        OldISR=_dos_getvect(TheVectorHere);
        _dos_setvect(TheVectorHere,ISR_0);
            :               :
        _dos_setvect(TheVectorHere,OldISR);
 
    }
 
    That's all there is to it! Remember all of the normal things involved
   with hooking into IRQs. Also, as the old vector (protected mode)
   redirects the IRQ to Real mode, it is possible to chain back through
   using it.
 
    The "auto-passup" range are INTs 08H to 02EH, excluding 021H (DOS)
 
-------------------------------------------------------------------------------
 
Q. Where can I find Watcom-specific files?
 
A. There is a small site run by Ivan Pulleyn at netcom.com:
 
        ftp.netcom.com /pub/hypereal/watcom
 
    You will find patches and other Watcom-related files here.
 
   WATCOM has several ways to get information, files and patches:
    BBS:            (519)884-2103.
    Internet FTP:   ftp.watcom.on.ca
    E-Mail:         tech@watcom.on.ca
    Compu$erve:     GO WATCOM
 
    Less specifically, but equally useful ftp sites:
 
    x2ftp.oulu.fi       /pub/msdos
    ftp.eng.ufl.edu     /demos
 
 
-------------------------------------------------------------------------------
Q. What kind of libraries are available?
 
A. Well, quite a few, with more coming every day.
 
    Commercial:
 
    MetaWindow/386  -   A graphics/windowing library
 
    ShareWare:  (two net sites to try: x2ftp.oulu.fi and ftp.eng.ufl.edu)
 
    WGT 5.0         -   A nice gaming graphics library, includes VESA SVGA
                        functions, joystick and keyboard handling, sprites
                        and more. Currently in Beta release.
 
    TinyPlay 2.11   -   A decent 8-track MOD player/sound effects package.
                        Source is included.
 
    ll_comm         -   "Lord Logic's" Communication code. Good start for
                        writing some basic serial port code.
 
    ll_kbd          -   "Lord Logic's" Keyboard handler.
 
    text_eng        -   Code to warp an image to any 4-sided polygon.
 
 
   I have successfully converted 99% of GifLib 1.2. Perhaps I'll get around
   to posting it sometime.
 
 
-------------------------------------------------------------------------------
 
Q. I've got library "X" in .LIB form. How come the linker keeps giving me
   this "_funcname not found" when "funcname" is in the header files?
 
A. WATCOM uses its own naming conventions for functions, which FOLLOWS the
   function name with an underscore instead of PRECEDING the function name.
   The fix for this is to use #pragma aux cdecl (funcname); for each
   external function. Note that if the .LIB calls other library functions
   (i.e., printf, abs, anything like that) the linker cannot resolve these
   names.                         (Thanks to Joe Ottinger for this one).
                      --------------------------
   WATCOM gives you pretty fine control over the linkage convention.
   For example, you can do
 
   #pragma aux foo "_*"  /* common style */
   #pragma aux foo "*_"  /* WATCOM style */
   #pragma aux foo "*"   /* common asm or HP style */
 
   or even
 
   #pragma aux foo "FOO" /* linked as FOO */
 
   I take advantage of this control to do profiling (through __PRO and
   __EPI) and occasionally to access directly WATCOM's internal functions
   for development and testing.   (Thanks to Charles Fu)
                      --------------------------
As a side note:
 
A.  Using a pre-compiled 16-bit library with a 32-bit compiler can be a very
    risky thing. Some code might work fine (small model?), but the general
    rule is that it must be recompiled. Also, some parameters won't match
    correctly (short->int->long problem). With straight C, this is pretty
    easy to convert, but inline assembly and .ASM files require greater
    conversion. (See below)
 
-------------------------------------------------------------------------------
 
Q. How do I use inline assembly? Why doesn't my old Borland C/C++ program
   compile correctly with asm { }?
 
A. Inline assembly is quite different in WATCOM C/C++ than in other
   compilers. The "asm {}" construct is in the ANSI standard, but may
   (according to the standard) simply treat it as comment, which WATCOM
   does.
    The mechanism for inline assembly in WCC++ is using the #pragma aux.
   The advantage is that registers are defined for input and output, and
   the compiler will optimize the code generated (something Borland and MSC
   don't do). Here is an example:
 
unsigned short int10(short,short,short,short);
 
#pragma aux int10 =             \
    "int 10H"                   \
    parm [ax] [bx] [cx] [dx]    \
    value[ax];
 
OR:
 
unsigned char GetRow(void);
 
#pragma aux GetRow =            \
    "mov ax,0300H"              \
    "mov bh,0"                  \
    "int 10H"                   \
    modify [ax bx cx dx]        \
    value [dh];
 
    Now, you need only use it like a function within your program!
 
-------------------------------------------------------------------------------
 
Q. What books are available specifically for WATCOM C/C++?
 
A. None that I know of right now.... anybody care to write one?
 
-------------------------------------------------------------------------------
 
Q. What other extenders are available? How good are they?
 
A. WATCOM C/C++ 10.0 (and prior versions) comes with DOS/4GW, a DOS extender
   from Rational Systems. It is a "freebie" - that is - it does not cost any
   extra, and may be distributed with your programs royalty-free. It does have
   a 32 megabyte limit on memory size, but works with DPMI, VCPI, EMS, XMS,
   and raw. There is also support for virtual memory (using disk for memory).
   It cannot be used to create TSRs.
 
    Rational also has a professional version, which accesses 4 gigabytes of
   memory, ability to generate TSR applications, better support of virtual
   memory and more. (about US$250)
 
     Phar-Lap is the extender of choice for Autodesk and others. Beyond that,
    I have almost no info.
 
     FlashTek is another one I have heard about.
 
-------------------------------------------------------------------------------
 
Q. What considerations do I have using assembly?
 
A. Well, you have more robust versions of the registers to use in protected
   mode. Back in real-mode, a programmer had to use size prefixes to use
   the full 32-bit registers of the 386 CPU. In protected-mode, they will
   *REDUCE* the size of the operands! Thus, all the 66H and 67H references
   (the opcodes of the size modifiers) will need to be stomped out.
   Now, you have "eax", "ebx", "ecx", "edx", "esi", "edi" and so forth. Only
   the "segment" registers remain 16-bit, but on that note, you won't have to
   use them anyway, as they become selectors, and you will see ALL OF YOUR
   MEMORY in the default selectors.
 
-------------------------------------------------------------------------------
 
Q. How do I use DPMI?
 
A. First, dig out the WATCOM C/C++ user's guide and read the
   "INTERRUPT 31H DPMI FUNCTIONS" chapter. Next, be prepared to wrap the
   DPMI functions for easier use. 
 
-------------------------------------------------------------------------------
 
Q. How do I access the VESA BIOS functions?
 
A. First, start off by getting the DPMI stuff down pat.
   Now, allocate a "buffer" (using DPMI function 0x0100) to store data
   you wish to pass back and forth, and use DPMI function 0x0300 to call
   the real-mode int 10H.
   This function will convert any pointers passed to a 32-bit address:
 
void *Dos2Protected(unsigned long dosaddr)
{
    unsigned long a,b;
 
    a=dosaddr>>16;
    b=dosaddr&0x0ffff;
    a<<=4;
    return((void *)(a+b));
}
 
    Also, you can't use the WinFuncPtr functions, as they are real-mode
    routines.
 
-------------------------------------------------------------------------------
 
Q. I bought "Tricks of the Game Programming Gurus" and can't get the code to
   compile at all.
 
A. Well, that, like ACK, YAKICONS, XLIB, and others, involves a major
   overhaul to compile, mostly because of the abundance of 16-bit assembly.
   Strange thing is, much of the assembly could be coded in pure "C" without
   affecting the performance. (this is of course my own opinion).
 
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
 
More Questions:  Some I will answer in the next edition, but I want to get
                 this posted right now...
 
Q. I *REALLY* need to use a Bimodal interrupt, how do I do it?
 
Q. How do I assemble my .ASM files? What switches using WASM/TASM/MASM?
 
 
 
 
I'm still calling for contributions, criticisms, and corrections.
I don't really want to maintain this (I don't have the time), so when
it reaches version 1.0, I will probably cut back on supporting this.
 
 
                                    Lee
 
                             llorenz@delphi.com
 
Check out my invisible .SIG:
-----------------------------------------------------------------------------
 
 
 
-----------------------------------------------------------------------------
