______ ___ ___
/\ _ \ /\_ \ /\_ \
\ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
\ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
\ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
\ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
\/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
/\____/
\_/__/ WinAllegro 3.0 + WIP
#include <std_disclaimer.h>
"I do not accept responsibility for any effects, adverse or otherwise, that this code may have on you, your computer, your sanity, your dog, and anything else that you can think of. Use it at your own risk."
Welcome to WinAllegro, the DirectX port of Shawn Hargreaves's great game programming library Allegro (http://www.talula.demon.co.uk/).
Everybody who have tried to develop a native Windows game with Microsoft's multi media api DirectX knows that the first step is the development of a nice, easy to use and powerfull wrapper. This wrapper should hide the complexity of "direct DirectX programming". In addtion to this the implementation of a Win32 program framework with a window class, message loop and a window procedure is neccessary before the first pixel can be drawn.
This work makes the steps from dos to windows programming harder than it should be. Many game programmers still prefer using their good old dos because windows programming seem to turn them away from the game programming itself.
WinAllegro tries to improve this situation by creating a dos like enviroment that makes it possible to create native windows applications with full DirectX support without looking into the details of windows programming. WinAllegro is mostly source code compatible to Allegro. All windows specific stuff like window handling is done internally by WinAllegro. The programmer can put his focus on the game rather than the operation system around it.
This file is meant as an addition to the original Allegro documentation. General topics that are equal between the dos and windows version can only be found in the Allegro help file (ALLEGRO.TXT).
WinAllegro is distributed in a zip file. Its name is wallxxxx.zip (xxxx has to be replaced with the version, 30w6 for example). To install WinAllegro on your computer extract the content of the archive to a directory of your choice. Pay attention to restore the directory structure.
If everything went correctly you have a directory with several sub directories: demo, docs, examples, lib, obj, setup, src, test, tests, tools. In the docs directory you will find this help file (winalleg.htm).
To be able to compile programs with WinAllegro you have to install some files manually:
- Copy the DLL files from lib\win32\debug and lib\win32\release (allxxxx.dll and allxxxxd.dll) to your system directory (c:\windows\system or c:\winnt\system32 on NT).
- Copy the lib files from the same directories into the lib directory of your Visual C++ installation (for Visual C++ users) or copy the lib file from the lib\rsx directory into the RSXNTDJ library directory (for RSXNTDJ users).
- Copy the headers (allegro.h and winalleg.h) from the main directory of your WinAllegro installation into the include directory of your compiler.
At the moment the following compilers are supported:
- Microsoft Visual C++ 5 (Some users have reported that it also works with Visual C++ 4.0 and 6.0)
- DJGPP + RSXNTDJ
Visual C++ uses workspaces with one or more projects to organize the creation of a program. To create a WinAllegro application you have to create a workspace with a Win32 GUI project:
- Create a Win32 application project.
- Open the property window of the project.
- Change the runtime library settings (C/C++ / Code generation) to "Multithreaded DLL" (for release target) and "Multithreaded DLL debug" (for the debug target).
- Include the import library in the module list (linker settings) by appending allegro.lib (for release target) and allegrod.lib (for debug target) to the existing list of libraries.
After you have closed the property dialog, you can start with your source code. If you have still problems with linking look into the WinAllegro workspace (winalleg.dsw)! There are all examples with correct compiler and linker settings.
Porting DOS Allegro programs to WinAllegro + RSXNTDJ
Because you're using the same compiler and because WinAllegro is well designed the porting is really very simple. The basic requirements for porting are described in later chapters.
In this section I'll mention some points which I think are specific to the RSXNTDJ port of WinAllegro. In brief, these points are:
- You can't use a `main' function
WinAllegro normally allows you to ignore `WinMain' completely and just write a `main' function, but as mentioned above that doesn't work on RSXNTDJ. You really do need to do what it says in `winalleg.htm' -- either write your own WinMain wrapper around your main function and rename it to something other than `main', or just write a WinMain function to do everything.
If you look in the `examples' directory you'll find `wrapper.h', which is a wrapper I used in all of the examples to allow them to go on using a function called `main'. In fact it gets renamed by a #define in `wrapper.h', to prevent it from confusing NtBind.
- The DLL can't access your memory
The WinAllegro DLL can't access some of your application's memory space. I don't really understand this; I noticed it when dealing with listbox callbacks, which return pointers to string constants. The listbox dialog routines try to modify the data pointed to, and hang the machine. Look at `demo.c' and `ex13.c' to see how to get around this problem; in the end I hope it will be solved inside the DLL itself so you don't have to worry about it.
As always for RSXNTDJ compilations you should pass `-Zwin32' to gcc at all stages. Because WinAllegro requires multithreading support you need to pass `-Zmt' as well. You also want to link to the import library, using `-lwinal', rather than the normal Allegro library (which would be `-lalleg').
WinAllegro programs must be GUI applications, not console applications. They'll crash otherwise. In RSXNTDJ this means that you must not have a `main' function -- otherwise the NtBind utility will assume you're making a console application. To check that it isn't doing this, look at the line it prints after linking, which should say:
Ntbind: Building GUI Application "foo.exe"
and not:
Ntbind: Building Console Application "foo.exe"
Differences between WinAllegro and Allegro
WinAllegro has nearly the same functionality as Allegro. One key goal during development was to keep the api the same. Programs that were developed in dos should be compilable with WinAllegro nearly without any changes to the source code. Because of some special requirement of DirectX this couldn't be reached completely. Nevertheless it is still very easy to port your application to WinAllegro.
The following items describe single differences you have to pay attention to:
There are different new drivers for video, audio and joysticks. All former driver like GFX_VGA have to be replaced with the new ones.
There are two new graphic drivers: GFX_DIRECTX is used for fullscreen applications. It can be used with any resolution that is supported by your graphic card. Keep in mind that different Windows graphic drivers support different resolution. Some resolution are quite common: 640x480, 800x600, 1024x768. Some graphic cards support a lot more resolutions like 320x200, 320x240, 320x400, 640x400, 1152x1024, 1280x1024, 1600x1280. Although in dos program the 320x200 mode is supported on every card, this is not the case in Windows. DirectX only supports low resolution modes if the windows graphic driver supports them. Unfortunately 320x200 is not implemented on many cards.
ModeX is not supported by WinAllegro because DirectX doesn't support direct access to those modes.
Although nearly every graphics chipset supports 15 and 16 color bit modes today, many Windows drivers only support one of them. This means that, if you want to use high color, you should try both color depths. For example try to set a 16 bit mode first. If set_gfx_mode returns an error, set the color depth to 15 bits and try again. The same is valid for truecolor (24 and 32 bits). If you don't pay attention to this warning, you program won't work on many computers.
Especially for debugging the GFX_DIRECTXWIN driver is important. Programs that use this one run in a window on the desktop. Every resolution is posible (i.e. 100x100). Keep in mind that the set_gfx_mode function return an error when the desktop has the wrong color depth. To make sure that your application can run in any color depth you should try every color depth until set_gfx_mode succeeds.
At the moment the "windowed" mode is not ready for release versions. For examples there is absolutely no clipping. If you move the window out of the right screen border, it will appear on the left. Please only use this driver for debugging sessions.
Similar to the graphic drivers, the new digital audio driver is called DIGI_DIRECTX. The midi driver is called MIDI_DIRECTX.
WinAllegro supports playing of digital audio samples and midi files. You can use all digital audio function like with Allegro. The current release has no support for audio streaming.
The MIDI_DIGMID also exists in WinAllegro, but doesn't work until now. There are still some problems with it. Try it out and you will see or better hear.
Digital sound input is not available in WinAllegro.
The cpu detection routines can be called, but don't work at the moment.
WinAllegro supports nearly all sorts of graphic functions. With memory bitmap that you have created with create_bitmap there're no differences to Allegro.
Video bitmaps (i.e. the screen) are different. DirectX has to share the video memory between more than one application. For this it is neccessary to acquire a bitmap before it is accessed by any graphic function. After this you have to release the bitmap.
Example:
acquire_bitmap(screen); putpixel(screen, 10, 100, 50); release_bitmap(screen);The first command acquires the screen bitmap. Internally the WinAllegro asks DirectDraw for the memory pointer. If you forget to acquire a video bitmap, you can crash your whole system in worst case. So always pay attention to:
When you want to access a video bitmap (i.e. the screen bitmap), you have to use a pair of acquire_bitmap and release_bitmap.
To reduce the work a bit there are two macros for the screen bitmap:
#define acquire_screen() acquire_bitmap(screen); #define release_screen() release_bitmap(screen);Of course it is not needed to acquire a bitmap for every access. If you have a lot of code that accesses the screen, it's enough to use one pair of acquire and release.
Example:
acquire_screen();
putpixel(screen, 10, 100, 50);
putpixel(screen, 10, 102, 51);
putpixel(screen, 10, 104, 52);
putpixel(screen, 10, 106, 53);
putpixel(screen, 10, 108, 54);
release_screen();But don't calls any other functions than Allegro drawing functions between acquire and release. Never do something like this:
acquire_screen(); putpixel(screen, 10, 100, 50); readkey(); putpixel(screen, 10, 108, 54); release_screen();This will crash your program because Windows is completely stopped by the acquire call and a key will never arrive. If you want to do thing like above, you have to type:
acquire_screen(); putpixel(screen, 10, 100, 50); release_screen(); readkey(); acquire_screen(); putpixel(screen, 10, 108, 54); release_screen();Another present of DirectX is the existence of lost bitmaps. Again because Windows is a multitasking system with many concurrent running processes, DirectX has to share the display memory between them. In most cases it has to share it between your fullscreen program and the desktop. DirectX gives the whole memory to the currently active one. When you application is in foreground, it can draw on its video bitmaps. When it lose the focus and gets minimized, all video bitmaps are destroyed! More exactly the contents of these bitmaps is destroyed. After your program comes back to fullscreen mode, you have to redraw all video bitmaps (i.e. the screen bitmap)!
How to find out whether the screen was lost? You have to install a "lost bitmap callback" by using the function install_lost_bitmap_callback. After all video bitmaps are lost, all registered callbacks are called to restore the content of the bitmap.
Example:
int Running = 1; int Redraw = 1; void Callback() { Redraw = 1; } void GameLoop() { install_lost_bitmap_callback(Callback); while (Running) { if (Redraw) { Redraw = 0; DrawBackground(); // Redraw whole background } DrawSprites(); // Draw sprites in new position sleep(100); RestoreBackground(); // Restore background of sprites MoveSprites(); // Move sprites and save background } remove_lost_bitmap_callback(Callback); }DirectX has no official way to save the content before it is lost. If anybody knows a stable way to do this, I would be very happy.
WinAllegro provide some additional functions that are only usefull and available in native Windows application that include the WINALLEG.H header.
int WinAllegro_Init(HINSTANCE hInstance);
Before any Allegro and WinAllegro can be called the WinAllegro library has to be initialiazed with WinAllegro_Init. hInstance is the instance handle that is passed by the WinMain function.
If the return value is zero, the initialisation was successfull. Any other return value indicates and error. Independent from the return value the WinAllegro_Exit function has to be called at the end of the program.
void WinAllegro_Exit();
At the end of your program the WinAllegro_Exit function has to be called to release all memory and Windows objects.
int WinAllegro_GetArgc();
char **WinAllegro_GetArgv();WinMain doesn't provide the command line arguments. Instead WinAllegro_GetArgc and WinAllegro_GetArgv can be used for this. WinAllegro_GetArgc returns the number of parameters. WinAllegro_GetArgv returns the address of the argument area that contains pointers to all command line arguments of the application.
void WinAllegro_SetWindowTitle(char *Title);
WinAllegro_SetWindowTitle sets the title text of the main window.
HWND WinAllegro_GetWindowHandle();
To use enhanced Windows 32 apis you need the handle of a window in many cases. WinAllegro_GetWindowHandle returns the handle of the WinAllegro main window.
void WinAllegro_SetWindowIcon(HICON hIcon);
WinAllegro_SetWindowIcon sets the icon of the WinAllegro application.
LPDIRECTDRAW WinAllegro_GetDirectDraw();
For "special effects" is usefull to call DirectDraw directly. To do this the DirectDraw interface can be retrieved.
LPDIRECTDRAW2 WinAllegro_GetDirectDraw2();
This functions returns the DirectDraw2 interface.
LPDIRECTDRAWSURFACE WinAllegro_GetSurface(struct BITMAP *bmp);
Every video bitmap is connected to a DirectDraw surface. To access this surface directly this call can be used. If the bitmap is no video bitmap, the result will be NULL.
In WINALLEG.H some more function definition can be found. They are matter of change. It is very likely that they will look completely different in future versions.
To use WinAllegro functions you will need to include the ALLEGRO.H header. It includes everything that is also available when you use DJGPP with the WinAllegro source (Yes, you can compile it with DJGPP!). Addtional features are found in WINALLEG.H. All function, that are not available in dos mode, have a WinAllegro prefix.
If you want to use Windows headers for enhanced functionality you will run into troubles, because Windows defines its own BITMAP and RGB macro. To solve this problem, you have to do this:
#define BITMAP WINDOWS_BITMAP #include <windows.h> #undef BITMAP #undef RGB #include <allegro.h>Dos programs normally have a main function with two parameters: argc, argv.
int main(int argc, char **argv)
Native Windows applications start with a WinMain procedure that looks different:
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
There are two different approaches for WinAllegro applications:
- You can write a little wrapper that calls a dos like main function:
#define WIN32_LEAN_AND_MEAN #include <windows.h> #include "winalleg.h" extern int main(int argc, char **argv);/* Pay attention that with RSXNTDJ you have to rename the main function to something different (for more information look above) */
extern "C" void allegro_exit(); int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { if (WinAllegro_Init(hInstance)==0) { int result = main(WinAllegro_GetArgc(), WinAllegro_GetArgv()); allegro_exit(); WinAllegro_Exit(); return result; } else { WinAllegro_Exit(); MessageBox(NULL, "WinAllegro can't be setup." "For more information look in allegro.log!", "WinAllegro Error", MB_ICONERROR | MB_OK); } }The dos like main function has to be in a seperate source file.
- The second approach is to simply use only this WinMain function:
#define WIN32_LEAN_AND_MEAN #define BITMAP WINDOWS_BITMAP #include <windows.h> #undef BITMAP #undef RGB #include <allegro.h> #include <winalleg.h> int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { if (WinAllegro_Init(hInstance)==0) { allegro_init(); set_gfx_mode(GFX_DIRECTX, 640, 480, 0, 0); acquire_screen(); line(screen, 0, 0, 100, 200, 10); release_screen(); allegro_exit(); WinAllegro_Exit(); } else { WinAllegro_Exit(); MessageBox(NULL, "WinAllegro can't be setup." "For more information look in allegro.log!", "WinAllegro Error", MB_ICONERROR | MB_OK); } return result; }
As you can see in both code excerpts it's neccessary to initialize the WinAllegro library with WinAllegro_Init before you use any "old" Allegro function. Furthermore a WinAllegro_Exit() call is needed at the end.
WWW:
http://1Stein.home.pages.de (Home of WinAllegro)
http://www.canvaslink.com/gfoot/winallegro/ (George Foot's page about WinAllegro with RSXNTDJ)
http://www.talula.demon.co.uk/ (Shawn Hargreaves' dos Allegro)Mailing list:
allegro@canvaslink.com. To add or remove yourself, write to listserv@canvaslink.com with the text "subscribe allegro yourname" or "unsubscribe allegro" in the body of your message.This is the main place where further development of Allegro and WinAllegro is discussed.
Usenet:
Try the djgpp newsgroup: comp.os.msdos.djgpp
My email:
Questions about WinAllegro with RSXNTDJ should be sent to George Foot who have ported WinAllegro to RSXNTDJ (george.foot@merton.oxford.ac.uk)
Snail mail:
Stefan Schimanski
Ginsterweg 19
D-38300 Wolfenbüttel
GermanyThe latest version of WinAllegro can always be found on the 1Stein-Software
homepage: http://1Stein.home.pages.de.