DOS/Mesa driver updates (Daniel Borca)
authorBrian Paul <brian.paul@tungstengraphics.com>
Sat, 23 Mar 2002 02:34:07 +0000 (02:34 +0000)
committerBrian Paul <brian.paul@tungstengraphics.com>
Sat, 23 Mar 2002 02:34:07 +0000 (02:34 +0000)
docs/README.DJ
src/glu/mesa/Makefile.DJ
src/glut/dos/Makefile.DJ
src/glut/dos/PC_HW/pc_keyb.c
src/glut/dos/PC_HW/pc_mouse.c
src/glut/dos/init.c
src/mesa/drivers/dos/dmesa.c
src/mesa/drivers/dos/video.c
src/mesa/drivers/dos/video.h
src/mesa/main/Makefile.DJ

index 8b3a0f5998b6516721c0dc7c7435a210d562f82e..8b4e6dc5a382a83137a9b17de11986635d295f28 100644 (file)
@@ -1,5 +1,5 @@
-                   Mesa 4.0.1 DOS/DJGPP Port version 0.3\r
-                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+                    Mesa 4.0 DOS/DJGPP Port version 0.4\r
+                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
 \r
 \r
 \r
@@ -21,16 +21,29 @@ Installation:
 ~~~~~~~~~~~~~\r
 \r
 Type "make -f Makefile.DJ" to compile the libraries. Long filename support is\r
