Initial commit of Command & Conquer Red Alert source code.

This commit is contained in:
LFeenanEA
2025-02-27 16:15:05 +00:00
parent b685cea758
commit 5e733d5dcc
2082 changed files with 797727 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,490 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
* *
* Project Name : Westwood Keyboard Library *
* *
* File Name : KEYBOARD.CPP *
* *
* Programmer : Philip W. Gorrow *
* *
* Start Date : 10/16/95 *
* *
* Last Update : October 26, 1995 [] *
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* WWKeyboardClass::Put -- Logic to insert a key into the keybuffer] *
* WWKeyboardClass::Get -- Logic to get a metakey from the buffer *
* WWKeyboardClass::Check -- Checks to see if a key is in the buffer *
* WWKeyboardClass::Put_Key_Message -- Translates and inserts wParam into Keyboard Buffer *
* WWKeyboardClass::Buff_Get -- Lowlevel function to get a key from key buffer *
* WWKeyboardClass::Get_Mouse_X -- Returns the mouses current x position in pixels *
* WWKeyboardClass::Get_Mouse_Y -- returns the mouses current y position in pixels *
* WWKeyboardClass::Get_Mouse_XY -- Returns the mouses x,y position via reference vars *
* Check_Key -- compatability routine for old 32 bit library *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "keyboard.h"
void Message_Loop(void);
WWKeyboardClass *_Kbd;
/***********************************************************************************************
* WWKeyboardClass::WWKeyBoardClass -- Construction for Westwood Keyboard Class *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* HISTORY: *
* 10/16/1995 PWG : Created. *
*=============================================================================================*/
WWKeyboardClass::WWKeyboardClass(void)
{
_Kbd = this;
//
// Initialize the keyboard remap table for our system (note it would be bad if someone
// switched keyboard modes after this happened.
//
memset(VKRemap, 0, 256);
memset(AsciiRemap, 0, 2048);
for (short lp = 31; lp < 255; lp ++) {
!----- Conflict 1 - Base File: C:\TEMP\KEYBOARD.CPP( *** PARENT *** )
!----- File 1: D:\WIN32LIB\KEYBOARD\KEYBOARD.CPP( *** Primary *** )
int vk_key = VkKeyScan((unsigned char)lp);
!----- File 2: I:\WIN32LIB\KEYBOARD\KEYBOARD.CPP( *** Secondary *** )
int vk_key = (int)VkKeyScan((TCHAR)lp);
!----- End Conflict
if (vk_key > 0 && vk_key < 2048) {
AsciiRemap[vk_key] = (unsigned char)lp;
VKRemap[lp] = (unsigned char)(vk_key & 0xFF);
}
}
//
// Build a remap table of the different keys which are affected by the caps lock and
// the num lock.
//
memset(ToggleKeys, 0, 256);
for (lp = 0; lp < 255; lp++ ) {
if (isalpha(lp) && isupper(lp)) {
ToggleKeys[lp] = 1;
}
if (lp >= VK_NUMPAD0 && lp <= VK_DIVIDE) {
ToggleKeys[lp] = 2;
}
}
//
// Our buffer should start devoid of keys.
//
memset(Buffer, 0, 256);
Head = 0;
Tail = 0;
//
// There should be no starting queued mouse events for us to have to worry
// about.
//
MouseQX = 0;
MouseQY = 0;
MState = 0;
Conditional = 0;
CurrentCursor = NULL;
}
/***********************************************************************************************
* WWKeyboardClass::Buff_Get -- Lowlevel function to get a key from key buffer *
* *
* INPUT: none *
* *
* OUTPUT: int - the key value that was pulled from buffer (includes bits) * *
* *
* WARNINGS: If the key was a mouse event MouseQX and MouseQY will be updated *
* *
* HISTORY: *
* 10/17/1995 PWG : Created. *
*=============================================================================================*/
int WWKeyboardClass::Buff_Get(void)
{
while (!Check()) {} // wait for key in buffer
int temp = Buffer[Head]; // get key out of the buffer
int newhead = Head; // save off head for manipulation
if (Is_Mouse_Key(temp)) { // if key is a mouse then
MouseQX = Buffer[Head+1]; // get the x and y pos
MouseQY = Buffer[Head+2]; // from the buffer
newhead += 3; // adjust head forward
} else {
newhead += 1; // adjust head forward
}
newhead &= 255;
Head = newhead;
return(temp);
}
BOOL WWKeyboardClass::Is_Mouse_Key(int key)
{
key &= 0xFF;
return (key == VK_LBUTTON || key == VK_MBUTTON || key == VK_RBUTTON);
}
/***********************************************************************************************
* WWKeyboardClass::Check -- Checks to see if a key is in the buffer *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/16/1995 PWG : Created. *
*=============================================================================================*/
BOOL WWKeyboardClass::Check(void)
{
Message_Loop();
unsigned short temp; // store temp holding spot for key
if (Head == Tail) return(FALSE); // if no keys in buff then get out
temp = Buffer[Head]; // get key out of the buffer
return(temp); // send it back to main program
}
/***********************************************************************************************
* WWKeyboardClass::Get -- Logic to get a metakey from the buffer *
* *
* INPUT: none *
* *
* OUTPUT: int - the meta key taken from the buffer. *
* *
* WARNINGS: This routine will not return until a keypress is received *
* *
* HISTORY: *
* 10/16/1995 PWG : Created. *
*=============================================================================================*/
int WWKeyboardClass::Get(void)
{
int temp,bits; // store temp holding spot for key
while (!Check()) {} // wait for key in buffer
temp = Buff_Get(); // get key from the buffer
bits = temp & 0xFF00; // save of keyboard bits
if (!(bits & WWKEY_VK_BIT)) { // if its not a virtual key
temp = AsciiRemap[temp&0x1FF] | bits; // convert to ascii equivalent
}
return(temp); // return the key that we pulled out
}
/***********************************************************************************************
* WWKeyboardClass::Put -- Logic to insert a key into the keybuffer] *
* *
* INPUT: int - the key to insert into the buffer *
* *
* OUTPUT: bool - true if key is sucessfuly inserted. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 10/16/1995 PWG : Created. *
*=============================================================================================*/
BOOL WWKeyboardClass::Put(int key)
{
int temp = (Tail + 1) & 255;
if (temp != Head)
{
Buffer[Tail] = (short)key;
//
// Critical Line
//
Tail = temp;
return(TRUE);
}
return(FALSE);
}
/***********************************************************************************************
* WWKeyboardClass::Put_Key_Message -- Translates and inserts wParam into Keyboard Buffer *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/16/1995 PWG : Created. *
*=============================================================================================*/
WWKeyboardClass::Put_Key_Message(UINT vk_key, BOOL release, BOOL dbl)
{
int bits = 0;
//
// Get the status of all of the different keyboard modifiers. Note, only pay attention
// to numlock and caps lock if we are dealing with a key that is affected by them.
//
int shift = (GetKeyState(VK_SHIFT) & 0xFF00) != 0;
int ctrl = (GetKeyState(VK_CONTROL) & 0xFF00) != 0;
int alt = (GetKeyState(VK_MENU) & 0xFF00) != 0;
int caps = ((GetKeyState(VK_CAPITAL) & 0x00FF) != 0) && (ToggleKeys[vk_key] == 1);
int nums = ((GetKeyState(VK_NUMLOCK) & 0x00FF) != 0) && (ToggleKeys[vk_key] == 2);
//
// Set the proper bits for whatever the key we got is.
//
if (shift || caps || nums) {
bits |= WWKEY_SHIFT_BIT;
}
if (ctrl) {
bits |= WWKEY_CTRL_BIT;
}
if (alt) {
bits |= WWKEY_ALT_BIT;
}
if (!AsciiRemap[vk_key|bits]) {
bits |= WWKEY_VK_BIT;
}
if (release) {
bits |= WWKEY_RLS_BIT;
}
if (dbl) {
bits |= WWKEY_DBL_BIT;
}
//
// Finally use the put command to enter the key into the keyboard
// system.
//
return(Put(vk_key|bits));
}
void WWKeyboardClass::Clear(void)
{
Head = Tail;
}
int WWKeyboardClass::To_ASCII(int key)
{
return(key);
}
WWKeyboardClass::Down(int key)
{
return(GetAsyncKeyState(key&0xFF));
}
VOID WWKeyboardClass::Split(int &key, int &shift, int &ctrl, int &alt, int &rls, int &dbl)
{
shift = (key & WWKEY_SHIFT_BIT) != 0;
ctrl = (key & WWKEY_CTRL_BIT) != 0;
alt = (key & WWKEY_ALT_BIT) != 0;
rls = (key & WWKEY_RLS_BIT) != 0;
dbl = (key & WWKEY_DBL_BIT) != 0;
key = (key & 0xFF);
}
extern "C" {
void __cdecl Stop_Execution (void);
}
#pragma off(unreferenced)
void WWKeyboardClass::Message_Handler(HWND , UINT message, UINT wParam, LONG lParam)
{
switch (message) {
case WM_SYSKEYDOWN:
case WM_KEYDOWN:
if ( wParam==VK_SCROLL ){
Stop_Execution();
} else {
Put_Key_Message(wParam);
}
break;
case WM_SYSKEYUP:
case WM_KEYUP:
Put_Key_Message(wParam, TRUE);
break;
case WM_LBUTTONDOWN:
Put_Key_Message(VK_LBUTTON);
Put(LOWORD(lParam));
Put(HIWORD(lParam));
break;
case WM_LBUTTONUP:
Put_Key_Message(VK_LBUTTON, TRUE);
Put(LOWORD(lParam));
Put(HIWORD(lParam));
break;
case WM_LBUTTONDBLCLK:
Put_Key_Message(VK_LBUTTON, TRUE, TRUE);
Put(LOWORD(lParam));
Put(HIWORD(lParam));
break;
case WM_MBUTTONDOWN:
Put_Key_Message(VK_MBUTTON);
Put(LOWORD(lParam));
Put(HIWORD(lParam));
break;
case WM_MBUTTONUP:
Put_Key_Message(VK_MBUTTON, TRUE);
Put(LOWORD(lParam));
Put(HIWORD(lParam));
break;
case WM_MBUTTONDBLCLK:
Put_Key_Message(VK_MBUTTON, TRUE, TRUE);
Put(LOWORD(lParam));
Put(HIWORD(lParam));
break;
case WM_RBUTTONDOWN:
Put_Key_Message(VK_RBUTTON);
Put(LOWORD(lParam));
Put(HIWORD(lParam));
break;
case WM_RBUTTONUP:
Put_Key_Message(VK_RBUTTON, TRUE);
Put(LOWORD(lParam));
Put(HIWORD(lParam));
break;
case WM_RBUTTONDBLCLK:
Put_Key_Message(VK_RBUTTON, TRUE, TRUE);
Put(LOWORD(lParam));
Put(HIWORD(lParam));
break;
case WM_MOUSEMOVE:
if (CurrentCursor)
SetCursor(CurrentCursor);
break;
}
}
#pragma on(unreferenced)
extern BOOL GameInFocus;
void Message_Loop(void)
{
MSG msg;
do {
while (PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE )) {
if( !GetMessage( &msg, NULL, 0, 0 ) ){
return;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
} while (!GameInFocus);
}
/***************************************************************************
* CHECK_KEY -- compatability routine for old 32 bit library *
* *
* This routine checks to see if there is a key in the keyboard buffer *
* and returns it to the sender if there is. It does not remove the key *
* from the buffer. *
* *
* INPUT: none *
* *
* OUTPUT: The key that was pressed. *
* *
* WARNINGS: You must declare a WWKeyboardClass object before calling *
* this routine. *
* *
* HISTORY: *
* 10/26/1995 : Created. *
*=========================================================================*/
int Check_Key(void)
{
if (!_Kbd) return(KA_NONE);
return(_Kbd->Check() & ~WWKEY_SHIFT_BIT);
}
void Clear_KeyBuffer(void)
{
if (!_Kbd) return;
_Kbd->Clear();
}
int Check_Key_Num(void)
{
if (!_Kbd) return(KN_NONE);
int key = _Kbd->Check();
int flags = key & 0xFF00;
key = key & 0x00FF;
if (isupper(key)) {
key = tolower(key);
flags |= WWKEY_SHIFT_BIT;
}
return(key | flags);
}
int Get_Key_Num(void)
{
if (!_Kbd) return(KN_NONE);
int key = _Kbd->Get();
int flags = key & 0xFF00;
key = key & 0x00FF;
if (isupper(key)) {
key = tolower(key);
flags |= WWKEY_SHIFT_BIT;
}
return(key | flags);
}
int KN_To_KA(int key)
{
if (!(key & WWKEY_VK_BIT)) {
int flags = key & 0xFF00;
key = key & 0x00FF;
if (flags & WWKEY_SHIFT_BIT) {
key = toupper(key);
flags &= ~WWKEY_SHIFT_BIT;
}
}
return(key);
}
int Key_Down(int key)
{
if (!_Kbd) return(FALSE);
return(_Kbd->Down(key));
}
int Get_Key(void)
{
if (!_Kbd) return(KN_NONE);
return(_Kbd->Get() & ~WWKEY_SHIFT_BIT);
}

View File

@@ -0,0 +1,485 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
* *
* Project Name : Westwood Keyboard Library *
* *
* File Name : KEYBOARD.CPP *
* *
* Programmer : Philip W. Gorrow *
* *
* Start Date : 10/16/95 *
* *
* Last Update : October 26, 1995 [] *
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* WWKeyboardClass::Put -- Logic to insert a key into the keybuffer] *
* WWKeyboardClass::Get -- Logic to get a metakey from the buffer *
* WWKeyboardClass::Check -- Checks to see if a key is in the buffer *
* WWKeyboardClass::Put_Key_Message -- Translates and inserts wParam into Keyboard Buffer *
* WWKeyboardClass::Buff_Get -- Lowlevel function to get a key from key buffer *
* WWKeyboardClass::Get_Mouse_X -- Returns the mouses current x position in pixels *
* WWKeyboardClass::Get_Mouse_Y -- returns the mouses current y position in pixels *
* WWKeyboardClass::Get_Mouse_XY -- Returns the mouses x,y position via reference vars *
* Check_Key -- compatability routine for old 32 bit library *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "keyboard.h"
void Message_Loop(void);
WWKeyboardClass *_Kbd;
/***********************************************************************************************
* WWKeyboardClass::WWKeyBoardClass -- Construction for Westwood Keyboard Class *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
* HISTORY: *
* 10/16/1995 PWG : Created. *
*=============================================================================================*/
WWKeyboardClass::WWKeyboardClass(void)
{
_Kbd = this;
//
// Initialize the keyboard remap table for our system (note it would be bad if someone
// switched keyboard modes after this happened.
//
memset(VKRemap, 0, 256);
memset(AsciiRemap, 0, 2048);
for (short lp = 31; lp < 255; lp ++) {
int vk_key = VkKeyScan((unsigned char)lp);
if (vk_key > 0 && vk_key < 2048) {
AsciiRemap[vk_key] = (unsigned char)lp;
VKRemap[lp] = (unsigned char)(vk_key & 0xFF);
}
}
//
// Build a remap table of the different keys which are affected by the caps lock and
// the num lock.
//
memset(ToggleKeys, 0, 256);
for (lp = 0; lp < 255; lp++ ) {
if (isalpha(lp) && isupper(lp)) {
ToggleKeys[lp] = 1;
}
if (lp >= VK_NUMPAD0 && lp <= VK_DIVIDE) {
ToggleKeys[lp] = 2;
}
}
//
// Our buffer should start devoid of keys.
//
memset(Buffer, 0, 256);
Head = 0;
Tail = 0;
//
// There should be no starting queued mouse events for us to have to worry
// about.
//
MouseQX = 0;
MouseQY = 0;
MState = 0;
Conditional = 0;
CurrentCursor = NULL;
}
/***********************************************************************************************
* WWKeyboardClass::Buff_Get -- Lowlevel function to get a key from key buffer *
* *
* INPUT: none *
* *
* OUTPUT: int - the key value that was pulled from buffer (includes bits) * *
* *
* WARNINGS: If the key was a mouse event MouseQX and MouseQY will be updated *
* *
* HISTORY: *
* 10/17/1995 PWG : Created. *
*=============================================================================================*/
int WWKeyboardClass::Buff_Get(void)
{
while (!Check()) {} // wait for key in buffer
int temp = Buffer[Head]; // get key out of the buffer
int newhead = Head; // save off head for manipulation
if (Is_Mouse_Key(temp)) { // if key is a mouse then
MouseQX = Buffer[Head+1]; // get the x and y pos
MouseQY = Buffer[Head+2]; // from the buffer
newhead += 3; // adjust head forward
} else {
newhead += 1; // adjust head forward
}
newhead &= 255;
Head = newhead;
return(temp);
}
BOOL WWKeyboardClass::Is_Mouse_Key(int key)
{
key &= 0xFF;
return (key == VK_LBUTTON || key == VK_MBUTTON || key == VK_RBUTTON);
}
/***********************************************************************************************
* WWKeyboardClass::Check -- Checks to see if a key is in the buffer *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/16/1995 PWG : Created. *
*=============================================================================================*/
BOOL WWKeyboardClass::Check(void)
{
Message_Loop();
unsigned short temp; // store temp holding spot for key
if (Head == Tail) return(FALSE); // if no keys in buff then get out
temp = Buffer[Head]; // get key out of the buffer
return(temp); // send it back to main program
}
/***********************************************************************************************
* WWKeyboardClass::Get -- Logic to get a metakey from the buffer *
* *
* INPUT: none *
* *
* OUTPUT: int - the meta key taken from the buffer. *
* *
* WARNINGS: This routine will not return until a keypress is received *
* *
* HISTORY: *
* 10/16/1995 PWG : Created. *
*=============================================================================================*/
int WWKeyboardClass::Get(void)
{
int temp,bits; // store temp holding spot for key
while (!Check()) {} // wait for key in buffer
temp = Buff_Get(); // get key from the buffer
bits = temp & 0xFF00; // save of keyboard bits
if (!(bits & WWKEY_VK_BIT)) { // if its not a virtual key
temp = AsciiRemap[temp&0x1FF] | bits; // convert to ascii equivalent
}
return(temp); // return the key that we pulled out
}
/***********************************************************************************************
* WWKeyboardClass::Put -- Logic to insert a key into the keybuffer] *
* *
* INPUT: int - the key to insert into the buffer *
* *
* OUTPUT: bool - true if key is sucessfuly inserted. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 10/16/1995 PWG : Created. *
*=============================================================================================*/
BOOL WWKeyboardClass::Put(int key)
{
int temp = (Tail + 1) & 255;
if (temp != Head)
{
Buffer[Tail] = (short)key;
//
// Critical Line
//
Tail = temp;
return(TRUE);
}
return(FALSE);
}
/***********************************************************************************************
* WWKeyboardClass::Put_Key_Message -- Translates and inserts wParam into Keyboard Buffer *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 10/16/1995 PWG : Created. *
*=============================================================================================*/
WWKeyboardClass::Put_Key_Message(UINT vk_key, BOOL release, BOOL dbl)
{
int bits = 0;
//
// Get the status of all of the different keyboard modifiers. Note, only pay attention
// to numlock and caps lock if we are dealing with a key that is affected by them.
//
int shift = (GetKeyState(VK_SHIFT) & 0xFF00) != 0;
int ctrl = (GetKeyState(VK_CONTROL) & 0xFF00) != 0;
int alt = (GetKeyState(VK_MENU) & 0xFF00) != 0;
int caps = ((GetKeyState(VK_CAPITAL) & 0x00FF) != 0) && (ToggleKeys[vk_key] == 1);
int nums = ((GetKeyState(VK_NUMLOCK) & 0x00FF) != 0) && (ToggleKeys[vk_key] == 2);
//
// Set the proper bits for whatever the key we got is.
//
if (shift || caps || nums) {
bits |= WWKEY_SHIFT_BIT;
}
if (ctrl) {
bits |= WWKEY_CTRL_BIT;
}
if (alt) {
bits |= WWKEY_ALT_BIT;
}
if (!AsciiRemap[vk_key|bits]) {
bits |= WWKEY_VK_BIT;
}
if (release) {
bits |= WWKEY_RLS_BIT;
}
if (dbl) {
bits |= WWKEY_DBL_BIT;
}
//
// Finally use the put command to enter the key into the keyboard
// system.
//
return(Put(vk_key|bits));
}
void WWKeyboardClass::Clear(void)
{
Head = Tail;
}
int WWKeyboardClass::To_ASCII(int key)
{
return(key);
}
WWKeyboardClass::Down(int key)
{
return(GetAsyncKeyState(key&0xFF));
}
VOID WWKeyboardClass::Split(int &key, int &shift, int &ctrl, int &alt, int &rls, int &dbl)
{
shift = (key & WWKEY_SHIFT_BIT) != 0;
ctrl = (key & WWKEY_CTRL_BIT) != 0;
alt = (key & WWKEY_ALT_BIT) != 0;
rls = (key & WWKEY_RLS_BIT) != 0;
dbl = (key & WWKEY_DBL_BIT) != 0;
key = (key & 0xFF);
}
extern "C" {
void __cdecl Stop_Execution (void);
}
#pragma off(unreferenced)
void WWKeyboardClass::Message_Handler(HWND , UINT message, UINT wParam, LONG lParam)
{
switch (message) {
case WM_SYSKEYDOWN:
case WM_KEYDOWN:
if ( wParam==VK_SCROLL ){
Stop_Execution();
} else {
Put_Key_Message(wParam);
}
break;
case WM_SYSKEYUP:
case WM_KEYUP:
Put_Key_Message(wParam, TRUE);
break;
case WM_LBUTTONDOWN:
Put_Key_Message(VK_LBUTTON);
Put(LOWORD(lParam));
Put(HIWORD(lParam));
break;
case WM_LBUTTONUP:
Put_Key_Message(VK_LBUTTON, TRUE);
Put(LOWORD(lParam));
Put(HIWORD(lParam));
break;
case WM_LBUTTONDBLCLK:
Put_Key_Message(VK_LBUTTON, TRUE, TRUE);
Put(LOWORD(lParam));
Put(HIWORD(lParam));
break;
case WM_MBUTTONDOWN:
Put_Key_Message(VK_MBUTTON);
Put(LOWORD(lParam));
Put(HIWORD(lParam));
break;
case WM_MBUTTONUP:
Put_Key_Message(VK_MBUTTON, TRUE);
Put(LOWORD(lParam));
Put(HIWORD(lParam));
break;
case WM_MBUTTONDBLCLK:
Put_Key_Message(VK_MBUTTON, TRUE, TRUE);
Put(LOWORD(lParam));
Put(HIWORD(lParam));
break;
case WM_RBUTTONDOWN:
Put_Key_Message(VK_RBUTTON);
Put(LOWORD(lParam));
Put(HIWORD(lParam));
break;
case WM_RBUTTONUP:
Put_Key_Message(VK_RBUTTON, TRUE);
Put(LOWORD(lParam));
Put(HIWORD(lParam));
break;
case WM_RBUTTONDBLCLK:
Put_Key_Message(VK_RBUTTON, TRUE, TRUE);
Put(LOWORD(lParam));
Put(HIWORD(lParam));
break;
case WM_MOUSEMOVE:
if (CurrentCursor)
SetCursor(CurrentCursor);
break;
}
}
#pragma on(unreferenced)
extern BOOL GameInFocus;
void Message_Loop(void)
{
MSG msg;
do {
while (PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE )) {
if( !GetMessage( &msg, NULL, 0, 0 ) ){
return;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
} while (!GameInFocus);
}
/***************************************************************************
* CHECK_KEY -- compatability routine for old 32 bit library *
* *
* This routine checks to see if there is a key in the keyboard buffer *
* and returns it to the sender if there is. It does not remove the key *
* from the buffer. *
* *
* INPUT: none *
* *
* OUTPUT: The key that was pressed. *
* *
* WARNINGS: You must declare a WWKeyboardClass object before calling *
* this routine. *
* *
* HISTORY: *
* 10/26/1995 : Created. *
*=========================================================================*/
int Check_Key(void)
{
if (!_Kbd) return(KA_NONE);
return(_Kbd->Check() & ~WWKEY_SHIFT_BIT);
}
void Clear_KeyBuffer(void)
{
if (!_Kbd) return;
_Kbd->Clear();
}
int Check_Key_Num(void)
{
if (!_Kbd) return(KN_NONE);
int key = _Kbd->Check();
int flags = key & 0xFF00;
key = key & 0x00FF;
if (isupper(key)) {
key = tolower(key);
flags |= WWKEY_SHIFT_BIT;
}
return(key | flags);
}
int Get_Key_Num(void)
{
if (!_Kbd) return(KN_NONE);
int key = _Kbd->Get();
int flags = key & 0xFF00;
key = key & 0x00FF;
if (isupper(key)) {
key = tolower(key);
flags |= WWKEY_SHIFT_BIT;
}
return(key | flags);
}
int KN_To_KA(int key)
{
if (!(key & WWKEY_VK_BIT)) {
int flags = key & 0xFF00;
key = key & 0x00FF;
if (flags & WWKEY_SHIFT_BIT) {
key = toupper(key);
flags &= ~WWKEY_SHIFT_BIT;
}
}
return(key);
}
int Key_Down(int key)
{
if (!_Kbd) return(FALSE);
return(_Kbd->Down(key));
}
int Get_Key(void)
{
if (!_Kbd) return(KN_NONE);
return(_Kbd->Get() & ~WWKEY_SHIFT_BIT);
}

View File

@@ -0,0 +1,671 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
* *
* Project Name : Westwood Keyboard Library *
* *
* File Name : KEYBOARD.H *
* *
* Programmer : Philip W. Gorrow *
* *
* Start Date : 10/16/95 *
* *
* Last Update : October 16, 1995 [PWG] *
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include <WWSTD.H>
typedef enum {
WWKEY_SHIFT_BIT = 0x100,
WWKEY_CTRL_BIT = 0x200,
WWKEY_ALT_BIT = 0x400,
WWKEY_RLS_BIT = 0x800,
WWKEY_VK_BIT = 0x1000,
WWKEY_DBL_BIT = 0x2000,
WWKEY_BTN_BIT = 0x8000,
} WWKey_Type;
class WWKeyboardClass
{
public:
/*===================================================================*/
/* Define the base constructor and destructors for the class */
/*===================================================================*/
WWKeyboardClass();
/*===================================================================*/
/* Define the functions which work with the Keyboard Class */
/*===================================================================*/
BOOL Check(void); // checks keybuff for meta key
int Get(void); // gets a meta key from the keybuffer
BOOL Put(int key); // dumps a key into the keybuffer
BOOL Put_Key_Message( UINT vk_key, BOOL release = FALSE, // handles keyboard related message
BOOL dbl = FALSE); // and mouse clicks and dbl clicks
int Check_Num(void); // checks keybuff for a keynum key
int Get_VK(void); // gets keynum key from key buff
int Check_ACII(void); // checks keybuff for an ascii key
int Get_ASCII(void); // gets an ascii key from keybuff
int Check_Bits(void); // checks keybuff for key w/ bits
int Get_Bits(void); // get key from keybuff w/ bits
int To_ASCII(int num); // converts keynum to ascii value
int Option_On(int option); // turns specified option on
int Option_Off(int option); // turns specified option off
void Clear(void); // clears all keys from keybuffer
int Down(int key); // tests to see if a key is down
void AI(void); // messaging logic for key manager
/*===================================================================*/
/* Define the main hook for the message processing loop. */
/*===================================================================*/
void Message_Handler(HWND hwnd, UINT message, UINT wParam, LONG lParam);
/*===================================================================*/
/* Define public routines which can be used on keys in general. */
/*===================================================================*/
VOID Split(int &key, int &shift, int &ctrl, int &alt, int &rls, int &dbl);
BOOL Is_Mouse_Key(int key);
/*===================================================================*/
/* Define the public access variables which are used with the */
/* Keyboard Class. */
/*===================================================================*/
int MouseQX;
int MouseQY;
private:
/*===================================================================*/
/* Define the private access functions which are used by keyboard */
/*===================================================================*/
int Buff_Get(void);
/*===================================================================*/
/* Define the private access variables which are used with the */
/* Keyboard Class. */
/*===================================================================*/
unsigned char AsciiRemap[2048]; // remap for shft/ctrl/alt key combos
unsigned char VKRemap[256]; // gives vk for any ascii char
unsigned short Buffer[256]; // buffer which holds actual keypresses
unsigned char ToggleKeys[256]; // determines toggles which affect key
long Head; // the head position in keyboard buffer
long Tail; // the tail position in keyboard buffer
int MState;
int Conditional;
HANDLE CurrentCursor;
};
#define VK_NONE 0x00
#define VK_LBUTTON 0x01
#define VK_RBUTTON 0x02
#define VK_CANCEL 0x03
#define VK_MBUTTON 0x04
#define VK_NONE_05 0x05
#define VK_NONE_06 0x06
#define VK_NONE_07 0x07
#define VK_BACK 0x08
#define VK_TAB 0x09
#define VK_NONE_0A 0x0A
#define VK_NONE_0B 0x0B
#define VK_CLEAR 0x0C
#define VK_RETURN 0x0D
#define VK_NONE_0E 0x0E
#define VK_NONE_0F 0x0F
#define VK_SHIFT 0x10
#define VK_CONTROL 0x11
#define VK_MENU 0x12
#define VK_PAUSE 0x13
#define VK_CAPITAL 0x14
#define VK_NONE_15 0x15
#define VK_NONE_16 0x16
#define VK_NONE_17 0x17
#define VK_NONE_18 0x18
#define VK_NONE_19 0x19
#define VK_NONE_1A 0x1A
#define VK_ESCAPE 0x1B
#define VK_NONE_1C 0x1C
#define VK_NONE_1D 0x1D
#define VK_NONE_1E 0x1E
#define VK_NONE_1F 0x1F
#define VK_SPACE 0x20
#define VK_PRIOR 0x21
#define VK_NEXT 0x22
#define VK_END 0x23
#define VK_HOME 0x24
#define VK_LEFT 0x25
#define VK_UP 0x26
#define VK_RIGHT 0x27
#define VK_DOWN 0x28
#define VK_SELECT 0x29
#define VK_PRINT 0x2A
#define VK_EXECUTE 0x2B
#define VK_SNAPSHOT 0x2C
#define VK_INSERT 0x2D
#define VK_DELETE 0x2E
#define VK_HELP 0x2F
#define VK_0 0x30
#define VK_1 0x31
#define VK_2 0x32
#define VK_3 0x33
#define VK_4 0x34
#define VK_5 0x35
#define VK_6 0x36
#define VK_7 0x37
#define VK_8 0x38
#define VK_9 0x39
#define VK_NONE_3B 0x3B
#define VK_NONE_3C 0x3C
#define VK_NONE_3D 0x3D
#define VK_NONE_3E 0x3E
#define VK_NONE_3F 0x3F
#define VK_NONE_40 0x40
#define VK_A 0x41
#define VK_B 0x42
#define VK_C 0x43
#define VK_D 0x44
#define VK_E 0x45
#define VK_F 0x46
#define VK_G 0x47
#define VK_H 0x48
#define VK_I 0x49
#define VK_J 0x4A
#define VK_K 0x4B
#define VK_L 0x4C
#define VK_M 0x4D
#define VK_N 0x4E
#define VK_O 0x4F
#define VK_P 0x50
#define VK_Q 0x51
#define VK_R 0x52
#define VK_S 0x53
#define VK_T 0x54
#define VK_U 0x55
#define VK_V 0x56
#define VK_W 0x57
#define VK_X 0x58
#define VK_Y 0x59
#define VK_Z 0x5A
#define VK_NONE_5B 0x5B
#define VK_NONE_5C 0x5C
#define VK_NONE_5D 0x5D
#define VK_NONE_5E 0x5E
#define VK_NONE_5F 0x5F
#define VK_NUMPAD0 0x60
#define VK_NUMPAD1 0x61
#define VK_NUMPAD2 0x62
#define VK_NUMPAD3 0x63
#define VK_NUMPAD4 0x64
#define VK_NUMPAD5 0x65
#define VK_NUMPAD6 0x66
#define VK_NUMPAD7 0x67
#define VK_NUMPAD8 0x68
#define VK_NUMPAD9 0x69
#define VK_MULTIPLY 0x6A
#define VK_ADD 0x6B
#define VK_SEPARATOR 0x6C
#define VK_SUBTRACT 0x6D
#define VK_DECIMAL 0x6E
#define VK_DIVIDE 0x6F
#define VK_F1 0x70
#define VK_F2 0x71
#define VK_F3 0x72
#define VK_F4 0x73
#define VK_F5 0x74
#define VK_F6 0x75
#define VK_F7 0x76
#define VK_F8 0x77
#define VK_F9 0x78
#define VK_F10 0x79
#define VK_F11 0x7A
#define VK_F12 0x7B
#define VK_F13 0x7C
#define VK_F14 0x7D
#define VK_F15 0x7E
#define VK_F16 0x7F
#define VK_F17 0x80
#define VK_F18 0x81
#define VK_F19 0x82
#define VK_F20 0x83
#define VK_F21 0x84
#define VK_F22 0x85
#define VK_F23 0x86
#define VK_F24 0x87
#define VK_NONE_88 0x88
#define VK_NONE_89 0x89
#define VK_NONE_8A 0x8A
#define VK_NONE_8B 0x8B
#define VK_NONE_8C 0x8C
#define VK_NONE_8D 0x8D
#define VK_NONE_8E 0x8E
#define VK_NONE_8F 0x8F
#define VK_NUMLOCK 0x90
#define VK_SCROLL 0x91
#define VK_NONE_92 0x92
#define VK_NONE_93 0x93
#define VK_NONE_94 0x94
#define VK_NONE_95 0x95
#define VK_NONE_96 0x96
#define VK_NONE_97 0x97
#define VK_NONE_98 0x98
#define VK_NONE_99 0x99
#define VK_NONE_9A 0x9A
#define VK_NONE_9B 0x9B
#define VK_NONE_9C 0x9C
#define VK_NONE_9D 0x9D
#define VK_NONE_9E 0x9E
#define VK_NONE_9F 0x9F
#define VK_NONE_A0 0xA0
#define VK_NONE_A1 0xA1
#define VK_NONE_A2 0xA2
#define VK_NONE_A3 0xA3
#define VK_NONE_A4 0xA4
#define VK_NONE_A5 0xA5
#define VK_NONE_A6 0xA6
#define VK_NONE_A7 0xA7
#define VK_NONE_A8 0xA8
#define VK_NONE_A9 0xA9
#define VK_NONE_AA 0xAA
#define VK_NONE_AB 0xAB
#define VK_NONE_AC 0xAC
#define VK_NONE_AD 0xAD
#define VK_NONE_AE 0xAE
#define VK_NONE_AF 0xAF
#define VK_NONE_B0 0xB0
#define VK_NONE_B1 0xB1
#define VK_NONE_B2 0xB2
#define VK_NONE_B3 0xB3
#define VK_NONE_B4 0xB4
#define VK_NONE_B5 0xB5
#define VK_NONE_B6 0xB6
#define VK_NONE_B7 0xB7
#define VK_NONE_B8 0xB8
#define VK_NONE_B9 0xB9
#define VK_NONE_BA 0xBA
#define VK_NONE_BB 0xBB
#define VK_NONE_BC 0xBC
#define VK_NONE_BD 0xBD
#define VK_NONE_BE 0xBE
#define VK_NONE_BF 0xBF
#define VK_NONE_C0 0xC0
#define VK_NONE_C1 0xC1
#define VK_NONE_C2 0xC2
#define VK_NONE_C3 0xC3
#define VK_NONE_C4 0xC4
#define VK_NONE_C5 0xC5
#define VK_NONE_C6 0xC6
#define VK_NONE_C7 0xC7
#define VK_NONE_C8 0xC8
#define VK_NONE_C9 0xC9
#define VK_NONE_CA 0xCA
#define VK_NONE_CB 0xCB
#define VK_NONE_CC 0xCC
#define VK_NONE_CD 0xCD
#define VK_NONE_CE 0xCE
#define VK_NONE_CF 0xCF
#define VK_NONE_D0 0xD0
#define VK_NONE_D1 0xD1
#define VK_NONE_D2 0xD2
#define VK_NONE_D3 0xD3
#define VK_NONE_D4 0xD4
#define VK_NONE_D5 0xD5
#define VK_NONE_D6 0xD6
#define VK_NONE_D7 0xD7
#define VK_NONE_D8 0xD8
#define VK_NONE_D9 0xD9
#define VK_NONE_DA 0xDA
#define VK_NONE_DB 0xDB
#define VK_NONE_DC 0xDC
#define VK_NONE_DD 0xDD
#define VK_NONE_DE 0xDE
#define VK_NONE_DF 0xDF
#define VK_NONE_E0 0xE0
#define VK_NONE_E1 0xE1
#define VK_NONE_E2 0xE2
#define VK_NONE_E3 0xE3
#define VK_NONE_E4 0xE4
#define VK_NONE_E5 0xE5
#define VK_NONE_E6 0xE6
#define VK_NONE_E7 0xE7
#define VK_NONE_E8 0xE8
#define VK_NONE_E9 0xE9
#define VK_NONE_EA 0xEA
#define VK_NONE_EB 0xEB
#define VK_NONE_EC 0xEC
#define VK_NONE_ED 0xED
#define VK_NONE_EE 0xEE
#define VK_NONE_EF 0xEF
#define VK_NONE_F0 0xF0
#define VK_NONE_F1 0xF1
#define VK_NONE_F2 0xF2
#define VK_NONE_F3 0xF3
#define VK_NONE_F4 0xF4
#define VK_NONE_F5 0xF5
#define VK_NONE_F6 0xF6
#define VK_NONE_F7 0xF7
#define VK_NONE_F8 0xF8
#define VK_NONE_F9 0xF9
#define VK_NONE_FA 0xFA
#define VK_NONE_FB 0xFB
#define VK_NONE_FC 0xFC
#define VK_NONE_FD 0xFD
#define VK_NONE_FE 0xFE
#define VK_NONE_FF 0xFF
#define VK_UPLEFT VK_HOME
#define VK_UPRIGHT VK_PRIOR
#define VK_DOWNLEFT VK_END
#define VK_DOWNRIGHT VK_NEXT
#define VK_ALT VK_MENU
enum {
//
// Define all the KA types as variations of the VK types. This is
// so the KA functions will work properly under windows 95.
//
KA_NONE = 0,
KA_MORE = 1,
KA_SETBKGDCOL = 2,
KA_SETFORECOL = 6,
KA_FORMFEED = 12,
KA_SPCTAB = 20,
KA_SETX = 25,
KA_SETY = 26,
KA_SPACE = 32, /* */
KA_EXCLAMATION, /* ! */
KA_DQUOTE, /* " */
KA_POUND, /* # */
KA_DOLLAR, /* $ */
KA_PERCENT, /* % */
KA_AMPER, /* & */
KA_SQUOTE, /* ' */
KA_LPAREN, /* ( */
KA_RPAREN, /* ) */
KA_ASTERISK, /* * */
KA_PLUS, /* + */
KA_COMMA, /* , */
KA_MINUS, /* - */
KA_PERIOD, /* . */
KA_SLASH, /* / */
KA_0, KA_1, KA_2, KA_3, KA_4, KA_5, KA_6, KA_7, KA_8, KA_9,
KA_COLON, /* : */
KA_SEMICOLON, /* ; */
KA_LESS_THAN, /* < */
KA_EQUAL, /* = */
KA_GREATER_THAN, /* > */
KA_QUESTION, /* ? */
KA_AT, /* @ */
KA_A, /* A */
KA_B, /* B */
KA_C, /* C */
KA_D, /* D */
KA_E, /* E */
KA_F, /* F */
KA_G, /* G */
KA_H, /* H */
KA_I, /* I */
KA_J, /* J */
KA_K, /* K */
KA_L, /* L */
KA_M, /* M */
KA_N, /* N */
KA_O, /* O */
KA_P, /* P */
KA_Q, /* Q */
KA_R, /* R */
KA_S, /* S */
KA_T, /* T */
KA_U, /* U */
KA_V, /* V */
KA_W, /* W */
KA_X, /* X */
KA_Y, /* Y */
KA_Z, /* Z */
KA_LBRACKET, /* [ */
KA_BACKSLASH, /* \ */
KA_RBRACKET, /* ] */
KA_CARROT, /* ^ */
KA_UNDERLINE, /* _ */
KA_GRAVE, /* ` */
KA_a, /* a */
KA_b, /* b */
KA_c, /* c */
KA_d, /* d */
KA_e, /* e */
KA_f, /* f */
KA_g, /* g */
KA_h, /* h */
KA_i, /* i */
KA_j, /* j */
KA_k, /* k */
KA_l, /* l */
KA_m, /* m */
KA_n, /* n */
KA_o, /* o */
KA_p, /* p */
KA_q, /* q */
KA_r, /* r */
KA_s, /* s */
KA_t, /* t */
KA_u, /* u */
KA_v, /* v */
KA_w, /* w */
KA_x, /* x */
KA_y, /* y */
KA_z, /* z */
KA_LBRACE, /* { */
KA_BAR, /* | */
KA_RBRACE, /* ] */
KA_TILDA, /* ~ */
KA_ESC = VK_ESCAPE | WWKEY_VK_BIT,
KA_EXTEND = VK_ESCAPE | WWKEY_VK_BIT,
KA_RETURN = VK_RETURN | WWKEY_VK_BIT,
KA_BACKSPACE = VK_BACK | WWKEY_VK_BIT,
KA_TAB = VK_TAB | WWKEY_VK_BIT,
KA_DELETE = VK_DELETE | WWKEY_VK_BIT, /* <DELETE> */
KA_INSERT = VK_INSERT | WWKEY_VK_BIT, /* <INSERT> */
KA_PGDN = VK_NEXT | WWKEY_VK_BIT, /* <PAGE DOWN> */
KA_DOWNRIGHT = VK_NEXT | WWKEY_VK_BIT,
KA_DOWN = VK_DOWN | WWKEY_VK_BIT, /* <DOWN ARROW> */
KA_END = VK_END | WWKEY_VK_BIT, /* <END> */
KA_DOWNLEFT = VK_END | WWKEY_VK_BIT,
KA_RIGHT = VK_RIGHT | WWKEY_VK_BIT, /* <RIGHT ARROW> */
KA_KEYPAD5 = VK_SELECT | WWKEY_VK_BIT, /* NUMERIC KEY PAD <5> */
KA_LEFT = VK_LEFT | WWKEY_VK_BIT, /* <LEFT ARROW> */
KA_PGUP = VK_PRIOR | WWKEY_VK_BIT, /* <PAGE UP> */
KA_UPRIGHT = VK_PRIOR | WWKEY_VK_BIT,
KA_UP = VK_UP | WWKEY_VK_BIT, /* <UP ARROW> */
KA_HOME = VK_HOME | WWKEY_VK_BIT, /* <HOME> */
KA_UPLEFT = VK_HOME | WWKEY_VK_BIT,
KA_F12 = VK_F12 | WWKEY_VK_BIT,
KA_F11 = VK_F11 | WWKEY_VK_BIT,
KA_F10 = VK_F10 | WWKEY_VK_BIT,
KA_F9 = VK_F9 | WWKEY_VK_BIT,
KA_F8 = VK_F8 | WWKEY_VK_BIT,
KA_F7 = VK_F7 | WWKEY_VK_BIT,
KA_F6 = VK_F6 | WWKEY_VK_BIT,
KA_F5 = VK_F5 | WWKEY_VK_BIT,
KA_F4 = VK_F4 | WWKEY_VK_BIT,
KA_F3 = VK_F3 | WWKEY_VK_BIT,
KA_F2 = VK_F2 | WWKEY_VK_BIT,
KA_F1 = VK_F1 | WWKEY_VK_BIT,
KA_LMOUSE = VK_LBUTTON | WWKEY_VK_BIT,
KA_RMOUSE = VK_RBUTTON | WWKEY_VK_BIT,
KA_SHIFT_BIT = WWKEY_SHIFT_BIT,
KA_CTRL_BIT = WWKEY_CTRL_BIT,
KA_ALT_BIT = WWKEY_ALT_BIT,
KA_RLSE_BIT = WWKEY_RLS_BIT,
//
// Define all the KN types as variations of the KA types. This is
// so the KN functions will work properly under windows 95.
//
KN_NONE = 0,
KN_GRAVE = KA_GRAVE,
KN_1 = KA_1,
KN_2 = KA_2,
KN_3 = KA_3,
KN_4 = KA_4,
KN_5 = KA_5,
KN_6 = KA_6,
KN_7 = KA_7,
KN_8 = KA_8,
KN_9 = KA_9,
KN_0 = KA_0,
KN_MINUS = KA_MINUS, /* - */
KN_EQUAL = KA_EQUAL, /* = */
KN_BACKSPACE = KA_BACKSPACE,
KN_TAB = KA_TAB, /* <TAB> */
KN_Q = KA_q,
KN_W = KA_w,
KN_E = KA_e,
KN_R = KA_r,
KN_T = KA_t,
KN_Y = KA_y,
KN_U = KA_u,
KN_I = KA_i,
KN_O = KA_o,
KN_P = KA_p,
KN_LBRACKET = KA_LBRACKET, /* [ */
KN_RBRACKET = KA_RBRACKET, /* ] */
KN_BACKSLASH = KA_BACKSLASH, /* \ */
KN_A = KA_a,
KN_S = KA_s,
KN_D = KA_d,
KN_F = KA_f,
KN_G = KA_g,
KN_H = KA_h,
KN_J = KA_j,
KN_K = KA_k,
KN_L = KA_l,
KN_SEMICOLON = KA_SEMICOLON, /* ; */
KN_SQUOTE = KA_SQUOTE, /* ' */
KN_BACKSLASH2 = KA_BACKSLASH,
KN_RETURN = KA_RETURN,
KN_Z = KA_z,
KN_X = KA_x,
KN_C = KA_c,
KN_V = KA_v,
KN_B = KA_b,
KN_N = KA_n,
KN_M = KA_m,
KN_COMMA = KA_COMMA, /* , */
KN_PERIOD = KA_PERIOD, /* . */
KN_SLASH = KA_SLASH, /* / */
KN_SPACE = KA_SPACE,
KN_LMOUSE = KA_LMOUSE,
KN_RMOUSE = KA_RMOUSE,
KN_HOME = KA_HOME, /* num key pad 7 */
KN_UPLEFT = KA_UPLEFT,
KN_LEFT = KA_LEFT, /* num key pad 4 */
KN_END = KA_END, /* num key pad 1 */
KN_DOWNLEFT = KA_DOWNLEFT,
KN_KEYPAD_SLASH = KA_SLASH, /* num key pad / */
KN_UP = KA_UP, /* num key pad 8 */
KN_CENTER = KA_KEYPAD5, /* num key pad 5 */
KN_DOWN = KA_DOWN, /* num key pad 2 */
KN_INSERT = KA_INSERT, /* num key pad 0 */
KN_KEYPAD_ASTERISK= KA_ASTERISK, /* num key pad * */
KN_PGUP = KA_PGUP, /* num key pad 9 */
KN_UPRIGHT = KA_UPRIGHT,
KN_RIGHT = KA_RIGHT, /* num key pad 6 */
KN_PGDN = KA_PGDN, /* num key pad 3 */
KN_DOWNRIGHT = KA_DOWNRIGHT,
KN_DELETE = KA_DELETE, /* num key pad . */
KN_KEYPAD_MINUS = KA_MINUS, /* num key pad - */
KN_KEYPAD_PLUS = KA_PLUS, /* num key pad + */
KN_KEYPAD_RETURN = KA_RETURN, /* num key pad <ENTER> */
KN_ESC = KA_ESC,
KN_F1 = KA_F1,
KN_F2 = KA_F2,
KN_F3 = KA_F3,
KN_F4 = KA_F4,
KN_F5 = KA_F5,
KN_F6 = KA_F6,
KN_F7 = KA_F7,
KN_F8 = KA_F8,
KN_F9 = KA_F9,
KN_F10 = KA_F10,
KN_F11 = KA_F11,
KN_F12 = KA_F12,
KN_PRNTSCRN = VK_PRINT | WWKEY_VK_BIT,
KN_CAPSLOCK = VK_CAPITAL | WWKEY_VK_BIT,
KN_SCROLLLOCK = VK_SCROLL | WWKEY_VK_BIT, /* <SCROLL LOCK> */
KN_PAUSE = VK_PAUSE | WWKEY_VK_BIT, /* <PAUSE> */
KN_LSHIFT = VK_SHIFT | WWKEY_VK_BIT,
KN_RSHIFT = VK_SHIFT | WWKEY_VK_BIT,
KN_LCTRL = VK_CONTROL | WWKEY_VK_BIT,
KN_RCTRL = VK_CONTROL | WWKEY_VK_BIT,
KN_LALT = VK_MENU | WWKEY_VK_BIT,
KN_RALT = VK_MENU | WWKEY_VK_BIT,
KN_E_INSERT = VK_INSERT | WWKEY_VK_BIT,
KN_E_DELETE = VK_DELETE | WWKEY_VK_BIT,
KN_E_LEFT = VK_LEFT | WWKEY_VK_BIT, /* extended <LEFT ARROW> */
KN_E_HOME = VK_HOME | WWKEY_VK_BIT, /* extended <HOME> */
KN_E_END = VK_END | WWKEY_VK_BIT, /* extended <END> */
KN_E_UP = VK_UP | WWKEY_VK_BIT, /* extended <UP ARROW> */
KN_E_DOWN = VK_DOWN | WWKEY_VK_BIT, /* extended <DOWN ARROW> */
KN_E_PGUP = VK_PRIOR | WWKEY_VK_BIT, /* extended <PAGE UP> */
KN_E_PGDN = VK_NEXT | WWKEY_VK_BIT, /* extended <PAGE DOWN> */
KN_E_RIGHT = VK_RIGHT | WWKEY_VK_BIT, /* extended <RIGHT ARROW> */
KN_NUMLOCK = VK_NUMLOCK | WWKEY_VK_BIT, /* <NUM LOCK> */
KN_SHIFT_BIT = WWKEY_SHIFT_BIT,
KN_CTRL_BIT = WWKEY_CTRL_BIT,
KN_ALT_BIT = WWKEY_ALT_BIT,
KN_RLSE_BIT = WWKEY_RLS_BIT,
KN_BUTTON = WWKEY_BTN_BIT,
};
extern WWKeyboardClass *_Kbd;
/*
** The following routines provide some compatability with the old westwood
** library.
*/
int Check_Key(void);
int Check_Key_Num(void);
int Get_Key_Num(void);
int Get_Key(void);
int KN_To_KA(int key);
void Clear_KeyBuffer(void);
int Key_Down(int key);

View File

@@ -0,0 +1,129 @@
;
; Command & Conquer Red Alert(tm)
; Copyright 2025 Electronic Arts Inc.
;
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see <http://www.gnu.org/licenses/>.
;
;***************************************************************************
;** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S **
;***************************************************************************
;* *
;* Project Name : Westwood 32 bit Library *
;* *
;* File Name : KEYBOARD.INC *
;* *
;* Programmer : Phil W. Gorrow *
;* *
;* Start Date : July 12, 1994 *
;* *
;* Last Update : July 12, 1994 [PWG] *
;* *
;*-------------------------------------------------------------------------*
;* Contains all the defines used by the keyboard interrupt for assembly *
;* includes. *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
TRUE EQU 1 ; numerical true
FALSE EQU 0 ; numerical false
DEBUG EQU 1
MAX_X_PIXEL EQU 319
MAX_Y_PIXEL EQU 199
KN_RESERVED1 EQU 14
KN_RESERVED2 EQU 45
KN_RESERVED3 EQU 56
; these two are reserved for AMIGA open and close.
KN_LCOMM EQU 59
KN_RCOMM EQU 63
KN_LMOUSE EQU 65
KN_RMOUSE EQU 66
KN_JBUTTON1 EQU 67
KN_JBUTTON2 EQU 68
KN_J_UP EQU 69
KN_J_RIGHT EQU 70
KN_J_DOWN EQU 71
KN_J_LEFT EQU 72
KN_LEFT EQU 92
KN_UPLEFT EQU 91
KN_UP EQU 96
KN_UPRIGHT EQU 101
KN_RIGHT EQU 102
KN_DOWNRIGHT EQU 103
KN_DOWN EQU 98
KN_DOWNLEFT EQU 93
KN_CENTER EQU 97
KN_INSERT EQU 99
KN_DELETE EQU 104
KN_RETURN EQU 43
KN_SPACE EQU 61
KN_KEYPAD_RETURN EQU 108
; these two are reserved for AMIGA K left and right paren
KN_KLPAREN EQU 87
KN_KRPAREN EQU 88
KN_NUMLOCK EQU 90
KN_SCROLLOCK EQU 125 ; key ignored by the logging system
KN_MOUSE_MOVE EQU 45 ; Indicate a mouse move (for playback of logged data)
; ----------------------------------------------------------------
; flags used in Keyflags to customize keystroke interrupt.
REPEATON EQU 0001H ; 1:all makes into buffer, 0:only 1st make
TRACKEXT EQU 0002H ; 1:Home != keypad Home, 0:Home=keypad Home
FILTERONLY EQU 0004H ; 1:Normal BIOS operation with filter
CTRLSON EQU 0008H ; 1:pass scroll lock sequence into BIOS
CTRLALTTURBO EQU 0010H ; 1:Allow turbo up and down in application
CTRLCON EQU 0020H ; 1:pass stop code to BIOS
SCROLLLOCKON EQU 0040H ; 1:pass scroll lock key into BIOS
PAUSEON EQU 0080H ; 1:pass the pause key and seq to BIOS
BREAKON EQU 0100H ; 1:pass the ctrl break seq to BIOS
NONUMLOCK EQU 0200H ; 1:do NOT remap keypad to numbers
TASKSWITCHABLE EQU 0400H ; 1:allows task switching keys thru ALT-TAB,
; ALT-ESC,CTRL-ESC
PASSBREAKS EQU 0800H ; 1:Pass all break codes to keyboard buffer.
KEYMOUSE EQU 1000H ; 1:Numeric keypad moves mouse
SIMLBUTTON EQU 2000H ; 1:have space and enter keys simulate Left
; mouse button when KEYMOUSE is set
SHIFTPRESS EQU 001H ; bit 0 for shift key pressed
CTRLPRESS EQU 002H ; bit 1 for ctrl key pressed
ALTPRESS EQU 004H ; bit 2 for alt key pressed
KEYRELEASE EQU 008H ; bit 3 for key released
NOTKEYRELEASE EQU 0F7H ; not of key released
CAPSLOCK EQU 00001H ; bit 0 for caps locked
NUMLOCK EQU 00002H ; bit 1 for num locked
CLEARISR EQU 020H ; value to clear In Service Register
DOS EQU 021H
INTCHIP0 EQU 020H ; 8259 interrupt chip controller 0
KEYCTRL EQU 061H ; control bits for KB sense data
KEYDATA EQU 060H ; keyboard scan code port

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,279 @@
DB 001h,000h,001h,000h,011h,000h,000h,000h,000h,000h,0FFh,000h,001h,0F0h,000h
DB 010h,0A0h,000h,000h,000h,03Fh,001h,000h,000h,03Fh,001h,045h,000h,03Fh,001h
DB 089h,000h,0A0h,000h,089h,000h,000h,000h,089h,000h,000h,000h,045h,000h,000h
DB 000h,000h,000h,0A0h,000h,045h,000h,001h,002h,004h,008h,010h,020h,040h,080h
DB 020h,002h,020h,003h,00Ch,006h,00Dh,007h,06Ah,006h,069h,006h,030h,002h,030h
DB 003h,07Dh,000h,07Dh,001h,05Ah,002h,05Ah,003h,000h,002h,010h,004h,06Eh,004h
DB 06Eh,002h,07Ch,000h,008h,000h,008h,000h,010h,000h,010h,000h,010h,000h,010h
DB 000h,020h,000h,020h,000h,040h,000h,040h,000h,080h,000h,080h,000h,000h,001h
DB 000h,004h,000h,004h,000h,004h,000h,001h,000h,000h,000h,000h,038h,01Dh,052h
DB 053h,04Bh,047h,04Fh,048h,050h,049h,051h,04Dh,035h,01Ch,037h,046h,03Eh,040h
DB 04Bh,04Ch,04Fh,050h,051h,053h,054h,055h,056h,059h,05Fh,06Ch,07Ch,000h,03Ch
DB 03Ah,063h,068h,05Ch,05Bh,05Dh,060h,062h,065h,067h,066h,037h,02Bh,07Ch,000h
DB 000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h
DB 000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h
DB 000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h
DB 000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h
DB 000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h
DB 000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h
DB 000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h
DB 000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h
DB 000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h
DB 000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h
DB 000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h
DB 000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h
DB 000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h
DB 000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h
DB 000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h
DB 000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h
DB 000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h
DB 000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,07Fh,06Eh
DB 002h,003h,004h,005h,006h,007h,008h,009h,00Ah,00Bh,00Ch,00Dh,00Fh,010h,011h
DB 012h,013h,014h,015h,016h,017h,018h,019h,01Ah,01Bh,01Ch,02Bh,03Ah,01Fh,020h
DB 021h,022h,023h,024h,025h,026h,027h,028h,029h,001h,02Ch,01Dh,02Eh,02Fh,030h
DB 031h,032h,033h,034h,035h,036h,037h,039h,064h,03Ch,03Dh,01Eh,070h,071h,072h
DB 073h,074h,075h,076h,077h,078h,079h,05Ah,07Dh,05Bh,060h,065h,069h,05Ch,061h
DB 066h,06Ah,05Dh,062h,067h,063h,068h,07Fh,07Fh,07Fh,07Ah,07Bh,000h,000h,0FEh
DB 087h,0FFh,0C0h,01Fh,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h
DB 000h,000h,000h,000h,000h,000h,000h,000h,000h,038h,0EFh,001h,000h,000h,000h
DB 000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h
DB 000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h
DB 000h,000h,000h,000h,000h,000h,000h,01Eh,02Ch,039h,03Ah,03Ch,03Eh,040h,05Ah
DB 080h,080h,080h,000h,000h,000h,000h,000h,0FFh,0FFh,0FFh,000h,0FFh,001h,000h
DB 000h,000h,000h,000h,0FFh,000h,000h,000h,001h,000h,000h,000h,000h,001h,0FFh
DB 001h,000h,001h,001h,008h,000h,002h,000h,008h,000h,006h,000h,004h,000h,003h
DB 000h,008h,000h,005h,000h,008h,000h,008h,000h,008h,000h,008h,000h,000h,000h
DB 001h,000h,008h,000h,007h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h
DB 000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h
DB 000h,000h,000h,000h,000h,018h,006h,07Ch,008h,000h,000h,000h,000h,000h,000h
DB 000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,06Bh
DB 008h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h
DB 000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,001h,000h,000h,000h,000h
DB 000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h
DB 000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h
DB 000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h
DB 000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h
DB 000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,06Eh
DB 009h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,0E4h,00Bh
DB 090h,00Ah,095h,00Eh,01Ch,00Dh,000h,000h,000h,000h,000h,000h,000h,000h,000h
DB 000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h
DB 000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h
DB 000h,000h,000h,000h,000h,000h,000h,0C8h,000h,000h,000h,051h,057h,006h,01Eh
DB 08Ch,0C8h,08Eh,0D8h,08Eh,0C0h,08Bh,046h,006h,0F7h,006h,004h,000h,002h,000h
DB 075h,013h,0B9h,010h,000h,0BFh,094h,000h,0F2h,0AEh,0E3h,009h,0BFh,0B4h,000h
DB 04Fh,02Bh,0F9h,026h,08Ah,005h,01Fh,007h,05Fh,059h,0C9h,0CBh,0C8h,000h,000h
DB 000h,056h,053h,01Eh,08Ch,0C8h,08Eh,0D8h,0A1h,0BAh,001h,08Bh,0F0h,005h,002h
DB 000h,025h,0FFh,000h,039h,006h,0B6h,001h,074h,011h,08Bh,05Eh,006h,089h,09Ch
DB 0B6h,000h,0A3h,0BAh,001h,033h,0C0h,01Fh,05Bh,05Eh,0C9h,0CBh,0B8h,001h,000h
DB 01Fh,05Bh,05Eh,0C9h,0CBh,0C8h,004h,000h,000h,053h,051h,052h,057h,056h,01Eh
DB 09Ch,0FAh,08Ch,0C8h,08Eh,0D8h,0A1h,0ABh,002h,0A3h,0AFh,002h,0A1h,0B1h,002h
DB 0A3h,0B5h,002h,08Bh,046h,006h,00Bh,0C0h,075h,003h,0E9h,0F7h,001h,0F7h,006h
DB 004h,000h,000h,010h,00Fh,084h,03Ah,001h,0F6h,0C4h,004h,00Fh,085h,033h,001h
DB 0F7h,006h,004h,000h,000h,020h,074h,00Ch,03Ch,02Bh,074h,00Ch,03Ch,03Dh,074h
DB 008h,03Ch,06Ch,074h,004h,03Ch,063h,075h,016h,0B0h,041h,080h,00Eh,0F6h,002h
DB 001h,0F6h,0C4h,008h,00Fh,084h,00Ah,001h,080h,026h,0F6h,002h,0FEh,0E9h,002h
DB 001h,03Ch,068h,075h,016h,0B0h,042h,080h,00Eh,0F6h,002h,002h,0F6h,0C4h,008h
DB 00Fh,084h,0F0h,000h,080h,026h,0F6h,002h,0FDh,0E9h,0E8h,000h,0F6h,0C4h,008h
DB 00Fh,085h,0E4h,000h,03Ch,061h,074h,01Eh,03Ch,05Bh,00Fh,082h,0DAh,000h,03Ch
DB 067h,00Fh,087h,0D4h,000h,03Ch,05Dh,076h,00Eh,03Ch,065h,073h,00Ah,03Ch,060h
DB 074h,006h,03Ch,062h,00Fh,085h,0C2h,000h,08Ah,0ECh,032h,0E4h,02Ch,05Bh,08Bh
DB 0D8h,0D1h,0E3h,081h,0C3h,06Fh,002h,08Bh,007h,08Ah,0DCh,098h,093h,098h,093h
DB 0F6h,0C5h,002h,075h,021h,0BAh,001h,000h,0F6h,0C5h,001h,074h,003h,083h,0C2h
DB 003h,003h,0DAh,08Ah,09Fh,00Ah,000h,093h,098h,093h,087h,0DAh,003h,0D8h,08Ah
DB 087h,00Ah,000h,098h,087h,0DAh,0EBh,034h,083h,0E3h,003h,025h,003h,000h,083h
DB 0E3h,003h,025h,003h,000h,0D1h,0E3h,0D1h,0E3h,00Bh,0D8h,0D1h,0E3h,08Bh,09Fh
DB 089h,002h,0D1h,0E3h,0D1h,0E3h,08Bh,087h,010h,000h,08Bh,09Fh,012h,000h,0A3h
DB 0AFh,002h,089h,01Eh,0B5h,002h,0A1h,0AFh,002h,08Bh,01Eh,0B5h,002h,0EBh,02Fh
DB 001h,006h,0AFh,002h,079h,005h,033h,0C0h,0A3h,0AFh,002h,001h,01Eh,0B5h,002h
DB 079h,006h,033h,0DBh,089h,01Eh,0B5h,002h,0A1h,0AFh,002h,08Bh,01Eh,0B5h,002h
DB 03Dh,03Fh,001h,07Eh,003h,0B8h,03Fh,001h,081h,0FBh,0C7h,000h,07Eh,003h,0BBh
DB 0C7h,000h,0A3h,0AFh,002h,089h,01Eh,0B5h,002h,0A3h,0ABh,002h,089h,01Eh,0B1h
DB 002h,083h,03Eh,0A9h,002h,000h,075h,008h,00Eh,0E8h,030h,003h,00Eh,0E8h,05Fh
DB 003h,0B8h,02Dh,000h,089h,046h,006h,08Bh,036h,0BAh,001h,089h,076h,0FEh,08Bh
DB 03Eh,0B6h,001h,050h,00Eh,0E8h,051h,0FEh,083h,0C4h,002h,00Bh,0C0h,075h,011h
DB 08Bh,046h,006h,03Ch,02Dh,074h,00Dh,03Ch,041h,074h,009h,03Ch,042h,074h,005h
DB 0EBh,029h,0E9h,080h,000h,0FFh,036h,0AFh,002h,00Eh,0E8h,02Eh,0FEh,083h,0C4h
DB 002h,00Bh,0C0h,075h,0EEh,083h,046h,0FCh,002h,0FFh,036h,0B5h,002h,00Eh,0E8h
DB 01Bh,0FEh,083h,0C4h,002h,00Bh,0C0h,075h,0DBh,083h,046h,0FCh,002h,0BBh,001h
DB 001h,08Bh,046h,006h,03Ch,02Dh,074h,01Bh,03Ch,07Fh,074h,017h,0F6h,0C4h,008h
DB 074h,016h,032h,0DBh,0F7h,006h,004h,000h,000h,008h,075h,00Ch,03Ch,041h,074h
DB 008h,03Ch,042h,074h,004h,089h,036h,0BAh,001h,08Bh,0F8h,083h,0E7h,07Fh,0B1h
DB 003h,0D3h,0EFh,08Ah,0C8h,080h,0E1h,007h,0D3h,0E3h,0F6h,0D7h,084h,09Dh,039h
DB 002h,074h,00Ch,0F7h,006h,004h,000h,001h,000h,075h,004h,089h,036h,0BAh,001h
DB 020h,0BDh,039h,002h,008h,09Dh,039h,002h,0B8h,001h,000h,0EBh,008h,08Bh,046h
DB 0FEh,0A3h,0BAh,001h,033h,0C0h,09Dh,01Fh,05Eh,05Fh,05Ah,059h,05Bh,0C9h,0CBh
DB 050h,053h,051h,057h,01Eh,052h,006h,056h,0FCh,08Ch,0C8h,08Eh,0D8h,083h,03Eh
DB 0CEh,002h,000h,0C7h,006h,0CEh,002h,000h,000h,00Fh,085h,0FDh,001h,08Bh,016h
DB 004h,000h,083h,026h,0BEh,001h,0FCh,0B8h,040h,000h,08Eh,0C0h,026h,0F6h,006h
DB 017h,000h,040h,074h,005h,083h,00Eh,0BEh,001h,001h,026h,0F6h,006h,017h,000h
DB 020h,074h,005h,083h,00Eh,0BEh,001h,002h,0C6h,006h,0B5h,000h,001h,026h,0F6h
DB 006h,096h,000h,010h,075h,005h,0C6h,006h,0B5h,000h,000h,08Ch,0C8h,08Eh,0C0h
DB 0FCh,032h,0E4h,0BBh,001h,001h,0E4h,060h,08Bh,01Eh,05Bh,002h,088h,087h,049h
DB 002h,043h,083h,0E3h,00Fh,089h,01Eh,05Bh,002h,0BBh,001h,001h,03Ch,0E1h,075h
DB 005h,0C6h,006h,05Eh,002h,003h,080h,03Eh,05Eh,002h,000h,074h,00Fh,0FEh,00Eh
DB 05Eh,002h,0F7h,0C2h,080h,000h,00Fh,085h,088h,001h,0E9h,097h,001h,03Ch,0E0h
DB 075h,008h,0C6h,006h,05Dh,002h,001h,0E9h,079h,001h,0A8h,080h,074h,007h,032h
DB 0DBh,024h,07Fh,080h,0CCh,008h,080h,03Eh,05Dh,002h,000h,074h,023h,0C6h,006h
DB 05Dh,002h,000h,0C6h,006h,0B7h,002h,001h,0BFh,084h,000h,0B9h,010h,000h,0F2h
DB 0AEh,0E3h,002h,0EBh,003h,0E9h,060h,001h,08Ah,045h,00Fh,0C6h,006h,0B7h,002h
DB 000h,0EBh,011h,03Ch,07Ah,075h,004h,0B0h,080h,0EBh,009h,08Bh,0F8h,083h,0E7h
DB 07Fh,08Ah,085h,0C0h,001h,0F6h,006h,041h,002h,001h,075h,01Bh,0F6h,006h,040h
DB 002h,004h,074h,017h,03Ch,05Ah,075h,010h,080h,03Eh,0B5h,000h,001h,074h,009h
DB 0F7h,0C2h,080h,000h,075h,003h,0E9h,023h,001h,080h,0CCh,002h,0F6h,006h,040h
DB 002h,050h,074h,003h,080h,0CCh,004h,050h,00Eh,0E8h,059h,0FCh,083h,0C4h,002h
DB 0F6h,006h,03Eh,002h,010h,075h,007h,0F6h,006h,040h,002h,002h,074h,003h,080h
DB 0CCh,001h,08Bh,0F8h,083h,0E7h,07Fh,0D1h,0EFh,0D1h,0EFh,0D1h,0EFh,08Bh,0D8h
DB 083h,0E3h,07Fh,080h,0E3h,007h,08Ah,0AFh,034h,000h,0F7h,006h,0BEh,001h,001h
DB 000h,074h,009h,084h,0ADh,019h,002h,074h,003h,080h,0F4h,001h,0F7h,006h,0BEh
DB 001h,002h,000h,074h,009h,084h,0ADh,029h,002h,074h,003h,080h,0F4h,001h,088h
DB 026h,06Ah,002h,066h,083h,03Eh,0EAh,002h,001h,075h,01Bh,03Dh,073h,000h,074h
DB 00Ah,03Dh,076h,000h,072h,00Eh,03Dh,078h,000h,077h,009h,066h,0C7h,006h,0EAh
DB 002h,000h,000h,000h,000h,0E9h,08Bh,000h,03Dh,07Dh,000h,075h,00Ch,066h,0C7h
DB 006h,0EAh,002h,001h,000h,000h,000h,0E9h,08Ch,000h,03Dh,068h,006h,074h,075h
DB 03Dh,04Ch,006h,074h,070h,03Dh,030h,002h,074h,005h,03Dh,07Eh,002h,075h,006h
DB 0C7h,006h,008h,000h,001h,000h,03Dh,020h,004h,075h,00Ch,050h,0A1h,000h,000h
DB 035h,001h,000h,050h,083h,0C4h,002h,058h,03Dh,034h,004h,075h,00Ch,050h,0A1h
DB 002h,000h,035h,001h,000h,050h,083h,0C4h,002h,058h,050h,00Eh,0E8h,0FAh,0FBh
DB 058h,03Ch,06Eh,075h,00Dh,083h,03Eh,082h,000h,000h,074h,006h,050h,0FFh,01Eh
DB 080h,000h,058h,0BFh,05Fh,002h,0B9h,00Ah,000h,0F2h,0AEh,00Bh,0C9h,075h,01Bh
DB 0BFh,03Ch,000h,0B9h,022h,000h,0D1h,0E9h,0F2h,0AFh,0E3h,009h,08Bh,05Dh,020h
DB 023h,0DAh,074h,002h,0EBh,006h,0F7h,0C2h,004h,000h,074h,012h,05Eh,007h,05Ah
DB 01Fh,05Fh,059h,05Bh,058h,02Eh,0FFh,006h,059h,002h,02Eh,0FFh,02Eh,0BAh,002h
DB 0E4h,061h,08Ah,0E0h,00Ch,080h,0E6h,061h,086h,0E0h,0E6h,061h,0B8h,040h,000h
DB 08Eh,0C0h,026h,0A0h,096h,000h,024h,0FDh,026h,0A2h,096h,000h,0B0h,020h,0E6h
DB 020h,05Eh,007h,05Ah,01Fh,05Fh,059h,05Bh,058h,0CFh,09Ch,050h,006h,0B8h,000h
DB 0B0h,08Eh,0C0h,026h,0FEh,006h,000h,000h,007h,058h,09Dh,0CFh,09Ch,00Eh,0E8h
DB 097h,0FDh,0CBh,050h,053h,051h,052h,01Eh,08Ch,0C8h,08Eh,0D8h,080h,03Eh,0F7h
DB 002h,000h,075h,01Dh,083h,03Eh,003h,003h,000h,075h,00Ch,0B8h,000h,000h,050h
DB 00Eh,0FFh,016h,051h,003h,083h,0C4h,002h,083h,006h,003h,003h,001h,083h,016h
DB 003h,003h,000h,01Fh,05Ah,059h,05Bh,058h,0CBh,0C8h,004h,000h,000h,050h,053h
DB 051h,052h,056h,057h,01Eh,006h,08Ch,0C8h,08Eh,0D8h,080h,03Eh,0F7h,002h,000h
DB 075h,050h,083h,03Eh,003h,003h,000h,074h,049h,0FFh,00Eh,003h,003h,083h,03Eh
DB 003h,003h,000h,075h,03Eh,08Bh,00Eh,03Fh,003h,08Bh,016h,043h,003h,0A1h,0ABh
DB 002h,089h,046h,0FEh,08Bh,01Eh,0B1h,002h,089h,05Eh,0FCh,0A3h,02Fh,003h,089h
DB 01Eh,033h,003h,089h,00Eh,037h,003h,089h,016h,03Bh,003h,0B8h,001h,000h,050h
DB 00Eh,0FFh,016h,051h,003h,083h,0C4h,002h,0FFh,076h,0FCh,0FFh,076h,0FEh,00Eh
DB 0FFh,016h,053h,003h,083h,0C4h,004h,007h,01Fh,05Fh,05Eh,05Ah,059h,05Bh,058h
DB 0C9h,0CBh,0C8h,002h,000h,000h,053h,08Ch,0C8h,08Eh,0D8h,0C7h,046h,0FEh,02Dh
DB 000h,08Bh,05Eh,006h,08Bh,0C3h,032h,01Eh,0F6h,002h,074h,029h,0A2h,0F6h,002h
DB 0F6h,0C3h,002h,074h,00Eh,0C7h,046h,0FEh,042h,000h,0A8h,002h,075h,005h,081h
DB 04Eh,0FEh,000h,008h,0F6h,0C3h,001h,074h,00Eh,0C7h,046h,0FEh,041h,000h,0A8h
DB 001h,075h,005h,081h,04Eh,0FEh,000h,008h,08Bh,046h,0FEh,05Bh,0C9h,0CBh,0C8h
DB 004h,000h,000h,050h,053h,051h,052h,01Eh,056h,006h,057h,089h,05Eh,0FCh,089h
DB 046h,0FEh,08Ch,0C8h,08Eh,0D8h,080h,03Eh,0F7h,002h,000h,00Fh,085h,0F9h,000h
DB 080h,03Eh,0F8h,002h,000h,00Fh,084h,0F0h,000h,08Bh,046h,0FEh,025h,01Eh,000h
DB 075h,009h,083h,03Eh,0A9h,002h,000h,00Fh,085h,0DFh,000h,083h,03Eh,0F9h,002h
DB 001h,075h,002h,0D1h,0E9h,03Bh,00Eh,049h,003h,072h,005h,08Bh,00Eh,049h,003h
DB 049h,03Bh,016h,04Dh,003h,072h,005h,08Bh,016h,04Dh,003h,04Ah,089h,00Eh,0ABh
DB 002h,089h,016h,0B1h,002h,066h,0F7h,006h,004h,000h,000h,010h,000h,000h,075h
DB 012h,0FFh,076h,0FCh,00Eh,0E8h,046h,0FFh,083h,0C4h,002h,050h,00Eh,0E8h,00Ah
DB 0FAh,083h,0C4h,002h,083h,03Eh,0A9h,002h,000h,00Fh,085h,092h,000h,083h,03Eh
DB 0FBh,002h,000h,074h,019h,08Bh,0C1h,08Bh,0CAh,02Bh,006h,0FFh,002h,08Bh,01Eh
DB 0FBh,002h,099h,0F7h,0FBh,0F7h,0EBh,003h,006h,0FFh,002h,08Bh,0D1h,08Bh,0C8h
DB 083h,03Eh,0FDh,002h,000h,074h,015h,08Bh,0C2h,02Bh,006h,001h,003h,08Bh,01Eh
DB 0FDh,002h,099h,0F7h,0FBh,0F7h,0EBh,003h,006h,001h,003h,08Bh,0D0h,083h,03Eh
DB 003h,003h,000h,075h,047h,039h,00Eh,007h,003h,075h,006h,039h,016h,009h,003h
DB 074h,03Bh,0A1h,00Bh,003h,025h,000h,0C0h,03Dh,000h,0C0h,074h,00Ch,00Eh,0E8h
DB 030h,0FEh,0F7h,006h,00Bh,003h,000h,080h,074h,020h,03Bh,00Eh,00Dh,003h,072h
DB 01Ah,03Bh,00Eh,015h,003h,077h,014h,03Bh,016h,011h,003h,072h,00Eh,03Bh,016h
DB 019h,003h,077h,008h,081h,00Eh,00Bh,003h,000h,040h,0EBh,004h,00Eh,0E8h,037h
DB 0FEh,089h,00Eh,007h,003h,089h,016h,009h,003h,05Fh,007h,05Eh,01Fh,05Ah,059h
DB 05Bh,058h,0C9h,0CBh,0C8h,00Ch,000h,000h,050h,053h,051h,052h,057h,056h,01Eh
DB 006h,08Ch,0C8h,08Eh,0D8h,0FCh,0A1h,02Fh,003h,08Bh,01Eh,033h,003h,02Bh,006h
DB 027h,003h,02Bh,01Eh,02Bh,003h,089h,046h,0FEh,089h,05Eh,0FCh,003h,006h,037h
DB 003h,003h,01Eh,03Bh,003h,089h,046h,0FAh,089h,05Eh,0F8h,0C7h,046h,0F6h,000h
DB 000h,0A1h,023h,003h,089h,046h,0F4h,033h,0C0h,033h,0D2h,08Bh,04Eh,0FEh,08Bh
DB 05Eh,0FAh,003h,0C9h,013h,0C0h,003h,0DBh,013h,0D2h,08Bh,04Eh,0FEh,08Bh,05Eh
DB 0FAh,02Bh,00Eh,049h,003h,02Bh,01Eh,049h,003h,049h,04Bh,003h,0C9h,013h,0C0h
DB 003h,0DBh,013h,0D2h,08Bh,04Eh,0FCh,08Bh,05Eh,0F8h,003h,0C9h,013h,0C0h,003h
DB 0DBh,013h,0D2h,08Bh,04Eh,0FCh,08Bh,05Eh,0F8h,02Bh,00Eh,04Dh,003h,02Bh,01Eh
DB 04Dh,003h,049h,04Bh,003h,0C9h,013h,0C0h,003h,0DBh,013h,0D2h,034h,005h,080h
DB 0F2h,005h,08Ah,0E0h,084h,0D0h,00Fh,085h,0AEh,000h,00Ah,0C2h,074h,040h,0F6h
DB 0C4h,008h,074h,00Dh,08Bh,05Eh,0FEh,0F7h,0DBh,089h,05Eh,0F6h,0C7h,046h,0FEh
DB 000h,000h,0F6h,0C4h,002h,074h,013h,052h,08Bh,046h,0FCh,0F7h,0D8h,0F7h,026h
DB 037h,003h,001h,046h,0F4h,0C7h,046h,0FCh,000h,000h,05Ah,0F6h,0C2h,004h,074h
DB 006h,0A1h,049h,003h,089h,046h,0FAh,0F6h,0C2h,001h,074h,006h,0A1h,04Dh,003h
DB 089h,046h,0F8h,0B8h,000h,0A0h,08Eh,0C0h,08Bh,046h,0FCh,0F7h,026h,049h,003h
DB 08Bh,016h,049h,003h,08Bh,0F8h,003h,07Eh,0FEh,08Bh,01Eh,03Fh,003h,0C5h,036h
DB 023h,003h,08Bh,076h,0F4h,003h,076h,0F6h,08Bh,046h,0FAh,08Bh,04Eh,0F8h,02Bh
DB 046h,0FEh,07Eh,03Ch,02Bh,04Eh,0FCh,07Eh,037h,02Bh,0D0h,02Bh,0D8h,055h,083h
DB 07Eh,006h,000h,075h,018h,08Bh,0E9h,08Bh,0C8h,0F3h,0A4h,003h,0F3h,003h,0FAh
DB 04Dh,075h,0F5h,05Dh,007h,01Fh,05Eh,05Fh,05Ah,059h,05Bh,058h,0C9h,0CBh,087h
DB 0F7h,08Bh,0E9h,006h,01Eh,007h,01Fh,08Bh,0C8h,0F3h,0A4h,003h,0F2h,003h,0FBh
DB 04Dh,075h,0F5h,05Dh,007h,01Fh,05Eh,05Fh,05Ah,059h,05Bh,058h,0C9h,0CBh,0C8h
DB 00Ch,000h,000h,050h,053h,051h,052h,057h,056h,01Eh,006h,08Ch,0C8h,08Eh,0D8h
DB 08Bh,046h,006h,08Bh,05Eh,008h,02Bh,006h,027h,003h,02Bh,01Eh,02Bh,003h,089h
DB 046h,0FEh,089h,05Eh,0FCh,003h,006h,03Fh,003h,003h,01Eh,043h,003h,089h,046h
DB 0FAh,089h,05Eh,0F8h,0C7h,046h,0F6h,000h,000h,0C4h,006h,01Dh,003h,089h,046h
DB 0F4h,033h,0C0h,033h,0D2h,08Bh,04Eh,0FEh,08Bh,05Eh,0FAh,003h,0C9h,013h,0C0h
DB 003h,0DBh,013h,0D2h,08Bh,04Eh,0FEh,08Bh,05Eh,0FAh,02Bh,00Eh,049h,003h,02Bh
DB 01Eh,049h,003h,049h,04Bh,003h,0C9h,013h,0C0h,003h,0DBh,013h,0D2h,08Bh,04Eh
DB 0FCh,08Bh,05Eh,0F8h,003h,0C9h,013h,0C0h,003h,0DBh,013h,0D2h,08Bh,04Eh,0FCh
DB 08Bh,05Eh,0F8h,02Bh,00Eh,04Dh,003h,02Bh,01Eh,04Dh,003h,049h,04Bh,003h,0C9h
DB 013h,0C0h,003h,0DBh,013h,0D2h,034h,005h,080h,0F2h,005h,08Ah,0E0h,084h,0D0h
DB 00Fh,085h,093h,000h,00Ah,0C2h,074h,042h,0F6h,0C4h,008h,074h,00Dh,08Bh,05Eh
DB 0FEh,0F7h,0DBh,089h,05Eh,0F6h,0C7h,046h,0FEh,000h,000h,0F6h,0C4h,002h,074h
DB 013h,052h,08Bh,046h,0FCh,0F7h,0D8h,0F7h,026h,03Fh,003h,001h,046h,0F4h,0C7h
DB 046h,0FCh,000h,000h,05Ah,0F6h,0C2h,004h,074h,007h,08Bh,01Eh,049h,003h,089h
DB 05Eh,0FAh,0F6h,0C2h,001h,074h,007h,08Bh,01Eh,04Dh,003h,089h,05Eh,0F8h,08Bh
DB 046h,0FCh,0F7h,026h,049h,003h,08Bh,016h,049h,003h,08Bh,0F8h,003h,07Eh,0FEh
DB 08Bh,01Eh,03Fh,003h,08Bh,076h,0F4h,003h,076h,0F6h,0B8h,000h,0A0h,08Eh,0D8h
DB 08Bh,046h,0FAh,08Bh,04Eh,0F8h,02Bh,046h,0FEh,07Eh,023h,02Bh,04Eh,0FCh,07Eh
DB 01Eh,02Bh,0D0h,02Bh,0D8h,08Ah,0E0h,026h,08Ah,02Ch,066h,046h,00Ah,0EDh,074h
DB 002h,088h,02Dh,047h,0FEh,0CCh,075h,0F0h,003h,0F3h,003h,0FAh,0FEh,0C9h,075h
DB 0E6h,007h,01Fh,05Eh,05Fh,05Ah,059h,05Bh,058h,0C9h,0CBh,0C8h,00Ch,000h,000h
DB 050h,053h,051h,052h,057h,056h,01Eh,006h,08Ch,0C8h,08Eh,0D8h,0E8h,0B7h,002h
DB 089h,056h,0F2h,0FCh,0A1h,02Fh,003h,08Bh,01Eh,033h,003h,02Bh,006h,027h,003h
DB 02Bh,01Eh,02Bh,003h,089h,046h,0FEh,089h,05Eh,0FCh,003h,006h,037h,003h,003h
DB 01Eh,03Bh,003h,089h,046h,0FAh,089h,05Eh,0F8h,0C7h,046h,0F6h,000h,000h,0A1h
DB 023h,003h,089h,046h,0F4h,033h,0C0h,033h,0D2h,08Bh,04Eh,0FEh,08Bh,05Eh,0FAh
DB 003h,0C9h,013h,0C0h,003h,0DBh,013h,0D2h,08Bh,04Eh,0FEh,08Bh,05Eh,0FAh,02Bh
DB 00Eh,049h,003h,02Bh,01Eh,049h,003h,049h,04Bh,003h,0C9h,013h,0C0h,003h,0DBh
DB 013h,0D2h,08Bh,04Eh,0FCh,08Bh,05Eh,0F8h,003h,0C9h,013h,0C0h,003h,0DBh,013h
DB 0D2h,08Bh,04Eh,0FCh,08Bh,05Eh,0F8h,02Bh,00Eh,04Dh,003h,02Bh,01Eh,04Dh,003h
DB 049h,04Bh,003h,0C9h,013h,0C0h,003h,0DBh,013h,0D2h,034h,005h,080h,0F2h,005h
DB 08Ah,0E0h,084h,0D0h,00Fh,085h,0C7h,000h,00Ah,0C2h,074h,040h,0F6h,0C4h,008h
DB 074h,00Dh,08Bh,05Eh,0FEh,0F7h,0DBh,089h,05Eh,0F6h,0C7h,046h,0FEh,000h,000h
DB 0F6h,0C4h,002h,074h,013h,052h,08Bh,046h,0FCh,0F7h,0D8h,0F7h,026h,037h,003h
DB 001h,046h,0F4h,0C7h,046h,0FCh,000h,000h,05Ah,0F6h,0C2h,004h,074h,006h,0A1h
DB 049h,003h,089h,046h,0FAh,0F6h,0C2h,001h,074h,006h,0A1h,04Dh,003h,089h,046h
DB 0F8h,0B8h,000h,0A0h,08Eh,0C0h,08Bh,046h,0FCh,0F7h,026h,049h,003h,003h,046h
DB 0FEh,083h,0D2h,000h,08Bh,0F8h,0E8h,0F1h,001h,08Bh,016h,049h,003h,08Bh,01Eh
DB 03Fh,003h,0C5h,036h,023h,003h,08Bh,076h,0F4h,003h,076h,0F6h,08Bh,046h,0FAh
DB 08Bh,04Eh,0F8h,02Bh,046h,0FEh,07Eh,04Fh,02Bh,04Eh,0FCh,07Eh,04Ah,02Bh,0D0h
DB 02Bh,0D8h,083h,07Eh,006h,000h,075h,021h,08Ah,0E0h,08Ah,02Ch,026h,088h,02Dh
DB 046h,047h,075h,003h,0E8h,0D9h,001h,0FEh,0CCh,075h,0F0h,003h,0F3h,003h,0FAh
DB 073h,003h,0E8h,0CCh,001h,0FEh,0C9h,075h,0E1h,0EBh,01Fh,08Ah,0E0h,026h,08Ah
DB 02Dh,088h,02Ch,046h,047h,075h,003h,0E8h,0B8h,001h,0FEh,0CCh,075h,0F0h,003h
DB 0F3h,003h,0FAh,073h,003h,0E8h,0ABh,001h,0FEh,0C9h,075h,0E1h,08Bh,056h,0F2h
DB 0E8h,06Ch,001h,007h,01Fh,05Eh,05Fh,05Ah,059h,05Bh,058h,0C9h,0CBh,0C8h,00Eh
DB 000h,000h,050h,053h,051h,052h,057h,056h,01Eh,006h,08Ch,0C8h,08Eh,0D8h,0E8h
DB 03Eh,001h,089h,056h,0F2h,08Bh,046h,006h,08Bh,05Eh,008h,02Bh,006h,027h,003h
DB 02Bh,01Eh,02Bh,003h,089h,046h,0FEh,089h,05Eh,0FCh,003h,006h,03Fh,003h,003h
DB 01Eh,043h,003h,089h,046h,0FAh,089h,05Eh,0F8h,0C7h,046h,0F6h,000h,000h,0C4h
DB 006h,01Dh,003h,089h,046h,0F4h,033h,0C0h,033h,0D2h,08Bh,04Eh,0FEh,08Bh,05Eh
DB 0FAh,003h,0C9h,013h,0C0h,003h,0DBh,013h,0D2h,08Bh,04Eh,0FEh,08Bh,05Eh,0FAh
DB 02Bh,00Eh,049h,003h,02Bh,01Eh,049h,003h,049h,04Bh,003h,0C9h,013h,0C0h,003h
DB 0DBh,013h,0D2h,08Bh,04Eh,0FCh,08Bh,05Eh,0F8h,003h,0C9h,013h,0C0h,003h,0DBh
DB 013h,0D2h,08Bh,04Eh,0FCh,08Bh,05Eh,0F8h,02Bh,00Eh,04Dh,003h,02Bh,01Eh,04Dh
DB 003h,049h,04Bh,003h,0C9h,013h,0C0h,003h,0DBh,013h,0D2h,034h,005h,080h,0F2h
DB 005h,08Ah,0E0h,084h,0D0h,00Fh,085h,0A0h,000h,00Ah,0C2h,074h,040h,0F6h,0C4h
DB 008h,074h,00Dh,08Bh,05Eh,0FEh,0F7h,0DBh,089h,05Eh,0F6h,0C7h,046h,0FEh,000h
DB 000h,0F6h,0C4h,002h,074h,013h,052h,08Bh,046h,0FCh,0F7h,0D8h,0F7h,026h,03Fh
DB 003h,001h,046h,0F4h,0C7h,046h,0FCh,000h,000h,05Ah,0F6h,0C2h,004h,074h,006h
DB 0A1h,049h,003h,089h,046h,0FAh,0F6h,0C2h,001h,074h,006h,0A1h,04Dh,003h,089h
DB 046h,0F8h,08Bh,046h,0FCh,0F7h,026h,049h,003h,003h,046h,0FEh,083h,0D2h,000h
DB 08Bh,0F8h,0E8h,07Eh,000h,08Bh,016h,049h,003h,08Bh,01Eh,03Fh,003h,08Bh,076h
DB 0F4h,003h,076h,0F6h,0B8h,000h,0A0h,08Eh,0D8h,08Bh,046h,0FAh,08Bh,04Eh,0F8h
DB 02Bh,046h,0FEh,07Eh,02Ch,02Bh,04Eh,0FCh,07Eh,027h,02Bh,0D0h,02Bh,0D8h,08Ah
DB 0E0h,026h,08Ah,02Ch,046h,00Ah,0EDh,074h,002h,088h,02Dh,047h,075h,003h,0E8h
DB 067h,000h,0FEh,0CCh,075h,0ECh,003h,0F3h,003h,0FAh,073h,003h,0E8h,05Ah,000h
DB 0FEh,0C9h,075h,0DDh,08Bh,056h,0F2h,0E8h,01Bh,000h,007h,01Fh,05Eh,05Fh,05Ah
DB 059h,05Bh,058h,0C9h,0CBh,050h,053h,0B8h,005h,04Fh,0B7h,001h,0B3h,000h,02Eh
DB 0FFh,01Eh,05Dh,003h,05Bh,058h,0C3h,050h,053h,052h,0B8h,005h,04Fh,0B7h,000h
DB 0B3h,000h,02Eh,0FFh,01Eh,05Dh,003h,05Ah,05Bh,058h,0C3h,050h,053h,052h,08Bh
DB 0DAh,0C1h,0E3h,002h,02Eh,089h,01Eh,089h,003h,02Eh,08Bh,097h,061h,003h,0B8h
DB 005h,04Fh,0B7h,000h,0B3h,000h,02Eh,0FFh,01Eh,05Dh,003h,05Ah,05Bh,058h,0C3h
DB 050h,053h,052h,02Eh,08Bh,01Eh,089h,003h,083h,0C3h,004h,02Eh,089h,01Eh,089h
DB 003h,02Eh,08Bh,097h,061h,003h,0B8h,005h,04Fh,0B7h,000h,0B3h,000h,02Eh,0FFh
DB 01Eh,05Dh,003h,05Ah,05Bh,058h,0C3h

View File

@@ -0,0 +1,162 @@
;
; Command & Conquer Red Alert(tm)
; Copyright 2025 Electronic Arts Inc.
;
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see <http://www.gnu.org/licenses/>.
;
;***************************************************************************
;** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S **
;***************************************************************************
;* *
;* Project Name : Westwood 32 bit Library *
;* *
;* File Name : KEYSTRUC.INC *
;* *
;* Programmer : Phil W. Gorrow *
;* *
;* Start Date : July 13, 1994 *
;* *
;* Last Update : July 13, 1994 [PWG] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
STRUC KeyboardType
SoundOn DW ? ; toggled by alt S
MusicOn DW ? ; toggled by alt M
KeyFlags DD ? ; all but repeat for now
Break DW ?
KeyMouseMove DB 6 DUP(?)
ScreenEdge DW 18 DUP (?)
Bits DB 8 DUP (?)
CondPassKey DW 17 DUP (?)
CondPassCond DW 17 DUP (?)
EscRoutine DD ?
ExtCodes DB 16 DUP (?)
ExtNums DB 16 DUP (?)
ExtRemap DB 16 DUP (?)
ExtRemapEnd DB ?
ExtKeyboard DB ?
KeyBuffer DW 128 DUP(?) ; set to empty
KeyBufferHead DD ? ; set to first entry
KeyBufferTail DD ? ; set to head for empty buffer
KeyLock DW ? ; num and caps lock bits
KeyNums DB 89 DUP (?)
KeysCapsLock DB 16 DUP (?)
KeysNumLock DB 16 DUP (?)
KeysUpDown DB 16 DUP (?)
KeyStream DB 16 DUP (?)
PassCount DW ?
KeyStreamIndex DW ?
LastKeyE0 DB ?
LastKeyE1 DB ?
PassAlways DB 10 DUP (?)
PassAlwaysEnd DB ? ; invalid code to END PassAlways
CtrlFlags DB ?
Buffer DW ?
Time DW ?
XYAdjust DB 26 DUP (?)
EdgeConv DW 16 DUP (?)
MouseUpdate DW ?
MouseX DD ?
LocalMouseX DW ?
MouseY DD ?
LocalMouseY DW ?
IsExtKey DB ?
ExtIndex DW ?
KeyOldRMI DD ? ; The origianl RM interrupt seg:off.
KeyOldPMIOffset DD ? ; The origianl PM interrupt offset
KeyOldPMISelector DD ? ; The original PM interrupt segment.
KeyCodeOffset DW ? ; Offset of the code in the RM stuff.
CallKeyRMIntOffset DW ? ; Offset of function to call DOS timer interrupt.
CallKeyRMIntAddr DD ? ; PM address of CallRealIntOffset for speed.
PMIssuedKeyInt DD ? ; did Protected mode pass this through?
BrkOldRMI DD ? ; The origianl RM interrupt seg:off.
BrkOldPMIOffset DD ? ; The origianl PM interrupt offset
BrkOldPMISelector DD ? ; The original PM interrupt segment.
BrkCodeOffset DW ? ; Offset of the code in the RM stuff.
CallBrkRMIntOffset DW ? ; Offset of function to call DOS timer interrupt.
CallBrkRMIntAddr DD ? ; PM address of CallRealIntOffset for speed.
PMIssuedBrkInt DD ? ; did Protected mode pass this through?
KeyIntDisabled DD ?
DbgOldPMIOffset DD ? ; The origianl PM interrupt offset
DbgOldPMISelector DD ? ; The original PM interrupt segment.
;---------------------------------------------------------------------------
; Begin definition of Mouse Specific Variables for real mode
;---------------------------------------------------------------------------
Button DB ? ; current value of the mouse button
MDisabled DB ? ; Is the mouse driver disabled
MInput DB ? ; Defaults to mouse input allowed.
Adjust DW ? ; flag to adjust coordinates if necessary
MouseStepX DW ? ; step values if the mouse moves at
MouseStepY DW ? ; more than one pixel at a time
MouseOffsetX DW ? ; Fractional step values used if a mouse
MouseOffsetY DW ? ; moves at less than one pixel at a time
MState DD ? ; Tracks if mouse is hidden (TRUE) or not (FALSE)
MouseXOld DW ? ; Holds last MouseX and MouseY to determine if
MouseYOld DW ? ; mouse needs to be redrawn
MCState DW ? ; Tracks if mouse conditional hidden (TRUE) or not
MouseCXLeft DD ? ; Conditional hide mouse left x position
MouseCYUpper DD ? ; Conditional hide mouse top y position
MouseCXRight DD ? ; Conditional hide mouse right x position
MouseCYLower DD ? ; Conditional hide mouse lower y position
MouseCursor DD ? ; Pointer to the mouse cursor to draw
MouseCursorSize DW ? ; Size of mouse cursor draw area
MouseBuffer DD ? ; Pointer to buffer mouse is saved in
MouseXHot DD ? ; Offset to mouse's x hot spot
MouseYHot DD ? ; Offset to mouse's y hot spot
MouseBuffX DD ? ; X position background was saved at
MouseBuffY DD ? ; Y position background was saved at
MouseBuffW DD ? ; Width of the region saved for mouse
MouseBuffH DD ? ; Height of the region saved for mouse
MouseWidth DD ? ; Mouse cursor theoretical width
MouseHeight DD ? ; Mouse cursor theoretical height
MouseCodeOffset DW ? ; Offset to the real mode code offset
MouseRight DD ? ; Right hand side of the screen
MouseBottom DD ? ; Bottom of the screen
ShadowPtr dw ?
DrawMousePtr dw ?
VGAMouseDraw dw ?
VGAMouseShadow dw ?
VESAMouseDraw dw ?
VESAMouseShadow dw ?
VesaPtr dd ?
VesaBankTable DD 8 dup (?)
Adjust_XPos dd ?
Adjust_YPos dd ?
ENDS
; InitFlags that are set to have a fully functional interrupt.
IF_ALLOC_RM equ 1 ; Allocation of RM was successful.
IF_SET_VECTORS equ 2 ; Vectors have been set.
IF_LOCKED_PM_CODE equ 4 ; Locked PM code for DPMI.
IF_LOCKED_PM_DATA equ 8 ; Locked PM code for DPMI.
IF_RATE_CHANGE equ 10 ; Timer rate was changed.
IF_FUNCTIONAL equ 20 ; Timer is in and functional.
IF_LOCKED_RM_CODE equ 40

View File

@@ -0,0 +1,181 @@
#
# Command & Conquer Red Alert(tm)
# Copyright 2025 Electronic Arts Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#***************************************************************************
#** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
#***************************************************************************
#* *
#* Project Name : Westwood Library .LIB makefile *
#* *
#* File Name : MAKEFILE *
#* *
#* Programmer : Julio R. Jerez *
#* *
#* Start Date : Jan 26, 1995 *
#* *
#* *
#*-------------------------------------------------------------------------*
#* *
#* Required environment variables: *
#* WIN32LIB = your root WIN32LIB path *
#* WIN32VCS = root directory for wwlib version control archive *
#* COMPILER = your Watcom installation path *
#* *
#* Required changes to makefile: *
#* PROJ_NAME = name of the library you're building *
#* OBJECTS = list of objects in your library *
#* *
#* Optional changes to makefile: *
#* PROJ_DIR = full pathname of your working directory *
#* .path.xxx = full pathname where various file types live *
#* *
#***************************************************************************
#---------------------------------------------------------------------------
# Verify user's environment
#---------------------------------------------------------------------------
!ifndef %WIN32LIB
!error WIN32LIB Environment var not configured.
!endif
!ifndef %WIN32VCS
!error WIN32VCS Environment var not configured.
!endif
!ifndef %WATCOM
!error WATCOM Environment var not configured.
!endif
#===========================================================================
# User-defined section: the user should tailor this section for each project
#===========================================================================
PROJ_NAME = keyboard
PROJ_DIR = $(%WIN32LIB)\$(PROJ_NAME)
LIB_DIR = $(%WIN32LIB)\lib
!include $(%WIN32LIB)\project.cfg
#---------------------------------------------------------------------------
# Project-dependent variables
#---------------------------------------------------------------------------
OBJECTS = &
keyboard.obj &
mouse.obj &
wwmouse.obj
#---------------------------------------------------------------------------
# Path macros: one path for each file type.
# These paths are used to tell make where to find/put each file type.
#---------------------------------------------------------------------------
.asm: $(PROJ_DIR)
.c: $(PROJ_DIR)
.cpp: $(PROJ_DIR)
.h: $(PROJ_DIR)
.obj: $(PROJ_DIR)
.lib: $(WIN32LIB)\lib
.exe: $(PROJ_DIR)
#===========================================================================
# Pre-defined section: there should be little need to modify this section.
#===========================================================================
#---------------------------------------------------------------------------
# Tools/commands
#---------------------------------------------------------------------------
C_CMD = wcc386
CPP_CMD = wpp386
LIB_CMD = wlib
LINK_CMD = wlink
ASM_CMD = tasm
#---------------------------------------------------------------------------
# Include & library paths
# If LIB & INCLUDE are already defined, they are used in addition to the
# WWLIB32 lib & include; otherwise, they're constructed from
# BCDIR & TNTDIR
#---------------------------------------------------------------------------
LIBPATH = $(%WIN32LIB)\LIB;$(%WATCOM)\LIB
INCLUDEPATH = $(%WIN32LIB)\INCLUDE;$(%WATCOM)\H
#---------------------------------------------------------------------------
# Implicit rules
# Compiler:
# ($< = full dependent with path)
# Assembler:
# output obj's are constructed from .obj: & the $& macro
# ($< = full dependent with path)
# tasm's cfg file is not invoked as a response file.
#---------------------------------------------------------------------------
.c.obj: $(%WIN32LIB)\project.cfg .AUTODEPEND
$(C_CMD) $(CC_CFG) $<
.cpp.obj: $(%WIN32LIB)\project.cfg .AUTODEPEND
$(CPP_CMD) $(CC_CFG) $(PROJ_DIR)\$^*.cpp
.asm.obj: $(%WIN32LIB)\project.cfg
$(ASM_CMD) $(ASM_CFG) $<
#---------------------------------------------------------------------------
# Default target: configuration files & library (in that order)
#---------------------------------------------------------------------------
all: $(LIB_DIR)\$(PROJ_NAME).lib .SYMBOLIC
#---------------------------------------------------------------------------
# Build the library
# The original library is deleted by the librarian
# Lib objects & -+ commands are constructed by substituting within the
# $^@ macro (which expands to all target dependents, separated with
# spaces)
# Tlib's cfg file is not invoked as a response file.
# All headers & source files are copied into WIN32LIB\SRCDEBUG, for debugging
#---------------------------------------------------------------------------
$(LIB_DIR)\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc
copy *.h $(%WIN32LIB)\include
copy *.inc $(%WIN32LIB)\include
copy *.cpp $(%WIN32LIB)\srcdebug
copy *.asm $(%WIN32LIB)\srcdebug
$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc
#---------------------------------------------------------------------------
# Objects now have a link file which is NOT generated everytime. Instead
# it just has its own dependacy rule.
#---------------------------------------------------------------------------
objects.lbc : $(OBJECTS)
%create $^@
for %index in ($(OBJECTS)) do %append $^@ +%index
#---------------------------------------------------------------------------
# Create the test directory and make it.
#---------------------------------------------------------------------------
test:
mkdir test
cd test
copy $(%WWVCS)\$(PROJ_NAME)\test\vcs.cfg
update
wmake
cd ..
#**************************** End of makefile ******************************

View File

@@ -0,0 +1,181 @@
#
# Command & Conquer Red Alert(tm)
# Copyright 2025 Electronic Arts Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#***************************************************************************
#** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
#***************************************************************************
#* *
#* Project Name : Westwood Library .LIB makefile *
#* *
#* File Name : MAKEFILE *
#* *
#* Programmer : Julio R. Jerez *
#* *
#* Start Date : Jan 26, 1995 *
#* *
#* *
#*-------------------------------------------------------------------------*
#* *
#* Required environment variables: *
#* WIN32LIB = your root WIN32LIB path *
#* WIN32VCS = root directory for wwlib version control archive *
#* COMPILER = your Watcom installation path *
#* *
#* Required changes to makefile: *
#* PROJ_NAME = name of the library you're building *
#* OBJECTS = list of objects in your library *
#* *
#* Optional changes to makefile: *
#* PROJ_DIR = full pathname of your working directory *
#* .path.xxx = full pathname where various file types live *
#* *
#***************************************************************************
#---------------------------------------------------------------------------
# Verify user's environment
#---------------------------------------------------------------------------
!ifndef %WIN32LIB
!error WIN32LIB Environment var not configured.
!endif
!ifndef %WIN32VCS
!error WIN32VCS Environment var not configured.
!endif
!ifndef %WATCOM
!error WATCOM Environment var not configured.
!endif
#===========================================================================
# User-defined section: the user should tailor this section for each project
#===========================================================================
PROJ_NAME = keyboard
PROJ_DIR = $(%WIN32LIB)\$(PROJ_NAME)
LIB_DIR = $(%WIN32LIB)\lib
!include $(%WIN32LIB)\project.cfg
#---------------------------------------------------------------------------
# Project-dependent variables
#---------------------------------------------------------------------------
OBJECTS = &
keyboard.obj &
mouse.obj &
wwmouse.obj
#---------------------------------------------------------------------------
# Path macros: one path for each file type.
# These paths are used to tell make where to find/put each file type.
#---------------------------------------------------------------------------
.asm: $(PROJ_DIR)
.c: $(PROJ_DIR)
.cpp: $(PROJ_DIR)
.h: $(PROJ_DIR)
.obj: $(PROJ_DIR)
.lib: $(WIN32LIB)\lib
.exe: $(PROJ_DIR)
#===========================================================================
# Pre-defined section: there should be little need to modify this section.
#===========================================================================
#---------------------------------------------------------------------------
# Tools/commands
#---------------------------------------------------------------------------
C_CMD = wcc386
CPP_CMD = wpp386
LIB_CMD = wlib
LINK_CMD = wlink
ASM_CMD = tasm
#---------------------------------------------------------------------------
# Include & library paths
# If LIB & INCLUDE are already defined, they are used in addition to the
# WWLIB32 lib & include; otherwise, they're constructed from
# BCDIR & TNTDIR
#---------------------------------------------------------------------------
LIBPATH = $(%WIN32LIB)\LIB;$(%WATCOM)\LIB
INCLUDEPATH = $(%WIN32LIB)\INCLUDE;$(%WATCOM)\H
#---------------------------------------------------------------------------
# Implicit rules
# Compiler:
# ($< = full dependent with path)
# Assembler:
# output obj's are constructed from .obj: & the $& macro
# ($< = full dependent with path)
# tasm's cfg file is not invoked as a response file.
#---------------------------------------------------------------------------
.c.obj: $(%WIN32LIB)\project.cfg .AUTODEPEND
$(C_CMD) $(CC_CFG) $<
.cpp.obj: $(%WIN32LIB)\project.cfg .AUTODEPEND
$(CPP_CMD) $(CC_CFG) $(PROJ_DIR)\$^*.cpp
.asm.obj: $(%WIN32LIB)\project.cfg
$(ASM_CMD) $(ASM_CFG) $<
#---------------------------------------------------------------------------
# Default target: configuration files & library (in that order)
#---------------------------------------------------------------------------
all: $(LIB_DIR)\$(PROJ_NAME).lib .SYMBOLIC
#---------------------------------------------------------------------------
# Build the library
# The original library is deleted by the librarian
# Lib objects & -+ commands are constructed by substituting within the
# $^@ macro (which expands to all target dependents, separated with
# spaces)
# Tlib's cfg file is not invoked as a response file.
# All headers & source files are copied into WIN32LIB\SRCDEBUG, for debugging
#---------------------------------------------------------------------------
$(LIB_DIR)\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc
copy *.h $(%WIN32LIB)\include
copy *.inc $(%WIN32LIB)\include
copy *.cpp $(%WIN32LIB)\srcdebug
copy *.asm $(%WIN32LIB)\srcdebug
$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc
#---------------------------------------------------------------------------
# Objects now have a link file which is NOT generated everytime. Instead
# it just has its own dependacy rule.
#---------------------------------------------------------------------------
objects.lbc : $(OBJECTS)
%create $^@
for %index in ($(OBJECTS)) do %append $^@ +%index
#---------------------------------------------------------------------------
# Create the test directory and make it.
#---------------------------------------------------------------------------
test:
mkdir test
cd test
copy $(%WWVCS)\$(PROJ_NAME)\test\vcs.cfg
update
wmake
cd ..
#**************************** End of makefile ******************************

View File

@@ -0,0 +1,168 @@
#
# Command & Conquer Red Alert(tm)
# Copyright 2025 Electronic Arts Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#***************************************************************************
#** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
#***************************************************************************
#* *
#* Project Name : Westwood Library .LIB makefile *
#* *
#* File Name : MAKEFILE *
#* *
#* Programmer : Julio R. Jerez *
#* *
#* Start Date : Jan 26, 1995 *
#* *
#* *
#*-------------------------------------------------------------------------*
#* *
#* Required environment variables: *
#* WIN32LIB = your root WWFLAT path *
#* WIN32VCS = root directory for wwlib version control archive *
#* COMPILER = your Watcom installation path *
#* *
#* Required changes to makefile: *
#* PROJ_NAME = name of the library you're building *
#* OBJECTS = list of objects in your library *
#* *
#* Optional changes to makefile: *
#* PROJ_DIR = full pathname of your working directory *
#* .path.xxx = full pathname where various file types live *
#* *
#***************************************************************************
#---------------------------------------------------------------------------
# Verify user's environment
#---------------------------------------------------------------------------
!ifndef WIN32LIB
!error WIN32LIB Environment var not configured.
!endif
!ifndef WIN32VCS
!error WIN32VCS Environment var not configured.
!endif
!ifndef COMPILER
!error COMPILER Environment var not configured.
!endif
#===========================================================================
# User-defined section: the user should tailor this section for each project
#===========================================================================
PROJ_NAME = keyboard
PROJ_DIR = $(WIN32LIB)\$(PROJ_NAME)
LIB_DIR = $(WIN32LIB)\lib
!include $(WIN32LIB)\\project.cfg
#---------------------------------------------------------------------------
# Project-dependent variables
#---------------------------------------------------------------------------
OBJECTS = \
keyboard.obj
#---------------------------------------------------------------------------
# Path macros: one path for each file type.
# These paths are used to tell make where to find/put each file type.
#---------------------------------------------------------------------------
.path.asm = $(PROJ_DIR)
.path.c = $(PROJ_DIR)
.path.cpp = $(PROJ_DIR)
.path.h = $(PROJ_DIR)
.path.obj = $(PROJ_DIR)
.path.lib = $(WIN32LIB)\lib
.path.exe = $(PROJ_DIR)
#===========================================================================
# Pre-defined section: there should be little need to modify this section.
#===========================================================================
#---------------------------------------------------------------------------
# Tools/commands
#---------------------------------------------------------------------------
C_CMD = bcc32
CPP_CMD = bcc32
LIB_CMD = tlib
LINK_CMD = tlink32
ASM_CMD = tasm32
#---------------------------------------------------------------------------
# Include & library paths
# If LIB & INCLUDE are already defined, they are used in addition to the
# WWLIB32 lib & include; otherwise, they're constructed from
# BCDIR & TNTDIR
#---------------------------------------------------------------------------
LIBPATH = $(WIN32LIB)\LIB;$(COMPILER)\LIB
INCLUDEPATH = $(WIN32LIB)\INCLUDE;$(COMPILER)\INCLUDE
#---------------------------------------------------------------------------
# Implicit rules
# Compiler:
# ($< = full dependent with path)
# Assembler:
# output obj's are constructed from .obj: & the $& macro
# ($< = full dependent with path)
# tasm's cfg file is not invoked as a response file.
#---------------------------------------------------------------------------
.c.obj:
$(C_CMD) $(CC_CFG) $<
.cpp.obj:
$(CPP_CMD) $(CC_CFG) $<
.asm.obj:
$(ASM_CMD) $(ASM_CFG) $<
#---------------------------------------------------------------------------
# Default target: configuration files & library (in that order)
#---------------------------------------------------------------------------
all: $(LIB_DIR)\$(PROJ_NAME).lib
#---------------------------------------------------------------------------
# Build the library
# The original library is deleted by the librarian
# Lib objects & -+ commands are constructed by substituting within the
# $^@ macro (which expands to all target dependents, separated with
# spaces)
# Tlib's cfg file is not invoked as a response file.
# All headers & source files are copied into WIN32LIB\SRCDEBUG, for debugging
#---------------------------------------------------------------------------
$(LIB_DIR)\\$(PROJ_NAME).lib: $(OBJECTS)
copy *.h $(WIN32LIB)\\include
copy *.inc $(WIN32LIB)\\include
copy *.cpp $(WIN32LIB)\\srcdebug
copy *.asm $(WIN32LIB)\\srcdebug
$(LIB_CMD) $< $(LIB_CFG) @&&|
-+keyboard.obj
|
#---------------------------------------------------------------------------
# Create the test directory and make it.
#---------------------------------------------------------------------------
test:
mkdir test
cd test
copy $(WWVCS)\\$(PROJ_NAME)\test\vcs.cfg
update
wmake
cd ..

View File

@@ -0,0 +1,179 @@
#
# Command & Conquer Red Alert(tm)
# Copyright 2025 Electronic Arts Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#***************************************************************************
#** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
#***************************************************************************
#* *
#* Project Name : Westwood Library .LIB makefile *
#* *
#* File Name : MAKEFILE *
#* *
#* Programmer : Julio R. Jerez *
#* *
#* Start Date : Jan 26, 1995 *
#* *
#* *
#*-------------------------------------------------------------------------*
#* *
#* Required environment variables: *
#* WIN32LIB = your root WIN32LIB path *
#* WIN32VCS = root directory for wwlib version control archive *
#* COMPILER = your Watcom installation path *
#* *
#* Required changes to makefile: *
#* PROJ_NAME = name of the library you're building *
#* OBJECTS = list of objects in your library *
#* *
#* Optional changes to makefile: *
#* PROJ_DIR = full pathname of your working directory *
#* .path.xxx = full pathname where various file types live *
#* *
#***************************************************************************
#---------------------------------------------------------------------------
# Verify user's environment
#---------------------------------------------------------------------------
!ifndef %WIN32LIB
!error WIN32LIB Environment var not configured.
!endif
!ifndef %WIN32VCS
!error WIN32VCS Environment var not configured.
!endif
!ifndef %WATCOM
!error WATCOM Environment var not configured.
!endif
#===========================================================================
# User-defined section: the user should tailor this section for each project
#===========================================================================
PROJ_NAME = keyboard
PROJ_DIR = $(%WIN32LIB)\$(PROJ_NAME)
LIB_DIR = $(%WIN32LIB)\lib
!include $(%WIN32LIB)\project.cfg
#---------------------------------------------------------------------------
# Project-dependent variables
#---------------------------------------------------------------------------
OBJECTS = &
keyboard.obj
#---------------------------------------------------------------------------
# Path macros: one path for each file type.
# These paths are used to tell make where to find/put each file type.
#---------------------------------------------------------------------------
.asm: $(PROJ_DIR)
.c: $(PROJ_DIR)
.cpp: $(PROJ_DIR)
.h: $(PROJ_DIR)
.obj: $(PROJ_DIR)
.lib: $(WWLIB)\lib
.exe: $(PROJ_DIR)
#===========================================================================
# Pre-defined section: there should be little need to modify this section.
#===========================================================================
#---------------------------------------------------------------------------
# Tools/commands
#---------------------------------------------------------------------------
C_CMD = wcc386
CPP_CMD = wpp386
LIB_CMD = wlib
LINK_CMD = wlink
ASM_CMD = tasm32
#---------------------------------------------------------------------------
# Include & library paths
# If LIB & INCLUDE are already defined, they are used in addition to the
# WWLIB32 lib & include; otherwise, they're constructed from
# BCDIR & TNTDIR
#---------------------------------------------------------------------------
LIBPATH = $(%WIN32LIB)\LIB;$(%WATCOM)\LIB
INCLUDEPATH = $(%WIN32LIB)\INCLUDE;$(%WATCOM)\H
#---------------------------------------------------------------------------
# Implicit rules
# Compiler:
# ($< = full dependent with path)
# Assembler:
# output obj's are constructed from .obj: & the $& macro
# ($< = full dependent with path)
# tasm's cfg file is not invoked as a response file.
#---------------------------------------------------------------------------
.c.obj: $(%WIN32LIB)\project.cfg .AUTODEPEND
$(C_CMD) $(CC_CFG) $<
.cpp.obj: $(%WIN32LIB)\project.cfg .AUTODEPEND
$(CPP_CMD) $(CC_CFG) $<
.asm.obj: $(%WIN32LIB)\project.cfg
$(ASM_CMD) $(ASM_CFG) $<
#---------------------------------------------------------------------------
# Default target: configuration files & library (in that order)
#---------------------------------------------------------------------------
all: $(LIB_DIR)\$(PROJ_NAME).lib .SYMBOLIC
#---------------------------------------------------------------------------
# Build the library
# The original library is deleted by the librarian
# Lib objects & -+ commands are constructed by substituting within the
# $^@ macro (which expands to all target dependents, separated with
# spaces)
# Tlib's cfg file is not invoked as a response file.
# All headers & source files are copied into WIN32LIB\SRCDEBUG, for debugging
#---------------------------------------------------------------------------
$(LIB_DIR)\$(PROJ_NAME).lib: $(OBJECTS) objects.lbc
copy *.h $(%WIN32LIB)\include
copy *.inc $(%WIN32LIB)\include
copy *.cpp $(%WIN32LIB)\srcdebug
copy *.asm $(%WIN32LIB)\srcdebug
$(LIB_CMD) $(LIB_CFG) $^@ @objects.lbc
#---------------------------------------------------------------------------
# Objects now have a link file which is NOT generated everytime. Instead
# it just has its own dependacy rule.
#---------------------------------------------------------------------------
objects.lbc : $(OBJECTS)
%create $^@
for %index in ($(OBJECTS)) do %append $^@ +%index
#---------------------------------------------------------------------------
# Create the test directory and make it.
#---------------------------------------------------------------------------
test:
mkdir test
cd test
copy $(%WWVCS)\$(PROJ_NAME)\test\vcs.cfg
update
wmake
cd ..
#**************************** End of makefile ******************************

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,629 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
* *
* Project Name : Westwood 32 bit Library *
* *
* File Name : MOUSE.CPP *
* *
* Programmer : Philip W. Gorrow *
* *
* Start Date : 12/12/95 *
* *
* Last Update : December 12, 1995 [PWG] *
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* WWMouseClass::WWMouseClass -- Constructor for the Mouse Class *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "mouse.h"
#include <mmsystem.h>
static WWMouseClass *_Mouse=NULL;
void CALLBACK Process_Mouse( UINT event_id, UINT res1 , DWORD user, DWORD res2, DWORD res3 );
/***********************************************************************************************
* MOUSECLASS::MOUSECLASS -- Constructor for the Mouse Class *
* *
* INPUT: GraphicBufferClass * screen - pointer to screen mouse is created for * *
* *
* OUTPUT: none *
* *
* HISTORY: *
* 12/12/1995 PWG : Created. *
*=============================================================================================*/
WWMouseClass::WWMouseClass(GraphicBufferClass *scr, int mouse_max_width, int mouse_max_height)
{
MouseCursor = new char[mouse_max_width * mouse_max_height];
MouseXHot = 0;
MouseYHot = 0;
CursorWidth = 0;
CursorHeight = 0;
MouseBuffer = new char[mouse_max_width * mouse_max_height];
MouseBuffX = -1;
MouseBuffY = -1;
MaxWidth = mouse_max_width;
MaxHeight = mouse_max_height;
MouseCXLeft = 0;
MouseCYUpper = 0;
MouseCXRight = 0;
MouseCYLower = 0;
MCFlags = 0;
MCCount = 0;
Screen = scr;
PrevCursor = NULL;
MouseUpdate = 0;
State = 1;
timeBeginPeriod ( 1000/ 60);
MutexObject = CreateMutex(NULL, FALSE, "WWLIB32MOUSEMUTEX");
//
// Install the timer callback event handler
//
EraseBuffer = new char[mouse_max_width * mouse_max_height];
EraseBuffX = -1;
EraseBuffY = -1;
EraseBuffHotX = -1;
EraseBuffHotY = -1;
EraseFlags = FALSE;
_Mouse = this;
TimerHandle = timeSetEvent( 1000/60 , 1 , ::Process_Mouse, 0 , TIME_PERIODIC);
}
WWMouseClass::~WWMouseClass()
{
WaitForSingleObject(MutexObject, INFINITE);
MouseUpdate++;
if (MouseCursor) delete[] MouseCursor;
if (MouseBuffer) delete[] MouseBuffer;
if (TimerHandle) {
timeKillEvent(TimerHandle);
}
timeEndPeriod (1);
ReleaseMutex(MutexObject);
}
void WWMouseClass::Process_Mouse(void)
{
POINT pt; // define a structure to hold current cursor pos
//
// If the mouse is currently hidden or it has not been installed, then we
// have no need to redraw the mouse.
//
if (!_Mouse || State > 0 || MouseUpdate || EraseFlags)
return;
//
// Wait until we have exclusive access to our data
//
WaitForSingleObject(MutexObject, INFINITE);
//
// Get the mouse's current real cursor position
//
GetCursorPos(&pt); // get the current cursor position
//
// If the mouse has moved then we are responsible to redraw the mouse
//
if (pt.x != MouseBuffX || pt.y != MouseBuffY) {
if (!EraseFlags) {
//
// If we can't lock the surface we need to draw to, we cannot update
// the mouse.
//
if (Screen->Lock()) {
//
// Erase the old mouse by dumping the mouses shadow buff
// to the screen (if its position had ever been recorded).
//
Low_Hide_Mouse();
//
// Verify that the mouse has not gone into a conditional hiden area
// If it has, mark it as being in one.
//
if (MCFlags & CONDHIDE && pt.x >= MouseCXLeft && pt.x <= MouseCXRight && pt.y >= MouseCYUpper && pt.y <= MouseCYLower) {
MCFlags |= CONDHIDDEN;
}
//
// Show the mouse if we are allowed to.
//
if (!(MCFlags & CONDHIDDEN)) {
Low_Show_Mouse(pt.x, pt.y);
}
//
// Finally unlock the destination surface as we have sucessfully
// updated the mouse.
//
Screen->Unlock();
}
} else {
if (MCFlags & CONDHIDE && pt.x >= MouseCXLeft && pt.x <= MouseCXRight && pt.y >= MouseCYUpper && pt.y <= MouseCYLower) {
MCFlags |= CONDHIDDEN;
State++;
}
}
}
ReleaseMutex(MutexObject);
}
void *WWMouseClass::Set_Cursor(int xhotspot, int yhotspot, void *cursor)
{
//
// If the pointer to the cursor we got is invalid, or its the same as the
// currently set cursor then just return.
if (!cursor || cursor == PrevCursor)
return(cursor);
//
// Wait until we have exclusive access to our data
//
WaitForSingleObject(MutexObject, INFINITE);
MouseUpdate++;
//
// Since we are updating the mouse we need to hide the cursor so we
// do not get some sort of weird transformation.
//
Hide_Mouse();
//
// Now convert the shape to a mouse cursor with the given hotspots and
// set it as our current mouse.
//
void *retval = ASM_Set_Mouse_Cursor(this, xhotspot, yhotspot, cursor);
//
// Show the mouse which will force it to appear with the new shape we
// have assigned.
//
Show_Mouse();
//
// We are done updating the mouse cursor so on to bigger and better things.
//
MouseUpdate--;
//
// Inform Windows that we are done using the exclusive data we requested.
//
ReleaseMutex(MutexObject);
//
// Return the previous mouse cursor which as conveniantly passed back by
// Asm_Set_Mouse_Cursor.
//
return(retval);
}
void WWMouseClass::Low_Hide_Mouse()
{
if (!State) {
while (!Screen->Lock()) {}
if (MouseBuffX != -1 || MouseBuffY != -1) {
Mouse_Shadow_Buffer(this, Screen, MouseBuffer, MouseBuffX, MouseBuffY, MouseXHot, MouseYHot, 0);
}
MouseBuffX = -1;
MouseBuffY = -1;
Screen->Unlock();
}
State++;
}
void WWMouseClass::Hide_Mouse()
{
//
// Wait until we have exclusive access to our data
//
WaitForSingleObject(MutexObject, INFINITE);
MouseUpdate++;
Low_Hide_Mouse();
MouseUpdate--;
ReleaseMutex(MutexObject);
}
void WWMouseClass::Low_Show_Mouse(int x, int y)
{
//
// If the mouse is already visible then just ignore the problem.
//
if (State == 0) return;
//
// Make the mouse a little bit more visible
//
State--;
//
// If the mouse is completely visible then draw it at its current
// position.
//
if (!State) {
//
// Try to lock the screen til we sucessfully get a lock.
//
while (!Screen->Lock()) {}
//
// Save off the area behind the mouse.
//
Mouse_Shadow_Buffer(this, Screen, MouseBuffer, x, y, MouseXHot, MouseYHot, 1);
//
// Draw the mouse in its new location
//
::Draw_Mouse(this, Screen, x, y);
//
// Save off the positions that we saved the buffer from
//
MouseBuffX = x;
MouseBuffY = y;
//
// Unlock the screen and lets get moving.
//
Screen->Unlock();
}
}
void WWMouseClass::Show_Mouse()
{
POINT pt;
GetCursorPos(&pt);
//
// Wait until we have exclusive access to our data
//
WaitForSingleObject(MutexObject, INFINITE);
MouseUpdate++;
Low_Show_Mouse(pt.x, pt.y);
MouseUpdate--;
ReleaseMutex(MutexObject);
}
void WWMouseClass::Conditional_Hide_Mouse(int x1, int y1, int x2, int y2)
{
POINT pt;
//
// Wait until we have exclusive access to our data
//
WaitForSingleObject(MutexObject, INFINITE);
MouseUpdate++;
//
// First of all, adjust all the coordinates so that they handle
// the fact that the hotspot is not necessarily the upper left
// corner of the mouse.
//
x1 -= (CursorWidth - MouseXHot);
x1 = MAX(0, x1);
y1 -= (CursorHeight - MouseYHot);
y1 = MAX(0, y1);
x2 += MouseXHot;
x2 = MIN(x2, Screen->Get_Width());
y2 += MouseYHot;
y2 = MIN(y2, Screen->Get_Height());
// The mouse could be in one of four conditions.
// 1) The mouse is visible and no conditional hide has been specified.
// (perform normal region checking with possible hide)
// 2) The mouse is hidden and no conditional hide as been specified.
// (record region and do nothing)
// 3) The mouse is visible and a conditional region has been specified
// (expand region and perform check with possible hide).
// 4) The mouse is already hidden by a previous conditional.
// (expand region and do nothing)
//
// First: Set or expand the region according to the specified parameters
if (!MCCount) {
MouseCXLeft = x1;
MouseCYUpper = y1;
MouseCXRight = x2;
MouseCYLower = y2;
} else {
MouseCXLeft = MIN(x1, MouseCXLeft);
MouseCYUpper = MIN(y1, MouseCYUpper);
MouseCXRight = MAX(x2, MouseCXRight);
MouseCYLower = MAX(y2, MouseCYLower);
}
//
// If the mouse isn't already hidden, then check its location against
// the hiding region and hide if necessary.
//
if (!(MCFlags & CONDHIDDEN)) {
GetCursorPos(&pt);
if (pt.x >= MouseCXLeft && pt.x <= MouseCXRight && pt.y >= MouseCYUpper && pt.y <= MouseCYLower) {
Hide_Mouse();
MCFlags |= CONDHIDDEN;
}
}
//
// Record the fact that a conditional hide was called and then exit
//
//
MCFlags |= CONDHIDE;
MCCount++;
MouseUpdate--;
ReleaseMutex(MutexObject);
}
void WWMouseClass::Conditional_Show_Mouse(void)
{
//
// Wait until we have exclusive access to our data
//
WaitForSingleObject(MutexObject, INFINITE);
MouseUpdate++;
//
// if there are any nested hides then dec the count
//
if (MCCount) {
MCCount--;
//
// If the mouse is now not hidden and it had actually been
// hidden before then display it.
//
if (!MCCount) {
if (MCFlags & CONDHIDDEN) {
Show_Mouse();
}
MCFlags = 0;
}
}
MouseUpdate--;
ReleaseMutex(MutexObject);
}
void WWMouseClass::Draw_Mouse(GraphicBufferClass *scr)
{
POINT pt;
if (State != 0) return;
//
// Wait until we have exclusive access to our data
//
WaitForSingleObject(MutexObject, INFINITE);
MouseUpdate++;
//
// Get the position that the mouse is currently located at
//
GetCursorPos(&pt);
if (MCFlags & CONDHIDE && pt.x >= MouseCXLeft && pt.x <= MouseCXRight && pt.y >= MouseCYUpper && pt.y <= MouseCYLower) {
Hide_Mouse();
MCFlags |= CONDHIDDEN;
} else {
//
// If the mouse is already visible then just ignore the problem.
//
EraseFlags = TRUE;
//
// Try to lock the screen til we sucessfully get a lock.
//
while (!scr->Lock()) {}
//
// Save off the area behind the mouse into two different buffers, one
// which will be used to restore the mouse and the other which will
// be used to restore the hidden surface when we get a chance.
//
Mouse_Shadow_Buffer(this, scr, EraseBuffer, pt.x, pt.y, MouseXHot, MouseYHot, 1);
memcpy(MouseBuffer, EraseBuffer, MaxWidth * MaxHeight);
//
// Draw the mouse in its new location
//
::Draw_Mouse(this, scr, pt.x, pt.y);
//
// Save off the positions that we saved the buffer from
//
EraseBuffX = pt.x;
MouseBuffX = pt.x;
EraseBuffY = pt.y;
MouseBuffY = pt.y;
EraseBuffHotX = MouseXHot;
EraseBuffHotY = MouseYHot;
//
// Unlock the screen and lets get moving.
//
scr->Unlock();
}
MouseUpdate--;
ReleaseMutex(MutexObject);
}
void WWMouseClass::Erase_Mouse(GraphicBufferClass *scr, int forced)
{
// if (!EraseFlags) return;
// if (State != 0) return;
//
// If we are forcing the redraw of a mouse we already managed to
// restore then just get outta here.
//
if (forced && EraseBuffX == -1 && EraseBuffY == -1) return;
//
// If we don't own the Mutex Object, then we need to because we may
// update the mouse.
//
WaitForSingleObject(MutexObject, INFINITE);
MouseUpdate++;
//
// If this is not a forced call, only update the mouse is we can legally
// lock the buffer.
//
if (!forced) {
#if(0)
if (scr->Lock()) {
//
// If the surface has not already been restore then restore it and erase the
// restoration coordinates so we don't accidentally do it twice.
//
if (EraseBuffX != -1 || EraseBuffY != -1) {
Mouse_Shadow_Buffer(this, scr, EraseBuffer, EraseBuffX, EraseBuffY, 0);
EraseBuffX = -1;
EraseBuffY = -1;
}
//
// We are done writing to the buffer so unlock it.
//
scr->Unlock();
}
#endif
} else {
//
// If this is a forced call then wait til we are allowed to update the buffer
//
while (!scr->Lock()) {}
//
// If the surface has not already been restore then restore it and erase the
// restoration coordinates so we don't accidentally do it twice.
//
if (EraseBuffX != -1 || EraseBuffY != -1) {
Mouse_Shadow_Buffer(this, scr, EraseBuffer, EraseBuffX, EraseBuffY, EraseBuffHotX, EraseBuffHotY, 0);
}
//
// We are done writing to the buffer so unlock it.
//
scr->Unlock();
}
MouseUpdate--;
ReleaseMutex(MutexObject);
EraseFlags = FALSE;
}
int WWMouseClass::Get_Mouse_State(void)
{
return(State);
}
/***********************************************************************************************
* WWKeyboardClass::Get_Mouse_X -- Returns the mouses current x position in pixels *
* *
* INPUT: none *
* *
* OUTPUT: int - returns the mouses current x position in pixels *
* *
* HISTORY: *
* 10/17/1995 PWG : Created. *
*=============================================================================================*/
int WWMouseClass::Get_Mouse_X(void)
{
POINT pt;
GetCursorPos(&pt);
return(pt.x);
}
/***********************************************************************************************
* WWKeyboardClass::Get_Mouse_Y -- returns the mouses current y position in pixels *
* *
* INPUT: none *
* *
* OUTPUT: int - returns the mouses current y position in pixels *
* *
* HISTORY: *
* 10/17/1995 PWG : Created. *
*=============================================================================================*/
int WWMouseClass::Get_Mouse_Y(void)
{
POINT pt;
GetCursorPos(&pt);
return(pt.y);
}
/***********************************************************************************************
* WWKeyboardClass::Get_Mouse_XY -- Returns the mouses x,y position via reference vars *
* *
* INPUT: int &x - variable to return the mouses x position in pixels *
* int &y - variable to return the mouses y position in pixels *
* *
* OUTPUT: none - output is via reference variables *
* *
* HISTORY: *
* 10/17/1995 PWG : Created. *
*=============================================================================================*/
void WWMouseClass::Get_Mouse_XY(int &x, int &y)
{
POINT pt;
GetCursorPos(&pt);
x = pt.x;
y = pt.y;
}
#pragma off(unreferenced)
void CALLBACK Process_Mouse( UINT event_id, UINT res1 , DWORD user, DWORD res2, DWORD res3 )
{
if (_Mouse) {
_Mouse->Process_Mouse();
}
}
#pragma on(unreferenced)
void Hide_Mouse(void)
{
if (!_Mouse) return;
_Mouse->Hide_Mouse();
}
void Show_Mouse(void)
{
if (!_Mouse) return;
_Mouse->Show_Mouse();
}
void Conditional_Hide_Mouse(int x1, int y1, int x2, int y2)
{
if (!_Mouse) return;
_Mouse->Conditional_Hide_Mouse(x1, y1, x2, y2);
}
void Conditional_Show_Mouse(void)
{
if (!_Mouse) return;
_Mouse->Conditional_Show_Mouse();
}
int Get_Mouse_State(void)
{
if (!_Mouse) return(0);
return(_Mouse->Get_Mouse_State());
}
void *Set_Mouse_Cursor(int hotx, int hoty, void *cursor)
{
if (!_Mouse) return(0);
return(_Mouse->Set_Cursor(hotx,hoty,cursor));
}
int Get_Mouse_X(void)
{
if (!_Mouse) return(0);
return(_Mouse->Get_Mouse_X());
}
int Get_Mouse_Y(void)
{
if (!_Mouse) return(0);
return(_Mouse->Get_Mouse_Y());
}

View File

@@ -0,0 +1,629 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
* *
* Project Name : Westwood 32 bit Library *
* *
* File Name : MOUSE.CPP *
* *
* Programmer : Philip W. Gorrow *
* *
* Start Date : 12/12/95 *
* *
* Last Update : December 12, 1995 [PWG] *
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* WWMouseClass::WWMouseClass -- Constructor for the Mouse Class *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "mouse.h"
#include <mmsystem.h>
static WWMouseClass *_Mouse=NULL;
void CALLBACK Process_Mouse( UINT event_id, UINT res1 , DWORD user, DWORD res2, DWORD res3 );
/***********************************************************************************************
* MOUSECLASS::MOUSECLASS -- Constructor for the Mouse Class *
* *
* INPUT: GraphicBufferClass * screen - pointer to screen mouse is created for * *
* *
* OUTPUT: none *
* *
* HISTORY: *
* 12/12/1995 PWG : Created. *
*=============================================================================================*/
WWMouseClass::WWMouseClass(GraphicBufferClass *scr, int mouse_max_width, int mouse_max_height)
{
MouseCursor = new char[mouse_max_width * mouse_max_height];
MouseXHot = 0;
MouseYHot = 0;
CursorWidth = 0;
CursorHeight = 0;
MouseBuffer = new char[mouse_max_width * mouse_max_height];
MouseBuffX = -1;
MouseBuffY = -1;
MaxWidth = mouse_max_width;
MaxHeight = mouse_max_height;
MouseCXLeft = 0;
MouseCYUpper = 0;
MouseCXRight = 0;
MouseCYLower = 0;
MCFlags = 0;
MCCount = 0;
Screen = scr;
PrevCursor = NULL;
MouseUpdate = 0;
State = 1;
timeBeginPeriod ( 1000/ 60);
MutexObject = CreateMutex(NULL, FALSE, "WWLIB32MOUSEMUTEX");
//
// Install the timer callback event handler
//
EraseBuffer = new char[mouse_max_width * mouse_max_height];
EraseBuffX = -1;
EraseBuffY = -1;
EraseFlags = FALSE;
_Mouse = this;
TimerHandle = timeSetEvent( 1000/60 , 1 , ::Process_Mouse, 0 , TIME_PERIODIC);
}
WWMouseClass::~WWMouseClass()
{
WaitForSingleObject(MutexObject, INFINITE);
MouseUpdate++;
if (MouseCursor) delete[] MouseCursor;
if (MouseBuffer) delete[] MouseBuffer;
if (TimerHandle) {
timeKillEvent(TimerHandle);
}
timeEndPeriod (1);
ReleaseMutex(MutexObject);
}
void WWMouseClass::Process_Mouse(void)
{
POINT pt; // define a structure to hold current cursor pos
//
// If the mouse is currently hidden or it has not been installed, then we
// have no need to redraw the mouse.
//
if (!_Mouse || State > 0 || MouseUpdate || EraseFlags)
return;
//
// Wait until we have exclusive access to our data
//
WaitForSingleObject(MutexObject, INFINITE);
//
// Get the mouse's current real cursor position
//
GetCursorPos(&pt); // get the current cursor position
//
// If the mouse has moved then we are responsible to redraw the mouse
//
if (pt.x != MouseBuffX || pt.y != MouseBuffY) {
if (!EraseFlags) {
//
// If we can't lock the surface we need to draw to, we cannot update
// the mouse.
//
if (Screen->Lock()) {
//
// Erase the old mouse by dumping the mouses shadow buff
// to the screen (if its position had ever been recorded).
//
Low_Hide_Mouse();
//
// Verify that the mouse has not gone into a conditional hiden area
// If it has, mark it as being in one.
//
if (MCFlags & CONDHIDE && pt.x >= MouseCXLeft && pt.x <= MouseCXRight && pt.y >= MouseCYUpper && pt.y <= MouseCYLower) {
MCFlags |= CONDHIDDEN;
}
//
// Show the mouse if we are allowed to.
//
if (!(MCFlags & CONDHIDDEN)) {
Low_Show_Mouse(pt.x, pt.y);
}
//
// Finally unlock the destination surface as we have sucessfully
// updated the mouse.
//
Screen->Unlock();
}
} else {
if (MCFlags & CONDHIDE && pt.x >= MouseCXLeft && pt.x <= MouseCXRight && pt.y >= MouseCYUpper && pt.y <= MouseCYLower) {
MCFlags |= CONDHIDDEN;
State++;
}
}
}
ReleaseMutex(MutexObject);
}
void *WWMouseClass::Set_Cursor(int xhotspot, int yhotspot, void *cursor)
{
//
// If the pointer to the cursor we got is invalid, or its the same as the
// currently set cursor then just return.
if (!cursor || cursor == PrevCursor)
return(cursor);
//
// Wait until we have exclusive access to our data
//
WaitForSingleObject(MutexObject, INFINITE);
MouseUpdate++;
//
// Since we are updating the mouse we need to hide the cursor so we
// do not get some sort of weird transformation.
//
Hide_Mouse();
//
// Now convert the shape to a mouse cursor with the given hotspots and
// set it as our current mouse.
//
void *retval = ASM_Set_Mouse_Cursor(this, xhotspot, yhotspot, cursor);
//
// Show the mouse which will force it to appear with the new shape we
// have assigned.
//
Show_Mouse();
//
// We are done updating the mouse cursor so on to bigger and better things.
//
MouseUpdate--;
//
// Inform Windows that we are done using the exclusive data we requested.
//
ReleaseMutex(MutexObject);
//
// Return the previous mouse cursor which as conveniantly passed back by
// Asm_Set_Mouse_Cursor.
//
return(retval);
}
void WWMouseClass::Low_Hide_Mouse()
{
if (!State) {
while (!Screen->Lock()) {}
if (MouseBuffX != -1 || MouseBuffY != -1) {
Mouse_Shadow_Buffer(this, Screen, MouseBuffer, MouseBuffX, MouseBuffY, 0);
}
MouseBuffX = -1;
MouseBuffY = -1;
Screen->Unlock();
}
State++;
}
void WWMouseClass::Hide_Mouse()
{
//
// Wait until we have exclusive access to our data
//
WaitForSingleObject(MutexObject, INFINITE);
MouseUpdate++;
Low_Hide_Mouse();
MouseUpdate--;
ReleaseMutex(MutexObject);
}
void WWMouseClass::Low_Show_Mouse(int x, int y)
{
//
// If the mouse is already visible then just ignore the problem.
//
if (State == 0) return;
//
// Make the mouse a little bit more visible
//
State--;
//
// If the mouse is completely visible then draw it at its current
// position.
//
if (!State) {
//
// Try to lock the screen til we sucessfully get a lock.
//
while (!Screen->Lock()) {}
//
// Save off the area behind the mouse.
//
Mouse_Shadow_Buffer(this, Screen, MouseBuffer, x, y, 1);
//
// Draw the mouse in its new location
//
::Draw_Mouse(this, Screen, x, y);
//
// Save off the positions that we saved the buffer from
//
MouseBuffX = x;
MouseBuffY = y;
//
// Unlock the screen and lets get moving.
//
Screen->Unlock();
}
}
void WWMouseClass::Show_Mouse()
{
POINT pt;
GetCursorPos(&pt);
//
// Wait until we have exclusive access to our data
//
WaitForSingleObject(MutexObject, INFINITE);
MouseUpdate++;
Low_Show_Mouse(pt.x, pt.y);
MouseUpdate--;
ReleaseMutex(MutexObject);
}
void WWMouseClass::Conditional_Hide_Mouse(int x1, int y1, int x2, int y2)
{
POINT pt;
//
// Wait until we have exclusive access to our data
//
WaitForSingleObject(MutexObject, INFINITE);
MouseUpdate++;
//
// First of all, adjust all the coordinates so that they handle
// the fact that the hotspot is not necessarily the upper left
// corner of the mouse.
//
x1 -= (CursorWidth - MouseXHot);
x1 = MAX(0, x1);
y1 -= (CursorHeight - MouseYHot);
y1 = MAX(0, y1);
x2 += MouseXHot;
x2 = MIN(x2, Screen->Get_Width());
y2 += MouseYHot;
y2 = MIN(y2, Screen->Get_Height());
// The mouse could be in one of four conditions.
// 1) The mouse is visible and no conditional hide has been specified.
// (perform normal region checking with possible hide)
// 2) The mouse is hidden and no conditional hide as been specified.
// (record region and do nothing)
// 3) The mouse is visible and a conditional region has been specified
// (expand region and perform check with possible hide).
// 4) The mouse is already hidden by a previous conditional.
// (expand region and do nothing)
//
// First: Set or expand the region according to the specified parameters
if (!MCCount) {
MouseCXLeft = x1;
MouseCYUpper = y1;
MouseCXRight = x2;
MouseCYLower = y2;
} else {
MouseCXLeft = MIN(x1, MouseCXLeft);
MouseCYUpper = MIN(y1, MouseCYUpper);
MouseCXRight = MAX(x2, MouseCXRight);
MouseCYLower = MAX(y2, MouseCYLower);
}
//
// If the mouse isn't already hidden, then check its location against
// the hiding region and hide if necessary.
//
if (!(MCFlags & CONDHIDDEN)) {
GetCursorPos(&pt);
if (pt.x >= MouseCXLeft && pt.x <= MouseCXRight && pt.y >= MouseCYUpper && pt.y <= MouseCYLower) {
Hide_Mouse();
MCFlags |= CONDHIDDEN;
}
}
//
// Record the fact that a conditional hide was called and then exit
//
//
MCFlags |= CONDHIDE;
MCCount++;
MouseUpdate--;
ReleaseMutex(MutexObject);
}
void WWMouseClass::Conditional_Show_Mouse(void)
{
//
// Wait until we have exclusive access to our data
//
WaitForSingleObject(MutexObject, INFINITE);
MouseUpdate++;
//
// if there are any nested hides then dec the count
//
if (MCCount) {
MCCount--;
//
// If the mouse is now not hidden and it had actually been
// hidden before then display it.
//
if (!MCCount) {
if (MCFlags & CONDHIDDEN) {
Show_Mouse();
}
MCFlags = 0;
}
}
MouseUpdate--;
ReleaseMutex(MutexObject);
}
void WWMouseClass::Draw_Mouse(GraphicBufferClass *scr)
{
POINT pt;
if (State != 0) return;
//
// Wait until we have exclusive access to our data
//
WaitForSingleObject(MutexObject, INFINITE);
MouseUpdate++;
//
// Get the position that the mouse is currently located at
//
GetCursorPos(&pt);
if (MCFlags & CONDHIDE) {
if (pt.x >= MouseCXLeft && pt.x <= MouseCXRight && pt.y >= MouseCYUpper && pt.y <= MouseCYLower) {
Hide_Mouse();
MCFlags |= CONDHIDDEN;
}
} else {
//
// If the mouse is already visible then just ignore the problem.
//
EraseFlags = TRUE;
//
// Try to lock the screen til we sucessfully get a lock.
//
while (!scr->Lock()) {}
//
// Save off the area behind the mouse into two different buffers, one
// which will be used to restore the mouse and the other which will
// be used to restore the hidden surface when we get a chance.
//
Mouse_Shadow_Buffer(this, scr, EraseBuffer, pt.x, pt.y, 1);
memcpy(MouseBuffer, EraseBuffer, MaxWidth * MaxHeight);
//
// Draw the mouse in its new location
//
::Draw_Mouse(this, scr, pt.x, pt.y);
//
// Save off the positions that we saved the buffer from
//
EraseBuffX = pt.x;
MouseBuffX = pt.x;
EraseBuffY = pt.y;
MouseBuffY = pt.y;
//
// Unlock the screen and lets get moving.
//
scr->Unlock();
}
MouseUpdate--;
ReleaseMutex(MutexObject);
}
void WWMouseClass::Erase_Mouse(GraphicBufferClass *scr, int forced)
{
if (!EraseFlags) return;
// if (State != 0) return;
//
// If we are forcing the redraw of a mouse we already managed to
// restore then just get outta here.
//
if (forced && EraseBuffX == -1 && EraseBuffY == -1) return;
//
// If we don't own the Mutex Object, then we need to because we may
// update the mouse.
//
WaitForSingleObject(MutexObject, INFINITE);
MouseUpdate++;
//
// If this is not a forced call, only update the mouse is we can legally
// lock the buffer.
//
if (!forced) {
#if(0)
if (scr->Lock()) {
//
// If the surface has not already been restore then restore it and erase the
// restoration coordinates so we don't accidentally do it twice.
//
if (EraseBuffX != -1 || EraseBuffY != -1) {
Mouse_Shadow_Buffer(this, scr, EraseBuffer, EraseBuffX, EraseBuffY, 0);
EraseBuffX = -1;
EraseBuffY = -1;
}
//
// We are done writing to the buffer so unlock it.
//
scr->Unlock();
}
#endif
} else {
//
// If this is a forced call then wait til we are allowed to update the buffer
//
while (!scr->Lock()) {}
//
// If the surface has not already been restore then restore it and erase the
// restoration coordinates so we don't accidentally do it twice.
//
if (EraseBuffX != -1 || EraseBuffY != -1) {
Mouse_Shadow_Buffer(this, scr, EraseBuffer, EraseBuffX, EraseBuffY, 0);
EraseBuffX = -1;
EraseBuffY = -1;
}
//
// We are done writing to the buffer so unlock it.
//
scr->Unlock();
}
MouseUpdate--;
ReleaseMutex(MutexObject);
EraseFlags = FALSE;
}
int WWMouseClass::Get_Mouse_State(void)
{
return(State);
}
/***********************************************************************************************
* WWKeyboardClass::Get_Mouse_X -- Returns the mouses current x position in pixels *
* *
* INPUT: none *
* *
* OUTPUT: int - returns the mouses current x position in pixels *
* *
* HISTORY: *
* 10/17/1995 PWG : Created. *
*=============================================================================================*/
int WWMouseClass::Get_Mouse_X(void)
{
POINT pt;
GetCursorPos(&pt);
return(pt.x);
}
/***********************************************************************************************
* WWKeyboardClass::Get_Mouse_Y -- returns the mouses current y position in pixels *
* *
* INPUT: none *
* *
* OUTPUT: int - returns the mouses current y position in pixels *
* *
* HISTORY: *
* 10/17/1995 PWG : Created. *
*=============================================================================================*/
int WWMouseClass::Get_Mouse_Y(void)
{
POINT pt;
GetCursorPos(&pt);
return(pt.y);
}
/***********************************************************************************************
* WWKeyboardClass::Get_Mouse_XY -- Returns the mouses x,y position via reference vars *
* *
* INPUT: int &x - variable to return the mouses x position in pixels *
* int &y - variable to return the mouses y position in pixels *
* *
* OUTPUT: none - output is via reference variables *
* *
* HISTORY: *
* 10/17/1995 PWG : Created. *
*=============================================================================================*/
void WWMouseClass::Get_Mouse_XY(int &x, int &y)
{
POINT pt;
GetCursorPos(&pt);
x = pt.x;
y = pt.y;
}
#pragma off(unreferenced)
void CALLBACK Process_Mouse( UINT event_id, UINT res1 , DWORD user, DWORD res2, DWORD res3 )
{
if (_Mouse) {
_Mouse->Process_Mouse();
}
}
#pragma on(unreferenced)
void Hide_Mouse(void)
{
if (!_Mouse) return;
_Mouse->Hide_Mouse();
}
void Show_Mouse(void)
{
if (!_Mouse) return;
_Mouse->Show_Mouse();
}
void Conditional_Hide_Mouse(int x1, int y1, int x2, int y2)
{
if (!_Mouse) return;
_Mouse->Conditional_Hide_Mouse(x1, y1, x2, y2);
}
void Conditional_Show_Mouse(void)
{
if (!_Mouse) return;
_Mouse->Conditional_Show_Mouse();
}
int Get_Mouse_State(void)
{
if (!_Mouse) return(0);
return(_Mouse->Get_Mouse_State());
}
void *Set_Mouse_Cursor(int hotx, int hoty, void *cursor)
{
if (!_Mouse) return(0);
return(_Mouse->Set_Cursor(hotx,hoty,cursor));
}
int Get_Mouse_X(void)
{
if (!_Mouse) return(0);
return(_Mouse->Get_Mouse_X());
}
int Get_Mouse_Y(void)
{
if (!_Mouse) return(0);
return(_Mouse->Get_Mouse_Y());
}

View File

@@ -0,0 +1,121 @@
/*
** Command & Conquer Red Alert(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
* *
* Project Name : Westwood 32 Bit Library *
* *
* File Name : MOUSE.H *
* *
* Programmer : Philip W. Gorrow *
* *
* Start Date : 12/12/95 *
* *
* Last Update : December 12, 1995 [PWG] *
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#ifndef WW_MOUSE_H
#define WW_MOUSE_H
#include <gbuffer.h>
class WWMouseClass {
public:
WWMouseClass(GraphicBufferClass *scr, int mouse_max_width, int mouse_max_height);
~WWMouseClass();
void *Set_Cursor(int xhotspot, int yhotspot, void *cursor);
void Process_Mouse(void);
void Hide_Mouse(void);
void Show_Mouse(void);
void Conditional_Hide_Mouse(int x1, int y1, int x2, int y2);
void Conditional_Show_Mouse(void);
int Get_Mouse_State(void);
int Get_Mouse_X(void);
int Get_Mouse_Y(void);
void Get_Mouse_XY(int &x, int &y);
//
// The following two routines can be used to render the mouse onto a graphicbuffer
// other than the hidpage.
//
void Draw_Mouse(GraphicBufferClass *scr);
void Erase_Mouse(GraphicBufferClass *scr, int forced = FALSE);
private:
enum {
CONDHIDE = 1,
CONDHIDDEN = 2,
};
void Low_Hide_Mouse(void);
void Low_Show_Mouse(int x, int y);
char *MouseCursor; // pointer to the mouse cursor in memory
int MouseXHot; // X hot spot of the current mouse cursor
int MouseYHot; // Y hot spot of the current mouse cursor
int CursorWidth; // width of the mouse cursor in pixels
int CursorHeight; // height of the mouse cursor in pixels
char *MouseBuffer; // pointer to background buffer in memory
int MouseBuffX; // pixel x mouse buffer was preserved at
int MouseBuffY; // pixel y mouse buffer was preserved at
int MaxWidth; // maximum width of mouse background buffer
int MaxHeight; // maximum height of mouse background buffer
int MouseCXLeft; // left x pos if conditional hide mouse in effect
int MouseCYUpper; // upper y pos if conditional hide mouse in effect
int MouseCXRight; // right x pos if conditional hide mouse in effect
int MouseCYLower; // lower y pos if conditional hide mouse in effect
char MCFlags; // conditional hide mouse flags
char MCCount; // nesting count for conditional hide mouse
GraphicBufferClass *Screen; // pointer to the surface mouse was init'd with
char * PrevCursor; // pointer to previous cursor shape
int MouseUpdate;
int State;
char *EraseBuffer; // Buffer which holds background to restore to hidden page
int EraseBuffX; // X position of the hidden page background
int EraseBuffY; // Y position of the hidden page background
int EraseBuffHotX; // X position of the hidden page background
int EraseBuffHotY; // Y position of the hidden page background
int EraseFlags; // Records whether mutex has been released
HANDLE MutexObject; // Handle the Mutex Object created when mouse is
unsigned TimerHandle;
};
extern "C" {
void __cdecl Mouse_Shadow_Buffer(void *thisptr, GraphicBufferClass *srcdst, void *buffer, int x, int y, int hotx, int hoty, int store);
void __cdecl Draw_Mouse(void *thisptr, GraphicBufferClass *srcdst, int x, int y);
void __cdecl *ASM_Set_Mouse_Cursor(void * thisptr, int hotspotx, int hotspoty, VOID *cursor);
};
void Hide_Mouse(void);
void Show_Mouse(void);
void Conditional_Hide_Mouse(int x1, int y1, int x2, int y2);
void Conditional_Show_Mouse(void);
int Get_Mouse_State(void);
void *Set_Mouse_Cursor(int hotx, int hoty, void *cursor);
int Get_Mouse_X(void);
int Get_Mouse_Y(void);
#endif

View File

@@ -0,0 +1,67 @@
;
; Command & Conquer Red Alert(tm)
; Copyright 2025 Electronic Arts Inc.
;
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see <http://www.gnu.org/licenses/>.
;
;***********************************************************************************************
;* *
;* Project Name : Westwood 32 bit Library *
;* *
;* File Name : MOUSE.INC *
;* *
;* Programmer : Philip W. Gorrow *
;* *
;* Start Date : 12/12/95 *
;* *
;* Last Update : December 12, 1995 [PWG] *
;* *
;*---------------------------------------------------------------------------------------------*
;* Functions: *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
STRUC MouseType
MouseCursor DD ? ; pointer to the mouse cursor in memory
MouseXHot DD ? ; X hot spot of the current mouse cursor
MouseYHot DD ? ; Y hot spot of the current mouse cursor
CursorWidth DD ? ; Width of mouse cursor in pixels
CursorHeight DD ? ; Height of the mouse cursor in pixels
MouseBuffer DD ? ; pointer to background buffer in memory
MouseBuffX DD ? ; pixel x mouse buffer was preserved at
MouseBuffY DD ? ; pixel y mouse buffer was preserved at
MaxWidth DD ? ; Maximum possible width of the background buffer
MaxHeight DD ? ; Maximum possible height of the background buffer
MouseCXLeft DD ? ; left hand x position if conditional hide mouse in effect
MouseCYUpper DD ? ; upper y position if conditional hide mouse in effect
MouseCXRight DD ? ; right hand x position if conditional hide mouse in effect
MouseCYLower DD ? ; lower y position if conditional hide mouse in effect
MCFlags DB ? ; conditional hide mouse flags
MCCount DB ? ; nesting count for conditional hide mouse
Screen DD ? ; pointer to the surface mouse was init'd with
PrevCursor DD ? ; pointer to the prev cursor shape
MouseUpdate DD ? ; is the mouse being currently updated
State DD ?
EraseBuffer DD ?
EraseBuffX DD ?
EraseBuffY DD ?
EraseBuffHotX DD ?
EraseBuffHotY DD ?
EraseFlags DD ?
ENDS

View File

@@ -0,0 +1,153 @@
;
; Command & Conquer Red Alert(tm)
; Copyright 2025 Electronic Arts Inc.
;
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see <http://www.gnu.org/licenses/>.
;
;***************************************************************************
;** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S **
;***************************************************************************
;* *
;* Project Name : Library *
;* *
;* File Name : PAGFAULT.ASM *
;* *
;* Programmer : Julio R Jerez *
;* *
;* Date : April 25,1995 *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;
; Here are prototypes for the routines defined within this module:
; VOID Install_Page_Fault_Handle (void) ;
;
; ----------------------------------------------------------------
IDEAL ; the product runs in ideal mode
P386 ; use 386 real mode instructions
MODEL USE32 FLAT
LOCALS ?? ; ?? is the symbol for a local
WARN ; generate all warnings we can
JUMPS ; optimize jumps if possible
;---------------------------------------------------------------------------
; Make some general equates for easy compatability
;---------------------------------------------------------------------------
DPMI_INTR EQU 31h
PAGE_FAULT equ 0eh
RESET_VIDEO_MODE equ -1
GLOBAL Install_Page_Fault_Handle : NEAR
GLOBAL Set_Video_Mode : NEAR
GLOBAL Remove_Mouse : NEAR
GLOBAL Remove_Keyboard_Interrupt : NEAR
GLOBAL Remove_Timer_Interrupt : NEAR
DATASEG
Old_Page_Fault_handle DF ?
Page_Fault_SS DD ?
Page_Fault_ESP DD ?
CODESEG
;***************************************************************************
;* INSTALL_PAGE_FAULT_HANDLE -- Installs new page fault handle *
;* This function will install a new page fault handle *
;* so in the event that we have a program crash thi handle will *
;* remove all interrupts and then will chain to the default Page *
;* Fault handle *
;* *
;* INPUT: none *
;* *
;* *
;* OUTPUT: none *
;* *
;* PROTO: VOID Install_Page_Fault_Handle( void); *
;* *
;* HISTORY: 04/25/96 Created *
;*=========================================================================*
PROC Install_Page_Fault_Handle C NEAR
USES eax,ebx,ecx,edx,esi,edi
mov eax,0202h ; get address of exception handle
mov bl,PAGE_FAULT
int DPMI_INTR
jc ??exit ; not action is taken
; save addrees of default handle
mov [dword ptr Old_Page_Fault_handle],edx
mov [word ptr Old_Page_Fault_handle+4],cx
; redirect default handle to a new Page Fault Handle
mov eax,0203h
mov bl,PAGE_FAULT
mov cx,cs
lea edx,[Page_Fault_Handle]
int DPMI_INTR
??exit:
ret
ENDP Install_Page_Fault_Handle
;***************************************************************************
;* PAGE_FAULT_HANDLE -- This *
;* *
;* *
;* *
;* HISTORY: 04/25/96 Created *
;*=========================================================================*
PROC Page_Fault_Handle far
; preserve used registers
push eax
push ebx
; save Page Fault satck frame
mov ax,ss
mov [Page_Fault_SS],eax
mov [Page_Fault_ESP],esp
; retrieve application original stack frame
mov eax , [ esp + ( 6 + 2 ) * 4 ]
mov ebx , [ esp + ( 7 + 2 ) * 4 ]
mov ss , bx
mov esp , eax
; set video mode to standard text mode
push RESET_VIDEO_MODE
call Set_Video_Mode
pop eax
call Remove_Mouse
call Remove_Keyboard_Interrupt
call Remove_Timer_Interrupt
; restore Page Fault stack frame
mov eax,[Page_Fault_SS]
mov ss , ax
mov esp, [Page_Fault_ESP]
; restore used registers and chain to default Page Fault Handle
pop ebx
pop eax
jmp [fword Old_Page_Fault_handle]
ENDP Page_Fault_Handle
;***************************************************************************
;* End of File. *
;***************************************************************************
END

View File

@@ -0,0 +1,659 @@
;
; Command & Conquer Red Alert(tm)
; Copyright 2025 Electronic Arts Inc.
;
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see <http://www.gnu.org/licenses/>.
;
;***************************************************************************
;** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S **
;***************************************************************************
;* *
;* Project Name : Westwood 32 bit Library *
;* *
;* File Name : BITBLIT.ASM *
;* *
;* Programmer : Philip W. Gorrow *
;* *
;* Start Date : December 12, 1995 *
;* *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
LOCALS ??
INCLUDE "drawbuff.inc"
INCLUDE "gbuffer.inc"
INCLUDE "shape.inc"
INCLUDE ".\mouse.inc"
GLOBAL C LCW_Uncompress:NEAR
GLOBAL C Get_Shape_Uncomp_Size :NEAR
GLOBAL C Get_Shape_Width :NEAR
GLOBAL C Get_Shape_Original_Height :NEAR
GLOBAL _ShapeBuffer :DWORD
CODESEG
;***************************************************************************
;* MOUSE_SHADOW_BUFFER -- Handles storing and restoring the mouse buffer *
;* *
;* INPUT: MouseClass * - pointer to mouse class data *
;* GraphicBufferClass * - screen to draw the mouse on *
;* int x - x position to store the mouse at *
;* int y - y position to store the mouse at *
;* int store - whether to store buffer or save *
;* *
;* OUTPUT: none *
;* *
;* Note: The x and y that this routine expects to receive are based on *
;* the mouse cursor position. This routine automatically adjusts *
;* for hot spot, so that adjustment should not be made prior to *
;* this point. *
;* *
;* PROTO: void Mouse_Shadow_Buffer(GraphicBufferClass *src/dest, *
;* void *buffer
;* int x_pixel, *
;* int y_pixel, *
;* int store); *
;* *
;* HISTORY: *
;* 10/27/1994 PWG : Created. *
;*=========================================================================*
GLOBAL C Mouse_Shadow_Buffer:NEAR
PROC Mouse_Shadow_Buffer C NEAR
USES eax,ebx,ecx,edx,edi,esi
ARG this: DWORD
ARG src_dst_obj: DWORD
ARG buffer:DWORD
ARG x: DWORD
ARG y: DWORD
ARG hotx: DWORD
ARG hoty: DWORD
ARG store: DWORD
local x0: dword
local y0: dword
local x1: dword
local y1: dword
local buffx0: dword
local buffy0: dword
;*=========================================================================*
; Direction flag must be forward in this routine.
;*=========================================================================*
cld
;*===================================================================
;* Copy of X, Y, Width and Height into local registers
;*===================================================================
mov esi, [this] ; get offset to mouse data
mov edi, [src_dst_obj] ; get offset to mouse data
mov eax, [x]
mov ebx, [y]
sub eax, [hotx]
sub ebx, [hoty]
mov [x0], eax
mov [y0], ebx
add eax, [(MouseType esi).CursorWidth]
add ebx, [(MouseType esi).CursorHeight]
mov [x1], eax
mov [y1], ebx
mov [buffx0], 0
mov eax, [buffer]
mov [buffy0], eax
;*===================================================================
;* Bounds check source X.
;*===================================================================
xor eax, eax
xor edx, edx
mov ecx, [x0]
mov ebx, [x1]
shld eax, ecx, 1
shld edx, ebx, 1
mov ecx, [x0]
mov ebx, [x1]
sub ecx, [(GraphicViewPort edi).GVPWidth]
sub ebx, [(GraphicViewPort edi).GVPWidth]
dec ecx
dec ebx
shld eax, ecx, 1
shld edx, ebx, 1
mov ecx, [y0]
mov ebx, [y1]
shld eax, ecx, 1
shld edx, ebx, 1
mov ecx, [y0]
mov ebx, [y1]
sub ecx, [(GraphicViewPort edi).GVPHeight]
sub ebx, [(GraphicViewPort edi).GVPHeight]
dec ecx
dec ebx
shld eax, ecx, 1
shld edx, ebx, 1
xor al, 5
xor dl, 5
mov ah, al
test dl, al
jnz ??out
or al, dl
jz ??not_clip
test ah, 1000b
jz ??scr_left_ok
mov ebx, [x0]
neg ebx
mov [buffx0], ebx
mov [x0], 0
??scr_left_ok:
test ah, 0010b
jz ??scr_bottom_ok
mov ebx, [y0]
neg ebx
imul ebx, [(MouseType esi).CursorWidth]
add [buffy0], ebx
mov [y0], 0
??scr_bottom_ok:
test dl, 0100b
jz ??scr_right_ok
mov eax, [(GraphicViewPort edi).GVPWidth] ; get width into register
mov [x1], eax
??scr_right_ok:
test dl, 0001b
jz ??not_clip
mov eax, [(GraphicViewPort edi).GVPHeight] ; get width into register
mov [y1], eax
??not_clip:
;*===================================================================
;* Get the offset into the screen.
;*===================================================================
mov eax, [y0]
mov edx, [(GraphicViewPort edi).GVPWidth]
add edx, [(GraphicViewPort edi).GVPXAdd]
add edx, [(GraphicViewPort edi).GVPPitch]
imul eax, edx
add eax, [x0]
mov edi, [(GraphicViewPort edi).GVPOffset]
add edi, eax
;*===================================================================
;* Adjust the source for the top clip.
;*===================================================================
mov ebx, [(MouseType esi).CursorWidth] ; turn this into an offset
mov esi, [buffy0] ; edx points to source
add esi, [buffx0] ; plus clipped lines
;*===================================================================
;* Calculate the bytes per row add value
;*===================================================================
mov eax, [x1]
mov ecx, [y1]
sub eax, [x0]
jle ??out
sub ecx, [y0]
jle ??out
sub edx, eax
sub ebx, eax
push ebp
cmp [store], 1 ; are we storing page?
je ??store_entry ; if so go to store
;*===================================================================
;* Handle restoring the buffer to the visible page
;*===================================================================
mov ebp, ecx
??restore_loop:
mov ecx, eax ; get number to really write
rep movsb ; store them into the buffer
add esi, ebx ; move past right clipped pixels
add edi, edx ; adjust dest to next line
dec ebp ; decrement number of rows to do
jnz ??restore_loop ; if more to do, do it
pop ebp
ret
;*===================================================================
;* Handle soting the visible page into the Mouse Shadow Buffer
;*===================================================================
??store_entry:
xchg esi, edi ; xchg the source and the dest
mov ebp, ecx
??store_loop:
mov ecx, eax ; get number to really write
rep movsb ; store them into the buffer
add esi, edx ; move past right clipped pixels
add edi, ebx ; adjust dest to next line
dec ebp ; decrement number of rows to do
jnz ??store_loop ; if more to do, do it
pop ebp
??out:
ret
ENDP Mouse_Shadow_Buffer
;***************************************************************************
;* DRAW_MOUSE -- Handles drawing the mouse cursor *
;* *
;* INPUT: MouseClass * - pointer to mouse class data *
;* GraphicBufferClass * - screen to draw the mouse on *
;* int x - x position to store the mouse at *
;* int y - y position to store the mouse at *
;* *
;* Note: The x and y that this routine expects to receive are based on *
;* the mouse cursor position. This routine automatically adjusts *
;* for hot spot, so that adjustment should not be made prior to *
;* this point. *
;* *
;* PROTO: void Draw_Mouse( MouseClass * mouse_data, *
;* GraphicBufferClass *destination, *
;* int x_pixel, *
;* int y_pixel); *
;* *
;* HISTORY: *
;* 10/27/1994 PWG : Created. *
;*=========================================================================*
GLOBAL C Draw_Mouse:NEAR
PROC Draw_Mouse C NEAR
USES eax,ebx,ecx,edx,edi,esi
ARG this:DWORD
ARG dest:DWORD
ARG mousex:DWORD
ARG mousey:DWORD
local x0:dword
local y0:dword
local x1:dword
local y1:dword
local buffx0:dword
local buffy0:dword
mov esi, [this] ; get 32 bit offset to mouse data
mov edi, [dest] ; get 32 bit offset to dest buffer
;*===================================================================
;* Copy of X, Y, Width and Height into local registers
;*===================================================================
mov eax, [mousex]
mov ebx, [mousey]
sub eax, [(MouseType esi).MouseXHot]
sub ebx, [(MouseType esi).MouseYHot]
mov [x0], eax
mov [y0], ebx
add eax,[(MouseType esi).CursorWidth]
add ebx,[(MouseType esi).CursorHeight]
mov [x1], eax
mov [y1], ebx
mov [buffx0], 0
mov eax, [(MouseType esi).MouseCursor]
mov [buffy0], eax
;*===================================================================
;* Bounds check source X. Y.
;*===================================================================
xor eax, eax
xor edx, edx
mov ecx, [x0]
mov ebx, [x1]
shld eax, ecx, 1
shld edx, ebx, 1
mov ecx, [x0]
mov ebx, [x1]
sub ecx, [(GraphicViewPort edi).GVPWidth]
sub ebx, [(GraphicViewPort edi).GVPWidth]
dec ecx
dec ebx
shld eax, ecx, 1
shld edx, ebx, 1
mov ecx, [y0]
mov ebx, [y1]
shld eax, ecx, 1
shld edx, ebx, 1
mov ecx, [y0]
mov ebx, [y1]
sub ecx, [(GraphicViewPort edi).GVPHeight]
sub ebx, [(GraphicViewPort edi).GVPHeight]
dec ecx
dec ebx
shld eax, ecx, 1
shld edx, ebx, 1
xor al, 5
xor dl, 5
mov ah, al
test dl, al
jnz ??out
or al, dl
jz ??not_clip
test ah, 1000b
jz ??scr_left_ok
mov ebx, [x0]
neg ebx
mov [buffx0], ebx
mov [x0], 0
??scr_left_ok:
test ah, 0010b
jz ??scr_bottom_ok
mov ebx, [y0]
neg ebx
imul ebx, [(MouseType esi).CursorWidth]
add [buffy0], ebx
mov [y0], 0
??scr_bottom_ok:
test dl, 0100b
jz ??scr_right_ok
mov eax, [(GraphicViewPort edi).GVPWidth] ; get width into register
mov [x1] , eax
??scr_right_ok:
test dl, 0001b
jz ??not_clip
mov eax, [(GraphicViewPort edi).GVPHeight] ; get width into register
mov [y1] , eax
??not_clip:
;*===================================================================
;* Get the offset into the screen.
;*===================================================================
mov eax, [y0]
mov edx, [(GraphicViewPort edi).GVPWidth]
add edx, [(GraphicViewPort edi).GVPXAdd]
add edx, [(GraphicViewPort edi).GVPPitch]
imul eax, edx
add eax, [x0]
mov edi, [(GraphicViewPort edi).GVPOffset]
add edi, eax
;*===================================================================
;* Adjust the source for the top clip.
;*===================================================================
mov ebx, [(MouseType esi).CursorWidth] ; turn this into an offset
mov esi, [buffy0] ; edx points to source
add esi, [buffx0] ; plus clipped lines
;*===================================================================
;* Calculate the bytes per row add value
;*===================================================================
mov eax, [x1]
mov ecx, [y1]
sub eax, [x0]
jle ??out
sub ecx, [y0]
jle ??out
sub edx, eax
sub ebx, eax
;*===================================================================
;* Handle restoring the buffer to the visible page
;*===================================================================
??top_loop:
mov ah, al
??inner_loop:
mov ch, [esi]
inc esi
or ch, ch
jz ??inc_edi
mov [edi], ch
??inc_edi:
inc edi
dec ah
jnz ??inner_loop
add esi, ebx ; move past right clipped pixels
add edi, edx ; adjust dest to next line
dec cl ; decrement number of rows to do
jnz ??top_loop ; if more to do, do it
??out:
ret
ENDP Draw_Mouse
;***************************************************************************
;* SET_MOUSE_CURSOR -- Sets the shape to be used as the mouse. *
;* *
;* This will inform the system of the shape desired as the mouse *
;* cursor. *
;* *
;* INPUT: xhotspot -- Offset of click point into shape. *
;* *
;* yhotspot -- Offset of click point into shape. *
;* *
;* cursor -- Shape to use as the new mouse shape. *
;* *
;* OUTPUT: Returns with a pointer to the original mouse shape. *
;* *
;* PROTO: VOID *Set_Mouse_Cursor( int xhotspot, *
;* int yhotspot, *
;* void *cursor); *
;* *
;* HISTORY: *
;* 02/13/1992 JLB : Created. *
;*=========================================================================*
GLOBAL C ASM_Set_Mouse_Cursor:NEAR
PROC ASM_Set_Mouse_Cursor C NEAR
USES ebx,ecx,edx,esi,edi
ARG this:DWORD ; pointer to mouse cursor struct
ARG xhotspot:DWORD ; the x hot spot of the mouse
ARG yhotspot:DWORD ; the y hot spot of the mouse
ARG cursor:DWORD ; ptr to the new mouse cursor
LOCAL datasize:DWORD
LOCAL stype:WORD
LOCAL swidth:DWORD ; Shape width.
LOCAL sheight:DWORD ; Shape height.
LOCAL ssize:DWORD ; Size of raw shape.
;*=========================================================================*
; Direction flag must be forward in this routine.
;*=========================================================================*
cld
mov esi,[this] ; get offset of real mode data start
;-------------------------------------------------------------------
; Calculate the size of the buffer needed.
;-------------------------------------------------------------------
push [cursor]
call Get_Shape_Uncomp_Size
pop edx
mov [datasize],eax
push [cursor]
call Get_Shape_Width
pop edx
mov [swidth],eax
cmp eax,[(MouseType esi).MaxWidth]
jg ??end
push [cursor]
call Get_Shape_Original_Height
pop edx
mov [sheight],eax
cmp eax,[(MouseType esi).MaxHeight]
jg ??end
mov ebx,[sheight]
mov eax,[swidth]
imul ebx,eax
??copy_mouse:
mov edi,[(MouseType esi).MouseCursor] ; set edi to point to mouse buffer
mov esi,[cursor] ; set esi to point to mouse shape
mov ax,[esi] ; get the shape type byte
mov [stype],ax ; save off the shape type
test ax,MAKESHAPE_NOCOMP ; is it marked as no compression?
je ??comp_shape ; if not go to the comped shape code
??copy_type:
test [stype],MAKESHAPE_COMPACT ; if the shape a 16 color shape?
jne ??16_color_copy ; if it is then go handle it
??normal_copy:
;-------------------------------------------------------------------
;* Uncompressed NORMAL shapes just get run-length uncompressed
;-------------------------------------------------------------------
add esi,10 ; adjust past header of shape
mov eax,[swidth] ; load up the width
mul [sheight] ; find size of shape in pixels
mov edx,eax ; save this in number of bytes
xor ecx,ecx ; clear high of loop variable
??norm_unrle:
mov al,[esi] ; get a byte out of the file
inc esi ; increment to the next pos
or al,al ; set the flags on register state
jz ??norm_trans ; if its a zero its transparent
mov [edi],al ; write out the pixel to dest
inc edi ; move to next dest position
dec edx ; we have now written another pix
jnz ??norm_unrle ; if more to write then do it
jmp ??done_copy ; otherwise we are all done
??norm_trans:
mov cl,[esi] ; get how many zeros to write
sub edx,ecx
inc esi ; increment the source position
xor al,al ; clear out al cuz we're writing zeros
rep stosb ; write all of them out
or edx,edx
jnz ??norm_unrle ; if more to do then do it
jmp ??done_copy ; otherwise we are done
??16_color_copy:
;-------------------------------------------------------------------
;* Uncompressed 16 color shapes just get remaped and UN-RLE'd
;-------------------------------------------------------------------
add esi,10 ; adjust past header of shape
mov ebx,esi ; save of position of remap
add esi,16 ; move past remap table
mov eax,[swidth] ; load up the width
mul [sheight] ; load up the height
mov edx,eax ; save this in number of bytes
xor eax,eax ; clear high of lookup variable
xor ecx,ecx ; clear high of loop variable
??16_color_unrle:
mov al,[esi] ; get a byte out of the file
inc esi ; increment to the next pos
or al,al ; set the flags on register state
jz ??16_color_trans ; if its a zero its transparent
mov al,[ebx+eax] ; remap the pixel from 16 color table
mov [edi],al ; store it out to the dest address
inc edi ; move to next dest address
dec edx ; we have now written a pixel
jnz ??16_color_unrle
jmp ??done_copy
??16_color_trans:
mov cl,[esi] ; get how many zeros to write
sub edx,ecx ; subtract off count ahead of time
inc esi ; increment the source position
xor al,al ; clear out al cuz we're writing zeros
rep stosb ; write all of them out
or edx,edx ; or edx to test for zero
jnz ??16_color_unrle
jmp ??done_copy
;-------------------------------------------------------------------
; Deal with the compressed shape by copying it into the shape
; staging buffer.
;-------------------------------------------------------------------
??comp_shape:
mov edi,[ShapeBuffer] ; get a pointer to ShapeBuffer
mov ax,[esi] ; load in the shape type
add esi,2 ; increment the shape pointer
or ax,MAKESHAPE_NOCOMP ; make the shape as uncompressed
mov [stype],ax ; save off the shape type
mov [edi],ax ; write out uncompressed shape
add edi,2
;-------------------------------------------------------------------
; Process the shape header information and copy it over to the new
; location.
;-------------------------------------------------------------------
mov ecx,4 ; transfer height, width, org and
test eax,MAKESHAPE_COMPACT ; is it a 16 color shape?
je ??copy_head ; no - don't worry about it
add ecx,8 ; otherwise adjust ecx for header
??copy_head:
rep movsw ; copy the necessary bytes
mov eax,[datasize] ; get uncompressed length
push eax ; push as third param
push edi ; push the destination offset
push esi ; push the source offset
call LCW_Uncompress ; do the uncompress
pop eax
pop eax
pop eax
mov esi,[this]
mov edi,[(MouseType esi).MouseCursor] ; set edi to point to mouse buffer
mov esi,[ShapeBuffer]
jmp ??copy_type
??done_copy:
mov esi,[this] ; get offset of real mode data start
mov eax,[xhotspot] ; get the mouse cursors x hotspot
mov [(MouseType esi).MouseXHot],eax
mov eax,[yhotspot] ; get the mouse cursors y hotspot
mov [(MouseType esi).MouseYHot],eax
mov ebx,[sheight] ; get shape height
mov [(MouseType esi).CursorHeight],ebx
mov ebx,[swidth]
mov [(MouseType esi).CursorWidth],ebx
;-------------------------------------------------------------------
; Final cleanup and exit.
;-------------------------------------------------------------------
??end:
push [cursor]
push [(MouseType esi).PrevCursor]
pop eax
pop [(MouseType esi).PrevCursor]
ret ; and return back to the world
ENDP ASM_Set_Mouse_Cursor
END

View File

@@ -0,0 +1,655 @@
;
; Command & Conquer Red Alert(tm)
; Copyright 2025 Electronic Arts Inc.
;
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see <http://www.gnu.org/licenses/>.
;
;***************************************************************************
;** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S **
;***************************************************************************
;* *
;* Project Name : Westwood 32 bit Library *
;* *
;* File Name : BITBLIT.ASM *
;* *
;* Programmer : Philip W. Gorrow *
;* *
;* Start Date : December 12, 1995 *
;* *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
LOCALS ??
INCLUDE "drawbuff.inc"
INCLUDE "gbuffer.inc"
INCLUDE "shape.inc"
INCLUDE ".\mouse.inc"
GLOBAL C LCW_Uncompress:NEAR
GLOBAL C Get_Shape_Uncomp_Size :NEAR
GLOBAL C Get_Shape_Width :NEAR
GLOBAL C Get_Shape_Original_Height :NEAR
GLOBAL _ShapeBuffer :DWORD
CODESEG
;***************************************************************************
;* MOUSE_SHADOW_BUFFER -- Handles storing and restoring the mouse buffer *
;* *
;* INPUT: MouseClass * - pointer to mouse class data *
;* GraphicBufferClass * - screen to draw the mouse on *
;* int x - x position to store the mouse at *
;* int y - y position to store the mouse at *
;* int store - whether to store buffer or save *
;* *
;* OUTPUT: none *
;* *
;* Note: The x and y that this routine expects to receive are based on *
;* the mouse cursor position. This routine automatically adjusts *
;* for hot spot, so that adjustment should not be made prior to *
;* this point. *
;* *
;* PROTO: void Mouse_Shadow_Buffer(GraphicBufferClass *src/dest, *
;* int x_pixel, *
;* int y_pixel, *
;* int store); *
;* *
;* HISTORY: *
;* 10/27/1994 PWG : Created. *
;*=========================================================================*
GLOBAL C Mouse_Shadow_Buffer:NEAR
PROC Mouse_Shadow_Buffer C NEAR
USES eax,ebx,ecx,edx,edi,esi
ARG this: DWORD
ARG src_dst_obj: DWORD
ARG x: DWORD
ARG y: DWORD
ARG store: DWORD
local x0: dword
local y0: dword
local x1: dword
local y1: dword
local buffx0: dword
local buffy0: dword
;*=========================================================================*
; Direction flag must be forward in this routine.
;*=========================================================================*
cld
;*===================================================================
;* Copy of X, Y, Width and Height into local registers
;*===================================================================
mov esi, [this] ; get offset to mouse data
mov edi, [src_dst_obj] ; get offset to mouse data
mov eax, [x]
mov ebx, [y]
sub eax, [(MouseType esi).MouseXHot]
sub ebx, [(MouseType esi).MouseYHot]
mov [x0], eax
mov [y0], ebx
add eax, [(MouseType esi).CursorWidth]
add ebx, [(MouseType esi).CursorHeight]
mov [x1], eax
mov [y1], ebx
mov [buffx0], 0
mov eax, [(MouseType esi).MouseBuffer]
mov [buffy0], eax
;*===================================================================
;* Bounds check source X.
;*===================================================================
xor eax, eax
xor edx, edx
mov ecx, [x0]
mov ebx, [x1]
shld eax, ecx, 1
shld edx, ebx, 1
mov ecx, [x0]
mov ebx, [x1]
sub ecx, [(GraphicViewPort edi).GVPWidth]
sub ebx, [(GraphicViewPort edi).GVPWidth]
dec ecx
dec ebx
shld eax, ecx, 1
shld edx, ebx, 1
mov ecx, [y0]
mov ebx, [y1]
shld eax, ecx, 1
shld edx, ebx, 1
mov ecx, [y0]
mov ebx, [y1]
sub ecx, [(GraphicViewPort edi).GVPHeight]
sub ebx, [(GraphicViewPort edi).GVPHeight]
dec ecx
dec ebx
shld eax, ecx, 1
shld edx, ebx, 1
xor al, 5
xor dl, 5
mov ah, al
test dl, al
jnz ??out
or al, dl
jz ??not_clip
test ah, 1000b
jz ??scr_left_ok
mov ebx, [x0]
neg ebx
mov [buffx0], ebx
mov [x0], 0
??scr_left_ok:
test ah, 0010b
jz ??scr_bottom_ok
mov ebx, [y0]
neg ebx
imul ebx, [(MouseType esi).CursorWidth]
add [buffy0], ebx
mov [y0], 0
??scr_bottom_ok:
test dl, 0100b
jz ??scr_right_ok
mov eax, [(GraphicViewPort edi).GVPWidth] ; get width into register
mov [x1], eax
??scr_right_ok:
test dl, 0001b
jz ??not_clip
mov eax, [(GraphicViewPort edi).GVPHeight] ; get width into register
mov [y1], eax
??not_clip:
;*===================================================================
;* Get the offset into the screen.
;*===================================================================
mov eax, [y0]
mov edx, [(GraphicViewPort edi).GVPWidth]
add edx, [(GraphicViewPort edi).GVPXAdd]
add edx, [(GraphicViewPort edi).GVPPitch]
imul eax, edx
add eax, [x0]
mov edi, [(GraphicViewPort edi).GVPOffset]
add edi, eax
;*===================================================================
;* Adjust the source for the top clip.
;*===================================================================
mov ebx, [(MouseType esi).CursorWidth] ; turn this into an offset
mov esi, [buffy0] ; edx points to source
add esi, [buffx0] ; plus clipped lines
;*===================================================================
;* Calculate the bytes per row add value
;*===================================================================
mov eax, [x1]
mov ecx, [y1]
sub eax, [x0]
jle ??out
sub ecx, [y0]
jle ??out
sub edx, eax
sub ebx, eax
push ebp
cmp [store], 1 ; are we storing page?
je ??store_entry ; if so go to store
;*===================================================================
;* Handle restoring the buffer to the visible page
;*===================================================================
mov ebp, ecx
??restore_loop:
mov ecx, eax ; get number to really write
rep movsb ; store them into the buffer
add esi, ebx ; move past right clipped pixels
add edi, edx ; adjust dest to next line
dec ebp ; decrement number of rows to do
jnz ??restore_loop ; if more to do, do it
pop ebp
ret
;*===================================================================
;* Handle soting the visible page into the Mouse Shadow Buffer
;*===================================================================
??store_entry:
xchg esi, edi ; xchg the source and the dest
mov ebp, ecx
??store_loop:
mov ecx, eax ; get number to really write
rep movsb ; store them into the buffer
add esi, edx ; move past right clipped pixels
add edi, ebx ; adjust dest to next line
dec ebp ; decrement number of rows to do
jnz ??store_loop ; if more to do, do it
pop ebp
??out:
ret
ENDP Mouse_Shadow_Buffer
;***************************************************************************
;* DRAW_MOUSE -- Handles drawing the mouse cursor *
;* *
;* INPUT: MouseClass * - pointer to mouse class data *
;* GraphicBufferClass * - screen to draw the mouse on *
;* int x - x position to store the mouse at *
;* int y - y position to store the mouse at *
;* *
;* Note: The x and y that this routine expects to receive are based on *
;* the mouse cursor position. This routine automatically adjusts *
;* for hot spot, so that adjustment should not be made prior to *
;* this point. *
;* *
;* PROTO: void Draw_Mouse( MouseClass * mouse_data, *
;* GraphicBufferClass *destination, *
;* int x_pixel, *
;* int y_pixel); *
;* *
;* HISTORY: *
;* 10/27/1994 PWG : Created. *
;*=========================================================================*
GLOBAL C Draw_Mouse:NEAR
PROC Draw_Mouse C NEAR
USES eax,ebx,ecx,edx,edi,esi
ARG this:DWORD
ARG dest:DWORD
ARG mousex:DWORD
ARG mousey:DWORD
local x0:dword
local y0:dword
local x1:dword
local y1:dword
local buffx0:dword
local buffy0:dword
mov esi, [this] ; get 32 bit offset to mouse data
mov edi, [dest] ; get 32 bit offset to dest buffer
;*===================================================================
;* Copy of X, Y, Width and Height into local registers
;*===================================================================
mov eax, [mousex]
mov ebx, [mousey]
sub eax, [(MouseType esi).MouseXHot]
sub ebx, [(MouseType esi).MouseYHot]
mov [x0], eax
mov [y0], ebx
add eax,[(MouseType esi).CursorWidth]
add ebx,[(MouseType esi).CursorHeight]
mov [x1], eax
mov [y1], ebx
mov [buffx0], 0
mov eax, [(MouseType esi).MouseCursor]
mov [buffy0], eax
;*===================================================================
;* Bounds check source X. Y.
;*===================================================================
xor eax, eax
xor edx, edx
mov ecx, [x0]
mov ebx, [x1]
shld eax, ecx, 1
shld edx, ebx, 1
mov ecx, [x0]
mov ebx, [x1]
sub ecx, [(GraphicViewPort edi).GVPWidth]
sub ebx, [(GraphicViewPort edi).GVPWidth]
dec ecx
dec ebx
shld eax, ecx, 1
shld edx, ebx, 1
mov ecx, [y0]
mov ebx, [y1]
shld eax, ecx, 1
shld edx, ebx, 1
mov ecx, [y0]
mov ebx, [y1]
sub ecx, [(GraphicViewPort edi).GVPHeight]
sub ebx, [(GraphicViewPort edi).GVPHeight]
dec ecx
dec ebx
shld eax, ecx, 1
shld edx, ebx, 1
xor al, 5
xor dl, 5
mov ah, al
test dl, al
jnz ??out
or al, dl
jz ??not_clip
test ah, 1000b
jz ??scr_left_ok
mov ebx, [x0]
neg ebx
mov [buffx0], ebx
mov [x0], 0
??scr_left_ok:
test ah, 0010b
jz ??scr_bottom_ok
mov ebx, [y0]
neg ebx
imul ebx, [(MouseType esi).CursorWidth]
add [buffy0], ebx
mov [y0], 0
??scr_bottom_ok:
test dl, 0100b
jz ??scr_right_ok
mov eax, [(GraphicViewPort edi).GVPWidth] ; get width into register
mov [x1] , eax
??scr_right_ok:
test dl, 0001b
jz ??not_clip
mov eax, [(GraphicViewPort edi).GVPHeight] ; get width into register
mov [y1] , eax
??not_clip:
;*===================================================================
;* Get the offset into the screen.
;*===================================================================
mov eax, [y0]
mov edx, [(GraphicViewPort edi).GVPWidth]
add edx, [(GraphicViewPort edi).GVPXAdd]
add edx, [(GraphicViewPort edi).GVPPitch]
imul eax, edx
add eax, [x0]
mov edi, [(GraphicViewPort edi).GVPOffset]
add edi, eax
;*===================================================================
;* Adjust the source for the top clip.
;*===================================================================
mov ebx, [(MouseType esi).CursorWidth] ; turn this into an offset
mov esi, [buffy0] ; edx points to source
add esi, [buffx0] ; plus clipped lines
;*===================================================================
;* Calculate the bytes per row add value
;*===================================================================
mov eax, [x1]
mov ecx, [y1]
sub eax, [x0]
jle ??out
sub ecx, [y0]
jle ??out
sub edx, eax
sub ebx, eax
;*===================================================================
;* Handle restoring the buffer to the visible page
;*===================================================================
??top_loop:
mov ah, al
??inner_loop:
mov ch, [esi]
inc esi
or ch, ch
jz ??inc_edi
mov [edi], ch
??inc_edi:
inc edi
dec ah
jnz ??inner_loop
add esi, ebx ; move past right clipped pixels
add edi, edx ; adjust dest to next line
dec cl ; decrement number of rows to do
jnz ??top_loop ; if more to do, do it
??out:
ret
ENDP Draw_Mouse
;***************************************************************************
;* SET_MOUSE_CURSOR -- Sets the shape to be used as the mouse. *
;* *
;* This will inform the system of the shape desired as the mouse *
;* cursor. *
;* *
;* INPUT: xhotspot -- Offset of click point into shape. *
;* *
;* yhotspot -- Offset of click point into shape. *
;* *
;* cursor -- Shape to use as the new mouse shape. *
;* *
;* OUTPUT: Returns with a pointer to the original mouse shape. *
;* *
;* PROTO: VOID *Set_Mouse_Cursor( int xhotspot, *
;* int yhotspot, *
;* void *cursor); *
;* *
;* HISTORY: *
;* 02/13/1992 JLB : Created. *
;*=========================================================================*
GLOBAL C ASM_Set_Mouse_Cursor:NEAR
PROC ASM_Set_Mouse_Cursor C NEAR
USES ebx,ecx,edx,esi,edi
ARG this:DWORD ; pointer to mouse cursor struct
ARG xhotspot:DWORD ; the x hot spot of the mouse
ARG yhotspot:DWORD ; the y hot spot of the mouse
ARG cursor:DWORD ; ptr to the new mouse cursor
LOCAL datasize:DWORD
LOCAL stype:WORD
LOCAL swidth:DWORD ; Shape width.
LOCAL sheight:DWORD ; Shape height.
LOCAL ssize:DWORD ; Size of raw shape.
;*=========================================================================*
; Direction flag must be forward in this routine.
;*=========================================================================*
cld
mov esi,[this] ; get offset of real mode data start
;-------------------------------------------------------------------
; Calculate the size of the buffer needed.
;-------------------------------------------------------------------
push [cursor]
call Get_Shape_Uncomp_Size
pop edx
mov [datasize],eax
push [cursor]
call Get_Shape_Width
pop edx
mov [swidth],eax
cmp eax,[(MouseType esi).MaxWidth]
jg ??end
push [cursor]
call Get_Shape_Original_Height
pop edx
mov [sheight],eax
cmp eax,[(MouseType esi).MaxHeight]
jg ??end
mov ebx,[sheight]
mov eax,[swidth]
imul ebx,eax
??copy_mouse:
mov edi,[(MouseType esi).MouseCursor] ; set edi to point to mouse buffer
mov esi,[cursor] ; set esi to point to mouse shape
mov ax,[esi] ; get the shape type byte
mov [stype],ax ; save off the shape type
test ax,MAKESHAPE_NOCOMP ; is it marked as no compression?
je ??comp_shape ; if not go to the comped shape code
??copy_type:
test [stype],MAKESHAPE_COMPACT ; if the shape a 16 color shape?
jne ??16_color_copy ; if it is then go handle it
??normal_copy:
;-------------------------------------------------------------------
;* Uncompressed NORMAL shapes just get run-length uncompressed
;-------------------------------------------------------------------
add esi,10 ; adjust past header of shape
mov eax,[swidth] ; load up the width
mul [sheight] ; find size of shape in pixels
mov edx,eax ; save this in number of bytes
xor ecx,ecx ; clear high of loop variable
??norm_unrle:
mov al,[esi] ; get a byte out of the file
inc esi ; increment to the next pos
or al,al ; set the flags on register state
jz ??norm_trans ; if its a zero its transparent
mov [edi],al ; write out the pixel to dest
inc edi ; move to next dest position
dec edx ; we have now written another pix
jnz ??norm_unrle ; if more to write then do it
jmp ??done_copy ; otherwise we are all done
??norm_trans:
mov cl,[esi] ; get how many zeros to write
sub edx,ecx
inc esi ; increment the source position
xor al,al ; clear out al cuz we're writing zeros
rep stosb ; write all of them out
or edx,edx
jnz ??norm_unrle ; if more to do then do it
jmp ??done_copy ; otherwise we are done
??16_color_copy:
;-------------------------------------------------------------------
;* Uncompressed 16 color shapes just get remaped and UN-RLE'd
;-------------------------------------------------------------------
add esi,10 ; adjust past header of shape
mov ebx,esi ; save of position of remap
add esi,16 ; move past remap table
mov eax,[swidth] ; load up the width
mul [sheight] ; load up the height
mov edx,eax ; save this in number of bytes
xor eax,eax ; clear high of lookup variable
xor ecx,ecx ; clear high of loop variable
??16_color_unrle:
mov al,[esi] ; get a byte out of the file
inc esi ; increment to the next pos
or al,al ; set the flags on register state
jz ??16_color_trans ; if its a zero its transparent
mov al,[ebx+eax] ; remap the pixel from 16 color table
mov [edi],al ; store it out to the dest address
inc edi ; move to next dest address
dec edx ; we have now written a pixel
jnz ??16_color_unrle
jmp ??done_copy
??16_color_trans:
mov cl,[esi] ; get how many zeros to write
sub edx,ecx ; subtract off count ahead of time
inc esi ; increment the source position
xor al,al ; clear out al cuz we're writing zeros
rep stosb ; write all of them out
or edx,edx ; or edx to test for zero
jnz ??16_color_unrle
jmp ??done_copy
;-------------------------------------------------------------------
; Deal with the compressed shape by copying it into the shape
; staging buffer.
;-------------------------------------------------------------------
??comp_shape:
mov edi,[ShapeBuffer] ; get a pointer to ShapeBuffer
mov ax,[esi] ; load in the shape type
add esi,2 ; increment the shape pointer
or ax,MAKESHAPE_NOCOMP ; make the shape as uncompressed
mov [stype],ax ; save off the shape type
mov [edi],ax ; write out uncompressed shape
add edi,2
;-------------------------------------------------------------------
; Process the shape header information and copy it over to the new
; location.
;-------------------------------------------------------------------
mov ecx,4 ; transfer height, width, org and
test eax,MAKESHAPE_COMPACT ; is it a 16 color shape?
je ??copy_head ; no - don't worry about it
add ecx,8 ; otherwise adjust ecx for header
??copy_head:
rep movsw ; copy the necessary bytes
mov eax,[datasize] ; get uncompressed length
push eax ; push as third param
push edi ; push the destination offset
push esi ; push the source offset
call LCW_Uncompress ; do the uncompress
pop eax
pop eax
pop eax
mov esi,[this]
mov edi,[(MouseType esi).MouseCursor] ; set edi to point to mouse buffer
mov esi,[ShapeBuffer]
jmp ??copy_type
??done_copy:
mov esi,[this] ; get offset of real mode data start
mov eax,[xhotspot] ; get the mouse cursors x hotspot
mov [(MouseType esi).MouseXHot],eax
mov eax,[yhotspot] ; get the mouse cursors y hotspot
mov [(MouseType esi).MouseYHot],eax
mov ebx,[sheight] ; get shape height
mov [(MouseType esi).CursorHeight],ebx
mov ebx,[swidth]
mov [(MouseType esi).CursorWidth],ebx
;-------------------------------------------------------------------
; Final cleanup and exit.
;-------------------------------------------------------------------
??end:
push [cursor]
push [(MouseType esi).PrevCursor]
pop eax
pop [(MouseType esi).PrevCursor]
ret ; and return back to the world
ENDP ASM_Set_Mouse_Cursor
END