diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 0215f62f7..39c2bcac9 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,6 @@ +March 28, 2007 +- Adding blinky text to the ENDOOM screen. + March 24, 2007 - Changed MakeKey's hash algorithm from a CRC32 to Paul Hsieh's SuperFastHash. diff --git a/src/c_dispatch.cpp b/src/c_dispatch.cpp index 6453a6068..eacaacad0 100644 --- a/src/c_dispatch.cpp +++ b/src/c_dispatch.cpp @@ -261,128 +261,128 @@ static int ListActionCommands (const char *pattern) return count; } -/* ======================================================================== */ - -/* By Paul Hsieh (C) 2004, 2005. Covered under the Paul Hsieh derivative - license. See: - http://www.azillionmonkeys.com/qed/weblicense.html for license details. - - http://www.azillionmonkeys.com/qed/hash.html */ - -#undef get16bits -#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \ - || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__) -#define get16bits(d) (*((const WORD *) (d))) -#endif - -#if !defined (get16bits) -#define get16bits(d) ((((DWORD)(((const BYTE *)(d))[1])) << 8)\ - +(DWORD)(((const BYTE *)(d))[0]) ) -#endif - -DWORD SuperFastHash (const char *data, size_t len) -{ - DWORD hash = 0, tmp; - size_t rem; - - if (len == 0 || data == NULL) return 0; - - rem = len & 3; - len >>= 2; - - /* Main loop */ - for (;len > 0; len--) - { - hash += get16bits (data); - tmp = (get16bits (data+2) << 11) ^ hash; - hash = (hash << 16) ^ tmp; - data += 2*sizeof (WORD); - hash += hash >> 11; - } - - /* Handle end cases */ - switch (rem) - { - case 3: hash += get16bits (data); - hash ^= hash << 16; - hash ^= data[sizeof (WORD)] << 18; - hash += hash >> 11; - break; - case 2: hash += get16bits (data); - hash ^= hash << 11; - hash += hash >> 17; - break; - case 1: hash += *data; - hash ^= hash << 10; - hash += hash >> 1; - } - - /* Force "avalanching" of final 127 bits */ - hash ^= hash << 3; - hash += hash >> 5; - hash ^= hash << 4; - hash += hash >> 17; - hash ^= hash << 25; - hash += hash >> 6; - - return hash; +/* ======================================================================== */ + +/* By Paul Hsieh (C) 2004, 2005. Covered under the Paul Hsieh derivative + license. See: + http://www.azillionmonkeys.com/qed/weblicense.html for license details. + + http://www.azillionmonkeys.com/qed/hash.html */ + +#undef get16bits +#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \ + || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__) +#define get16bits(d) (*((const WORD *) (d))) +#endif + +#if !defined (get16bits) +#define get16bits(d) ((((DWORD)(((const BYTE *)(d))[1])) << 8)\ + +(DWORD)(((const BYTE *)(d))[0]) ) +#endif + +DWORD SuperFastHash (const char *data, size_t len) +{ + DWORD hash = 0, tmp; + size_t rem; + + if (len == 0 || data == NULL) return 0; + + rem = len & 3; + len >>= 2; + + /* Main loop */ + for (;len > 0; len--) + { + hash += get16bits (data); + tmp = (get16bits (data+2) << 11) ^ hash; + hash = (hash << 16) ^ tmp; + data += 2*sizeof (WORD); + hash += hash >> 11; + } + + /* Handle end cases */ + switch (rem) + { + case 3: hash += get16bits (data); + hash ^= hash << 16; + hash ^= data[sizeof (WORD)] << 18; + hash += hash >> 11; + break; + case 2: hash += get16bits (data); + hash ^= hash << 11; + hash += hash >> 17; + break; + case 1: hash += *data; + hash ^= hash << 10; + hash += hash >> 1; + } + + /* Force "avalanching" of final 127 bits */ + hash ^= hash << 3; + hash += hash >> 5; + hash ^= hash << 4; + hash += hash >> 17; + hash ^= hash << 25; + hash += hash >> 6; + + return hash; } /* A modified version to do a case-insensitive hash */ #undef get16bits -#define get16bits(d) ((((DWORD)tolower(((const BYTE *)(d))[1])) << 8)\ - +(DWORD)tolower(((const BYTE *)(d))[0]) ) +#define get16bits(d) ((((DWORD)tolower(((const BYTE *)(d))[1])) << 8)\ + +(DWORD)tolower(((const BYTE *)(d))[0]) ) -DWORD SuperFastHashI (const char *data, size_t len) -{ - DWORD hash = 0, tmp; - size_t rem; - - if (len <= 0 || data == NULL) return 0; - - rem = len & 3; - len >>= 2; - - /* Main loop */ - for (;len > 0; len--) - { - hash += get16bits (data); - tmp = (get16bits (data+2) << 11) ^ hash; - hash = (hash << 16) ^ tmp; - data += 2*sizeof (WORD); - hash += hash >> 11; - } - - /* Handle end cases */ - switch (rem) - { - case 3: hash += get16bits (data); - hash ^= hash << 16; - hash ^= tolower(data[sizeof (WORD)]) << 18; - hash += hash >> 11; - break; - case 2: hash += get16bits (data); - hash ^= hash << 11; - hash += hash >> 17; - break; - case 1: hash += tolower(*data); - hash ^= hash << 10; - hash += hash >> 1; - } - - /* Force "avalanching" of final 127 bits */ - hash ^= hash << 3; - hash += hash >> 5; - hash ^= hash << 4; - hash += hash >> 17; - hash ^= hash << 25; - hash += hash >> 6; - - return hash; +DWORD SuperFastHashI (const char *data, size_t len) +{ + DWORD hash = 0, tmp; + size_t rem; + + if (len <= 0 || data == NULL) return 0; + + rem = len & 3; + len >>= 2; + + /* Main loop */ + for (;len > 0; len--) + { + hash += get16bits (data); + tmp = (get16bits (data+2) << 11) ^ hash; + hash = (hash << 16) ^ tmp; + data += 2*sizeof (WORD); + hash += hash >> 11; + } + + /* Handle end cases */ + switch (rem) + { + case 3: hash += get16bits (data); + hash ^= hash << 16; + hash ^= tolower(data[sizeof (WORD)]) << 18; + hash += hash >> 11; + break; + case 2: hash += get16bits (data); + hash ^= hash << 11; + hash += hash >> 17; + break; + case 1: hash += tolower(*data); + hash ^= hash << 10; + hash += hash >> 1; + } + + /* Force "avalanching" of final 127 bits */ + hash ^= hash << 3; + hash += hash >> 5; + hash ^= hash << 4; + hash += hash >> 17; + hash ^= hash << 25; + hash += hash >> 6; + + return hash; } -/* ======================================================================== */ +/* ======================================================================== */ unsigned int MakeKey (const char *s) { diff --git a/src/win32/st_start.cpp b/src/win32/st_start.cpp index b5f27dda6..db7124bb0 100644 --- a/src/win32/st_start.cpp +++ b/src/win32/st_start.cpp @@ -104,6 +104,12 @@ #define TEXT_FONT_NAME "vga-rom-font.16" +// How many ms elapse between blinking text flips. On a standard VGA +// adapter, the characters are on for 16 frames and then off for another 16. +// The number here therefore corresponds roughly to the blink rate on a +// 60 Hz display. +#define BLINK_PERIOD 267 + // TYPES ------------------------------------------------------------------- class FBasicStartupScreen : public FStartupScreen @@ -186,6 +192,7 @@ BYTE *ST_Util_LoadFont (const char *filename); void ST_Util_FreeFont (BYTE *font); BITMAPINFO *ST_Util_AllocTextBitmap (const BYTE *font); void ST_Util_DrawTextScreen (BITMAPINFO *bitmap_info, const BYTE *text_screen, const BYTE *font); +void ST_Util_UpdateTextBlink (BITMAPINFO *bitmap_info, const BYTE *text_screen, const BYTE *font, bool blink_on); void ST_Util_DrawChar (BITMAPINFO *screen, const BYTE *font, int x, int y, BYTE charnum, BYTE attrib); // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- @@ -1092,6 +1099,8 @@ void ST_Endoom() BYTE *font; MSG mess; BOOL bRet; + bool blinking = false, blinkstate = false; + int i; if (endoom_lump < 0 || Wads.LumpLength (endoom_lump) != 4000) { @@ -1125,7 +1134,6 @@ void ST_Endoom() // Draw the loading screen to a bitmap. StartupBitmap = ST_Util_AllocTextBitmap (font); ST_Util_DrawTextScreen (StartupBitmap, endoom_screen, font); - ST_Util_FreeFont (font); // Make the title banner go away. if (GameTitleWindow != NULL) @@ -1138,20 +1146,38 @@ void ST_Endoom() LayoutMainWindow (Window, NULL); InvalidateRect (StartupScreen, NULL, TRUE); - // Wait until any key has been pressed or a quit message has been received - - while ((bRet = GetMessage(&mess, NULL, 0, 0)) != 0) + // Does this screen need blinking? + for (i = 0; i < 80*25; ++i) { - if (bRet == 0) // Received WM_QUIT + if (endoom_screen[1+i*2] & 0x80) { - exit (int(mess.wParam)); + blinking = true; + break; } - else if (bRet != -1) + } + if (blinking && SetTimer (Window, 0x5A15A, BLINK_PERIOD, NULL) == 0) + { + blinking = false; + } + + // Wait until any key has been pressed or a quit message has been received + for (;;) + { + bRet = GetMessage (&mess, NULL, 0, 0); + if (bRet == 0 || bRet == -1 || // bRet == 0 means we received WM_QUIT + mess.message == WM_KEYDOWN || mess.message == WM_SYSKEYDOWN || mess.message == WM_LBUTTONDOWN) { - if (mess.message == WM_KEYDOWN || mess.message == WM_SYSKEYDOWN || mess.message == WM_LBUTTONDOWN) + if (blinking) { - exit (0); + KillTimer (Window, 0x5A15A); } + ST_Util_FreeFont (font); + exit (int(bRet == 0 ? mess.wParam : 0)); + } + else if (blinking && mess.message == WM_TIMER && mess.hwnd == Window && mess.wParam == 0x5A15A) + { + ST_Util_UpdateTextBlink (StartupBitmap, endoom_screen, font, blinkstate); + blinkstate = !blinkstate; } TranslateMessage (&mess); DispatchMessage (&mess); @@ -1550,11 +1576,11 @@ void ST_Util_DrawTextScreen (BITMAPINFO *bitmap_info, const BYTE *text_screen, c void ST_Util_DrawChar (BITMAPINFO *screen, const BYTE *font, int x, int y, BYTE charnum, BYTE attrib) { - const BYTE bg_left = attrib & 0xF0; + const BYTE bg_left = attrib & 0x70; const BYTE fg = attrib & 0x0F; const BYTE fg_left = fg << 4; const BYTE bg = bg_left >> 4; - const BYTE color_array[4] = { bg_left | bg, attrib, fg_left | bg, fg_left | fg }; + const BYTE color_array[4] = { bg_left | bg, attrib & 0x7F, fg_left | bg, fg_left | fg }; const BYTE *src = font + 1 + charnum * font[0]; int pitch = screen->bmiHeader.biWidth >> 1; BYTE *dest = ST_Util_BitsForBitmap(screen) + x*4 + y * font[0] * pitch; @@ -1574,3 +1600,30 @@ void ST_Util_DrawChar (BITMAPINFO *screen, const BYTE *font, int x, int y, BYTE dest += pitch; } } + +//========================================================================== +// +// ST_Util_UpdateTextBlink +// +// Draws the parts of the text screen that blink to the bitmap. The bitmap +// must be the proper size for the font. +// +//========================================================================== + +void ST_Util_UpdateTextBlink (BITMAPINFO *bitmap_info, const BYTE *text_screen, const BYTE *font, bool on) +{ + int x, y; + + for (y = 0; y < 25; ++y) + { + for (x = 0; x < 80; ++x) + { + if (text_screen[1] & 0x80) + { + ST_Util_DrawChar (bitmap_info, font, x, y, on ? text_screen[0] : ' ', text_screen[1]); + ST_Util_InvalidateRect (Window, bitmap_info, x*8, y*font[0], x*8+8, y*font[0]+font[0]); + } + text_screen += 2; + } + } +}