-required during compilation. The examples are not built automagically (see\r
-Pitfalls below).\r
+required during compilation. Also, you must have the DXE2 package (available\r
+on SimTel.Net, courtesy of Andrew Zabolotny) installed in order to build the\r
+dynamic modules; if you encounter errors, you can fetch a patched version from\r
+my web page.\r
+The demos are not built automagically (see Pitfalls below). To make them, use\r
+one of the following rules:\r
+       Static:\r
+           gcc -o OUT.exe IN.c -lglut -lglu -lgl\r
+       Dynamic:\r
+           gcc -o OUT.exe -include dmesadxe.h IN.c -ligl -liglu -liglut -ldl\r
+Usage of the dynamic modules requires three things:\r
+       - include DMESADXE.H in one of the sources, so references inside\r
+         dynamic modules will get resolved (or use `-include' directive)\r
+       - link against import libraries (libIgl*.a) and LIBDL.A, which will do\r
+         the dynamic linkage job for you\r
+       - put the DXEs somewhere along the library path (LD_LIBRARY_PATH) or\r
+         in the current directory\r
 \r
 Tested on:\r
        CPU:            Intel Pentium w/ MMX @166 MHz\r
        Mainboard:      ViA Apollo VP2 w/ 128 MB SDRAM\r
        Video card:     Matrox Millenium 2064W w/ 2048 kB WRAM, BIOS v3.0\r
-       DJGPP:          djdev 2.03\r
-                       gcc v3.0.3\r
-                       make v3.79\r
+       DJGPP:          djdev 2.03 + gcc v3.0.3 + make v3.79\r
 \r
 \r
 \r
@@ -76,7 +89,11 @@ My keyboard driver used only scancodes, but since GLUT requires ASCII values
 for keys, I borrowed the translation tables (and maybe more) from Allegro.\r
 Ctrl-Alt-Del (plus Ctrl-Alt-End, for Windows users) will shut down the GLUT\r
 engine unconditionally: it will raise SIGINT, which in turn will call the\r
-destructors (let's hope), thus cleaning up your/my mess ;-)\r
+destructors (let's hope), thus cleaning up your/my mess ;-) NB: since the\r
+DJGPP guys ensured signal handlers won't go beyond program's space (and since\r
+dynamic modules shall) the SIGINT can't be hooked (well, it can, but it is\r
+useless), therefore you must live with the 'Exiting due to signal SIGINT'\r
+message...\r
 \r
 The mouse driver is far from complete (lack of positioning, drawing, etc),\r
 but is enough to make almost all the demos work.\r
@@ -90,7 +107,8 @@ but timer B will probably loose precision!
 As an addition, stdout and stderr are redirected and dumped upon exit. This\r
 means that printf can be safely called during graphics, but all messages come\r
 in bulk! A bit of a hack, I know, but I think it's better than to miss them\r
-at all.\r
+at all. "Borrowed" from RHIDE (Robert Hoehne) or SETEDIT (Salvador Eduardo\r
+Tropea)... I'm not sure.\r
 \r
 Window creating defaults: 640x480x16 at (0,0), 8-bit stencil, 16-bit accum.\r
 However, the video mode is chosen in such a way that first window will fit.\r
@@ -113,6 +131,7 @@ v0.2        feb-2002        + fast triangle rasterizers
                        ! minor PC_HW corrections\r
 v0.3   mar-2002        - removed FreeBE/AF code\r
                        - removed single-buffer modes\r
+v0.4   mar-2002        + dynamic module support\r
 \r
 \r
 \r
index e09780626bacf48f664f851c27dff3aab6ea3bcb..0232fe5592210ff66af66cee02a857636bd0b52d 100644 (file)
@@ -20,7 +20,7 @@
 # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
 # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
 \r
-# DOS/DJGPP glu makefile v0.1 for Mesa 4.0\r
+# DOS/DJGPP glu makefile v0.4 for Mesa 4.0\r
 #\r
 #  Copyright (C) 2002 - Borca Daniel\r
 #  Email : dborca@yahoo.com\r
@@ -36,7 +36,15 @@ AR = ar
 ARFLAGS = ruv\r
 LIBDIR = $(TOP)/lib\r
 \r
+ifeq ($(wildcard $(DJDIR)/lib/dxe2.ld),)\r
+DXE2GEN =\r
+else\r
+DXE2GEN = $(wildcard $(addsuffix /dxe2gen.exe,$(subst ;, ,$(PATH))))\r
+endif\r
+\r
 GLU_LIB = libglu.a\r
+GLU_DXE = glu.dxe\r
+GLU_IMP = libiglu.a\r
 \r
 CORE_SOURCES = \\r
        glu.c \\r
@@ -58,11 +66,19 @@ OBJECTS = $(SOURCES:.c=.o)
 .c.o:\r
        gcc -o $@ -c $(CFLAGS) $<\r
 \r
-all: $(LIBDIR)/$(GLU_LIB)\r
+all: $(LIBDIR)/$(GLU_LIB) $(LIBDIR)/$(GLU_DXE) $(LIBDIR)/$(GLU_IMP)\r
 \r
 $(LIBDIR)/$(GLU_LIB): $(OBJECTS)\r
        $(AR) $(ARFLAGS) $(LIBDIR)/$(GLU_LIB) $(OBJECTS)\r
 \r
+$(LIBDIR)/$(GLU_DXE) $(LIBDIR)/$(GLU_IMP): $(OBJECTS)\r
+ifeq ($(DXE2GEN),)\r
+       @echo Missing DXE2GEN and/or DXE2.LD! You must have DXE2GEN\r
+       @echo somewhere in PATH, and DXE2.LD in DJGPP/LIB directory.\r
+else\r
+       dxe2gen -o $(LIBDIR)/$(GLU_DXE) -I $(LIBDIR)/$(GLU_IMP) $(OBJECTS) -D "Glu" -U\r
+endif\r
+\r
 clean:\r
        -$(RM) *.o\r
 \r
index 7cacd8d009055ad3469a0e1fffb7a2b695cb6ab5..7a26eb2d0c91befa84ac86cfd7a48f54ed681360 100644 (file)
@@ -20,7 +20,7 @@
 # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
 # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
 \r
-# DOS/DJGPP glut makefile v0.2 for Mesa 4.0\r
+# DOS/DJGPP glut makefile v0.4 for Mesa 4.0\r
 #\r
 #  Copyright (C) 2002 - Borca Daniel\r
 #  Email : dborca@yahoo.com\r
@@ -36,7 +36,15 @@ AR = ar
 ARFLAGS = ruv\r
 LIBDIR = $(TOP)/lib\r
 \r
+ifeq ($(wildcard $(DJDIR)/lib/dxe2.ld),)\r
+DXE2GEN =\r
+else\r
+DXE2GEN = $(wildcard $(addsuffix /dxe2gen.exe,$(subst ;, ,$(PATH))))\r
+endif\r
+\r
 GLUT_LIB = libglut.a\r
+GLUT_DXE = glut.dxe\r
+GLUT_IMP = libiglut.a\r
 \r
 CORE_SOURCES = \\r
        callback.c \\r
@@ -69,11 +77,19 @@ OBJECTS = $(SOURCES:.c=.o) $(PC_HW_OBJECTS)
 .c.o:\r
        gcc -o $@ -c $(CFLAGS) $<\r
 \r
-all: $(LIBDIR)/$(GLUT_LIB)\r
+all: $(LIBDIR)/$(GLUT_LIB) $(LIBDIR)/$(GLUT_DXE) $(LIBDIR)/$(GLUT_IMP)\r
 \r
 $(LIBDIR)/$(GLUT_LIB): $(OBJECTS)\r
        $(AR) $(ARFLAGS) $(LIBDIR)/$(GLUT_LIB) $(OBJECTS)\r
 \r
+$(LIBDIR)/$(GLUT_DXE) $(LIBDIR)/$(GLUT_IMP): $(OBJECTS)\r
+ifeq ($(DXE2GEN),)\r
+       @echo Missing DXE2GEN and/or DXE2.LD! You must have DXE2GEN\r
+       @echo somewhere in PATH, and DXE2.LD in DJGPP/LIB directory.\r
+else\r
+       dxe2gen -o $(LIBDIR)/$(GLUT_DXE) -I $(LIBDIR)/$(GLUT_IMP) $(OBJECTS) -D "DOS Glut" -U\r
+endif\r
+\r
 clean:\r
        -$(RM) *.o\r
        -$(RM) PC_HW\*.o\r
index f5f4bd8e764e986bccecd10e0e190c80bf2f7f48..d3987d8e34016c7f209e9cb82ecf9a5bb7e798a1 100644 (file)
@@ -1,5 +1,5 @@
 /*\r
- * PC/HW routine collection v0.1 for DOS/DJGPP\r
+ * PC/HW routine collection v0.4 for DOS/DJGPP\r
  *\r
  *  Copyright (C) 2002 - Borca Daniel\r
  *  Email : dborca@yahoo.com\r
@@ -32,7 +32,7 @@ static volatile struct {
 static volatile int key_enhanced, key_pause_loop, key_shifts;\r
 static int leds_ok = TRUE;\r
 static int in_a_terrupt = FALSE;\r
-volatile char pc_key[KEY_MAX];\r
+static volatile char pc_key[KEY_MAX];\r
 \r
 \r
 \r
@@ -400,6 +400,10 @@ static int keyboard ()
  }\r
 \r
  if (((temp==0x4F)||(temp==0x53))&&(key_shifts&KB_CTRL_FLAG)&&(key_shifts&KB_ALT_FLAG)) {\r
+    /* Hack alert:\r
+       only SIGINT (but not Ctrl-Break)\r
+       calls the destructors and will safely clean up\r
+    */\r
     __asm__("\n\\r
                movb    $0x79, %%al             \n\\r
                call    ___djgpp_hw_exception   \n\\r
@@ -436,6 +440,11 @@ int pc_readkey (void)
  }\r
 }\r
 \r
+int pc_keydown (int code)\r
+{\r
+ return pc_key[code];\r
+}\r
+\r
 void pc_remove_keyb (void)\r
 {\r
  if (keyboard_installed) {\r
index 2a692eceb667309340ecc9d2e58086f559da7046..aa1fbe4da7302336d349a879713097cd6fbe97fb 100644 (file)
@@ -1,5 +1,5 @@
 /*\r
- * PC/HW routine collection v0.2 for DOS/DJGPP\r
+ * PC/HW routine collection v0.4 for DOS/DJGPP\r
  *\r
  *  Copyright (C) 2002 - Borca Daniel\r
  *  Email : dborca@yahoo.com\r
@@ -29,7 +29,7 @@ static void *mouse_stack;
 static long mouse_callback;\r
 static __dpmi_regs mouse_regs;\r
 \r
-volatile int pc_mouse_x, pc_mouse_y, pc_mouse_b;\r
+static volatile int pc_mouse_x, pc_mouse_y, pc_mouse_b;\r
 \r
 static int minx = 0;\r
 static int maxx = 319;\r
@@ -205,6 +205,13 @@ void pc_mouse_speed (int xspeed, int yspeed)
  ENABLE();\r
 }\r
 \r
+int pc_query_mouse (int *x, int *y)\r
+{\r
+ *x = pc_mouse_x;\r
+ *y = pc_mouse_y;\r
+ return pc_mouse_b;\r
+}\r
+\r
 void pc_show_mouse (void)\r
 {\r
  /* not implemented */\r
index 41170e37c922c1431145aa849375145b2f1f23c8..9cda3a8b5b55daa1dadf3cc2b88ac15bc53d156b 100644 (file)
@@ -19,7 +19,7 @@
  */\r
 \r
 /*\r
- * DOS/DJGPP glut driver v0.2 for Mesa 4.0\r
+ * DOS/DJGPP glut driver v0.4 for Mesa 4.0\r
  *\r
  *  Copyright (C) 2002 - Borca Daniel\r
  *  Email : dborca@yahoo.com\r
  */\r
 \r
 \r
-#include <signal.h>\r
 #include "GL/glut.h"\r
 #include "internal.h"\r
 \r
 \r
-static void *old_sig_int  = NULL;\r
-\r
-\r
-static void signal_handler (int num)\r
-{\r
- signal(SIGINT, old_sig_int);\r
-\r
- raise(num);\r
-}\r
-\r
-\r
 void APIENTRY glutInit (int *argcp, char **argv)\r
 {\r
  glutGet(GLUT_ELAPSED_TIME);\r
- /* Hack alert:\r
-    only SIGINT (but not Ctrl-Break)\r
-    calls the destructors and will safely clean up\r
- */\r
- old_sig_int = signal(SIGINT, signal_handler);\r
 }\r
 \r
 \r
@@ -133,34 +116,42 @@ void APIENTRY glutMainLoop (void)
           }\r
        }\r
 \r
-       if (g_mouse && motion_func && ((pc_mouse_x != old_mouse_x) || (pc_mouse_y != old_mouse_y))) {\r
-          idle        = GL_FALSE;\r
-          old_mouse_x = pc_mouse_x;\r
-          old_mouse_y = pc_mouse_y;\r
-\r
-          motion_func(old_mouse_x, old_mouse_y);\r
-       }\r
-\r
-       if (g_mouse && mouse_func && (pc_mouse_b != old_mouse_b)) {\r
-          int new_mouse_b = pc_mouse_b;\r
-\r
-          if ((old_mouse_b & 1) && !(new_mouse_b & 1))\r
-             mouse_func(GLUT_LEFT_BUTTON, GLUT_UP,   pc_mouse_x, pc_mouse_y);\r
-          else if (!(old_mouse_b & 1) && (new_mouse_b & 1))\r
-             mouse_func(GLUT_LEFT_BUTTON, GLUT_DOWN, pc_mouse_x, pc_mouse_y);\r
-\r
-          if ((old_mouse_b & 2) && !(new_mouse_b & 2))\r
-             mouse_func(GLUT_RIGHT_BUTTON, GLUT_UP,   pc_mouse_x, pc_mouse_y);\r
-          else if (!(old_mouse_b & 2) && (new_mouse_b & 2))\r
-             mouse_func(GLUT_RIGHT_BUTTON, GLUT_DOWN, pc_mouse_x, pc_mouse_y);\r
-\r
-          if ((old_mouse_b & 4) && !(new_mouse_b & 4))\r
-             mouse_func(GLUT_MIDDLE_BUTTON, GLUT_UP,   pc_mouse_x, pc_mouse_y);\r
-          else if (!(old_mouse_b & 3) && (new_mouse_b & 4))\r
-             mouse_func(GLUT_MIDDLE_BUTTON, GLUT_DOWN, pc_mouse_x, pc_mouse_y);\r
-\r
-          idle        = GL_FALSE;\r
-          old_mouse_b = new_mouse_b;\r
+       if (g_mouse) {\r
+          int mouse_x;\r
+          int mouse_y;\r
+          int mouse_b;\r
+       \r
+          mouse_b = pc_query_mouse(&mouse_x, &mouse_y);\r
+          \r
+          if (motion_func && ((mouse_x != old_mouse_x) || (mouse_y != old_mouse_y))) {\r
+             idle        = GL_FALSE;\r
+             old_mouse_x = mouse_x;\r
+             old_mouse_y = mouse_y;\r
+   \r
+             motion_func(old_mouse_x, old_mouse_y);\r
+          }\r
+   \r
+          if (mouse_func && (mouse_b != old_mouse_b)) {\r
+             int new_mouse_b = mouse_b;\r
+   \r
+             if ((old_mouse_b & 1) && !(new_mouse_b & 1))\r
+                mouse_func(GLUT_LEFT_BUTTON, GLUT_UP,   mouse_x, mouse_y);\r
+             else if (!(old_mouse_b & 1) && (new_mouse_b & 1))\r
+                mouse_func(GLUT_LEFT_BUTTON, GLUT_DOWN, mouse_x, mouse_y);\r
+   \r
+             if ((old_mouse_b & 2) && !(new_mouse_b & 2))\r
+                mouse_func(GLUT_RIGHT_BUTTON, GLUT_UP,   mouse_x, mouse_y);\r
+             else if (!(old_mouse_b & 2) && (new_mouse_b & 2))\r
+                mouse_func(GLUT_RIGHT_BUTTON, GLUT_DOWN, mouse_x, mouse_y);\r
+   \r
+             if ((old_mouse_b & 4) && !(new_mouse_b & 4))\r
+                mouse_func(GLUT_MIDDLE_BUTTON, GLUT_UP,   mouse_x, mouse_y);\r
+             else if (!(old_mouse_b & 3) && (new_mouse_b & 4))\r
+                mouse_func(GLUT_MIDDLE_BUTTON, GLUT_DOWN, mouse_x, mouse_y);\r
+   \r
+             idle        = GL_FALSE;\r
+             old_mouse_b = new_mouse_b;\r
+          }\r
        }\r
 \r
        if (idle && idle_func)\r
index d150cdca5acfbf6277773e884204bfeb1ccbb34f..454b891c08b364b51679911a956efb75f3d2cebb 100644 (file)
@@ -540,13 +540,8 @@ static GLboolean set_draw_buffer (GLcontext *ctx, GLenum mode)
  * If anything special has to been done when the buffer/window is\r
  * resized, do it now.\r
  */\r
-static void get_buffer_size (GLframebuffer *buffer, GLuint *width, GLuint *height)\r
+static void get_buffer_size (GLcontext *ctx, GLuint *width, GLuint *height)\r
 {\r
- /* XXX this may not be right.  We should query the size of the DOS window\r
-  * associated with <buffer>.    This function should work whether or\r
-  * not there is a current context.\r
-  */\r
- GET_CURRENT_CONTEXT(ctx);\r
  DMesaContext c = (DMesaContext)ctx->DriverCtx;\r
 \r
  *width  = c->Buffer->width;\r
@@ -641,7 +636,7 @@ void dmesa_init_pointers (GLcontext *ctx)
  ctx->Driver.Accum = _swrast_Accum;\r
  ctx->Driver.Bitmap = _swrast_Bitmap;\r
  ctx->Driver.Clear = clear;\r
- ctx->Driver.ResizeBuffers = _swrast_alloc_buffers;\r
+ ctx->Driver.ResizeBuffersMESA = _swrast_alloc_buffers;\r
  ctx->Driver.CopyPixels = _swrast_CopyPixels;\r
  ctx->Driver.DrawPixels = _swrast_DrawPixels;\r
  ctx->Driver.ReadPixels = _swrast_ReadPixels;\r
index 5c2c84a84f78bc31b5b1c4ac7c1af67c0fa50de3..9d50952c52730c82976a70ccbea594e22f226a75 100644 (file)
@@ -23,7 +23,7 @@
  */\r
 \r
 /*\r
- * DOS/DJGPP device driver v0.3 for Mesa 4.0\r
+ * DOS/DJGPP device driver v0.4 for Mesa 4.0\r
  *\r
  *  Copyright (C) 2002 - Borca Daniel\r
  *  Email : dborca@yahoo.com\r
@@ -180,9 +180,9 @@ void vl_rect (void *buffer, int x, int y, int width, int height, int color)
 /*\r
  * virtual dumping:\r
  */\r
-void *(*vl_flip) (void *buffer, int width, int height);\r
+void (*vl_flip) (void *buffer, int width, int height);\r
 \r
-extern void *b_dump_virtual (void *buffer, int width, int height);\r
+extern void b_dump_virtual (void *buffer, int width, int height);\r
 __asm__("\n\\r
                .text                           \n\\r
                .balign 4                       \n\\r
@@ -242,7 +242,7 @@ _b_dump_virtual:                            \n\
                popl    %esi                    \n\\r
                popl    %ebx                    \n\\r
                ret");\r
-extern void *l_dump_virtual (void *buffer, int width, int height);\r
+extern void l_dump_virtual (void *buffer, int width, int height);\r
 __asm__("\n\\r
                .text                           \n\\r
                .balign 4                       \n\\r
index ff81ac9d2e94054ddf25d78df5bb8ca735f31f24..c806aa7c885104b33d01f4ab50045d39473cd256 100644 (file)
@@ -23,7 +23,7 @@
  */\r
 \r
 /*\r
- * DOS/DJGPP device driver v0.3 for Mesa 4.0\r
+ * DOS/DJGPP device driver v0.4 for Mesa 4.0\r
  *\r
  *  Copyright (C) 2002 - Borca Daniel\r
  *  Email : dborca@yahoo.com\r
@@ -42,7 +42,7 @@ void *vl_sync_buffer (void *buffer, int x, int y, int width, int height);
 extern void (*vl_clear) (void *buffer, int len, int color);\r
 void vl_rect (void *buffer, int x, int y, int width, int height, int color);\r
 \r
-void *(*vl_flip) (void *buffer, int width, int height);\r
+void (*vl_flip) (void *buffer, int width, int height);\r
 \r
 extern int (*vl_mixrgba) (const unsigned char rgba[]);\r
 extern int (*vl_mixrgb) (const unsigned char rgb[]);\r
index 214882d1cfa6fc98347870203ca4e0c94650c239..fc540dc60bbe6db2f14408fa86069a6cd402f37f 100644 (file)
@@ -20,7 +20,7 @@
 # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
 # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
 \r
-# DOS/DJGPP core makefile v0.2 for Mesa 4.0\r
+# DOS/DJGPP core makefile v0.4 for Mesa 4.0\r
 #\r
 #  Copyright (C) 2002 - Borca Daniel\r
 #  Email : dborca@yahoo.com\r
@@ -36,7 +36,15 @@ AR = ar
 ARFLAGS = ruv\r
 LIBDIR = $(TOP)/lib\r
 \r
+ifeq ($(wildcard $(DJDIR)/lib/dxe2.ld),)\r
+DXE2GEN =\r
+else\r
+DXE2GEN = $(wildcard $(addsuffix /dxe2gen.exe,$(subst ;, ,$(PATH))))\r
+endif\r
+\r
 GL_LIB = libgl.a\r
+GL_DXE = gl.dxe\r
+GL_IMP = libigl.a\r
 \r
 CORE_SOURCES = \\r
        swrast_setup/ss_context.c \\r
@@ -166,11 +174,19 @@ OBJECTS = $(SOURCES:.c=.o)
 .c.o:\r
        gcc -o $@ -c $(CFLAGS) $<\r
 \r
-all: $(LIBDIR)/$(GL_LIB)\r
+all: $(LIBDIR)/$(GL_LIB) $(LIBDIR)/$(GL_DXE) $(LIBDIR)/$(GL_IMP)\r
 \r
 $(LIBDIR)/$(GL_LIB): $(OBJECTS)\r
        $(AR) $(ARFLAGS) $(LIBDIR)/$(GL_LIB) $(OBJECTS)\r
 \r
+$(LIBDIR)/$(GL_DXE) $(LIBDIR)/$(GL_IMP): $(OBJECTS)\r
+ifeq ($(DXE2GEN),)\r
+       @echo Missing DXE2GEN and/or DXE2.LD! You must have DXE2GEN\r
+       @echo somewhere in PATH, and DXE2.LD in DJGPP/LIB directory.\r
+else\r
+       dxe2gen -o $(LIBDIR)/$(GL_DXE) -I $(LIBDIR)/$(GL_IMP) $(OBJECTS) -D "DOS Mesa" -U\r
+endif\r
+\r
 clean:\r
        -$(RM) *.o\r
        -$(RM) DOS\*.o\r