4 // Dissolve in/out messages into the "matrix"
14 // this isn't really a random-number generator. It's based on
15 // a 16bit CRC algorithm. With the right mask (0xb400) it is possible
16 // to call this function 65536 times and get a unique result every time
17 // with *NO* repeats. The results look random but they're not - if we
18 // call this function another 65536 times we get exactly the same results
19 // in the same order. This is necessary for fading in messages because
20 // we need to be guaranteed that all cells...it's completely uniform in
21 // operation but looks random enough to be very effective
23 WORD
crc_msgrand(WORD reg
)
25 const WORD mask
= 0xb400;
28 reg
= (reg
>> 1) ^ mask
;
36 // Set a new message based on font and text
38 void SetMatrixMessage(MATRIX_MESSAGE
*msg
, HFONT hFont
, TCHAR
*text
)
47 HANDLE hOldFont
, hOldBmp
;
50 // Create a monochrome off-screen buffer
54 hdcMessage
= CreateCompatibleDC(hdc
);
55 hbmMessage
= CreateBitmap(MAXMSG_WIDTH
, MAXMSG_HEIGHT
, 1, 1, 0);
56 hOldBmp
= SelectObject(hdcMessage
, hbmMessage
);
61 // Draw text into bitmap
63 SetRect(&rect
, 0, 0, msg
->width
, MAXMSG_HEIGHT
);
64 FillRect(hdcMessage
, &rect
, GetStockObject(WHITE_BRUSH
));
66 hOldFont
= SelectObject(hdcMessage
, g_hFont
);
67 DrawText(hdcMessage
, text
, -1, &rect
, DT_CENTER
|DT_VCENTER
|DT_WORDBREAK
|DT_CALCRECT
);
69 OffsetRect(&rect
, (msg
->width
-(rect
.right
-rect
.left
))/2, (msg
->height
-(rect
.bottom
-rect
.top
))/2);
70 DrawText(hdcMessage
, text
, -1, &rect
, DT_CENTER
|DT_VCENTER
|DT_WORDBREAK
);
73 // Convert bitmap into an array of cells for easy drawing
75 for(y
= 0; y
< msg
->height
; y
++)
77 for(x
= 0; x
< msg
->width
; x
++)
79 msg
->message
[x
][y
] = GetPixel(hdcMessage
, x
, y
) ? 0 : 1;
86 SelectObject(hdcMessage
, hOldFont
);
87 SelectObject(hdcMessage
, hOldBmp
);
90 DeleteObject(hbmMessage
);
94 // Draw any part of the message that is visible. Make the
95 // message "shimmer" by using a random glyph each time
97 void DrawMatrixMessage(MATRIX
*matrix
, MATRIX_MESSAGE
*msg
, HDC hdc
)
101 for(x
= 0; x
< msg
->width
; x
++)
102 for(y
= 0; y
< msg
->height
; y
++)
103 if((msg
->message
[x
][y
] & 0x8000) &&
104 (msg
->message
[x
][y
] & 0x00FF))
106 DrawGlyph(matrix
, hdc
, x
* GLYPH_WIDTH
, y
* GLYPH_HEIGHT
, RandomGlyph(MAX_INTENSITY
));
111 // Reveal specified amount of message
113 void RevealMatrixMessage(MATRIX_MESSAGE
*msg
, int amount
)
119 msg
->random_reg1
= crc_msgrand(msg
->random_reg1
);
120 pos
= msg
->random_reg1
& 0xffff;
122 msg
->message
[pos
/ 256][pos
% 256] |= GLYPH_REDRAW
;
127 // Reset (hide) the message
129 void ClearMatrixMessage(MATRIX_MESSAGE
*msg
)
133 for(x
= 0; x
< msg
->width
; x
++)
134 for(y
= 0; y
< msg
->height
; y
++)
135 msg
->message
[x
][y
] = 0;
139 // convert from 50-500 (fast-slow) to slow(50) - fast(500)
143 return (MSGSPEED_MAX
-MSGSPEED_MIN
) - (g_nMessageSpeed
-MSGSPEED_MIN
) + MSGSPEED_MIN
;
147 // Called once for each iteration of the matrix
149 void DoMatrixMessage(HDC hdc
, MATRIX
*matrix
)
151 MATRIX_MESSAGE
*msg
= matrix
->message
;
153 int RealSpeed
= MessageSpeed();
155 if(g_nNumMessages
> 0)
157 // nothing to do yet..
158 if(msg
->counter
++ < 0)
161 // has counter reached limit..clear the message
162 if(msg
->counter
++ == RealSpeed
/ 2 + (RealSpeed
/4))
163 ClearMatrixMessage(msg
);
165 // reset counter + display a new message
166 if(msg
->counter
>= RealSpeed
)
168 // mark all message-cells as being "invisible" so the
169 // message gets cleared by the matrix decoding naturally
171 if(g_fRandomizeMessages
)
172 msg
->msgindex
= crc_rand() % g_nNumMessages
;
174 msg
->msgindex
= (msg
->msgindex
+ 1) % g_nNumMessages
;
176 // make a new message..initially invisible
177 SetMatrixMessage(msg
, 0, g_szMessages
[msg
->msgindex
]);
179 msg
->counter
= -(int)(crc_rand() % MSGSPEED_MAX
);
181 // reveal the next part of the message
182 else if(msg
->counter
< RealSpeed
/ 2)
184 int w
= (g_nMessageSpeed
- MSGSPEED_MIN
);
185 w
= (1 << 16) + ((w
<<16) / MSGSPEED_MAX
);
186 w
= (w
* 3 * g_nMessageSpeed
) >> 16;
188 RevealMatrixMessage(msg
, w
+ 100);
192 // draw whatever part of the message is visible at this time
194 DrawMatrixMessage(matrix
, msg
, hdc
);
199 // Set current font used for messages
201 void SetMessageFont(HWND hwnd
, TCHAR
*szFontName
, int nPointSize
, BOOL fBold
)
209 lfHeight
= -MulDiv(nPointSize
, GetDeviceCaps(hdc
, LOGPIXELSY
), 72);
211 ReleaseDC(hwnd
, hdc
);
213 hFont
= CreateFont(lfHeight
, 0, 0, 0, fBold
? FW_BOLD
: FW_NORMAL
, 0, 0, 0,
214 ANSI_CHARSET
, OUT_DEFAULT_PRECIS
, CLIP_DEFAULT_PRECIS
,
215 ANTIALIASED_QUALITY
, DEFAULT_PITCH
, szFontName
);
220 DeleteObject(g_hFont
);
229 MATRIX_MESSAGE
*InitMatrixMessage(HWND hwnd
, int width
, int height
)
233 if((msg
= malloc(sizeof(MATRIX_MESSAGE
))) == 0)
236 ClearMatrixMessage(msg
);
239 msg
->width
= min(width
, MAXMSG_WIDTH
);
240 msg
->height
= min(height
, MAXMSG_HEIGHT
);
241 msg
->counter
= -(int)(crc_rand() % MSGSPEED_MIN
+ MSGSPEED_MIN
);
243 msg
->random_reg1
= (WORD
)GetTickCount();
245 SetMessageFont(hwnd
, g_szFontName
, g_nFontSize
, g_fFontBold
);
247 SetMatrixMessage(msg
, 0, g_szMessages
[0]);