diff options
| author | Steven Fuller <relnev@icculus.org> | 2001-07-01 00:55:22 +0000 |
|---|---|---|
| committer | Patryk Obara <dreamer.tan@gmail.com> | 2019-08-20 02:09:04 +0200 |
| commit | 2186d5f3f95cd74a070a490d899291648d58667a (patch) | |
| tree | 55241a1afa3e1a22e0b6593a8dead0b703800f44 /src/win95/db.c | |
| parent | 218ca90543758a20ac326e444ca0643174ca7384 (diff) | |
Initial revision
Diffstat (limited to 'src/win95/db.c')
| -rw-r--r-- | src/win95/db.c | 1039 |
1 files changed, 1039 insertions, 0 deletions
diff --git a/src/win95/db.c b/src/win95/db.c new file mode 100644 index 0000000..90fd200 --- /dev/null +++ b/src/win95/db.c @@ -0,0 +1,1039 @@ +#ifndef NDEBUG + +/* ******************************************************************** * + * * + * DB.C - Debugging functions. * + * * + * By: Garry Lancaster Version: 2.0 * + * * + * ******************************************************************** */ + +/* N O T E S ********************************************************** */ + +/* A lot of these functions should be called via macros defined in db.h */ + +/* If you don't want to link this file with Windows OS files set the + * define DB_NOWINDOWS. This will also stop linking with the Direct Draw + * stuff, which is, after all, a part of Windows. If you want Windows + * stuff, but NOT Direct Draw, define DB_NODIRECTDRAW. + */ + +/* ******************************************************************** * + * * + * I N T E R F A C E - both internal and external. * + * * + * ******************************************************************** */ + +/* I N C L U D E S **************************************************** */ + +/* Windows includes. Actually internal, but here to allow pre-compilation. */ +#include "advwin32.h" +#ifndef DB_NOWINDOWS + #include <windows.h> + #include "advwin32.h" +#endif +#ifndef DB_NODIRECTDRAW + #include <ddraw.h> +#endif +#include "db.h" /* Contains most off the interface. */ + +/* G L O B A L S ****************************************************** */ +/* Have external linkage. */ +volatile BOOL DZ_NULL; + +/* This variable dictates whether macros ending _opt get executed. */ +int db_option = 0; /* Default is off. */ + +/* ******************************************************************** * + * * + * I N T E R N A L * + * * + * ******************************************************************** */ + +/* I N C L U D E S **************************************************** */ + +/* Defining DB_NOWINDOWS implies DB_NODIRECTDRAW should also be defined. */ +#ifdef DB_NOWINDOWS + #ifndef DB_NODIRECTDRAW + #define DB_NODIRECTDRAW + #endif +#endif + +/* ANSI includes. */ +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <conio.h> +#include <direct.h> /* For getcwd() */ +#include <stdarg.h> /* For variable arguments. */ + +/* C O N S T A N T S ************************************************** */ + +/* Possible return value for MessageBox() */ +#define NO_MEMORY 0 + +/* Possible value for the width field of a font_struct. */ +#define PROP_WIDTH 0 + +/* Logfile name */ +#define LOGFILE_NAME "LOGFILE.TXT" + +/* Set this to 1 if the logfile name is an absolute path. Otherwise the + * logfile will go in the directory that is current when db_log_init() + * is called. + */ +#define ABSOLUTE_PATH 0 + +/* M A C R O S ******************************************************** */ + +/* Causes a division by zero exception. */ +#define DB_FORCE_EXCEPTION() ( db_vol_zero = 1 / db_vol_zero ) + +/* Cause a brakepoint. */ +#define DB_FORCE_BRAKEPOINT() do {__asm int 3} while(0) + +/* T Y P E S ********************************************************** */ + + +typedef struct font_struct *fontPtr; + +struct font_struct { + void *dummy1; + unsigned short dummy2, dummy3; + void *dummy4; + char filename[16]; + unsigned short width, height; + unsigned short ascent, avgwidth; + unsigned char byte_width; + unsigned char filler1; + short filler2; + char facename[28]; + unsigned short *prop_width_dataP; + unsigned char *bitmapP; +}; + +union PtrPackTag +{ + unsigned char *cP; + unsigned short *wP; + unsigned long *lP; +}; + +/* G L O B A L ******************************************************** */ +/* Should all be static. */ +static BOOL db_use_brakepoints = FALSE; + +/* Name of file to output log messages to. */ +static char LogFileNameP[255]; + +/* Have we initialized the log file? */ +static int InitialisedLog = 0; + +/* Type of display mode we are in. */ +static int db_display_type = DB_DOS; + +/* For DirectDraw mode. */ +static struct db_dd_mode_tag dd_mode = {NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0}; +static fontPtr FontP = NULL; + +/* Volatile zero. */ +static volatile int db_vol_zero = 0; + +/* Text strings for output. */ +static const char* db_assert_textA[ 3 ] = +{ + "ASSERTION FAILED!", + "Expression: %s", + "File: %s Line: %d" +}; +static const char* db_prompt_std = + "Quit program/force e(x)ception? [y/n/x]"; +static const char* db_prompt_windows = + "Quit program? [Yes/No]/force exception? [Cancel]"; +static const char* db_assert_log_begin_text = + "DB: FAILED ASSERTION BEGINS"; +static const char* db_assert_log_end_text = + "DB: FAILED ASSERTION ENDS"; +static const char* db_msg_log_begin_text = + "DB: MSG BEGINS"; +static const char* db_msg_log_end_text = + "DB: MSG ENDS"; + +#ifdef DB_NOWINDOWS +static char db_log_file_name[261] = LOGFILE_NAME; +#else +static char db_log_file_name[MAX_PATH+1] = LOGFILE_NAME; +#endif + + +/* P R O T O S ******************************************************** */ +/* Should all be static. */ + +static void db_do_std_prompt(unsigned yOffset); + +#ifndef DB_NOWINDOWS +static void db_do_win_prompt(const char* titleStrP, const char* bodyStrP); +#endif /* ifndef DB_NOWINDOWS */ + +#ifndef DB_NODIRECTDRAW + +/* Load debugging font, return NULL if we fail. */ +static fontPtr guiload_font(char *new_fname); + +/* Cleanup function for the above. */ +static fontPtr CleanupFontLoadFail(HANDLE fH, fontPtr fontP); + +/* Outputs debugging text. */ +static void out_text(LPDIRECTDRAWSURFACE surfP, int xc, int yc, + const char *text, short x_limit, fontPtr fP); + +/* Debounce all the keys the Direct Draw stuff uses. */ +static void Debounce(void); + +/* Wait for any outstanding flip operations to be completed, provided + * that the user specified DB_FLIP in the bltOrFlip field of the + * db_dd_mode_tag function. If they specified DB_BLIT this function returns + * immediately. + */ +static void DbWaitForHw(void); + +/* Flips between the draw and visible surfaces. */ +static void DbFlip(void); + +/* Blits the contents of the draw surface to the visible surface. */ +static void DbBlt(void); + +#endif /* ifndef DB_NODIRECTDRAW */ + +/* F U N C T I O N S ************************************************** */ + +/* ******************************************************************** * + * * + * I N T E R F A C E - both internal and external. * + * * + * ******************************************************************** */ + +/* NEW FNS for formatted debug strings. */ +void __cdecl db_logf_fired(const char *fmtStrP, ...) +{ + char msg[ 1024 ]; + va_list varArgList; + + va_start( varArgList, fmtStrP ); + vsprintf( msg, fmtStrP, varArgList ); + va_end( varArgList ); + + db_log_fired( msg ); +} + +void __cdecl db_printf_fired(int x, int y, const char *fmtStrP, ...) +{ + char msg[ 256 ]; + va_list varArgList; + + va_start( varArgList, fmtStrP ); + vsprintf( msg, fmtStrP, varArgList ); + va_end( varArgList ); + + db_print_fired( x, y, msg ); +} + +void __cdecl db_msgf_fired(const char *fmtStrP, ...) +{ + char msg[ 256 ]; + va_list varArgList; + + va_start( varArgList, fmtStrP ); + vsprintf( msg, fmtStrP, varArgList ); + va_end( varArgList ); + + db_msg_fired( (const char *) msg ); +} + +/* Called whenever an assertion fails. */ +void db_assert_fail(const char *exprP, const char *fileP, int line) +{ + db_log_fired( db_assert_log_begin_text ); + db_log_fired( db_assert_textA[ 0 ] ); + db_logf_fired( db_assert_textA[ 1 ], exprP ); + db_logf_fired( db_assert_textA[ 2 ], fileP, line ); + db_log_fired( db_assert_log_end_text ); + + switch(db_display_type) + { + case DB_DOS: + printf( db_assert_textA[ 0 ] ); + printf("\n"); + printf( db_assert_textA[ 1 ], exprP ); + printf("\n"); + printf( db_assert_textA[ 2 ], fileP, line ); + printf("\n"); + db_do_std_prompt( 0 ); + break; +#ifndef DB_NODIRECTDRAW + case DB_DIRECTDRAW: + { + char msg[256]; + unsigned short xLimit = (unsigned short) dd_mode.width; + + /* Wait for any hardware to finish flipping. */ + DbWaitForHw(); + + out_text((LPDIRECTDRAWSURFACE) dd_mode.drawSurfaceP, + 0, 0, db_assert_textA[ 0 ], xLimit, FontP); + wsprintf(msg, db_assert_textA[ 1 ], exprP); + out_text((LPDIRECTDRAWSURFACE) dd_mode.drawSurfaceP, + 0, 16, msg, xLimit, FontP); + wsprintf(msg, db_assert_textA[ 2 ], fileP, line); + out_text((LPDIRECTDRAWSURFACE) dd_mode.drawSurfaceP, + 0, 32, msg, xLimit, FontP); + db_do_std_prompt( 48 ); + } + break; +#endif +#ifndef DB_NOWINDOWS + case DB_WINDOWS: + { + char fmtMsg[ 256 ]; + char msg[256]; + + strcpy( fmtMsg, db_assert_textA[ 1 ] ); + strcat( fmtMsg, db_assert_textA[ 2 ] ); + strcat( fmtMsg, db_prompt_windows ); + sprintf(msg, fmtMsg, exprP, fileP, line); + + db_do_win_prompt( db_assert_textA[ 0 ], msg ); + } + break; +#endif + default: + break; + } +} + +/* Displays a message and has the program pause until the user responds + * to it. + */ +void db_msg_fired(const char *strP) +{ + db_log_fired( db_msg_log_begin_text ); + db_log_fired( strP ); + db_log_fired( db_msg_log_end_text ); + + switch(db_display_type) + { + case DB_DOS: + printf("%s\n", strP); + db_do_std_prompt( 0 ); + break; +#ifndef DB_NOWINDOWS + case DB_WINDOWS: + db_do_win_prompt( "Debugging Message", strP ); + break; +#endif +#ifndef DB_NODIRECTDRAW + case DB_DIRECTDRAW: + { + unsigned short xLimit = (unsigned short) dd_mode.width; + + /* Wait for any flip hardware to be ready. */ + DbWaitForHw(); + + out_text((LPDIRECTDRAWSURFACE) dd_mode.drawSurfaceP, + 0, 0, strP, xLimit, FontP); + db_do_std_prompt( 16 ); + } + break; +#endif + default: + break; + } +} + +/* Displays a message and continues program execution immediately. */ +void db_print_fired(int x, int y, const char *strP) +{ + switch(db_display_type) + { + case DB_DOS: + printf("%s\n", strP); + break; +#ifndef DB_NOWINDOWS + case DB_WINDOWS: + break; +#endif +#ifndef DB_NODIRECTDRAW + case DB_DIRECTDRAW: + { + unsigned short xLimit = (unsigned short) (dd_mode.width - x); + out_text((LPDIRECTDRAWSURFACE) dd_mode.drawSurfaceP, x, y, + strP, xLimit, FontP); + break; + } +#endif + default: + break; + } +} + +/* Writes a message to a log file. */ +/* At least files can be output in the same way under DOS, Windows and + * Direct Draw! + */ +void db_log_fired(const char *strP) +{ + /* Have we intialised the file? */ + if(!InitialisedLog) db_log_init(); + { + /* Open a file for appending, creating one if it doesn't yet exist. */ + FILE *fP = fopen(LogFileNameP, "a+"); + + if(!fP) return; + + fprintf(fP, "%s\n", strP); + fclose(fP); + } +} + +void db_log_init(void) +{ + #if ABSOLUTE_PATH + sprintf( LogFileNameP, "%s", db_log_file_name ); + #else + /* Append the log file name to the current working directory. */ + sprintf( LogFileNameP, "%s\\%s", getcwd( LogFileNameP, 240 ), + db_log_file_name ); + #endif + + /* Delete old log file. */ + remove(LogFileNameP); + + /* Flag that we have initialised the log file. */ + InitialisedLog = 1; +} + +extern void db_set_log_file_ex(const char *strP) +{ + InitialisedLog = 0; + + strcpy(db_log_file_name, strP); +} + +void db_set_mode_ex(int mode, void *modeInfoP, void *newFontP) +{ + db_display_type = mode; +#ifndef DB_NODIRECTDRAW + if(dd_mode.visibleSurfaceP) + { + IDirectDrawSurface_Release((LPDIRECTDRAWSURFACE) dd_mode.visibleSurfaceP); + dd_mode.visibleSurfaceP = NULL; + } + + if(dd_mode.drawSurfaceP) + { + IDirectDrawSurface_Release((LPDIRECTDRAWSURFACE) dd_mode.drawSurfaceP); + dd_mode.drawSurfaceP = NULL; + } + + if(mode == DB_DIRECTDRAW) + { + dd_mode = *((struct db_dd_mode_tag *) modeInfoP); + + if(dd_mode.visibleSurfaceP) + { + IDirectDrawSurface_AddRef((LPDIRECTDRAWSURFACE) dd_mode.visibleSurfaceP); + } + + if(dd_mode.drawSurfaceP) + { + IDirectDrawSurface_AddRef((LPDIRECTDRAWSURFACE) dd_mode.drawSurfaceP); + } + + if(!FontP) + { + if(!newFontP) + FontP = guiload_font("DIALOG.FNT"); + else + FontP = (fontPtr) newFontP; + } + if(!FontP) + { + db_log_fired("DB ERROR: Font load failed. Exiting..."); + exit(0); + } + } +#endif +} + +/* Called to set whether exceptions or brakepoints are called. */ +void DbUseBrakepoints(BOOL use_brakepoints) +{ + db_use_brakepoints = use_brakepoints; +} + +int db_get_mode(void** modeInfoPP, void **FontPP) +{ + // blank return areas + *FontPP = NULL; + *modeInfoPP = NULL; + +#ifndef DB_NODIRECTDRAW + if(db_display_type == DB_DIRECTDRAW) + { + // copy font data + *FontPP = (void *) FontP; + + // copy surface data + *modeInfoPP = (void *) &dd_mode; + } +#endif + return db_display_type; +} + +void db_uninit(void) +{ + #ifndef DB_NODIRECTDRAW + if(FontP) + { + if(FontP->bitmapP) + { + GlobalFree(FontP->bitmapP); + } + if(FontP->prop_width_dataP) + { + GlobalFree(FontP->prop_width_dataP); + } + + GlobalFree(FontP); + FontP = NULL; + } + + if(dd_mode.visibleSurfaceP) + { + IDirectDrawSurface_Release((LPDIRECTDRAWSURFACE) dd_mode.visibleSurfaceP); + } + + if(dd_mode.drawSurfaceP) + { + IDirectDrawSurface_Release((LPDIRECTDRAWSURFACE) dd_mode.drawSurfaceP); + } + + #endif +} + +/* ******************************************************************** * + * * + * I N T E R N A L * + * * + * ******************************************************************** */ + +static void db_do_std_prompt(unsigned yOffset) +{ + int ch = 0; + + switch(db_display_type) + { + case DB_DOS: + printf( db_prompt_std ); + printf("\n"); + do + { + ch = toupper(getch()); + } + while((ch != 'N') && (ch != 'Y') && (ch != 'X')); + break; +#ifndef DB_NODIRECTDRAW + case DB_DIRECTDRAW: + { + SHORT response; + BOOL done = FALSE; + unsigned short xLimit = (unsigned short) dd_mode.width; + + out_text((LPDIRECTDRAWSURFACE) dd_mode.drawSurfaceP, + 0, yOffset, db_prompt_std, xLimit, FontP); + + /* Show the message. */ + if(dd_mode.bltOrFlip == DB_FLIP) + { + DbFlip(); + } + else + { + DbBlt(); + } + + /* Wait for a valid key press. */ + do + { + response = GetAsyncKeyState('Y'); + if(response & 0x8000) + { + ch = 'Y'; + done = TRUE; + } + response = GetAsyncKeyState('N'); + if(response & 0x8000) + { + ch = 'N'; + done = TRUE; + } + response = GetAsyncKeyState('X'); + if(response & 0x8000) + { + ch = 'X'; + done = TRUE; + } + } + while(!done); + + Debounce(); + + /* Return the flip surfaces to their pre-message state. */ + if(dd_mode.bltOrFlip == DB_FLIP) + { + DbFlip(); + } + break; + } +#endif /* ifndef DB_NODIRECTDRAW */ + }/* switch(db_display_type) */ + + if(ch == 'Y') + { + exit(-10); + } + else if(ch == 'X') + { + if(db_use_brakepoints) + { + DB_FORCE_BRAKEPOINT(); + } + else + { + DB_FORCE_EXCEPTION(); + } + } + +}/* db_do_std_prompt() */ + +#ifndef DB_NOWINDOWS +static void db_do_win_prompt(const char* titleStrP, const char* bodyStrP) +{ + int response; + + response = MessageBox + ( + NULL, /* Dialog has no KNOWN parent window. */ + bodyStrP, /* Message to go in box. */ + titleStrP, /* Box title. */ + MB_YESNOCANCEL| /* Put up a 'Yes' and a 'No' button. */ + MB_SETFOREGROUND| /* Shove message box to front of display. */ + MB_ICONEXCLAMATION| /* Use an exclamation mark to decorate box. */ + MB_TASKMODAL /* Suspend current task until box is closed. */ + ); + + if((response == IDYES) || (response == NO_MEMORY)) + { + exit( -10 ); + } + else if(response == IDCANCEL) + { + if(db_use_brakepoints) + { + DB_FORCE_BRAKEPOINT(); + } + else + { + DB_FORCE_EXCEPTION(); + } + } +}/* db_do_win_prompt() */ +#endif /* ifndef DB_NOWINDOWS */ + +#ifndef DB_NODIRECTDRAW + +static fontPtr guiload_font(char *new_fname) +{ + HANDLE *fH; + BOOL status; + unsigned short c, byte, y; + union PtrPackTag dest; + unsigned char inByte; + fontPtr fntSP; + DWORD bytesRead; + + /* Open file for reading */ + fH = CreateFile(new_fname, GENERIC_READ, 0, NULL, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL|FILE_FLAG_SEQUENTIAL_SCAN, NULL); + if(!fH) + { + db_log_fired("DB ERROR: Couldn't open font file."); + return CleanupFontLoadFail(NULL, NULL); + } + + + /* Allocate memory for our font structure */ + fntSP = (fontPtr) + GlobalAlloc(GMEM_FIXED, sizeof(struct font_struct)); + if(!fntSP) + { + db_log_fired("DB ERROR: Not enough memory for font structure."); + return CleanupFontLoadFail(fH, NULL); + } + + /* Nullify pointers inside the font structure. */ + fntSP->bitmapP = NULL; + fntSP->prop_width_dataP = NULL; + + /* Load up font structure */ + status = ReadFile(fH, fntSP, sizeof(struct font_struct), &bytesRead, + NULL); + if((!status) || (bytesRead != sizeof(struct font_struct))) + { + db_log_fired("DB ERROR: Error reading structure from font file."); + return CleanupFontLoadFail(fH, fntSP); + } + + /* Allocate memory for font bitmap */ + fntSP->bitmapP = (unsigned char *) GlobalAlloc(GMEM_FIXED, + fntSP->byte_width * dd_mode.bitsPerPixel * fntSP->height * 128); + if(!fntSP->bitmapP) + { + db_log_fired("DB ERROR: Not enough memory for font bitmap."); + return CleanupFontLoadFail(fH, fntSP); + } + + /* Work out proportional text widths for this font + * (if the font is proportional). + */ + if(fntSP->width == PROP_WIDTH) + { + /* Allocate memory for proportional width data */ + fntSP->prop_width_dataP = (unsigned short *) + GlobalAlloc(GMEM_FIXED, 256); + if(!fntSP->prop_width_dataP) + { + db_log_fired("DB ERROR: Not enough memory for proportional " + "font data"); + return CleanupFontLoadFail(fH, fntSP); + } + + /* Read proportional width data */ + status = ReadFile(fH, fntSP->prop_width_dataP, 256, &bytesRead, + NULL); + if((!status) || (bytesRead != 256)) + { + db_log_fired("DB ERROR: Error reading proportional font data " + "from file."); + return CleanupFontLoadFail(fH, fntSP); + } + + /* Round width of font to nearest long word. */ + { + int i; + unsigned short *propP = fntSP->prop_width_dataP; + + if(dd_mode.bitsPerPixel == 8) + { + for(i = 0; i < 128; i ++) + { + /* Round up to 4 pixels. */ + *propP = (unsigned short) ((*propP + 3U) & (~3U)); + } + propP++; + } + else + { + for(i = 0; i < 128; i ++) + { + /* Round up to 2 pixels. */ + *propP = (unsigned short) ((*propP + 1U) & (~1U)); + } + propP++; + } + } + } + else + { + /* Round width to nearest long word. */ + if(dd_mode.bitsPerPixel == 8) + { + /* Round up to 4 pixels. */ + fntSP->width = (unsigned char) ((fntSP->width + 2) & (~3)); + } + else + { + /* Round up to 2 pixels. */ + fntSP->width = (unsigned char) ((fntSP->width + 1) & (~1)); + } + } + + /* Load up bitmap data */ + dest.cP = fntSP->bitmapP; + for(c = 0; c < 128; c ++) + { + for(y = 0; y < fntSP->height; y ++) + { + for(byte = 0; byte < fntSP->byte_width; byte ++) + { + unsigned char bitMask = 0x80; + + /* Read a byte of data */ + status = ReadFile(fH, &inByte, 1, &bytesRead, NULL); + if((!status) || (bytesRead != 1)) + { + db_log_fired("DB ERROR: Error reading font bitmap from " + "file."); + return CleanupFontLoadFail(fH, fntSP); + } + + /* Translate 1 bit per pixel data into current Direct Draw + * screen mode bit depth. + */ + if(dd_mode.bitsPerPixel == 8) + { + do + { + if(inByte & bitMask) *(dest.cP) = + (unsigned char) dd_mode.foreCol; + else *(dest.cP) = (unsigned char) dd_mode.backCol; + dest.cP++; + + /* Shift bitMask 1 bit to the right */ + bitMask >>= 1; + } + while(bitMask); + } + else + { + do + { + if(inByte & bitMask) *(dest.wP) = dd_mode.foreCol; + else *(dest.wP) = dd_mode.backCol; + dest.wP++; + + /* Shift bitMask 1 bit to the right */ + bitMask >>= 1; + } + while(bitMask); + } + } + } + } + + /* Close the font file */ + CloseHandle(fH); + + return fntSP; +} + +static fontPtr CleanupFontLoadFail(HANDLE fH, fontPtr fontP) +{ + /* Close file if necessary */ + if(fH) CloseHandle(fH); + + /* Is the font struct allocated? */ + if(fontP) + { + /* Yes. Is the bitmap allocated? If so, free it. */ + if(fontP->bitmapP) GlobalFree(fontP->bitmapP); + + /* Is the proportional width data allocated. If so, free it. */ + if(fontP->prop_width_dataP) GlobalFree(fontP->prop_width_dataP); + + /* Free the font structure. */ + GlobalFree(fontP); + } + + return NULL; +} + +static void out_text(LPDIRECTDRAWSURFACE surfP, int xc, int yc, + const char *text, short x_limit, fontPtr fP) +{ + register unsigned long *srcP, *destP; + register unsigned int x, y; + unsigned long heightTimesPitch, charOffset; + unsigned int prop_width; + int srcIncr, longsPerLine; + unsigned int bitShift; + DDSURFACEDESC surfaceDesc; + + /* Lock the surface. */ + { + HRESULT res; + + surfaceDesc.dwSize = sizeof surfaceDesc; + res = IDirectDrawSurface_Lock(surfP, NULL, &surfaceDesc, + DDLOCK_WAIT, NULL); + if(res != DD_OK) + { + db_log3("Couldn't lock surface."); + return; + } + } + + /* Round xc to nearest long word. */ + if(dd_mode.bitsPerPixel == 8) + { + xc = (xc + 2) & (~3); + bitShift = 2; + } + else + { + xc = (xc + 1) & (~1); + bitShift = 1; + } + + /* Point to DRAM buffer co-ordinate where the top left of the + * first character should be written. + */ + destP = (unsigned long *) surfaceDesc.lpSurface + + ((yc * surfaceDesc.lPitch) >> 2) + (xc >> bitShift); + heightTimesPitch = (fP->height * surfaceDesc.lPitch) >> 2; + longsPerLine = (fP->byte_width * dd_mode.bitsPerPixel) >> 2; + charOffset = longsPerLine * fP->height; + + /* Write our text string */ + while(*text != '\0') + { + /* Blit a single character */ + /* Point srcP to first byte of the bitmap for the current + * character. + */ + srcP = ((unsigned long *) fP->bitmapP) + (*text) * charOffset; + + /* Get width of this character (in pixels). */ + if(fP->width == PROP_WIDTH) + prop_width = *(fP->prop_width_dataP + (*text)); + else prop_width = fP->width; + + /* Check we will not exceed our original x_limit if we blit + * this character. If we will, we should stop writing. + */ + x_limit = (short) (x_limit - prop_width); + if(x_limit < 0) break; + + /* Convert prop_width from pixels to longs. */ + prop_width >>= bitShift; + + srcIncr = longsPerLine - prop_width; + + y = fP->height; + do + { + x = prop_width; + do + { + /* Move 1 long word. */ + *destP++ = *srcP++; + } + while(--x != 0); + + /* Point to start of next horizontal line of character square + * in DRAM buffer. + */ + destP += (surfaceDesc.lPitch >> 2) - prop_width; + srcP += srcIncr; + } + while(--y != 0); + + /* Point to start of next character position in DRAM buffer */ + destP -= heightTimesPitch - prop_width; + + /* Advance one character in text string */ + text++; + } + + /* Unlock surface. */ + { + HRESULT res; + + res = IDirectDrawSurface_Unlock(surfP, + (LPVOID) surfaceDesc.lpSurface); + if(res != DD_OK) db_log_fired("Couldn't unlock surface."); + } + return; +} + +static void Debounce(void) +{ + BOOL bouncing; + + /* Debounce all the keys we use - that is Y, N, and RETURN. */ + do + { + bouncing = FALSE; + if(GetAsyncKeyState('Y') & 0x8000) bouncing = TRUE; + if(GetAsyncKeyState('N') & 0x8000) bouncing = TRUE; + if(GetAsyncKeyState('X') & 0x8000) bouncing = TRUE; + if(GetAsyncKeyState(VK_RETURN) & 0x8000) bouncing = TRUE; + } + while(bouncing); +} + +static void DbWaitForHw(void) +{ + /* Wait until the last flip is finished and the last blt done */ + BOOL finished; + + /* Stay in this loop until the hardware is free. */ + do + { + finished = TRUE; + + /* Make sure all flips are done. */ + if(dd_mode.bltOrFlip == DB_FLIP) + { + if(IDirectDrawSurface_GetFlipStatus( + (LPDIRECTDRAWSURFACE) dd_mode.visibleSurfaceP, + DDGFS_ISFLIPDONE) != DD_OK) + finished = FALSE; + } + } + while(!finished); +} + +static void DbFlip(void) +{ + LPDIRECTDRAWSURFACE fromSurfP = + (LPDIRECTDRAWSURFACE) dd_mode.drawSurfaceP; + LPDIRECTDRAWSURFACE toSurfP = + (LPDIRECTDRAWSURFACE) dd_mode.visibleSurfaceP; + HRESULT res; + + /* Try to flip the screen. */ + res = IDirectDrawSurface_Flip(toSurfP, fromSurfP, DDFLIP_WAIT); + + if(res != DD_OK) + db_log_fired("Internal debug flip failed - message lost!"); +} + +static void DbBlt(void) +{ + LPDIRECTDRAWSURFACE fromSurfP = + (LPDIRECTDRAWSURFACE) dd_mode.drawSurfaceP; + LPDIRECTDRAWSURFACE toSurfP = + (LPDIRECTDRAWSURFACE) dd_mode.visibleSurfaceP; + HRESULT res; + RECT toRect; + + /* Initialise to Rect. */ + toRect.left = dd_mode.bltXOffset; + toRect.top = dd_mode.bltYOffset; + toRect.right = toRect.left + dd_mode.width; + toRect.bottom = toRect.top + dd_mode.height; + + /* Try to blit from the draw to the visible surface. */ + res = IDirectDrawSurface_Blt(toSurfP, &toRect, fromSurfP, NULL, + DDBLT_WAIT, NULL); + + if(res != DD_OK) + db_log_fired("Internal debug blit failed - message lost."); +} + +#endif + +#else + ; +#endif /* ! NDEBUG */ |
